[alt.sources] GDXBBS -- A unix bbs gdxbbs/part01

jay@gdx.UUCP (Jay A. Snyder) (01/17/91)

GDXBBS V1.0 (beta)
(C) 1990
Jay A. Snyder

Well, it is only 9 months later than I expected.  I promised to post
this about nine months ago, but I got very busy with other projects.

Here it is, finally, an easy to use, easy to administrate, highly
configurable BBS for the unix world.

I will be doing a port to MSDOS, in the near future.  This main
entails writing terminal handling and communication routines.  I plan
to make this version DesqView aware for ease of a multi-line system,
and also so you can have your full CPU under DesqView when no users
are logged in.

Please feel free to port this to other systems (please port the termio
stuff to a BSD system), Amigas, Macs, etc.

When making ports to other systems please try to just replease term.c,
and make minimal changes to main.c for startup.  Then PLEASE send me
either diffs, or the modified code.   (diffs are probably better).  If
a clean port is made (as I just described), I can support it in future
releases. 

echo `flames` >/dev/null

Report bugs, problems and suggestions to:
Jay Snyder
....uunet!wa3wbu!gdx!jay
wa3wbu!gdx!jay@uunet.uu.net

or feel free to call my board to sample GDX:
    ______   _____
   /         /    |  | /    /      717-737-3249
  /  ____   /    /   |/    /       2400/1200/300bd
 /      /  /    /   /|    /        24 Hrs.
/______/ _/____/   / |   o         GDX-BBS Version 1
 
  Supporting both MSDOS and Unix users.
  SCO Xenix binaries online.
  Unix source code file areas
  USENET Access
  FIDONET Access in the works
  Online Games  (NetHack  -- exellent D&D game)
  MSDOS, Unix, HAM discussion Groups

This is the board for you if you are looking for unix software.
Lots of unix source code.

Submitted-by: root@gdx
Archive-name: gdxbbs/part01
---- Cut Here and unpack ----
#!/bin/sh
# This is gdxbbs, a shell archive (shar 3.21)
# made 01/17/1991 04:29 UTC by root@gdx
# Source directory /bbs
#
# existing files WILL be overwritten
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1700 -rw-r--r-- RELEASE.NOTES
#   2123 -rw-r--r-- GDXBBS.DOC
#   5645 -rw-r--r-- .emacsmail
#   5039 -rw-r--r-- main.c
#   9026 -rw-r--r-- menu.c
#   5459 -rw-r--r-- misc.c
#   1506 -rw-r--r-- error.c
#   5842 -rw-r--r-- cle.c
#   4139 -rw-r--r-- parse.c
#   5277 -rw-r--r-- funcs.c
#    178 -rw-r--r-- chat.c
#   1832 -rw-r--r-- spawn.c
#  10647 -rw-r--r-- users.c
#    233 -rw-r--r-- bulletin.c
#   6459 -rw-r--r-- config.c
#   6091 -rw-r--r-- file.c
#   3831 -rw-r--r-- who.c
#   1945 -rw-r--r-- quest.c
#   1155 -rw-r--r-- script.c
#  20376 -rw-r--r-- mail.c
#   1355 -rw-r--r-- packmsg.c
#   3833 -rw-r--r-- atout.c
#   7639 -rw-r--r-- term.c
#   2171 -rw-r--r-- env.c
#   6355 -rw-r--r-- areas.c
#    871 -rw-r--r-- sig.c
#   1013 -rw-r--r-- priv.c
#   1455 -rw------- config.h
#    492 -rw------- defs2.h
#    611 -rw-r--r-- inc.h
#    853 -rw------- termdefs.h
#   1327 -rw------- defs.h
#   2245 -rw------- global.h
#   1576 -rw------- structs.h
#   3129 -rw------- Makefile
#   2331 -rw------- answer.bbs
#   3968 -rw-r--r-- areas.bbs
#    990 -rw------- config.bbs
#    183 -rw-r--r-- filelibs.bbs
#    497 -rw-r--r-- msgareas.bbs
#    546 -rw------- question.bbs
#    625 -rw------- userpriv.bbs
#     87 -rw------- users.bbs
#     82 -rw------- welcome.bbs
#     32 -rwx------ sysop
#    451 -rw------- sysop.cfg
#   3074 -rw-r--r-- menu.mcl
#   1871 -rw------- sysop.mcl
#    856 -rw-r--r-- csee.src
#    141 -rw------- newuser.src
#     91 -rw------- startup.src
#    123 -rw------- sysop.src
#    113 -rw-r--r-- files.help
#    668 -rw-r--r-- mail.help
#    924 -rw-r--r-- main.help
#   1447 -rw-r--r-- packmain.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
if test -r @shar_seq_.tmp; then
	echo "Must unpack archives in sequence!"
	next=`cat @shar_seq_.tmp`; echo "Please unpack part $next next"
	exit 1
fi
# ============= RELEASE.NOTES ==============
echo "x - extracting RELEASE.NOTES (Text)"
sed 's/^X//' << 'SHAR_EOF' > RELEASE.NOTES &&
XGDXBBS V1.0 (beta)
X(C) 1990
XJay A. Snyder
X
XWell, it is only 9 months later than I expected.  I promised to post
Xthis about nine months ago, but I got very busy with other projects.
X
XHere it is, finally, an easy to use, easy to administrate, highly
Xconfigurable BBS for the unix world.
X
XI will be doing a port to MSDOS, in the near future.  This main
Xentails writing terminal handling and communication routines.  I plan
Xto make this version DesqView aware for ease of a multi-line system,
Xand also so you can have your full CPU under DesqView when no users
Xare logged in.
X
XPlease feel free to port this to other systems (please port the termio
Xstuff to a BSD system), Amigas, Macs, etc.
X
XWhen making ports to other systems please try to just replease term.c,
Xand make minimal changes to main.c for startup.  Then PLEASE send me
Xeither diffs, or the modified code.   (diffs are probably better).  If
Xa clean port is made (as I just described), I can support it in future
Xreleases. 
X
Xecho `flames` >/dev/null
X
XReport bugs, problems and suggestions to:
XJay Snyder
X....uunet!wa3wbu!gdx!jay
Xwa3wbu!gdx!jay@uunet.uu.net
X
Xor feel free to call my board to sample GDX:
X    ______   _____
X   /         /    |  | /    /      717-737-3249
X  /  ____   /    /   |/    /       2400/1200/300bd
X /      /  /    /   /|    /        24 Hrs.
X/______/ _/____/   / |   o         GDX-BBS Version 1
X 
X  Supporting both MSDOS and Unix users.
X  SCO Xenix binaries online.
X  Unix source code file areas
X  USENET Access
X  FIDONET Access in the works
X  Online Games  (NetHack  -- exellent D&D game)
X  MSDOS, Unix, HAM discussion Groups
X
XThis is the board for you if you are looking for unix software.
XLots of unix source code.
X
X 
SHAR_EOF
$TOUCH -am 0116232191 RELEASE.NOTES &&
chmod 0644 RELEASE.NOTES ||
echo "restore of RELEASE.NOTES failed"
set `wc -c RELEASE.NOTES`;Wc_c=$1
if test "$Wc_c" != "1700"; then
	echo original size 1700, current size $Wc_c
fi
# ============= GDXBBS.DOC ==============
echo "x - extracting GDXBBS.DOC (Text)"
sed 's/^X//' << 'SHAR_EOF' > GDXBBS.DOC &&
XSorry if the documentation is sparse -- this IS a pre-release
X
XGDXBBS V1.0 (beta)
X(C) 1990
XJay A. Snyder
X========
XMany of the functions are not yet written.  I'll will post new
Xversions as these are completed.
X========
Xusers file:
Xthe file under files -> users token in config.bbs
Xcontains username, password, and user level information.
Xformat ala unix passwd file:
X
Xname:encrypted-password:user-level:
X
Xuser-levels are 32bit fields.  For a user to have access to a command,
Xmenu entry, file or message area; either the required level must be
Xzero, or a the user must have a common bit set.  Each of the 32 bits
Xrepresents a privledge.
X
XUser levels will be done with keywords in the final release, but this
Xis at least functional.
X
XExample:
X1 = access to message area A
X2 = access to message area B
X
Xa user with user level of 1 has access to area A
Xa user with user level of 2 has access to area B
Xa user with user level of 3 has access to both
X
X
X========
Xconfig.bbs --> this file contains most of the configuration information,
X	user access levels to various commands, filenames and location,
X	idle - timeout, command line to run full screen editor,
X	maximum number of attempts at password, default terminal type,
X	prompt, and sysop's login name
X
XUse the included config.bbs, and menu.mcl as examples.  As is, they
Xshould both server you're needes.
X
XNote: if defterm isn't defined, then the value is taken from /etc/ttytypes
X========
XMenus --> see comments in menu.c for format of menu file.  (menu.mcl)
X========
XMessage Areas:
X
X  Access:
X    A user can access a message area if his priviledge level shares
X  an access bit with the message area, or if the level of that area is zero.
X========
Xareas.bbs, msgareas.bbs
X
XThese should both serve as examples.  (they are what I use on my system).
X========
XThings to do:
X
XI'm in the process of writing USENET support into the message areas.
X
XFIDONET support should be added to the final release, or possibly a
Xsubsequent release.  Any information on FIDONET protocol, and mail
Xfile formats would be appreciated.
X
XJay Snyder
X....uunet!wa3wbu!gdx!jay
Xwa3wbu!gdx!jay@uunet.uu.net
SHAR_EOF
$TOUCH -am 0116231591 GDXBBS.DOC &&
chmod 0644 GDXBBS.DOC ||
echo "restore of GDXBBS.DOC failed"
set `wc -c GDXBBS.DOC`;Wc_c=$1
if test "$Wc_c" != "2123"; then
	echo original size 2123, current size $Wc_c
fi
# ============= .emacsmail ==============
echo "x - extracting .emacsmail (Text)"
sed 's/^X//' << 'SHAR_EOF' > .emacsmail &&
X;	EMACS.RC:	Standard micro Startup program
X;			for MicroEMACS 3.9d and above
X;			(C)opyright 1987 by Daniel M Lawrence
X;			Last Update: 10/20/87
X
Xset $discmd FALSE
Xwrite-message "[Setting up....]"
X
X; If you screen "SNOWS", comment this line
X	set $flicker "FALSE"
X
X; To use an IBM-PC EGA card, uncomment the following line
X;	set $sres "EGA"
X
X;	Set Default Global modes
X;add-global-mode "blue"
X;bind-to-key next-page FN<
X;bind-to-key previous-page FNC
X;bind-to-key meta-prefix `
X
X
X;	Toggle function key window display
X
X1	store-macro
X	!if %rcfkeys
X		!goto rcfoff
X	!endif
X
X;	toggle function key window on
X	save-window
X	1 next-window
X	!if &sequal $cbufname "emacs.hlp"
X		delete-window
X	!endif
X	!if &not &sequal $cbufname "Function Keys"
X		1 split-current-window
X		1 select-buffer "Function Keys"
X		add-mode "red"
X		!force 5 resize-window
X		1 goto-line
X	!endif
X	set %rcfkeys TRUE
X	!force restore-window
X	!if &sequal $cbufname "Function Keys"
X		next-window
X	!endif
X	write-message "[Function key window ON]"
X	!return
X
X	;Toggle the function key window off
X*rcfoff
X	save-window
X	1 next-window
X	!if &sequal "Function Keys" $cbufname
X		delete-window
X	!endif
X	!force restore-window
X	write-message "[Function key window OFF]"
X	set %rcfkeys FALSE
X!endm
X
X;	Toggle HELP file onscreen
X
X2 store-macro
X	1 next-window
X
X	;Make sure the function key window isn't up!
X	!if &sequal $cbufname "Function Keys"
X		delete-window
X	!endif
X	set %rcfkeys FALSE
X
X	;Bring up page 1
X	!if &not &seq $cbufname "emacs.hlp"
X;		split-current-window
X;		view-file /usr/local/uemacs/emacs.hlp
X		help
X		8 resize-window
X		add-mode "red"
X		beginning-of-file
X		2 forward-character
X	!endif
X
X*rchelp
X
X	write-message "[n] Next Page [p] Previous Page   [^Z] EXIT HELP"
X	update-screen
X	set %rctmp &gtcmd
X	!if &seq %rctmp p
X		beginning-of-line
X		!force search-reverse "=>"
X		1 redraw-display
X		!goto rchelp
X	!endif
X	!if &seq %rctmp ^P
X		beginning-of-line
X		!force search-reverse "=>"
X		1 redraw-display
X		!goto rchelp
X	!endif
X	!if &seq %rctmp n
X		beginning-of-line
X		2 forward-character
X		!force search-forward "=>"
X		1 redraw-display
X		!goto rchelp
X	!endif
X	!if &seq %rctmp ^N
X		beginning-of-line
X		2 forward-character
X		!force search-forward "=>"
X		1 redraw-display
X		!goto rchelp
X	!endif
X	!if &seq %rctmp ^Z
X		delete-window
X		!if &seq %rcfkeys TRUE
X			set %rcfkeys FALSE
X			execute-macro-1
X		!endif
X		write-message "[Help Exited]"
X		!return
X	!endif
X	!goto rchelp
X!endm
X
X;	Load a new page
X
X3	store-macro
X	!if &seq &find newpage.cmd ""
X		write-message "[Can not find NEWPAGE.CMD]"
X		!return
X	!endif
X	execute-file newpage.cmd
X!endm
X
X;procedure to clean out the current page (which is nothing right now)
X
Xstore-procedure	clean
X	; nothing by default
X!endm
X
X;	Set up auto CMODE
X
X20	store-macro
X	set %rctmp &sin $cfname "."
X	!if &equ %rctmp 0
X		!return
X	!endif
X	set %rctmp &mid $cfname &add %rctmp 1 5
X	!if &or &seq %rctmp "c" &seq %rctmp "h"
X		add-mode "cmode"
X	!endif
X	!if &seq %rctmp "mss"
X		add-mode "wrap"
X	!endif
X!endm
Xset $readhook execute-macro-20
X
X;	This function activates the function key window as
X;	a legitimate place to call up function keys
X
X21	store-macro
X
X	;remember where we started, and do the mouse movement
X	save-window
X	mouse-move-down
X
X	;If not in the function key window... leave
X	!if &not &sequal $cbufname "Function Keys"
X		!return
X	!endif
X
X	;Find out what function key were gonna do
X	add-mode magic
X	2 forward-character
X	set %rctmp $search
X	!force search-reverse "[fF][0-9]"
X	!if &seq $status FALSE
X		delete-mode magic
X		set $search %rctmp
X		!return
X	!endif
X
X	;we are on the "f" or "F".  Get the function key type and number now
X	set $search %rctmp
X	set %fcase lower
X	!if &equ $curchar 70
X		set %fcase upper
X	!endif
X	1 forward-character
X	set %fnum &chr $curchar
X	1 forward-character
X	set %fnum &cat %fnum &chr $curchar
X	set %fnum &add %fnum 0
X	!if &equ %fnum 10
X		set %fnum "0"
X	!endif
X	set %fname &cat "FN" %fnum
X	!if &seq %fcase upper
X		set %fname &cat "S-" %fname
X	!endif
X
X	;save the function
X	set %rccmd &bind %fname
X	delete-mode MAGIC
X
X	;swallow the up-button
X	set %rctmp &gtc
X
X	;restore the window and exit
X	restore-window
X
X	;and then execute it
X	execute-named-command &ind %rccmd
X!endm	
Xbind-to-key execute-macro-21 MSa
X
X
X33	store-macro
X
X	unmark-buffer
X	next-window
X	unmark-buffer
X	next-window
X	unmark-buffer
X        exit-emacs
X!endm
X
X32	store-macro
X
X	save-file
X        exit-emacs
X!endm
X
X23	store-macro
X	next-window
X	delete-window
X	execute-macro-2
X        split-current-window
X	!force 4 resize-window
X	select-buffer "GDXBBS-Mail"
X	1 goto-line
X	next-window
X!endm
X
Xbind-to-key execute-macro-23 M-?
Xbind-to-key execute-macro-32 ^Z
Xbind-to-key execute-macro-33 M-q
Xbind-to-key incremental-search ^S
Xunbind-key ^Xo
Xunbind-key ^X1
Xunbind-key ^XP
Xunbind-key ^X^
Xunbind-key M-^L
Xunbind-key ^X^F
Xunbind-key ^X^R
Xunbind-key ^X^V
Xunbind-key ^X^W
Xunbind-key ^XN
X; don't let the user muck up the windows
Xunbind-key ^X^Z 
Xunbind-key ^XZ 
Xunbind-key M-^Z
Xunbind-key M-^V
X;don't let the user delete current window - he'll get confused
Xunbind-key ^X0 
Xunbind-key ^XB
Xunbind-key ^X^B
Xunbind-key ^XK
Xunbind-key ^X$
Xunbind-key ^X@
Xunbind-key ^X!
X
X
X      split-current-window
X	!force 4 resize-window
X	select-buffer "UBBS-Mail"
X        beginning-of-file
X	insert-string "^P -- Previos Line       [ ^Z exit and send message~n"
X	insert-string "^N -- Next Line          [ Escape-Q Quit without sending message~n"
X	insert-string "^F -- Forward Character  [ Escape-? Help with MicroEMACS~n"
X	insert-string "^B -- Backward Character [ ^D -- Delete charcter to right.~n"
X	unmark-buffer
X	beginning-of-file
X        next-window
X	set %rcfkeys FALSE
X	set $discmd TRUE
X	add-global-mode "wrap"
X	end-of-file
SHAR_EOF
$TOUCH -am 0115115391 .emacsmail &&
chmod 0644 .emacsmail ||
echo "restore of .emacsmail failed"
set `wc -c .emacsmail`;Wc_c=$1
if test "$Wc_c" != "5645"; then
	echo original size 5645, current size $Wc_c
fi
# ============= main.c ==============
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#define MAIN 1
X#include "inc.h"
X
Xlogout1();
Xtoggle_monitor();
X
Xinit_vars()
X{
X  idletime=0;
X  alarm_interval=ALARM_INTERVAL;
X  idlewarn=DEF_IDLEWARN;
X  idleout=DEF_IDLEOUT;
X  maxtime=DEF_MAXTIME;
X  user_is_logged=0;
X  ctrlc_stat=0;
X  kbd_pid=0;
X  msg_ptrs=NULL;
X  defterm[0]=0;
X  fsedit[0]=0;
X  cur_forecolor=7;
X  cur_backcolor=0;
X  curses_init=0;
X  terminfo_mode=0;
X  termset=0;
X  CO=80;
X  who_switch=0;
X  LI=24;
X  expert_mode=0;
X  sysop=0;
X  sysop_login=0;
X  doing_source=0;
X  pagemode=1;
X  debug=0;
X  ansi=0;
X  monitor_on=FALSE;
X  cur_msg_area=NULL;
X  cur_file_area=NULL;
X  cur_file_lib=NULL;
X  first_msg_area=NULL;
X  first_file_area=NULL;
X  strcpy(prompt,DEF_PROMPT);
X  strcpy(mondev,DEF_MONDEV);
X  strcpy(mail_dir,DEF_MAIL_DIR);
X  strcpy(home_dir,DEF_HOME_DIR);
X  strcpy(CONFIG_FILE,DEF_CONFIG_FILE);
X  strcpy(MENU_FILE,DEF_MENU_FILE);
X  strcpy(ERRORLOG_FILE,DEF_ERRORLOG_FILE);
X  strcpy(USER_FILE,DEF_USER_FILE);
X  strcpy(UTMP_FILE,DEF_UTMP_FILE);
X  strcpy(LOG_FILE,DEF_LOG_FILE);
X  strcpy(AREAS_FILE,DEF_AREAS_FILE);
X  strcpy(FILELIBS_FILE,DEF_FILELIBS_FILE);
X  strcpy(MSGAREAS_FILE,DEF_MSGAREAS_FILE);
X  strcpy(QUEST_FILE,DEF_QUEST_FILE);
X  strcpy(QUEST_OUT_FILE,DEF_QUEST_OUT_FILE);
X  strcpy(sysop_name,SYSOP);
X  strcpy(def_ul_path,DEF_UL_PATH);
X  dl_exe[0]=0;
X  ul_exe[0]=0;
X  maxtry=MAXTRY;
X}
X
Xexitprog(exitcode)
Xint exitcode;
X{
Xnormattr();
X#ifdef USECURSES
Xif (curses_init) endwin();
X#endif
Xif (terminfo_mode) exit_terminfo();
Xunsetraw();
Xcurses_init=0;
Xif (kbd_pid!=0)
X  kill(kbd_pid,SIGTERM);
Xexit(exitcode);
X}
X
X
Xquit()
X{
Xexitprog(0);
X}
X
Xset_switches(argc,argv)
Xint argc;
Xchar **argv;
X{
Xextern char *optarg;
Xint i;
Xwhile ((i=getopt(argc,argv, "cx:C:tSs:wi")) != EOF)
X	{
X	switch (i)
X		{
X		case 'c' : /* attempt to use as shell */
X		case 'i' : /* attempt to use as shell */
X			exit(0);
X			break;
X		case 'C' : /* alternate config file */
X			strcpy(config_file,optarg);
X			break;
X		case 't' : /* don't ask for terminal type */
X			termset=1;
X			break;
X		case 'x' : /* debug mode */
X			debug=atoi(optarg);
X			break;
X		case 'S' : /* login as sysop */
X		  if (getuid()!=0)
X		    {
X		      portsout("Sorry, must be root to use -S\n");
X		      exitprog(1);
X		    }
X		  sysop_login=1;
X		  sysop=1;
X		  break;
X		case 's' : /* set command stack size */
X			cmd_stack_size=atoi(optarg);
X			rprintf("\nCommand stack size set to %s.\n",optarg);
X			break;
X		case 'w' : /* just do a who */
X			who_switch=1;
X			break;
X		default :
X			break;
X		} /* end case */
X	}
X}
X
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv,**envp;
X{
Xint err,i,c;
Xchar **v,*cptr,*s;
Xenviron=envp;
Xgetcwd(sys_home_dir,80);
Xthistty[0]=0;
Xs=strrchr(ttyname(0),'/');
Xif (*s=='/') ++s;
Xstrcpy(thistty,s);
Xinit_vars();
Xset_switches(argc,argv);
Xinit_env();
Xdef_cmds();
Xchkpriv=0;
Xload_config();
Xload_areas();
Xset_ctrl_chars();
Xsetraw();
Xif (who_switch)
X  {
X  who(0);
X  exitprog(0);
X  }
Xctrlc_on();
Xalarm_off();
Xsignal(SIGIOT,SIG_IGN);
X#ifdef DEBUG
Xsignal(SIGQUIT,SIG_DFL);
X#else
Xsignal(SIGQUIT,SIG_IGN);
X#endif
Xsignal(SIGTERM,logout1);
Xsignal(SIGHUP,logout1);
Xsignal(SIGUSR1,toggle_monitor);
Xmalloc(sizeof(USER));
Xload_users();
Xif (defterm[0]==0 || termset)
X  strcpy(term,(char *) getenv("TERM"));
Xelse strcpy(term,defterm);
Xver();
Xif (sysop_login)
X  {
X  if ((tmp_user=chk_name(sysop_name))==NULL)
X    {
X    errorsout("No sysop login present!\n");
X    exitprog(0xffff);
X    }
X  load_userrec(tmp_user->name,&logged_user);
X  user_is_logged=1;
X  }
Xelse if (login()) /* return non-zero indicates unsucessful login  */
X  {
X  sprintf(str,"Login as %s failed\n",logged_user.name);
X  errorsout(str);
X  logsout(str);
X  exitprog(0xffff);
X  }
Xsprintf(str,"%-20s logged  in at %s\n",logged_user.name,timestr());
Xlogsout(str);
Xportsout(str);
Xlogin_utmp();
Xload_menu();
Xif ((mail_menu_ptr=(m_header_ptr) chk_menu_tag("mail"))== (m_header_ptr) NULL)
X  {
X    errorsout("! No mail menu !");
X  }
Xif ((pubmsg_menu_ptr=(m_header_ptr) chk_menu_tag("pubmsg"))== (m_header_ptr) NULL)
X  {
X    errorsout("! No pubmsg menu !");
X  }
Xif ((proto_menu_ptr=(m_header_ptr) chk_menu_tag("proto"))== (m_header_ptr) NULL)
X  {
X    errorsout("! No proto menu !");
X  }
Xcurrent_menu=first_menu_ptr;
Xif (!ncstrcmp(sysop_name,logged_user.name)) sysop=1;
Xsprintf(str,"MYNAME=%s",MYNAME);
Xsetenv(str);
Xchkpriv=0;
Xuser_home_dir(str);
Xsprintf(str1,"%s/%s",sys_home_dir,str);
X  /* set env var HOME to user's home directory */
Xsprintf(buf,"set HOME=%s",(str[0]=='/') ? str : str1);
Xchkpriv=1; /* enable user to run set command */
Xrun_line(buf);
Xload_setup();
Xsprintf(buf,"source %s -s",STARTUP_FILE);
Xchkpriv=1; /* enable user to source startup file */
Xrun_line(buf);
X/* forkkbd(); */
Xwhile (1)
X  {
X  portout('\n');
X  print_menu(current_menu);
X  input[0]=0;
X  i=3;
X  while (i==3)
X    {
X      setcolor(BRWHITE,BLACK);
X      portsout(prompt);
X      setcolor(YELLOW,BLACK);
X      boldon();
X      i=getline(input,79);
X      boldoff();
X      setcolor(LTGREEN,BLACK);
X    }
X  portout('\n');
X/*  if (strlen(input)>3 && line_change)
X  	push_line(input); */
X   run_line(input); 
X  }
X}
X
X
X
SHAR_EOF
$TOUCH -am 1231004490 main.c &&
chmod 0644 main.c ||
echo "restore of main.c failed"
set `wc -c main.c`;Wc_c=$1
if test "$Wc_c" != "5039"; then
	echo original size 5039, current size $Wc_c
fi
# ============= menu.c ==============
echo "x - extracting menu.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > menu.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X/* menu.c
X	routines to print menus, and interpret MCL 
X	(Menu Control Language) code
X
Xmenu entries:
XEntry Text, command
X
Xpreceed character to use as activation key with a ^
X>menu
Xinternal command
X! system command, terminal in native mode
X% system command, output redirected, and paged with cat
X-s means one shot menu (used for transfer protocall menus)
X* in priviledge field signifies special menu used by the system (i.e. mail)
Xexample menu syntax:
Xmenu, menu title [-s],0
X{
X^Messages, >messages,0
X^Files, >files, 1
X^System Info, % view ~/systeminfo,0
X^Who\'s On, % who,0
X^Yell at sysop, % chat console,0
X^Chat, % chat,0
X^Goodbye, % goodbye,0
X^Play Games, >games,2
XSystem ^Load, ! w -t,0
X}
X*/
X
X#include "inc.h"
X
X/* return NULL if none exist */
Xm_header_ptr last_menu_ptr()
X{
Xm_header_ptr ptr;
Xint db;
Xdb=0;
Xptr=first_menu_ptr;
Xif (ptr==NULL) return (NULL);
Xif (ptr==NULL) return ptr;
Xwhile (ptr->next!=NULL)
X	{
X	ptr=ptr->next;
X	}
Xreturn ptr;
X}
X
Xm_header_ptr new_menu_ptr()
X{
Xm_header_ptr ptr;
Xint db;
Xdb=0;
Xptr=last_menu_ptr();
Xif (ptr==NULL) 
X  {
X    if ((ptr=(m_header_ptr) malloc(sizeof(struct m_header)))==NULL)
X	{
X	  error_message(MALLOC_ERROR);
X	  assert(0);
X	  quit();
X	}
X  }
Xelse
X  {
X    if ((ptr->next=(m_header_ptr) malloc(sizeof(struct m_header)))==NULL)
X	{
X	  error_message(MALLOC_ERROR);
X	  assert(0);
X	  quit();
X	}
X    ptr=ptr->next;
X  }
Xptr->next=NULL; /* set next to NULL */
Xreturn ptr;
X}
X
Xm_entry_ptr new_entry_ptr()
X{
Xm_entry_ptr ptr;
Xif ((ptr=(m_entry_ptr) malloc(sizeof(struct m_entry)))==NULL)
X	{
X	  error_message(MALLOC_ERROR);
X	  assert(0);
X	  quit();
X	}
Xptr->next=NULL;
Xreturn ptr;
X}
X
X
X/*
X	load_menu()
X		load in menus from file
X*/
Xload_menu()
X{
XFILE *fp;
Xchar *cptr,xx,cc,db;
Xm_header_ptr current_menu_ptr;
Xm_entry_ptr current_entry_ptr;
Xfp=fopen(MENU_FILE, "r");
Xif (fp==NULL)
X	{
X	fatal_error(MENU_FILE_ERROR);
X	}
Xfirst_menu_ptr=new_menu_ptr();
Xcurrent_menu_ptr=first_menu_ptr;
Xxx=0;db=0;
Xwhile (!feof(fp))
X{
Xfscanf(fp, "%[\n ]",str);
Xfscanf(fp, "%[^\n,-]",str);
Xif (strlen(str)==0) break;
Xstrip_space(str);
Xif (xx) current_menu_ptr=new_menu_ptr();
Xxx=1;
Xif (strlen(str)>12)
X	{
X	portsout("Warning: menu tag name too long, truncated to ");
X	str[12]=0;
X	atout(str);
X	portsout("\n");
X	}
Xstrcpy(current_menu_ptr->tag,str);
Xfscanf(fp, "%[\n,-]",str);
Xcurrent_menu_ptr->one_shot=0;
Xif (str[0]=='-') /* is a switch specified? */
X	{
X	fscanf(fp, "%[^\n,]", str);
X	if (str[0]='s') current_menu_ptr->one_shot=1;
X	}
Xfscanf(fp, "%[\n, ]",str); /* skip white space */
Xif (strchr(str,'\n')!=NULL)
X	{
X	portsout("Warning: No menu title specified for menu ");
X	atout(current_menu_ptr->tag);
X	portsout("\n");
X	current_menu_ptr->name[0]=0;
X	}
Xelse	{
X	fscanf(fp, "%[^\n,]", str);
X	if (strlen(str)>39) 
X		{
X		portsout("Warning: menu title too long, truncated to ");
X		str[39]=0;
X		atout(str);
X		portsout("\n");
X		}
X	strcpy(current_menu_ptr->name, str);
X	fscanf(fp, "%[ ,\n]",str); /* skip spaces and ,'s */
X	fscanf(fp, "%[^,\n]",str);
X	if (str[0]=='*') current_menu_ptr->priv=-1;
X	else current_menu_ptr->priv=strtol(str,NULL,16);
X	}
Xif (debug>2)
X	{
X	printf("tag=[%s]\ntitle=[%s]\none_shot=%d\npriv=%lu\n",
X	current_menu_ptr->tag,
X	current_menu_ptr->name,
X	current_menu_ptr->one_shot,
X	current_menu_ptr->priv);
X	}
Xcurrent_entry_ptr=new_entry_ptr();
Xcurrent_menu_ptr->first_entry=current_entry_ptr;
Xfscanf(fp,"%[^{]",str); /* seek { */
Xfscanf(fp,"%[{ \n\r]",str); /* skip white space */
Xcurrent_menu_ptr->count=0;
Xif (debug>2) printf("[begin menu]\n");
Xwhile (1 && !feof(fp))
X	{
X	++(current_menu_ptr->count);
X	fscanf(fp, "%[^,\n]", str);
X	if (strchr(str,'}')!=NULL)
X		{
X		if (debug>2)
X			{
X 			printf("[end menu %d entries]\n",
X			  current_menu_ptr->count);
X		  printf("[**]\n");
X			}
X		break; /* from while (1) loop */
X		}
X	if (strlen(str)>18)
X		{
X		portsout("Warning: menu entry name too long, trucated to ");
X		str[18]=0;
X		atout(str);
X		portsout("\n");
X		}
X	strcpy(current_entry_ptr->name, str);
X	if ((cptr=strchr(str, '^'))==NULL)
X		{
X		atprintf( 
X		"Warning: no activation key specified for menu:%s, entry:%s\n",
X		current_menu_ptr->tag,
X		current_entry_ptr->name);
X		}
X	else	{
X		++cptr;
X		current_entry_ptr->actkey=*cptr;
X		}
X	fscanf(fp, "%[} ,\n]",str);
X	if (strchr(str,',')==NULL)
X		{
X		atprintf("Warning: no command for menu:%s, entry:%s\n",
X			current_menu_ptr->tag,
X			current_entry_ptr->name);
X		if (strchr(str,'}')!=NULL)
X			{
X			if (debug>2)
X			  {
X			  printf("[end menu %d entries]\n",
X	 			  current_menu_ptr->count);
X			  printf("[**]\n");
X			  }
X			break; /* from while (1) loop */
X		}
X		}
X	else	{
X		fscanf(fp, "%[^},\n]", str);
X		if (strlen(str)>59)
X			{
X			portsout("Warning: command entry truncated to [");
X			str[59]=0;
X			atout(str);
X			portsout("]\n");
X			}
X		strcpy(current_entry_ptr->cmd,str);
X		current_entry_ptr->priv=0;
X		cc=fgetc(fp);
X		if (cc==',')
X		  {
X		  fscanf(fp, "%[^},\n]",str);
X		  current_entry_ptr->priv=strtol(str,NULL,16);
X		  }
X		}
X	if (debug>2)
X		{
X		printf("entry:%20.20s actkey=%c command=%s priv=%lu\n",
X			current_entry_ptr->name,
X			current_entry_ptr->actkey,
X			current_entry_ptr->cmd,
X			current_entry_ptr->priv);
X		}
X	fscanf(fp, "%[}\n]", str);
X	if (strchr(str,'}')!=NULL)
X		{
X		if (debug>2)
X		  {
X 		  printf("[end menu %d entries]\n",
X	 		  current_menu_ptr->count);
X		  printf("[**]\n");
X		  }
X		break; /* from while (1) loop */
X		}
X	else	{ /* get next entry */
X		if ((current_entry_ptr->next=new_entry_ptr())==NULL)
X		  {
X		    error_message(MALLOC_ERROR);
X		    assert(0);
X		    quit();
X		  }
X		current_entry_ptr=current_entry_ptr->next;
X		}
X	} /* inner while (1) loop */
X}
Xfclose(fp);
X}
X
Xprint_entry(ptr)
Xm_entry_ptr ptr;
X{
Xchar *s;
Xint count;
Xs=ptr->name;
Xcount=0;
Xwhile (*s)
X	{
X	if (*s=='^')
X		{
X		if (terminfo_mode)
X		  {
X		    setcolor(WHITE,BLACK);
X		    boldon();
X		  }
X		else portout('[');
X		++s;
X		portout(*s++);
X		if (terminfo_mode)
X		  {
X		    boldoff();
X		    setcolor(LTGREEN,BLACK);
X		  }
X		else portout(']');
X		}
X	else	portout(*s++);
X	++count;
X	}
Xwhile (count++<17) portout(' ');
X}
X	
Xprint_menu(menu_ptr)
Xm_header_ptr menu_ptr;
X{
Xint i,ii,db;
Xm_entry_ptr ptr;
Xdb=0;
Xif (terminfo_mode)
X  {
X    setcolor(YELLOW,BLACK);
X    boldon();
X  }
Xatout(menu_ptr->name);
Xportout('\n');
Xif (terminfo_mode)
X  {
X    boldoff();
X    setcolor(LTGREEN,BLACK);
X  }
Xptr=menu_ptr->first_entry;
Xswitch (expert_mode)
X  {
X  case 0:
X    ii=0;
X    for (i=0;i<menu_ptr->count;++i)
X	{
X 	if (chk_menu_priv(ptr))
X	  {
X 	  print_entry(ptr);
X 	  if (ii-3-(ii/4)*4==0) portout('\n');
X	  ++ii;
X	  }
X	ptr=ptr->next;
X	}
X    portout('\n');
X    break;
X  case 1:
X    if (chk_menu_priv(ptr))
X       portout(ptr->actkey);
X    ptr=ptr->next;
X    for (i=1;i<menu_ptr->count;++i)
X	{
X          if (chk_menu_priv(ptr))
X 	  {
X	  portout(',');
X	  portout(ptr->actkey);
X	  }
X	ptr=ptr->next;
X	}
X	portout(' ');
X    break;
X  default:
X    break;
X  } /* end switch */
X}
X
Xm_header_ptr chk_menu_tag(s)
Xchar *s;
X{
Xm_header_ptr header;
Xheader=first_menu_ptr;
Xwhile (header!=NULL)
X  {
X  if (!strcmp(s,header->tag)) return(header);
X  header=header->next;
X  }
Xreturn(NULL);
X}
X
Xm_entry_ptr chk_entry(c,mptr)
Xchar c;
Xm_header_ptr mptr;
X{
Xm_entry_ptr entry;
Xint i;
Xc=toupper(c);
Xentry=mptr->first_entry;
Xfor (i=0;i<mptr->count;++i)
X	{
X	if (c==toupper(entry->actkey)) return (entry);
X	entry=entry->next;
X	}
Xreturn(NULL);
X}
X
Xmexec_line(argc,argv)
Xint argc;
Xchar **argv;
X{
Xint c,i;
Xchar **v;
Xchar tmpstr[80];
Xm_entry_ptr entry;
Xm_header_ptr header;
Xc=argc;
Xv=argv;
Xif (strlen(v[0])==1)
X  if ((entry=chk_entry(v[0][0],current_menu))!=NULL)
X    /* process menu selection */
X	{
X	v[0]=entry->cmd;
X	chkpriv=chk_menu_priv(entry);
X	if (chkpriv || doing_source)
X	  {
X	  unparse_line(c,v,input);
X	  parse_line(&c,v,input);
X	  return(mexec_line(c,v));
X	  }
X	else 
X	  {
X	  error_message(PRIV_ERROR);
X	  return(-1);
X	  }
X	}
Xif (c)
X  {
X  if (v[0][0]=='>') /* select new menu */
X    {
X    if ((header=chk_menu_tag(&v[0][1]))==NULL)
X      {
X      portout('\n');
X      error_message(BAD_MENU_TAG);
X      }
X    else if (header->priv==(PRIV)-1)
X      {
X	portsout("Sorry, special menu entry, not directly executable.\n");
X	return(0);
X      }
X    else if (chk_menu_header_priv(header))
X      {
X      current_menu=header;
X      chkpriv=0;
X      if (c>1) return(mexec_line(c-1,&v[1]));
X      return(0);
X      }
X    else
X      {
X      error_message(PRIV_ERROR);
X      return(-1);
X      }
X    } /* if (v.. */
X  } /* if (c) */
Xif (v[0][0]=='!' && (chkpriv || sysop || doing_source))
X  {
X  /* put system command code here */
X  unparse_line(c,v,input);
X  systemx(&input[1]);
X  pause();
X  chkpriv=0;
X  }
Xelse if (v[0][0]=='%' && (chkpriv || sysop || doing_source))
X  {
X  /* put system command code here */
X  unparse_line(c,v,input);
X  strcpy(buf,&input[1]);
X  sprintf(tmpstr,"/tmp/.tmp.ubbs.%s",thistty);
X#ifdef F_SYSV
X  unlink(tmpstr);
X#else
X  remove(tmpstr);
X#endif
X  strcat(buf," >");
X  strcat(buf,tmpstr);
X  system(buf);
X  sprintf(buf,"cat %s",tmpstr);
X  run_line(buf);
X#ifdef F_SYSV
X  unlink(tmpstr);
X#else
X  remove(tmpstr);
X#endif
X  chkpriv=0;
X  }
Xelse
X  exec_line(c,v);
Xchkpriv=0;
X}
SHAR_EOF
$TOUCH -am 1231001390 menu.c &&
chmod 0644 menu.c ||
echo "restore of menu.c failed"
set `wc -c menu.c`;Wc_c=$1
if test "$Wc_c" != "9026"; then
	echo original size 9026, current size $Wc_c
fi
# ============= misc.c ==============
echo "x - extracting misc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > misc.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X#include <varargs.h>
X
Xchar *eatnl(s) /* kill the new-line character on the end of string */
X     char *s;
X{
X  int l;
X  if ((l=strlen(s))==0) return;
X  if (s[l-1]=='\n') s[l-1]=0;
X  return(s);
X}
X
X
Xchar *stripquote(s)
X     char *s;
X{
X  int i;
X  if (s==NULL) return(NULL);
X  if ((i=strlen(s))==0) return(s);
X  if (s[i-1]=='\"' && s[0]=='\"')
X    {
X      s[i-1]=0;
X      delchr(s,0);
X    }
X  return(s);
X}
X
Xchar *myfgets(s,maxnum,fp)
X     char *s;
X     int maxnum;
X     FILE *fp;
X{
X  char *err;
X  if (s==NULL)
X    {
X      fprintf(stderr,"s=NULL\n");
X      return(NULL);
X    }
X  if (fp==NULL)
X    {
X      fprintf(stderr,"fp=NULL\n");
X      return(NULL);
X    }
X  s[0]=0;
X  err=fgets(s,maxnum,fp);
X  eatnl(s);
X  return(err);
X}
X
Xstrdncase(s)
Xchar *s;
X{
Xwhile (*s)
X  {
X  *s=tolower(*s);
X  ++s;
X  }
X}
X
Xchar *timestr()
X{
Xchar *s;
Xtime_t t;
Xt=time((time_t *) 0);
Xs=ctime(&t);
Xeatnl(s);
Xreturn(s);
X}
X
X
Xdelchr(s,p)
Xchar *s;
Xint p;
X{
Xs=&s[p];
Xwhile (*s)
X	*s=*(++s);
X}
X
Xinschr(s,p)
Xchar *s;
Xint p;
X{
Xint pp;
Xpp=strlen(s)+1;
Xwhile (pp>p+1)
X	s[pp]=s[pp-1];
X}
X
Xstrip_space(s)
Xchar *s;
X{
Xint i;
Xi=0;
Xwhile(isspace(s[i]))
X	++i;
Xstrcpy(s,&s[i]);
Xi=0;
Xwhile (!(isspace(s[i])) && s[i]!=0)
X	++i;
Xs[i]=0;
X}
X
Xlogsout(s) /* append text to log file */
Xchar *s;
X{
X  FILE *fp;
X  if ((fp=fopen(LOG_FILE,"a"))==NULL)
X    {
X      printf("logfile=%s\n",LOG_FILE);
X      error_message(LOG_FILE_ERROR);
X/*       exitprog(LOG_FILE_ERROR); */
X      return(1);
X    }
X  fprintf(fp,"%s",s);
X  fclose(fp);
X}
X
Xpause()
X{
X  if (color_mode) _setcolor(BRWHITE,BLUE);
X  else reverseon();
X  portsout("\r[Press any key to continue]");
X  if (color_mode) fixcolor();
X  else reverseoff();
X  portin();
X  portsout("\r                            \r");
X}
X
Xyesno(yn)
X     int yn;
X{
X  char c;
X  c=0;
X  if (yn>=0)
X    portsout((yn) ? "(Y or n): " : "(n or Y): ");
X  else portsout("(Y or N): ");
X  while (c!='y' && c!='n' && (!(c==0x0d &&  yn>=0)))
X    {
X      c=portin();
X      c=tolower(c);
X    }
X  portout(c);
X  switch(c)
X    {
X    case 'y': return(1);
X      break;
X    case 'n': return(0);
X      break;
X    case 0x0d: return(yn);
X      break;
X    }
X}
X
X
X/*
X  colors: 0-7 black,red,green,yellow/brown,blue,magenta,cyan,white
X  for ansi terminals only.
X
X*/
X  
X
X
Xmore_prompt()
X{
X  char c;
X  if (color_mode) _setcolor(BRWHITE,BLUE);
X  else reverseon();
X  portsout(" More? (Y,n,non-Stop) ");
X  if (color_mode) fixcolor();
X  else reverseoff();
X  c=0;
X  while (c!='y' && c!='n' && c!='s' && c!=CR)
X    {
X      c=portin(c);
X      c=tolower(c);
X      if (c==' ') c='y';
X    }
X  portsout("\r                      \r");
X  return(c);
X}
X
X
Xstr_cmp(p1,p2)
X     char **p1,**p2;
X{
X  return(strcmp(*p1,*p2));
X}
X
Xprint_args(argc,argv)
X     int argc;
X     char **argv;
X{
X  int i;
X  printf("argc=%d ", argc);
X  for (i=0;i<argc;++i)
X    printf("[%s]\n",argv[i]);
X  portout('\n');
X}
X
X/*
X  insert_chr --> insert character 'c' in string 's'
X*/
Xinsert_chr(s,c)
X     char *s,c;
X{
X  int i;
X  i=strlen(s);
X  s[i+1]=0;
X  while (i)
X    {
X      s[i]=s[i-1];
X      --i;
X    }
X  s[0]=c;
X}
X
X
Xappend_file(file1,file2) /* use only for TEXT files !! */
X     char *file1,*file2;
X{
X  char s[255];
X  FILE *fp1,*fp2;
X  if ((fp1=fopen(file1,"r"))==NULL)
X    {
X      portsout("append_file(): error openning input file: ");
X      portsout(file1);
X      portout('\n');
X      return(-1);
X    }
X  if ((fp2=fopen(file2,"a"))==NULL)
X    {
X      portsout("append_file(): error openning input file: ");
X      portsout(file2);
X      portout('\n');
X      return(-2);
X    }
X  while (!feof(fp1))
X    {
X      s[0]=0;
X      fgets(s,254,fp1);
X      if (!feof(fp1))
X	fputs(s,fp2);
X    }
X  fclose(fp1);
X  fclose(fp2);
X}
X
X#ifdef F_SYSV
Xrename(oldname,newname)
X     char *oldname,*newname;
X{
X  int err;
X  if ((err=link(oldname,newname))!=0) return(err);
X  return(unlink(oldname));
X}
X#endif
X
Xcreate_file(filename)
X     char *filename;
X{
X  FILE *fp;
X  if ((fp=fopen(filename,"w"))==NULL) return(-1);
X  fclose(fp);
X  return(0);
X}
X
Xncstrcmp(s1,s2) /* case insensitive string compare */
Xchar *s1,*s2;
X{
Xint i;
Xwhile(!(i=toupper(*s1) - toupper(*s2)) && *s1 && *s2) {++s1;++s2;}
Xreturn(i);
X}
X
Xchar *basename(pathname)
X     char *pathname;
X{
X  char *p;
X  if ((p=strrchr(pathname,'/'))==NULL)
X    return(pathname);
X  ++p;
X  return(p);
X}
X
Xchar *dirname(pathname,s)
X     char *pathname,*s;
X{
X  char *p;
X  strcpy(s,pathname);
X  if ((p=strrchr(s,'/'))==NULL)
X    s[0]=0;
X  else *p=0;
X  return(s);
X}
X
Xkill_trailing_space(s)
X     char *s;
X{
X  int i;
X  if (s==NULL) return;
X  if (s[0]==0) return;
X  i=strlen(s)-1;
X  while (i>=0 && isspace(s[i]))
X    {
X      --i;
X    }
X  if (isspace(s[i+1])) s[i+1]=0;
X}
X
Xrprintf(va_alist)
X     va_dcl
X{
X  va_list vlist;
X  char *fmt;
X  char buf[BUFSIZE];
X
X  va_start(vlist);
X  fmt=va_arg(vlist, char *);
X  vsprintf(buf,fmt,vlist);
X  portsout(buf);
X  va_end(vlist);
X  return;
X}
X
Xatprintf(va_alist)
X     va_dcl
X{
X  va_list vlist;
X  char *fmt;
X  char buf[BUFSIZE];
X
X  va_start(vlist);
X  fmt=va_arg(vlist, char *);
X  vsprintf(buf,fmt,vlist);
X  atout(buf);
X  va_end(vlist);
X  return;
X}
X
Xtoggle_monitor()
X{
X#ifdef DEBUG
Xif (debug)
X  fprintf(stderr,"monitor\n");
X#endif
X  if (monitor_on)
X    {
X#ifdef DEBUG
Xif (debug)
X  fprintf(stderr,"monitor off\n");
X#endif
X      fclose(monfp);
X      monitor_on=FALSE;
X    }
X  else
X    {
X      if ((monfp=fopen(mondev,"w")))
X	{
X          monitor_on=TRUE;
X#ifdef DEBUG
Xif (debug)
X  fprintf(stderr,"monitor on\n");
X#endif
X	}
X    }
X  signal(SIGUSR1,toggle_monitor);
X}
SHAR_EOF
$TOUCH -am 1226003290 misc.c &&
chmod 0644 misc.c ||
echo "restore of misc.c failed"
set `wc -c misc.c`;Wc_c=$1
if test "$Wc_c" != "5459"; then
	echo original size 5459, current size $Wc_c
fi
# ============= error.c ==============
echo "x - extracting error.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > error.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X#include <varargs.h>
X
Xchar *err_msg[]={
X	"No error!\n",
X	"! Cannot open menu file\n", /* 1 */
X	"! Cannot open utmp file\n", /*  2 */
X	"! memory allocation error\n", /* 3 */
X	"unsupported terminal type\n", /* 4 */
X	"! invalid menu tag\n", /* 5 */
X	"! Cannot open error log!\n", /* 6 */
X	"! Cannot open user file\n", /* 7 */
X	"! Cannot open log file\n", /* 8 */
X	"! Cannot open config file\n", /* 9 */
X	"Insufficient priviledge!\n", /* 10 */
X	"! Cannot open questionaire file\n", /* 11 */
X	"! Cannot open temporary user file!\n", /* 12 */
X	"invalid username\n", /* 13 */
X	"! Could not fork()!\n", /* 14 */
X	"! exec() error!\n", /* 15 */
X	"! Cannot open message area file!\n", /* 16 */
X	"! Cannot open file area file!\n", /* 17 */
X	"! Cannot open file lib file!\n", /* 18 */
X	""
X	};
X	
X
Xerror_message(errno)
Xint errno;
X{
Xif (errno>=sizeof(err_msg)/sizeof(char *))
X	errorsout("! Invalid error number!\n");	
Xelse 	errorsout(err_msg[errno]);
X}
X
X/*
Xfatal_error(errno)
Xint errno;
X{
Xportsout("FATAL: ");
Xerror_message(errno);
Xexitprog(errno);
X}
X*/
X
Xerrorsout(va_alist)
X     va_dcl
X{
X  va_list vlist;
X  char *fmt;
X  char buf[BUFSIZE];
X  FILE *fp;
X  va_start(vlist);
X  fmt=va_arg(vlist, char *);
X  vsprintf(buf,fmt,vlist);
X  portsout(buf);
X  if (buf[0]=='!')
X    {
X      if ((fp=fopen(ERRORLOG_FILE,"a"))==NULL)
X	{
X	  portsout(ERRORLOG_ERROR);
X	  exitprog(ERRORLOG_ERROR);
X	}
X      fprintf(fp,"%s",buf);
X      fclose(fp);
X    }
X  va_end(vlist);
X}
SHAR_EOF
$TOUCH -am 0507212690 error.c &&
chmod 0644 error.c ||
echo "restore of error.c failed"
set `wc -c error.c`;Wc_c=$1
if test "$Wc_c" != "1506"; then
	echo original size 1506, current size $Wc_c
fi
# ============= cle.c ==============
echo "x - extracting cle.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > cle.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X  
X  rawportout();
X
Xgetline(s,maxlen)
X     char *s;
X     int maxlen;
X{
X  char q,c,buf[80],insert_mode;
X  int p,l,i,x,y;
X  ctrlc_off();
X  idletime=0;
X  if (maxlen>79) 
X    {
X      maxlen=79;
X      s[maxlen]=0;
X    }
X  strcpy(buf,s);
X  q=0;p=0;l=strlen(buf);insert_mode=1;
X  portsout(buf);
X  for(i=0;i<l;++i) portout(8);
X  while(!q)
X    {
X      c=portin();
X      switch (c)
X	{
X	case 9 : /* ^I, TAB */
X	  insert_mode=!insert_mode;
X	  break;
X	case CR :
X	case NL :
X	  q=1;
X	  break;
X	case BS :
X	case DEL :
X	  if ((p==l) && (p>0)) /* at end of line */
X	    {
X	      portsout("\b \b"); /* backup and kill character */
X	      --p;--l;
X	      buf[p]=0;
X	    }
X	  else if (p>0)
X	    {
X	      line_change=1;
X	      --p;
X	      portout('\b');
X	      delchr(buf,p);
X	      --l;
X	      if (terminfo_mode && DC!=NULL)
X		tputs(DC,1,rawportout);
X	      else
X		{
X		  portsout(&buf[p]);
X		  portout(' ');
X		  for (i=p;i<l+1;++i) portout(8);
X		}
X	    }
X	  break;	
X	case 1: /* ^A, beginning of line */
X	  while (p>0)
X	    {
X	      portout(8); /* backup one character */
X	      --p;
X	    }
X	  break;
X	case 2: /* ^B, backward character */
X	  if (p>0)
X	    {
X	      portout(8); /* backup one character */
X	      --p;
X	    }
X	  break;
X	case 3: /* ^C */
X	  q=1;
X	  buf[0]=0;
X	  portout('\n');
X	  if (color_mode) _setcolor(BRWHITE,BLUE);
X	  else reverseon();
X	  portsout(" CANCEL ");
X	  if (color_mode) fixcolor();
X	  else reverseoff();
X	  portout('\n');
X	  line_change=0;break;
X	case 4: /* ^D, delete character to right of cursor */
X	  if (l>p)
X	    {
X	      line_change=1;
X	      delchr(buf,p);
X	      --l;
X	      if (terminfo_mode && DC!=NULL)
X		tputs(DC,1,rawportout);
X	      else
X		{
X		  portsout(&buf[p]);
X		  portout(' ');
X		  for (i=p;i<l+1;++i) portout(8);
X		}
X	    }
X	  break;
X	case 5: /* ^E, end of line */
X	  while (p<l)
X	    {
X	      portout(buf[p++]);
X	    }
X	  break;
X	case 6: /* ^F, forward characer */
X	  if (p<l)
X	    {
X	      portout(buf[p++]);
X	    }
X	  break;
X	case 11: /* ^K, kill rest of line */
X	  line_change=1;
X	  if (terminfo_mode)
X	    {
X	      clreol();
X	    }
X	  else
X	    {
X	      for (i=p;i<l;++i) portout(' ');
X	      for (i=p;i<l;++i) portout(8);
X	    }
X	  l=p;buf[p]=0;
X	  break;
X	case 21: /* ^U, kill all of line */
X	  line_change=1;
X	  if (terminfo_mode)
X	    {
X	      for (i=p;i>0;--i) portout('\b');
X	      clreol();
X	    }
X	  else
X	    {
X	      for (i=p;i>0;--i) portout('\b');
X	      for (i=0;i<l;++i) portout(' ');
X	      for (i=0;i<l;++i) portout('\b');
X	    }
X	  l=0;p=0;buf[0]=0;
X	  break;
X	case 18: /* ^R, redisplay line */
X	  for (i=p;i>0;--i) portout('\b');
X	  if (terminfo_mode)
X	    {
X	      clreol();
X	    }
X	  else
X	    {
X	      for (i=0;i<l;++i) portout(' ');
X	      for (i=0;i<l;++i) portout('\b');
X	    }
X	  buf[l]=0;
X	  portsout(buf);
X	  p=l;
X	  break;
X	case 16: /* ^P, previous line */
X	  break;
X	  dec_rcmdptr();line_change=0;
X	  for (i=0;i<p;++i) portout(8);
X	  for (i=0;i<l;++i) portout(' ');
X	  for (i=0;i<l;++i) portout(8);
X	  pop_line(buf);
X	  p=strlen(buf);
X	  l=p;
X	  printf("%s",buf);
X	  break;
X	case 14: /* ^N, next line */
X	  break;
X	  inc_rcmdptr();line_change=0;
X	  pop_line(buf);
X	  for (i=0;i<p;++i) portout(8);
X	  for (i=0;i<l;++i) portout(' ');
X	  for (i=0;i<l;++i) portout(8);
X	  pop_line(buf);
X	  p=strlen(buf);
X	  l=p;
X	  printf("%s",buf);
X	  break;
X	default:
X	  if ((isprint(c) || isspace(c)) && c>31 &&
X	      !((insert_mode || p==l) && l>maxlen-1))
X	    {
X	      line_change=1;
X	      if (insert_mode && p<l)
X		{
X		  insert_chr(&buf[p],c);
X		  ++l;
X		  if (terminfo_mode && IC!=NULL)
X		    {
X		      tputs(IC,1,rawportout);
X		      portout(c);
X		    }
X		  else
X		    {
X		      portsout(&buf[p]);
X		      for (i=p+1;i<l;++i) portout('\b');
X		    }
X		  ++p;
X		}
X	      else
X		{
X		  if (p==l) buf[p+1]=0;
X		  portout(c);
X		  buf[p]=c;
X		  ++p;
X		  if (p>l) ++l;
X		}
X	    }
X	  break;
X	} /* end switch */
X    }/* end while(!q) */
X  strcpy(s,buf);
X  ctrlc_on();
X  return(c);
X}
X
X
Xinc_rcmdptr()
X{
X  while(*(++rcmdptr))
X    if (rcmdptr>=cmd_stack+cmd_stack_size) rcmdptr=cmd_stack;
X  /* ++rcmdptr; */
X  if (!(*rcmdptr))
X    {
X      while(!(*(++rcmdptr)))
X	if (rcmdptr>=cmd_stack+cmd_stack_size) rcmdptr=cmd_stack;
X    }
X  if (rcmdptr>=cmd_stack+cmd_stack_size) rcmdptr=cmd_stack;
X}
X
X
Xdec_rcmdptr()
X{
X  --rcmdptr;
X  if (rcmdptr<cmd_stack)
X    rcmdptr=cmd_stack+cmd_stack_size;
X  while(*(--rcmdptr))
X    if (rcmdptr<cmd_stack)
X      {
X	rcmdptr=cmd_stack;
X	return(0);
X      }
X  if (!(rcmdptr[-1]))
X    {
X      while(!(*(--rcmdptr)))
X	if (rcmdptr<=cmd_stack) rcmdptr=cmd_stack+cmd_stack_size;
X      while(*(--rcmdptr))
X	if (rcmdptr<=cmd_stack) rcmdptr=cmd_stack+cmd_stack_size;
X    }
X  ++rcmdptr;
X}
X
Xhome_rcmdptr()
X{
X  rcmdptr=cmdptr;
X  inc_rcmdptr();
X}
X
Xhistory(argc,argv)
X     int argc;
X     char **argv;
X{
X  char *sto_rcmdptr,*p,q;
X  int i;
X  if (!argc)
X    {
X      printf("history  -- print command history\n");
X      printf("Syntax:\n   hist [command]\n");
X      printf("when command is specified, then history of that command's\n");
X      printf("is listed.\n\n");
X      printf("Typing !# where # is a number associated with a particular\n");
X      printf("line in the history will get that line and put it in the\n");
X      printf("current line buffer\n");
X      return(0);
X    }
X  sto_rcmdptr=rcmdptr;
X  home_rcmdptr();
X  p=rcmdptr;
X  q=1;i=0;
X  while(q)
X    {
X      ++i;
X      if (argc<2 || !strncmp(argv[1],rcmdptr,strlen(argv[1])))
X	printf("%3d: %s\n",i,rcmdptr);
X      inc_rcmdptr();
X      if (rcmdptr==p) q=0;
X    }
X  rcmdptr=sto_rcmdptr;
X  return(0);
X}
X
X
Xpush_line(str)
X     char *str;
X{
X  while (*str) *cmdptr++=*str++;
X  *cmdptr++=0;*cmdptr=0;
X  if (strlen(str)>= ((int) cmd_stack) + cmd_stack_size - (int) cmdptr)
X    cmdptr=cmd_stack;
X  rcmdptr=cmdptr;
X}
X
Xpop_line(str)
X     char *str;
X{
X  strcpy(str,rcmdptr);
X}
SHAR_EOF
$TOUCH -am 0507213490 cle.c &&
chmod 0644 cle.c ||
echo "restore of cle.c failed"
set `wc -c cle.c`;Wc_c=$1
if test "$Wc_c" != "5842"; then
	echo original size 5842, current size $Wc_c
fi
# ============= parse.c ==============
echo "x - extracting parse.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > parse.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
X
Xchar *cmds[]={
X	"bulletin","cat","chat","chfa","chfal","chma","dl","echo",
X	"expert","find","help","history","logout","ls","mail",
X	"mscan","passwd","pause","pwd","quest","set","setpage",
X	"setproto","setterm","source","ul","users","ver","who","\377\377"
X	};
X#define CMDCOUNT (int) sizeof(cmds)/sizeof(char *)
XCOMMAND *com[CMDCOUNT];
X
Xint cat(),chfa(),chfal(),chma(),help(),history(),ls(),pwd(),ver(),logout(),
X  expert(),who(),chat(),setpage(),mscan(),bulletin(),
X  passwd(),doquest(),findfile(),uploadfile(),dnloadfile(),doscript(),
X  echo(),pause(),mail(),list_users(),set(),setterm(),setproto();
X
Xdef_cmds()
X{
Xint i;
Xcmdcount=CMDCOUNT;
Xfor (i=0;i<CMDCOUNT;++i)
X	{
X	com[i]=(COMMAND *) malloc(sizeof(COMMAND));
X	if (com[i]==NULL)
X	  {
X	    error_message(MALLOC_ERROR);
X	    assert(0);
X	    quit();
X	  }
X	}
Xi=0;
Xcom[i]->priv=0;com[i++]->func=bulletin;
Xcom[i]->priv=SYSOP_PRIV;com[i++]->func=cat;
Xcom[i]->priv=1;com[i++]->func=chat;
Xcom[i]->priv=1;com[i++]->func=chfa;
Xcom[i]->priv=1;com[i++]->func=chfal;
Xcom[i]->priv=1;com[i++]->func=chma;
Xcom[i]->priv=1;com[i++]->func=dnloadfile; /* dl */
Xcom[i]->priv=0;com[i++]->func=echo;
Xcom[i]->priv=1;com[i++]->func=expert;
Xcom[i]->priv=1;com[i++]->func=findfile;
Xcom[i]->priv=0;com[i++]->func=help;
Xcom[i]->priv=0;com[i++]->func=history;
Xcom[i]->priv=0;com[i++]->func=logout;
Xcom[i]->priv=1;com[i++]->func=ls;
Xcom[i]->priv=0;com[i++]->func=mail;
Xcom[i]->priv=1;com[i++]->func=mscan;
Xcom[i]->priv=1;com[i++]->func=passwd;
Xcom[i]->priv=1;com[i++]->func=pause;
Xcom[i]->priv=1;com[i++]->func=pwd;
Xcom[i]->priv=0;com[i++]->func=doquest;
Xcom[i]->priv=0x100;com[i++]->func=set;
Xcom[i]->priv=0;com[i++]->func=setpage;
Xcom[i]->priv=0;com[i++]->func=setproto;
Xcom[i]->priv=0;com[i++]->func=setterm;
Xcom[i]->priv=0x100;com[i++]->func=doscript; /* source */
Xcom[i]->priv=1;com[i++]->func=uploadfile;
Xcom[i]->priv=0;com[i++]->func=list_users;
Xcom[i]->priv=0;com[i++]->func=ver;
Xcom[i]->priv=1;com[i++]->func=who;
Xfor (i=0;i<CMDCOUNT;++i)
X	{
X	com[i]->name=cmds[i];
X	com[i]->fnum=i;
X	}
X}
X
X
X
Xunparse_line(argc,argv,s)
Xint argc;
Xchar **argv,*s;
X{
Xchar temp[160],*t,*t1;
Xint i;
Xtemp[0]=0;
Xt=temp;
Xfor (i=0;i<argc;++i)
X  {
X  t1=argv[i];
X  while (*t1)
X    *t++=*t1++;
X  *t++=' ';  
X  }
X *(--t)=0;
Xstrcpy(s,temp);
X}
X
X
Xparse_line(argc,argv,str)
Xint *argc;
Xchar **argv,*str;
X{
Xchar *s,quote;
Xint index;
Xs=str;index=1;
Xsub_env(str,str);
Xwhile ((*s) && isspace(*s)) ++s;
Xif (!*s)
X  {
X    *argc=0;return(0);
X  }
Xargv[0]=s;
Xquote=0;
Xwhile(*s)
X  {
X    if (isspace(*s) && !quote)
X      {
X	*s++=0;
X	while ((*s) && (isspace(*s))) ++s;
X	if (*s)
X	  {
X	    argv[index]=s;
X	    ++index;
X	  }
X      }
X    if (*s=='\"')
X      {
X	quote=~quote;
X	if (quote) ++s;
X      }
X    if (*s=='\\')
X      {
X	delchr(s,0);
X      }
X    ++s;
X  }
X*argc=index;
Xif (debug)
X  print_args(*argc,argv);
X}
X
X
Xcmd_cmp(p1,p2)
XCOMMAND **p1,**p2;
X{
Xreturn(strcmp((**p1).name,(**p2).name));
X}
X
Xint chk_cmd(str)
Xchar *str;
X{
XCOMMAND *s,s1,**p;
Xs1.name=str;
Xs1.func=NULL;
Xs1.fnum=3;
Xs=&s1;
Xp=(COMMAND **) 
X	bsearch((char *) &s,(char *) com,CMDCOUNT,sizeof(COMMAND *),cmd_cmp);
Xif (p==NULL) return(0xffff);
Xreturn((**p).fnum);
X}
X
Xexec_line(argc,argv)
Xint argc;
Xchar **argv;
X{
Xint i,er;
Xfptr func;
Xint fnum;
Xchar pathname[64];
Xif (argc==0) {return(0);}
Xargv[argc]=NULL;
Xif (argv[0][0]=='#') return(0);
Xif (debug>3)
X  {
X    for (i=0;i<argc;++i)
X      {
X	printf("%s ",argv[i]);
X      }
X    printf("\n");
X  }
Xfnum=chk_cmd(argv[0]);
Xif (fnum!=0xffff)
X{
X  func=com[fnum]->func;
X  if (!doing_source && !chkpriv && !chk_cmd_priv(com[fnum]) && !sysop)
X    {
X      sprintf(buf,"Sorry, you are not authorized to use %s\n",
X	      com[fnum]->name);
X      portsout(buf);
X    }
Xelse return((*func)(argc,argv));
X}
Xelse
X  {
X    sprintf(buf,"Invalid command: %s\n",argv[0]);
X    portsout(buf);
X    return(0xffff);
X  }
X}
X
Xrun_line(str)
X     char *str;
X{
X  int c;
X  char *v[20],s[LINE_SIZE];
X  strcpy(s,str); /* destroying the string */
X  if (echo_mode)
X    {
X      portsout(s);
X      portout('\n');
X    }		/* make copy so args can be null terminated w/o */
X  parse_line(&c,v,s);
X  if (c)
X    mexec_line(c,v);
X}
SHAR_EOF
$TOUCH -am 1230232990 parse.c &&
chmod 0644 parse.c ||
echo "restore of parse.c failed"
set `wc -c parse.c`;Wc_c=$1
if test "$Wc_c" != "4139"; then
	echo original size 4139, current size $Wc_c
fi
# ============= funcs.c ==============
echo "x - extracting funcs.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > funcs.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
XUSER *chk_name();
Xchar portin();
X
Xint cat(argc,argv)
Xint argc;
Xchar **argv;
X{
Xextern char *optarg;
Xextern optind;
Xint i,page_lines;
Xchar rawtype,nopage,silent,*filename,c,q,s[255],noat;
XFILE *fp;
Xoptind=1;
Xnopage=0;rawtype=0;silent=0;noat=0;
Xwhile ((i=getopt(argc,argv, "anrs")) != EOF)
X  {
X  switch (i)
X    {
X    case 'a' : /* no at commands */
X      noat=1;
X    case 's' : /* silent, no error for file not found */
X      silent=1;
X      break;
X    case 'r' : /* raw type of file (no filtering) */
X      rawtype=1; 
X      break;
X    case 'n' : /* no page */
X      nopage=1;
X      break;
X    default: break;
X    }
X  }
Xi=1;
Xwhile (i<argc && argv[i][0]=='-') ++i;
Xif (i<argc) filename=argv[i];
Xelse	{
X	errorsout("\ncat: no filename specified\n");
X	return(-1);
X	}
Xif ((fp=fopen(filename,"r"))==NULL)
X	{
X	  if (!silent)
X	    {
X	      sprintf(str,"\nError opening %s!\n",filename);
X	      errorsout(str);
X	    }
X	return(0xffff);
X	}
Xpage_lines=0;q=0;
Xif (rawtype)
X  while (!feof(fp) && !q && !ctrlc())
X    {
X      c=fgetc(fp);
X      portout(c);
X    }
Xelse while (!feof(fp) && !q && !ctrlc())
X  {
X    s[0]=0;
X    if (!feof(fp))
X      fscanf(fp,"%[^\n]",s);
X    if (!feof(fp))
X      fgetc(fp);
X    if (noat) portsout(s);
X    else atout(s);
X    portsout("\n\r");
X    if (!nopage && pagemode && ++page_lines>LI-2)
X      {
X	c=more_prompt();
X	switch (c)
X	  {
X	  case CR:
X	  case 'y':
X	    page_lines=0;
X	    break;
X	  case 'n':
X	    q=1;
X	    break;
X	  case 's':
X	    nopage=1;
X	    break;
X	  }
X      }
X  }
Xfclose(fp);
Xif (!nopage && pagemode && ++page_lines>LI-8)
X  {
X    if (color_mode) _setcolor(BRWHITE,BLUE);
X    else reverseon();
X    portsout(" End of File -- Press any key to continue");
X    if (color_mode) fixcolor();
X    else reverseoff();
X    portin();
X    portsout("\r                                              \r");
X  }
Xreturn(0);
X}
X
Xint echo(argc,argv)
Xint argc;
Xchar **argv;
X{
X  int i;
X  for (i=1;i<argc;++i)
X    {
X      atout(argv[i]);
X      portout(' ');
X    }
SHAR_EOF
echo "End of gdxbbs part 1"
echo "File funcs.c is continued in part 2"
echo "2" > @shar_seq_.tmp
exit 0