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

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

Submitted-by: root@gdx
Archive-name: gdxbbs/part02

---- Cut Here and unpack ----
#!/bin/sh
# this is gdxbbs.02 (part 2 of gdxbbs)
# do not concatenate these parts, unpack them in order with /bin/sh
# file funcs.c continued
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
if test ! -r @shar_seq_.tmp; then
	echo "Please unpack part 1 first!"
	exit 1
fi
(read Scheck
 if test "$Scheck" != 2; then
	echo "Please unpack part $Scheck next!"
	exit 1
 else
	exit 0
 fi
) < @shar_seq_.tmp || exit 1
echo "x - Continuing file funcs.c"
sed 's/^X//' << 'SHAR_EOF' >> funcs.c &&
X  portout('\n');
X}
X
Xint expert(argc,argv)
Xint argc;
Xchar **argv;
X{
Xif (argc==1)
X	{
X	if (expert_mode) expert_mode=0;
X	else expert_mode=1;
X	}
Xif (argc==2)
X	{
X	expert_mode=atoi(argv[1]);
X	}
Xreturn(0);
X}
X
Xint help(argc,argv)
X     int argc;
X     char **argv;
X{
Xint i;
Xfor (i=0;i<argc;++i)
X  {
X    printf("%s ",argv[i]);
X  }
Xprintf("\n");
Xreturn(0);
X}
X
X
Xint passwd(argc,argv)
Xint argc;
Xchar **argv;
X{
X  char temp[15],temp2[15],name[20];
X  USER *cur;
X  if (argc>1)
X    {
X      if (sysop)
X	{
X	  if (argc==3) sprintf(name,"%s %s",argv[1],argv[2]);
X	  else strcpy(name,argv[1]);
X	  cur=chk_name(name);
X	  if (cur==NULL)
X	    {
X	      portsout("passwd: invalid user name\n");
X	      return(0xffff);
X	    }
X	  portsout("New Password:");
X	  temp[0]=0;
X	  getline(temp,14);
X	  portsout("\n\r");
X	  encodepw(temp,cur->name);
X	  save_passwd(cur->name,temp);
X	  return(0);
X	}
X      else
X	{
X	  portsout("\nSysop priviledge required to change someone elses password!\n");
X	  return(0xffff);
X	}
X    }
X  portsout("Old ");
X  getpw(temp);
X  encodepw(temp,logged_user.name);
X  if (!strcmp(temp,logged_user.passwd))
X    {
X      portsout("New ");
X      getpw(temp);
X      portsout("Confirm New ");
X      getpw(temp2);
X      if (!strcmp(temp,temp2))
X	{
X	  encodepw(temp,logged_user.name);
X	  strcpy(logged_user.passwd,temp);
X	  portsout("Password successfully changed.");
X	  save_userrec(&logged_user);
X	}
X      else
X	{
X	  portsout("passwd: retype of new password doesn't match\n");
X	  return(0xffff);
X	}
X    }
X  else /* old pw not typed right */
X    portsout("passwd: old password incorrect\n");
X  return(0);
X}
X
Xint pwd()
X{
Xportsout("Current message area: ");
Xboldon();
Xif (cur_msg_area!=NULL)
X  portsout(cur_msg_area->name);
Xelse
X  portsout("None selected.");
Xboldoff();
Xportsout("\n   Current file area: ");
Xboldon();
Xif (cur_file_area!=NULL)
X  portsout(cur_file_area->name);
Xelse
X  portsout("None selected.");
Xboldoff();
Xreturn(0);
X}
X
Xint setpage(argc,argv)
Xint argc;
Xchar **argv;
X{
Xif (argc>1)
X	{
X	pagemode=atoi(argv[1]);
X	}
Xelse	pagemode= !pagemode;
Xportsout("\nPage mode turned ");
Xif (pagemode) portsout("on.\n");
Xelse portsout("off.\n");
Xreturn(0);
X}
X
Xint ver()
X{
Xatout("\n@bold @color(yellow)GDXBBS V1.0@normal @color(ltmagenta)(beta release)\n");
Xatout("@color(ltgreen)(C) 1990 Jay A. Snyder@color(ltgreen)\n\n");
Xreturn(0);
X}
X
X
Xint setterm(argc,argv)
X     int argc;
X     char *argv[];
X{
X  int i;
X  exit_terminfo();
X  ansi=0;
X  color_mode=0;
X  i=3;
X  if (argc>=2) 
X    strcpy(term,argv[1]);
X  else if (argc>=0)
X    while (i==3) /* if the user ^C's then retry */
X      {
X	sprintf(str,"Terminal type (%s):",term);
X	portsout(str);
X	str[0]=0;
X	boldon();
X	setcolor(YELLOW,BLACK);
X	i=getline(str,19);
X	boldoff();
X	setcolor(LTGREEN,BLACK);
X	portsout("\n\r");
X	if (str[0]!=0) strcpy(term,str);
X      }
X  strcpy(str,term);
X  if (strlen(str)>4) str[4]=0;
X  if (!strcmp(str,"ansi") && argc>0)
X    {
X      ansi=1;
X      portsout("\nDo you want color?\n");
X      if (yesno(1))
X        color_mode=1;
X    }
X  if (term[0]==0)
X    {
X      error_message(BAD_TERM);
X    }
X  else
X    getcaps();
X  sprintf(str,"TERM=%s",term);
X  setenv(str);
X  if (termset) 
X    {
X      sprintf(str,"\nterminal type set to %s\n",term);
X      portsout(str);
X      enter_terminfo();
X    }
X}
X
SHAR_EOF
echo "File funcs.c is complete" &&
$TOUCH -am 1227221790 funcs.c &&
chmod 0644 funcs.c ||
echo "restore of funcs.c failed"
set `wc -c funcs.c`;Wc_c=$1
if test "$Wc_c" != "5277"; then
	echo original size 5277, current size $Wc_c
fi
# ============= chat.c ==============
echo "x - extracting chat.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > chat.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
Xchat(argc,argv)
Xint argc;
Xchar **argv;
X{
Xif (argc<2) argv[1]="";
Xprintf("chat with user %s\n",argv[1]);
X}
SHAR_EOF
$TOUCH -am 0507212690 chat.c &&
chmod 0644 chat.c ||
echo "restore of chat.c failed"
set `wc -c chat.c`;Wc_c=$1
if test "$Wc_c" != "178"; then
	echo original size 178, current size $Wc_c
fi
# ============= spawn.c ==============
echo "x - extracting spawn.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > spawn.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#define SYSTEM 1
X#include "inc.h"
X
X
Xsystemx(line)
Xchar *line;
X{
X#ifdef USECURSES
X  WINDOW *sh_win, *newwin();
X#endif
X  int w;
X  char *shell, *shellpath, *getenv(), *strrchr();
X  unsigned int sleep();
X  
X#ifdef USECURSES
X  /* a full window */
X  if (curses_init)
X    {
X      sh_win = newwin(LINES, COLS, 0, 0);
X      
X      touchwin(sh_win);
X      wrefresh(sh_win);
X      /* out of curses mode */
X      resetterm();
X    }
X  else
X#endif
X    if (terminfo_mode) /* if not in curses, but terminal is set */
X      {
X	exit_terminfo();
X	terminfo_mode=1;
X      }
X  if (kbd_pid!=0) /* tell kbd routine to shut up */
X    kill(kbd_pid,SIGUSR1);
X  unsetraw();
X  system(line);
X  setraw();
X  if (kbd_pid!=0) /* tell kbd routine to restart */
X    kill(kbd_pid,SIGUSR1);
X  /*  	sleep(1); */
X#ifdef USECURSES
X  if (curses_init)
X    {
X      portsout("[Press return to continue]\r");
X      buf[0]=0;
X      getline(buf,1);
X      portsout("                          ");
X      /* back to curses mode */
X      fixterm();
X      clearok(curscr, TRUE);
X      werase(sh_win);
X      wrefresh(sh_win);
X      delwin(sh_win);
X    }
X  else
X#endif
X    if (terminfo_mode)
X      {
X	enter_terminfo();
X      }
X  return;
X}
X
Xspawn(path,argv)
X     char *path, *argv[]/*, *envp[]*/;
X{
X  int ch_pid, status;
X  union {
X          int i;
X	  struct
X	    {
X	      char lo;
X	      char hi;
X	    } b;
X        } ch_stat;
X  if ((ch_pid=fork())<0)
X    {
X      error_message(FORK_ERROR);
X      return(errno);
X    }
X  else if (ch_pid==0) /* child */
X    {
X      execvp(path,argv);
X      error_message(EXEC_ERROR);
X    }
X  else /* parent */
X    {
X      while ((status=wait(&ch_stat.i)) !=ch_pid)
X	{
X	  if (status<0 && errno==ECHILD)
X	    break;
X	  errno=0;
X	}
X      if (ch_stat.b.lo==0)
X	return(ch_stat.b.hi);
X      return(0);
X    }
X}
SHAR_EOF
$TOUCH -am 0507213790 spawn.c &&
chmod 0644 spawn.c ||
echo "restore of spawn.c failed"
set `wc -c spawn.c`;Wc_c=$1
if test "$Wc_c" != "1832"; then
	echo original size 1832, current size $Wc_c
fi
# ============= users.c ==============
echo "x - extracting users.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > users.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
Xchar *user_home_dir();
Xchar *setup_file();
Xchar portin();
Xint scmp();
XAREA *find_msg_area();
XAREA *find_file_area();
X
X/* setup file tokens */
X
Xchar *sf_tok[]={
X  "color",
X  "curfilearea",
X  "curmsgarea",
X  "expert",
X  "logdate",
X  "maildate",
X  "pagemode",
X  "rdate",
X  "term",
X  "\033\033"
X};
X
X#define SF_COUNT (int) sizeof(sf_tok)/sizeof(char *)
X
X/*
X  return pointer to last user in list
X*/
XUSER *last_user_ptr()
X{
X  USER *ptr;
X  ptr=first_user_ptr;
X  while (ptr->next !=NULL)
X    ptr=ptr->next;
X}
X
Xload_userrec(username,userrec)
X     char *username;
X     USERREC *userrec;
X{
XFILE *fp;
Xchar name[20],passwd[15];
XPRIV priv;
Xif ((fp=fopen(USER_FILE,"r"))==NULL)
X	{
X	fatal_error(USER_FILE_ERROR);
X	}
Xwhile (!feof(fp))
X  {
X    name[0]=0;passwd[0]=0;priv=0;
X    fscanf(fp,"%[^:]",name);
X    fscanf(fp,"%*c%[^:]",passwd);
X    fscanf(fp,"%*c%lx%*[^\n]%*[\n]",&priv);
X    if (!ncstrcmp(name,username)) /* correct user found */
X      {
X	strcpy(userrec->name,name);
X	strcpy(userrec->passwd,passwd);
X	userrec->priv=priv;
X	break;
X      }
X  }
Xfclose(fp);
X}
X
X
Xsave_userrec(userrec)
X     USERREC *userrec;
X{
X  FILE *fp,*fpout;
X  char name[20],s[160];
X  if ((fp=fopen(USER_FILE,"r"))==NULL)
X    {
X      fatal_error(USER_FILE_ERROR);
X    }
X  unlink(TMP_USER_FILE);
X  if ((fpout=fopen(TMP_USER_FILE,"w"))==NULL)
X    {
X      fatal_error(TMP_USER_FILE_ERROR);
X    }
X  while (!feof(fp))
X    {
X      fscanf(fp,"%[^\n]%*[ \n]",s);
X      sscanf(s,"%[^:]",name);
X      if (!ncstrcmp(name,userrec->name)) /* correct user found */
X	{
X	  write_userrec(fpout,userrec);
X	}
X      else
X	fprintf(fpout,"%s\n",s);
X    }
X  fclose(fp);
X  fclose(fpout);
X  remove(USER_FILE);
X  rename(TMP_USER_FILE,USER_FILE);
X}
X
Xsave_passwd(name,passwd)
X     char *name,*passwd;
X{
X  USERREC userrec;
X  if (load_userrec(name,&userrec))
X    {
X      error_message(INVALID_USER);
X      return(INVALID_USER);
X    }
X  strcpy(userrec.passwd,passwd);
X  save_userrec(&userrec);
X}
X
Xload_users()
X{
XUSER *current;
XFILE *fp;
Xif ((first_user_ptr=(USER *) malloc(sizeof(USER)))==NULL)
X	{
X	  error_message(MALLOC_ERROR);
X	  assert(0);
X	  quit();
X	}
Xif ((fp=fopen(USER_FILE,"r"))==NULL)
X	{
X	fatal_error(USER_FILE_ERROR);
X	}
Xcurrent=first_user_ptr;
Xwhile (!feof(fp))
X  {
X  current->next=NULL;
X  fscanf(fp,"%[^:]%*[^\n]%*[ \n]",current->name);
X  if (!feof(fp))
X    {
X    if ((current->next=(USER *) malloc(sizeof(USER)))==NULL)
X      {
X	error_message(MALLOC_ERROR);
X	assert(0);
X	quit();
X      }
X    current=current->next;
X    }
X  }
Xfclose(fp);
X}
X
Xwrite_userrec(fp,user)
XFILE *fp;
XUSERREC *user;
X{
Xfprintf(fp,"%s:%s:%lx:\n",user->name,user->passwd,user->priv);
X}
X
Xappend_new_user()
X{
XFILE *fp;
Xif ((fp=fopen(USER_FILE,"a"))==NULL)
X	{
X	fatal_error(USER_FILE_ERROR);
X	}
Xwrite_userrec(fp,&logged_user);
Xfclose(fp);
X}
X
X
XUSER *chk_name(name)
Xchar *name;
X{
XUSER *current;
Xcurrent=first_user_ptr;
Xwhile (1)
X  {
X  if (!ncstrcmp(current->name,name)) /* user name matches */
X  	return(current);
X  if (current->next==NULL) break;
X  else current=current->next;
X  }
Xreturn(NULL);
X}
X
Xencodepw(pw,name)
Xchar *pw,*name;
X{
Xchar i,ii;
Xii=0x15;i=0;
Xwhile (*pw)
X  {
X  if (i>strlen(name)) i=0;
X  *pw=*pw^(0x1f & name[i])^(i);
X  ++i;
X  *pw=*pw-5;
X  if (*pw<'!') *pw=*pw+32;
X  if (*pw==':') *pw='$';
X  ++pw;
X  }
X}
X
Xgetpw(s)
Xchar *s;
X{
Xchar c;
Xint i;
Xc=2;i=0;
Xportsout("Password:");
Xwhile (c)
X  {
X  c=portin();
X  c=tolower(c);
X  switch (c)
X    {
X    case NL:
X    case CR:c=0;
X            break;
X    case DEL:
X    case BS:if (i) --i;
X    	    break;
X    default:if (i<15 && c>=' ') s[i++]=c;
X            break;
X    } /* end switch */
X  }
Xs[i]=0;
Xportsout("\n\r");
X}
X
Xnew_user(name)
Xchar *name;
X{
Xchar temp[15],tmpstr[80];
Xchar *cptr;
XUSER *uptr;
Xstrcpy(logged_user.name,name);
Xlogged_user.name[0]=toupper(logged_user.name[0]); /* upcase first character */
Xcptr=strchr(logged_user.name,' ');
Xif (cptr!=NULL) {++cptr;*cptr=toupper(*cptr);}
Xlogged_user.priv=0;
Xportsout("\n\nPasswords may consist of any combination of digits, and\n");
Xportsout("letters.  They may be up to 14 characters long.\n");
Xwhile (1)
X  {
X  portsout("Please enter your new ");
X  getpw(temp);
X  portsout("Please reenter to confirm ");
X  getpw(logged_user.passwd);
X  if (!strcmp(temp,logged_user.passwd))
X    {
X    encodepw(logged_user.passwd,logged_user.name);
X    sprintf(buf,"source -s %s",NEWUSER_FILE);
X    chkpriv=1; /* so user can do source command for startup */
X    run_line(buf);
X    chkpriv=0;
X    append_new_user();
X    uptr=last_user_ptr();
X    if ((uptr->next=(USER *) malloc(sizeof(USER)))==NULL)
X      {
X	error_message(MALLOC_ERROR);
X	assert(0);
X	quit();
X      }
X    uptr=uptr->next;
X    strcpy(uptr->name,logged_user.name);
X    uptr->next=NULL;
X    create_file(priv_mail_file(str)); /* make file */
X    sprintf(tmpstr,"mkdir %s",user_home_dir(str)); /* make users' home directory */
X    system(tmpstr);
X    return(0);
X    }
X  portsout("\nreentry doesn't match, please try again.\n\n");
X  }
X}
X
Xlogin()
X{
Xint try;
Xchar name[20];
Xtry=0;
Xwhile (try==0)
X  {
X  portsout("\nEnter your name (first and last):");
X  name[0]=0;
X  boldon();
X  setcolor(YELLOW,BLACK);
X  if (getline(name,19)==3) quit();
X  boldoff();
X  setcolor(LTGREEN,BLACK);
X  portsout("\n\r");
X  if (name[0]==0)
X    try=0;
X  else if (chk_name(name)!=NULL)
X    try=1;
X  else
X    {  
X    try=0;
X    portsout("\nUsername not on file.\n");
X    atout("Login as @color(brwhite)@bold((N))@color(ltgreen)ew user, @color(brwhite)@bold((R))@color(ltgreen)etry, or @color(brwhite)@bold((Q))@color(ltgreen)uit");
X    while (try==0)
X      {
X      try=portin();
X      try=tolower(try);
X      if (try!='r' && try!='n' && try!='q') try=0;
X      }
X    portout('\n');
X    if (try=='n')
X      {
X      new_user(name);
X      user_is_logged=1;
X      return(0);
X      }
X    if (try=='q')
X      logout(-1);
X    try=0;
X    }
X  }
Xtry=0;
Xload_userrec(name,&logged_user);
Xwhile (try<maxtry)
X  {
X    getpw(name);
X    encodepw(name,logged_user.name);
X    if (!strcmp(name,logged_user.passwd) || (logged_user.passwd[0]==0))
X      { /* password right */
X	if (logged_user.priv & SYSOP_PRIV) (sysop=1);
X	user_is_logged=1;
X	return(0);
X      }
X    portsout("Incorrect password, try again.\n");
X    ++try;
X  }
Xreturn(1); /* invalid login */
X}
X
Xlogout1() /* forced logout via hangup */
X{
X  logout(-2);
X}
X
X
Xlogout(argc,argv)
X     int argc;
X     char *argv[];
X{
X  char c;
X  if (user_is_logged)
X    {
X      if (argc>=0)
X	{
X	  c=1;
X	  if (argc>1)
X	    {
X	      if (!strcmp(argv[1],"now")) c=0;
X	    }
X	  if (c)
X	    {
X	      atprintf("\nDo you want to leave @sysop a message\n");
X	      c=(yesno(0));
X	      rawportout('\n');
X	      if (c)
X		{
X		  sprintf(str1,"mail -s %s",sysop_name);
X		  run_line(str1);
X		}
X	      rawportsout("\nAre you sure you want to logout?\n");
X	      c=(!yesno(1));
X	      rawportout('\n');
X	      if (c) return(0);
X	    }
X	}
X      else
X	rawportsout("Please call back later when you wake up!\n");
X      sprintf(str,"%-20s logged out at %s\n",logged_user.name,timestr());
X      if (argc>-2)
X	{
X	  rawportout('\n');
X	  rawportsout(str);
X	  rawportsout("Please hangup the line.\n");
X	}
X      save_setup();
X      logsout(str);
X      logout_utmp();
X    }
X  else
X    {
X      sprintf(str,"Unlogged user logged out.\n");
X      rawportsout(str);
X      rawportsout("Please hangup the line.\n");
X      logsout(str);
X    }
X  exitprog(0);
X}
X
Xlist_users(argc,argv)
X     int argc;
X     char **argv;
X{
X  USER *cur;
X  int x,y;
X  char c,nopage,q;
X  cur=first_user_ptr;
X  x=0;y=0;nopage=0;
X  q=0;
X  while (cur!=NULL && !q)
X    {
X      rprintf("%-19s",cur->name);
X      cur=cur->next;
X      if (x++ ==3)
X	{
X	  x=0;
X	  portout('\n');
X	  if ((y++>LI-2) &&!nopage && pagemode)
X	    {
X	      y=0;
X	      c=more_prompt();
X	      switch (c)
X		{
X		case CR:
X		case 'y':
X		  y=0;
X		  break;
X		case 'n':
X		  q=1;
X		  break;
X		case 's':  nopage=1;
X		  break;
X		}
X
X	    }
X	}
X      else portout(' ');
X    }
X  portsout("\r\n");
X}
X
X
X
X
Xload_setup()
X{
X  FILE *fp;
X  AREA *a;
X  int i;
X  char tmpstr[80],token[20],value[60],*p;
X  a=first_msg_area;
X  time(&logdate);
X  if ((fp=fopen(setup_file(tmpstr),"r"))==NULL)
X    {
X      portsout("Creating default setup file\n");
X      mk_def_setup();
X      return(-1);
X    }
X  while (!feof(fp))
X    {
X      if (read_tokstr(fp,token,value)==-1)
X	{
X	  fclose(fp);
X	  return(-1);
X	}
X      p=token;
X      i=nbsearch((char *) &p,(char *) sf_tok, SF_COUNT, sizeof(char *), scmp);
X      if (debug>2)
X	{
X	  printf("\007token %d:%s=%s\n",i,token,value);
X	  more_prompt();
X	}
X      switch(i)
X	{
X	case 0: /* color */
X	  color_mode=atoi(value);
X	  break;
X	case 1: /* curfilearea */
X	  if ((a=find_file_area(value))!=NULL)
X	    cur_file_area=a;
X	  break;
X	case 2: /* curmsgarea */
X	  if ((a=find_msg_area(value))!=NULL)
X	    cur_msg_area=a;
X	  break;
X	case 3: /* expert */
X	  expert_mode=atoi(value);
X	  break;
X	case 4: /* logdate */
X	  logdate=atol(value);
X	  break;
X	case 5: /* maildate */
X	  maildate=atol(value);
X	  break;
X	case 6: /* pagemode */
X	  pagemode=atoi(value);
X	  break;
X	case 7: /* rdate */
X	  p=strchr(&value[1],'\"');
X	  *p++=0; /* null terminate area name */
X	  ++p; /* skip space */
X	  if ((a=find_msg_area(&value[1]))!=NULL)
X	    {
X	      a->tm=atol(p);
X	    }
X	  break;
X	case 8: /* term */
X	  strcpy(term,value);
X	  setterm(-1);
X	  break;
X	}
X    }
X  fclose(fp);
X}
X
Xsave_setup() /* save user setup */
X{
X  FILE *fp;
X  AREA *a;
X  char tmpstr[80];
X  a=first_msg_area;
Xif (debug)
X  fprintf(stderr,"starting save_setup()\n");
X  if ((fp=fopen(setup_file(tmpstr),"w"))==NULL)
X    {
X      perror(tmpstr);
X      return(-1);
X    }
Xif (debug)
X  fprintf(fp,"expert %d\n",expert_mode);
X  fprintf(fp,"term %s\n",term);
X  fprintf(fp,"color %d\n",color_mode);
X  fprintf(fp,"pagemode %d\n",pagemode);
X  while(a != NULL)
X    {
X      fprintf(fp,"rdate \"%s\" %lu\n",a->name,a->tm);
X      a=a->next;
X    }
X  fprintf(fp,"maildate %lu\n",maildate);
X  fprintf(fp,"logdate %lu\n",logdate);
X  fprintf(fp,"curfilearea %s\n",cur_file_area->name);
X  fprintf(fp,"curmsgarea %s\n",cur_msg_area->name);
X  fclose(fp);
X}
X
Xmk_def_setup()
X{
X  AREA *a;
X  setterm(1);
X  a=first_msg_area;
X  while (a != NULL) /* set read times to default */
X    {
X      if (debug)
X	{
X	  fprintf(stderr,"a=%lu ",(long) a);
X	  fprintf(stderr,"area=%s\n",a->name);
X	}
X      a->tm=0;
X      a=a->next;
X    }
X  maildate=0; /* also set mail read time to default */
X}
X
Xchar *setup_file(s) /* return path name of user's mail file */
X     char *s;
X{
X  sprintf(s,"%s/.gdxbbs.cfg",user_home_dir());
X  return(s);
X}
X
Xchar *user_home_dir(s) /* return path name of user's mail file */
X     char *s;
X{
X  char tmp[80];
X  strcpy(tmp,MYNAME);
X  cvt_spc(tmp);
X  sprintf(s,"%s/%s",home_dir,tmp);
X  return(s);
X}
X
SHAR_EOF
$TOUCH -am 0116225391 users.c &&
chmod 0644 users.c ||
echo "restore of users.c failed"
set `wc -c users.c`;Wc_c=$1
if test "$Wc_c" != "10647"; then
	echo original size 10647, current size $Wc_c
fi
# ============= bulletin.c ==============
echo "x - extracting bulletin.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > bulletin.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
X
X/*
X  this is currently implemented with the menu
X*/
X
Xint bulletin(argc,argv)
Xint argc;
Xchar **argv;
X{
XFILE *fp;
X
Xreturn(0);
X}
SHAR_EOF
$TOUCH -am 0507213390 bulletin.c &&
chmod 0644 bulletin.c ||
echo "restore of bulletin.c failed"
set `wc -c bulletin.c`;Wc_c=$1
if test "$Wc_c" != "233"; then
	echo original size 233, current size $Wc_c
fi
# ============= config.c ==============
echo "x - extracting config.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > config.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X/*
X	config.c --> load configuration file config.bbs
X
Xsyntax:
Xsection name
X{
Xtokken_name <value>
X}
X*******
Xsection: command permissions:
Xsection name : comperm
Xtokens:
X
Xnote: default command permissions are 1, except cat=0x100, help=0, history=0
X      regsiter=0, ver=0, who=0
X      be careful with cat, don't give users direct priviledge over cat,
X      only let them cat specific files with menus.
X      for obvious reasons, no permissions can be set on the logout command.
X******
Xsection: filenames, if token is not defined, defaults are assumed
Xsection name: files
Xtokens:
Xareas	 (default "areas.bbs")
Xfilelibs (default "filelibs.bbs")
Xerrlog	 (default "error.log")
Xlogfile	 (default "callers.bbs")
Xmenu	 (default "menu.mcl")
Xnewscr   (default "new.scr")      new user startup script
Xmsgareas (default "msgareas.bbs")
Xregister (default "question.bbs")
Xanswer   (default "answer.bbs")
Xusers	 (default "users.bbs")
Xutmp	 (default "utmp.bbs")
Xstartup  (default "startup.scr")  startup script
Xmaildir  (default "mail")
Xhomedir (default "setup") directory for users' home directorys
Xulpath   (default curarea/upload)  default upload path
X*******
Xsection: system parameters
Xsection name: system
Xtokens:
Xprompt  system prompt
Xsysop	username of sysop
Xmaxtry	maximum number of tries at password prompt
Xdefterm default terminal type
Xfsedit  define full screen editor to be used with mail
Xidlewarn number of minutes idle time to allow before warning
Xidleout number of minutes idle time to allow before loging out
Xmondev  device to output to when monitor is turned on
X********
X*/
X
X#include "inc.h"
X
XFILE *config_fp;
X
Xchar *toksections[]={"comperm","files","system"};
X#define SECCOUNT (int) sizeof(toksections)/sizeof(char *)
X
XCOMMAND *com[];
Xextern char *cmds[];
Xextern cmdcount;
X
Xchar *filestok[]={"answer","areas","errlog","filelibs","homedir","logfile",
X        "maildir","menu","msgareas","newuser","quest","startup",
X	"ulpath","users","utmp","\0377"};
X#define FILE_COUNT (int) sizeof(filestok)/sizeof(char *)
Xchar *filesptr[FILE_COUNT];
X
Xchar *systemtok[]={"defterm","fsedit","idleout","idlewarn","maxtry",
X   "mondev","prompt","sysop","\0377"};
X#define SYSTEM_COUNT (int) sizeof(systemtok)/sizeof(char *)
X
Xint scmp(s1,s2)
Xchar **s1, **s2;
X{
Xreturn(strcmp(*s1,*s2));
X}
X
Xint nbsearch(find, root, size, elesize, comp) /* return index of find */
Xint *find, *root;
Xint size, elesize;
Xint *(comp)();
X{
Xchar **p;
Xp=(char **) bsearch((char *) find,(char *) root, size, elesize, (int (*)()) comp);
Xif (p==NULL) return(-1);
Xreturn((int) ((int *) p-root));
X}
X
Xint read_tokstr(fp,tokname,value) /* return -1 if } found */
XFILE *fp;
Xchar *tokname, *value;
X{
X  char c;
X  buf[0]=0;
X  fscanf(fp,"%[} \n\011]",buf); /* skip white space */
X  if (strchr(buf,'}')) return(-1);
X  buf[0]=0;
X  fscanf(fp,"%[^ ,\011\n]",tokname);
X  strdncase(tokname);
X  buf[0]=0;
X  fscanf(fp,"%[ :=,\011\n]",buf); /* tab,=: can be used as separator */
X  if (strchr(buf,'\n')!=NULL) /* \n in string */
X    {
X    rprintf("Warning: no value specified for token %s\n",tokname);
X    value[0]=0;
X    return (1);
X    }
X  else
X    {
X    value[0]=0;
X    fscanf(fp, "%[^;\n}]",value);
X    c=fgetc(fp); /* comment? */
X    if (c==';') fscanf(fp, "%[^\n}]",buf); /* skip it! */
X    return (0);
X    }
X}
X
X
Xint read_tokint(fp,tokname,value) /* return -1 if } found */
XFILE *fp;
Xchar *tokname;
Xlong *value;
X{
Xchar values[60];
Xint i;
Xi=read_tokstr(fp,tokname,values);
X*value=strtol(values,NULL,16);
Xreturn (i);
X}
X
X
Xconfig_system()
X{
Xchar *p,c,token[20],value[60];
Xint i;
Xwhile (!feof(config_fp))
X  {
X  if (read_tokstr(config_fp,token,value)==-1) return;
X  p=token;
X  i=nbsearch((char *) &p,(char *) systemtok, SYSTEM_COUNT, sizeof(char *), scmp);
X  if (debug>2) printf("token %d:%s=%s\n",i,token,value);
X  switch (i)
X    {
X    case 0: /* defterm */
X      strcpy(defterm,value);
X      break;
X    case 1: /* fsedit */
X      strcpy(fsedit,value);
X      break;
X    case 2: /* idle out */
X      idleout=atoi(value);
X      break;
X    case 3: /* idle warning */
X      idlewarn=atoi(value);
X      break;
X    case 4: /* maxtry */
X      maxtry=atoi(value);
X      break;
X    case 5: /* mondev */
X      if (strlen(value)>19) value[19]=0;
X      strcpy(mondev,value);
X      break;
X    case 6:
X      if (strlen(value)>19) value[19]=0;
X      strcpy(prompt,value);
X      break;
X    case 7:
X      strcpy(sysop_name,value);
X      break;
X    default:
X      portsout("Illegal token in section system\n");
X      break;
X    }
X  }
X}
X
Xconfig_comperm()
X{
Xchar *p,c,token[20];
Xint i;
Xlong value;
Xwhile (!feof(config_fp))
X  {
X  if (read_tokint(config_fp,token,&value)==-1) return;
X  p=token;
X  i=nbsearch((char *) &p,(char *) cmds, cmdcount, sizeof(char *), scmp);
X  if (debug>2) printf("token %d:%s=%lu\n",i,token,value);
X  if (i>-1 && i<cmdcount)
X    com[i]->priv=value;
X  else
X    printf("Illegal token in section comperm\n");
X  }
X}
X
Xconfig_files()
X{
Xchar *p,c,token[20],value[80];
Xint i;
Xwhile (!feof(config_fp))
X  {
X  if (read_tokstr(config_fp,token,value)==-1) return;
X  p=token;
X  i=nbsearch((char *) &p,(char *) filestok, FILE_COUNT, sizeof(char *), scmp);
X  if (debug>2) printf("token %d:%s=%s\n",i,token,value);
X  if (i>-1 && i<FILE_COUNT)
X    strcpy(filesptr[i],value);
X  else
X    printf("Illegal token in section files\n");
X  }
X}
X
Xload_config()
X{
Xchar *p;
Xint i;
Xi=0;
Xfilesptr[i++]=quest_out_file;
Xfilesptr[i++]=areas_file;
Xfilesptr[i++]=errorlog_file;
Xfilesptr[i++]=filelibs_file;
Xfilesptr[i++]=home_dir;
Xfilesptr[i++]=log_file;
Xfilesptr[i++]=mail_dir;
Xfilesptr[i++]=menu_file;
Xfilesptr[i++]=msgareas_file;
Xfilesptr[i++]=newuser_file;
Xfilesptr[i++]=quest_file;
Xfilesptr[i++]=startup_file;
Xfilesptr[i++]=def_ul_path;
Xfilesptr[i++]=user_file;
Xfilesptr[i++]=utmp_file;
Xif ((config_fp=fopen(config_file,"r"))==NULL)
X	fatal_error(CONFIG_FILE_ERROR);
Xwhile (!feof(config_fp))
X  {
X  fscanf(config_fp,"%[^ \011\n{]",str);
X  fscanf(config_fp,"%[ \011\n{]",buf); /* skip spaces and { */
X  p=str;
X  i=nbsearch((char *) &p,(char *) toksections, SECCOUNT, sizeof(char *), scmp);
X  if (debug>2) printf("Config section name [%s],%d\n",str,i);
X  switch (i)
X     {
X     case 0: /* comperm */
X        config_comperm();
X     	break;
X     case 1: /* files */
X        config_files();
X     	break;
X     case 2: /* system */
X     	config_system();
X     	break;
X     default:
X	rprintf("Warning: Invalid section name %s in config file\n",str);
X     	break;
X     } /* end switch */
X  }
Xfclose(config_fp);
X}
SHAR_EOF
$TOUCH -am 1230235690 config.c &&
chmod 0644 config.c ||
echo "restore of config.c failed"
set `wc -c config.c`;Wc_c=$1
if test "$Wc_c" != "6459"; then
	echo original size 6459, current size $Wc_c
fi
# ============= file.c ==============
echo "x - extracting file.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > file.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X/*
Xfile.c --> file area stuff
X
Xfile.bbs file format:
X
X<title header>
X~~~~
Xfilename description
X....
X
X
X*/
X
X#include "inc.h"
Xoff_t filesize(filename)
X     char *filename;
X{
X  struct stat fs;
X  if (stat(filename,&fs)) return(-1);
X  return(fs.st_size);
X}
X
Xint _ls(filebase,mask)
X  char filebase[80],mask[15];
X{
X  FILE *fp;
X  int page_lines;
X  char filename[80],x,nopage,c,q;
X  char desc[80];
X  off_t fsize;
X  if ((fp=fopen(filebase,"r"))==NULL)
X    {
X      rprintf("Error opening file base index \"%s\"",filebase);
X      return(1);
X    }
X  setcolor(LTGREEN,BLACK);
X  x=0;
X  page_lines=0;
X  while (!x && !ctrlc() && !feof(fp))
X    {
X      myfgets(buf,BUFSIZE,fp);
X      if (!strcmp(buf,"~~~~")) x=1;
X      else atprintf("%s\n",buf);
X      ++page_lines;
X    }
X  boldon();
X  setcolor(YELLOW,BLACK);
X  rprintf("\nFile area: %s\n",cur_file_area->name);
X  rprintf("%14.14s %8.8s %s\n","Filename","  Size","  Description");
X  boldoff();
X  page_lines+=3;
X  nopage=0;q=0;
X  while (!feof(fp) && !q)
X    {
X      fscanf(fp,"%s",buf);
X      if (buf[0]!='/' && buf[0]!='#')
X	{
X	  sprintf(filename,"%s/%s",cur_file_area->dir,buf);
X	}
X      else strcpy(filename,buf);
X      fscanf(fp,"%*[ \t]");
X      if (feof(fp)) break;
X      myfgets(desc,79,fp);
X      setcolor(YELLOW,BLACK);
X      if (filename[0]!='#')
X	{
X	  rprintf("%-14.14s ",basename(filename));
X	  if ((fsize=filesize(filename))==-1)
X	    {
X	      setcolor(LTRED,BLACK);
X	      rprintf(" OFFLINE ");
X	    }
X	  else
X	    {
X	      setcolor(LTGREEN,BLACK);
X	      rprintf("%8d ",fsize);
X	    }
X	}
X      else
X	rprintf("%-23.23s ","");
X      setcolor(LTCYAN,BLACK);
X      rprintf("%-*.*s\n",CO-26,CO-26,desc);
X      if (++page_lines>LI-2 && pagemode && !nopage)
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    }
X  fclose(fp);
X  return(0);
X}
X
Xls(argc,argv)
X  int argc;char *argv[];
X{
X  if (argc==1)
X    _ls(cur_file_area->file,"*");
X}  
X  
Xfindfile()
X{
X  printf("findfile command\n");
X  return(0);
X}
X
X
Xchar *upload_path(s)
X     char *s;
X{
X  char *p;
X  if (cur_file_area->udir[0]!=0) p=cur_file_area->udir;
X  else p=def_ul_path;
X  if (p[0]=='*')
X    sprintf(s,"%s%s",cur_file_area->dir,&cur_file_area->udir[1]);
X  else
X    strcpy(s,p);
X  return(s);
X}
X
Xchar *dnload_path(path,file)
X     char *path,*file;
X{
X  FILE *fp;
X  char filename[80],x,*p;
X  if ((fp=fopen(p=cur_file_area->file,"r"))==NULL)
X    {
X      rprintf("Error opening file base index \"%s\"",p);
X      return(NULL);
X    }
X  x=0;
X  while (!x && !ctrlc() && !feof(fp))
X    {
X      myfgets(buf,BUFSIZE,fp);
X      if (!strcmp(buf,"~~~~")) x=1;
X    }
X  x=0;
X  while (!feof(fp) && !x)
X    {
X      fscanf(fp,"%s",buf);
X      if (buf[0]!='/' && buf[0]!='#')
X	{
X	  sprintf(filename,"%s/%s",cur_file_area->dir,buf);
X	}
X      else strcpy(filename,buf);
X      fscanf(fp,"%*[ \t]");
X      fscanf(fp,"%*[^\n]");
X      fscanf(fp,"%*[\n]");
X      if (!strcmp(file,basename(filename)))
X	{
X          strcpy(path,filename);
X	  return(0);
X	}
X    }
X}
X
Xuploadfile(argc,argv)
X     int argc;
X     char **argv;
X{
X  FILE *fp;
X  char filename[15];
X  char pathname[80];
X  char stopath[80];
X  char desc[80];
X  if (argc==1)
X    {
X      setcolor(BRWHITE);
X      portsout("Enter filename:");
X      setcolor(YELLOW);
X      pathname[0]=0;
X      filename[0]=0;
X      getline(filename,14);
X      portout('\n');
X      if (filename[0]==0) return(1);
X      getcwd(stopath,79);
X      if (chdir(upload_path(pathname)))
X	{
X	  errorsout("! %s: Cannot chdir to %s\n",argv[0],pathname);
X	}
X      else
X	{
X	  rprintf("Please enter a description for %s:\n",filename);
X	  desc[0]=0;
X	  setcolor(YELLOW,BLACK);
X	  if (getline(desc,80)==3) return(1);
X	  setcolor(LTGREEN,BLACK);
X	  if ((fp=fopen("files.bbs","a"))==NULL)
X	    {
X	      rprintf("%s: Error opening %s for append access.\n",
X		      argv[0],"files.bbs");
X	      return(1);
X	    }
X	  fprintf(fp,"%s\t%s\n",filename,desc);
X	  fclose(fp);
X	  if (ul_exe[0]==0) setproto(0);
X	  if (ul_exe[0]==0)
X	    {
X	      rprintf("%s: No file transfer protocol selected.\n",argv[0]);
X	      return(1);
X	    }
X	  sprintf(buf,ul_exe,filename);
X	  systemx(buf);
X	}
X      chdir(stopath);
X    }
X}
X
Xdnloadfile(argc,argv)
X     int argc;
X     char **argv;
X{
X  char filename[15];
X  char pathname[80];
X  if (cur_file_area==NULL)
X    {
X      rprintf("No current file area.\n");
X      return(1);
X    }
X  if (argc==1)
X    {
X      setcolor(BRWHITE,BLACK);
X      portsout("Enter filename:");
X      setcolor(YELLOW,BLACK);
X      filename[0]=0;
X      getline(filename,14);
X      if (filename[0]==0) return(1);
X    }
X  else
X    {
X      if (strlen(argv[1])>=14) argv[1][14]=0;
X      strcpy(filename,argv[1]);
X    }
X  dnload_path(pathname,filename);
X  if (filesize(pathname)==-1)
X    {
X      rprintf("Sorry, file %s doens't exist\n",filename);
X      return(1);
X    }
X  if (dl_exe[0]==0) setproto(0);
X  if (dl_exe[0]==0)
X    {
X      rprintf("No file transfer protocol selected.\n");
X      return(1);
X    }
X  sprintf(buf,dl_exe,pathname);
X  systemx(buf);
X}
X
X
X
X/*
X  setproto --> set file transfer protocol
X*/
Xsetproto(argc,argv)
X     int argc;
X     char *argv[];
X{
X  char c;
X  m_entry_ptr entry;
X  portout('\n');
X  ctrlc_off();
X  if (argc<=1)
X    {
X      print_menu(proto_menu_ptr);
X      setcolor(BRWHITE,BLACK);
X      portsout("\nSelect file transfer protocol:");
X      c=portin();    
X    }
X  else c=argv[1][0];
X  while (c)
X    {
X      if (c==ESC || c==3 || c==CR || c==NL) return (1);
X      if ((entry=(m_entry_ptr) chk_entry(c,proto_menu_ptr))!=NULL)
X	{
X	  c=0;
X	  extract_file_cmd(entry->cmd,dl_exe,ul_exe);
X	  setcolor(LTGREEN,BLACK);
X	  portsout("\rFile transfer protocol changed to: ");
X	  print_entry(entry);
X	  portsout("\n");
X	}
X      else
X	c=portin();
X    }
X  ctrlc_on();
X}
X
Xextract_file_cmd(cmd,d,e)
X     char *cmd,*d,*e;
X{
X  while (*cmd && (*cmd++)!='\"');
X  while (*cmd && *cmd!='\"') *d++=*cmd++;
X  *d=0;
X  ++cmd;
X  while (*cmd && (*cmd++)!='\"');
X  while (*cmd && *cmd!='\"') *e++=*cmd++;
X  *e=0;
X  ++cmd;
X}
X
SHAR_EOF
$TOUCH -am 1127232790 file.c &&
chmod 0644 file.c ||
echo "restore of file.c failed"
set `wc -c file.c`;Wc_c=$1
if test "$Wc_c" != "6091"; then
	echo original size 6091, current size $Wc_c
fi
# ============= who.c ==============
echo "x - extracting who.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > who.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
X
X
Xint who(argc,argv)
Xint argc;
Xchar **argv;
X{
Xstruct utmp_entry ut;
XFILE *fp;
Xint users;
Xif ((fp=fopen(UTMP_FILE,"r"))==NULL)
X	{
X	error_message(UTMP_FILE_ERROR);
X	return(UTMP_FILE_ERROR);
X	}
Xfscanf(fp,"%d",&users);
Xfscanf(fp,"%[^\n]",buf);
Xfscanf(fp,"%[\n]",buf);
Xrprintf("		%d Users %s\n",users,timestr());
Xrprintf("%-20s %-6s %s\n","User","TTY","Time On");
Xwhile (!feof(fp) && (users--)>0)
X  {
X  fscanf(fp,"%[^:]%[:]%[^:]%[:]%[^\n]%[\n]",
X  	ut.name,buf,ut.tty,buf,ut.t,buf);
X  rprintf("%-20s %-6s %s\n",ut.name,ut.tty,ut.t);
X  }
Xfclose(fp);
Xreturn(0);
X}
X
Xclr_utmp()
X{
Xutmpentry *cur,*next;
Xcur=first_utmp;
Xwhile (cur!=NULL)
X  {
X  next=cur->next;
X  free(cur);
X  cur=next;
X  }
Xfirst_utmp=NULL;
Xlogged_users=0;
X}
X
Xload_utmp()
X{
XFILE *fp;
Xutmpentry *cur;
Xint users;
Xclr_utmp();
Xif (debug>6) pause();
Xif ((fp=fopen(UTMP_FILE,"r"))==NULL)
X	{
X	error_message(UTMP_FILE_ERROR);
X	return(UTMP_FILE_ERROR);
X	}
Xfscanf(fp,"%d\n",&users);
Xlogged_users=users;
Xif (users>0)
X  {
X  if ((first_utmp=(utmpentry *) malloc(sizeof(utmpentry)))==NULL) 
X      {
X	error_message(MALLOC_ERROR);
X	assert(0);
X	quit();
X      }
X  last_utmp=first_utmp;
X  cur=last_utmp;
X  cur->next=NULL;
X  fscanf(fp,"%[^:]%[:]%[^:]%[:]%[^\n]%[\n]",
X  	cur->name,buf,cur->tty,buf,cur->t,buf);
X  while (!feof(fp) && (--users)>0)
X    {
X    if ((last_utmp=(utmpentry *) malloc(sizeof(utmpentry)))==NULL) 
X      {
X	error_message(MALLOC_ERROR);
X	assert(0);
X	quit();
X      }
X    cur->next=last_utmp;
X    cur=last_utmp;
X    cur->next=NULL;
X    fscanf(fp,"%[^:]%[:]%[^:]%[:]%[^\n]%[\n]",
X  	cur->name,buf,cur->tty,buf,cur->t,buf);
X    }
X  }
Xelse
X  {
X  first_utmp=NULL;
X  last_utmp=NULL;
X  }
Xfclose(fp);
Xif (debug>6) pause();
X}
X
X
Xsave_utmp()
X{
XFILE *fp;
Xutmpentry *cur;
Xif (debug>6) printf("save_utmp 0\n");
Xif ((fp=fopen(UTMP_FILE,"w"))==NULL)
X	{
X	error_message(UTMP_FILE_ERROR);
X	return(UTMP_FILE_ERROR);
X	}
Xif (debug>6) printf("save_utmp 1\n");
Xif (debug>6) printf("save_utmp 2\n");
Xfprintf(fp,"%d\n",logged_users);
Xif (debug>6) printf("save_utmp 3\n");
Xif (logged_users>0)
X{
Xif (debug>6) printf("save_utmp 4\n");
X  cur=first_utmp;
X  if (debug>6) 
X    {
X    if (cur==NULL) printf("cur=NULL\n");
X    else printf("cur!=NULL\n");
X    }
X  while (cur!=NULL)
X    {
X	  if (debug>6) 
X	    {
X	    if (cur==NULL) printf("cur=NULL\n");
X	    else printf("cur!=NULL\n");
X	    }
X    fprintf(fp,"%s:%s:%s\n",cur->name,cur->tty,cur->t);
X    cur=cur->next;
X    }
X}
Xfclose(fp);
X}
X
X/*
X   add login to utmp file
X*/
Xlogin_utmp()
X{
Xutmpentry *cur;
Xif (debug>6) printf("\n load_utmp()...\n");
Xload_utmp();
Xif (debug>6) printf("\n load_utmp() done\n");
Xif (debug>6) printf("last_utmp=%lx\n",last_utmp);
Xif (debug>6) pause();
Xif (first_utmp!=NULL)
X  cur=last_utmp;
Xif (debug>6) {if (cur==NULL) printf("\ncur=NULL\n",0);}
Xif ((last_utmp=(utmpentry *) malloc(sizeof(utmpentry)))==NULL) 
X      {
X	error_message(MALLOC_ERROR);
X	assert(0);
X	quit();
X      }
Xstrcpy(last_utmp->name,logged_user.name);
Xstrcpy(last_utmp->tty,thistty);
Xstrcpy(last_utmp->t,timestr());
Xif (debug>6) printf("\nstrcpy's done\n");
Xif (first_utmp==NULL) first_utmp=last_utmp;
Xelse cur->next=last_utmp;
Xif (debug>6) printf("\ncur->next=last_utmp done\n");
Xlast_utmp->next=NULL;
X++logged_users;
Xif (debug>6) printf("\n save_utmp()...\n");
Xsave_utmp();
Xif (debug>6) printf("\n save_utmp() done\n");
Xclr_utmp();
Xif (debug>6) printf("\n clr_utmp() done\n");
X}
X
X/*
X   remove login from utmp file
X*/
Xlogout_utmp()
X{
Xutmpentry *cur,*curn;
Xload_utmp();
Xcur=first_utmp;
Xcurn=cur;
X--logged_users;
Xif (!strcmp(first_utmp->tty,thistty))
X  {
X  first_utmp=first_utmp->next;
X  }
Xelse while (cur->next!=NULL)
X  {
X  if (!strcmp(curn->tty,thistty))
X    {
X    cur->next=curn->next; /* delete entry */
X    cur=NULL; /* end loop */
X    }
X  else cur=cur->next;
X  }
Xsave_utmp();
Xclr_utmp();
X}
X
SHAR_EOF
$TOUCH -am 0507212590 who.c &&
chmod 0644 who.c ||
echo "restore of who.c failed"
set `wc -c who.c`;Wc_c=$1
if test "$Wc_c" != "3831"; then
	echo original size 3831, current size $Wc_c
fi
# ============= quest.c ==============
echo "x - extracting quest.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > quest.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
Xchar portin();
X
X/*
X  if no arguments are specified, the default questionaire is
X  answered.
X  otherwise, the first argument is taken as a file and used.
X*/
Xint doquest(argc,argv)
Xint argc;
Xchar **argv;
X{
XFILE *tf, *of;
Xchar skip,quit,*filename;
Xskip=0;quit=0;
Xif (argc<2) filename=QUEST_FILE;
Xelse filename=argv[1];
Xif ((tf=fopen(filename,"r"))==NULL)
X  {
X    error_message(QUEST_FILE_ERROR);
X    return(-1);
X  }
Xif ((of=fopen(QUEST_OUT_FILE,"a"))==NULL)
X  {
X    error_message(QUEST_FILE_ERROR);
X    return(-1);
X  }
Xfprintf(of,"**********************************\n");
Xfscanf(tf,"%[\n ]",buf);
Xfscanf(tf,"%[^\n]",buf);
Xboldon();
Xatout(&buf[1]);
Xboldoff();
Xportout('\n');
Xfprintf(of,"%s: %s\n",filename,&buf[1]);
Xfprintf(of,"User: %s\n",logged_user.name);
Xwhile (!feof(tf) && !quit)
X  {
X    fscanf(tf,"%[\n ]",buf);
X    fscanf(tf,"%[^\n]",buf);
X    if ((skip==0) || (buf[0]=='}'))
X	switch(buf[0])
X	  {
X	  case 'Q':
X	    quit=1;
X	    break;
X	  case '{':
X	    break;
X	  case '}':
X	    skip=0;
X	    break;
X	  case 'Y':
X	  case 'y':
X	  case 'N':
X	  case 'n':
X	    atout(&buf[1]);
X	    portout('\n');
X	    fscanf(tf,"%[^{]",str1);
X	    buf[0]=tolower(buf[0]);
X	    buf[1]=(char) yesno(-1);
X	    portout('\n');
X	    if ((!buf[1] && buf[0]=='y') || (buf[1] && buf[0]=='n'))
X	      { /* skip if they answer no to a yes, or yes to a no */
X		skip=1;
X	      }
X	    break;
X	  case '@':
X	    atout(&buf[1]);
X	    portout('\n');
X	    break;
X	  case '!':
X	    atout(&buf[1]);
X	    portout('\n');
X	    buf[0]=0;
X	    getline(buf,79);
X	    portout('\n');
X	    fprintf(of,"%s\n",buf);
X	    break;
X	  case '&':
X	    atout(&buf[1]);
X	    portout('\n');
X	    buf[0]=1;
X	    while (buf[0]!=0)
X	      {
X		buf[0]=0;
X		getline(buf);
X		portout('\n');
X		if (buf[0]!=0)
X		  fprintf(of,"%s\n",buf);
X	      }
X	    break;
X	  default:
X	    break;
X	  } /* end case */
X  }
Xfclose(tf);
Xfclose(of);
Xreturn(0);
X}
SHAR_EOF
$TOUCH -am 1225225890 quest.c &&
chmod 0644 quest.c ||
echo "restore of quest.c failed"
set `wc -c quest.c`;Wc_c=$1
if test "$Wc_c" != "1945"; then
	echo original size 1945, current size $Wc_c
fi
# ============= script.c ==============
echo "x - extracting script.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > script.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
Xchar portin();
X
X_doscript(filename)
X     char *filename;
X{
X  FILE *fp;
X  char s[LINE_SIZE];
X  if ((fp=fopen(filename,"r"))==NULL) return (1);
X  while (!feof(fp))
X    {
X      s[0]=0;
X      fscanf(fp,"%[^\n\004]",s);
X      fgetc(fp); /* get the newline character */
X      run_line(s);
X    }
X  fclose(fp);
X}
X
X/*
X  for now, all doscript does is read commands from a file and
X  execute them
X*/
Xdoscript(argc,argv)
X     int argc;
X     char **argv;
X{
X  extern char *optarg;
X  extern int optind;
X  char silent,flag;
X  int err;
X  int i;
X  silent=0;echo_mode=0;
X  doing_source=1;
X  optind=1;
X  while ((i=getopt(argc,argv, "se")) != EOF)
X	{
X	switch (i)
X		{/* silent -> don't display error if file doens't exist */
X		case 's': 
X		  silent=1;
X		  break;
X		case 'e': /* echo */
X		  echo_mode=1;
X		  break;
X		default:
X		  break;
X		} /* end case */
X	}
X  i=1;err=0;
X  while (i<argc && argv[i]!=NULL)
X    {
X      if (argv[i][0]!='-')
X	{
X	  err=_doscript(argv[i]);
X	  if (err && !silent)
X	    sprintf(buf,"Error reading script file:%s\n",argv[i]);
X	}
X      ++i;
X    }
X  echo_mode=0;
X  doing_source=0;
X}
SHAR_EOF
$TOUCH -am 0507213790 script.c &&
chmod 0644 script.c ||
echo "restore of script.c failed"
set `wc -c script.c`;Wc_c=$1
if test "$Wc_c" != "1155"; then
	echo original size 1155, current size $Wc_c
fi
# ============= mail.c ==============
echo "x - extracting mail.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > mail.c &&
X/*
X  GDX-BBS V1.0 Beta
X  (C) 1990
X  Jay A. Snyder
X*/
X
X#include "inc.h"
X
Xint str_cmp();
Xm_entry_ptr chk_entry();
X
Xchar *mailcmds[]={
X  	"*","chma","delete","headers","help","logout","newscan","next",
X	"prev","quit","reply","send","\377\377"
X	};
X#define MAILCMDCOUNT (int) sizeof(mailcmds)/sizeof(char *)
X
X/*
X  mail file header format:
X
X####TIME
XFrom
XTo
XSubject
X
X  deleted message:
X####~~~~
X
X*/
X
Xchar *timestr();
Xchar *priv_mail_file();
X
X/*
X  mail_header()  put mail header in string s
X*/
Xchar *mail_header(s,to,subject)
X     char *s,*to,*subject;
X{
X  if (subject[0]==0) subject=" ";
X  sprintf(s,"####%lu\nFrom: %s\nTo: %s\nSubject: %s\n",
X	  (long) time(NULL),MYNAME,to,subject);
X  return (s);
X}
X
X
X/*
X  msg_date()  return date of current message
X*/
Xtime_t msg_date(fp)
X     FILE *fp;
X{
X  time_t tm;
X  char s[255];
X  myfgets(s,30,fp);
X  if (!strcmp(s,"~~~~"))
X    {
X      return((time_t) 0); /* deleted message */
X    }
X  tm= (time_t) atol(s);
X  return(tm);
X}
X
X/*
X  read_mail_header()
X*/
X
Xchar read_mail_header(fp,at,from,to,subject,ret_tm)
X     FILE *fp;
X     char *at,*from,*to,*subject;
X     time_t *ret_tm;
X{
X  char s[255],c;
X  time_t tm;
X  if (at!=NULL) at[0]=0;
X  if (from!=NULL) from[0]=0;
X  if (to!=NULL) to[0]=0;
X  if (subject!=NULL) subject[0]=0;
X  myfgets(s,30,fp);
X  if (!strcmp(s,"~~~~"))
X    {
X      return(-1); /* deleted message */
X    }
X  tm= (time_t) atol(s);
X  if (ret_tm!=NULL)
X    *ret_tm=tm;
X  if (at!=NULL)
X    {
X      strcpy(at,ctime(&tm));
X      at[strlen(at)-1]=0;
X    }
X  fscanf(fp,"%[^:\n]",s);
X  c=fgetc(fp);
X  fscanf(fp,"%*[ \t]"); /* skip white space */
X  if (c==':' && !ncstrcmp(s,"from"))
X    {
X      if (from!=NULL)
X	{
X	  myfgets(from,30,fp);
X	}
X      else fgets(s,30,fp); /* skip rest of line */
X    }
X  else /* if no From: there is an error in the mail file */
X    {
X      portsout("\n? Error in mail file.\n");
X      return(-1);
X    }
X  fscanf(fp,"%[^:\n]",s);
X  c=fgetc(fp);
X  fscanf(fp,"%*[ \t]"); /* skip white space */
X  if (c==':' && !ncstrcmp(s,"to"))
X    {
X      if (to!=NULL)
X	{
X	  myfgets(to,159,fp);
X	}
X      else fgets(s,159,fp); /* skip rest of line */
X      fscanf(fp,"%[^:\n]",s);
X      c=fgetc(fp);
X      fscanf(fp,"%*[ \t]"); /* skip white space */
X    }
X  if (c==':' && !ncstrcmp(s,"subject"))
X    {
X      if (subject!=NULL)
X	{
X	  myfgets(subject,65,fp);
X	}
X      else fgets(s,65,fp); /* skip rest of line */
X    }
X  return(0);
X}
X
X/*
X  disp_msg(fp) --> display mail message
X*/
Xdisp_msg(fp,priv)
X     FILE *fp;
X{
X  char c,q,s[255];
X  char at[30],from[20],to[160],subject[66];
X  time_t tm;
X  int i,page_lines,nopage;
X  q=0;nopage=0;page_lines=5; /* start page_lines at 5 for header */
X  if (feof(fp)) return(EOF);
X  cls();
X  setcolor(YELLOW,BLACK);boldoff();
X  rprintf("Message #%d",cur_msg+1);
X  if (read_mail_header(fp,at,from,to,subject,&tm))
X    {
X      portsout("\n[deleted message]\n");
X      return(0);
X    }
X  if (tm > *mdate)
X    *mdate = tm;
X  setcolor(YELLOW,BLACK);boldoff();
X  portsout("\nAt: ");
X  setcolor(WHITE,BLACK);boldon();
X  portsout(at);
X  setcolor(YELLOW,BLACK);boldoff();
X  portsout("\nFrom: ");
X  setcolor(WHITE,BLACK);boldon();
X  portsout(from);
X  setcolor(YELLOW,BLACK);boldoff();
X  portsout("\nTo: ");
X  setcolor(WHITE,BLACK);boldon();
X  portsout(to);
X  setcolor(YELLOW,BLACK);boldoff();
X  portsout("\nSubject: ");
X  setcolor(WHITE,BLACK);boldon();
X  portsout(subject);
X  portsout("\n\r");
X  setcolor(LTGREEN,BLACK);boldoff();
X  while (!feof(fp) && !q && !ctrlc())
X    {
X      s[0]=0;
X      fscanf(fp,"%[^#\n]",s);
X      if (fgetc(fp)=='#')
X	{
X	  if (fgetc(fp)=='#')
X	    {
X	      if (fgetc(fp)=='#')
X		{
X		  if (fgetc(fp)=='#')
X		    {
X		      q=1;
X		      break;
X		    }
X		}
X	    }
X	}
X      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':  nopage=1;
X	    }
X	}
X    }
Xif (!nopage && pagemode && ++page_lines>LI-8)
X  {
X    atout("@reverse( End of File -- Press any key to continue.)");
X    portin();
X    portsout("\r                                               \r");
X  }
X  return(0);
X}
X
X
X/*
X  chk_del_perm() --> check if user has permission to delete message
X*/
Xchk_del_perm(fp,msgnum)
X     FILE *fp;
X     int msgnum;
X{
X  char to[160], from[160];
X  if (sysop) return(1);
X  fseek(fp,msg_ptrs[msgnum],SEEK_SET);
X  read_mail_header(fp,(char *) NULL,from,to,(char *) NULL,(time_t *)NULL);
X  if (!ncstrcmp(from,MYNAME))
X    return(1);
X  if (!ncstrcmp(to,MYNAME))
X    return(1);
X  return(0);
X}
X
X/*
X  delmarkmsg()  mark message for deletion
X*/
Xdelmarkmsg(fp,msgnum)
X     FILE *fp;
X     int msgnum;
X{
X  if (msgnum<0 || msgnum>=msg_count) return(-1);
X  fseek(fp,msg_ptrs[msgnum],SEEK_SET);
X  fputs("~~~~\n",fp);
X  return(0);
X}
X
X/*
X  mail_seek(fp,inc) --> seek "####" header in file
X*/
Xmail_seek(fp,inc)
X     FILE *fp;
X     int inc;
X{
X  char c,x,q;
X  long int fpos;
X  q=0;
X  fpos=(long int) ftell(fp);
X  if (inc>0)
X    {
X      while ((inc>0) && !q && !feof(fp))
X	{
X	  --inc;
X          x=0;
X	  while (!q && !x && !feof(fp))
X	    {
X	      c=0;
X	      while(!feof(fp) && c!='#')
X		{
X		  c=fgetc(fp);
X		}
X	      if (fgetc(fp)=='#' && fgetc(fp)=='#' && fgetc(fp)=='#') x=1;
X	    }
X	}
X      if (feof(fp))
X	{
X	  fseek(fp,fpos,SEEK_SET);
X	  return(EOF);
X	}
X    }
Xreturn(0);
X}
X
X/*
X  print_headers()
X*/
Xprint_headers(fp,priv,tm)
X     FILE *fp;int priv;
X     time_t tm;
X{
X  char s[80],c,nopage;
X  int page_lines,i,count;
X  page_lines=0;nopage=0;count=0;
X  for (i=0;i<msg_count;++i)
X    {
X      if (ctrlc()) return(1);
X      fseek(fp,msg_ptrs[i],SEEK_SET);
X      if (!print_mail_header(fp,i+1,priv,tm))
X	{
X	  ++count;
X	  ++page_lines;
X	  if (!nopage && pagemode && ++page_lines>LI-8)
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		  i=msg_count;
X		  break;
X		case 's':  nopage=1;
X		}
X	    }
X	}
X    }
X  rprintf("%d Messages\n\n",count);
X}
X
X/*
X  if priv_mail=1 then the mail to name is not displayed (no need,
X  the user is just reading his own mail)
X*/
Xprint_mail_header(fp,num,priv_mail,ttm)
X     FILE *fp;
X     int priv_mail,num;
X     time_t ttm;
X{
X  char ss[80];
X  int x;
X  char from[20],to[160],subject[66],dt[30];
X  time_t tm;
X  if (read_mail_header(fp,dt,from,to,subject,&tm))
X      return(-1);
X  if (tm<=ttm) return(0);
X  if (strlen(to)>20) {to[20]=0;}
X  x=strlen(from)+strlen(dt)+4;
X  if (!priv_mail) x=x+strlen(to);
X  if (strlen(subject)>66-x)
X    {
X      subject[66-x-3]=0;
X      strcat(subject,"...");
X    }
X  if (num<0)
X    rprintf("%s From:%s To:%s \042%s\042\n",dt,from,to,subject);
X  else if (priv_mail)
X    rprintf("%3d %s From:%s \042%s\042\n",num,dt,from,subject);
X  else
X    rprintf("%3d %s From:%s To:%s \042%s\042\n",num,dt,from,to,subject);
X  return(0);
X}
X
X/* 
X  reply to message currently pointed to by file pointer
X  send NULL for area if private mail
X*/
Xreplymail(fp,msg_area)
X     FILE *fp;
X     AREA *msg_area;
X{
X  char s[255], subject[66], from[20];
X  long int pos;
X  pos=ftell(fp);
X  strcpy(subject,"Re:  ");
X  read_mail_header(fp,(char *) NULL,from,(char *) NULL,&subject[4],(time_t *)NULL);
X  fseek(fp,pos,SEEK_SET);
X  if (msg_area==NULL)
X    sprintf(s,"mail -s -S\"%s\" %s",subject,from);
X  else
X    sprintf(s,"mail -s -S\"%s\" -a\"%s\" %s",subject,msg_area->name,from);
Xif (debug)
X  {
X    printf("%s\n",s);
X    pause();
X  }
X  run_line(s);
X}
X
X/*
X  mail -s user.... --> send private mail to users
X  mail -s -p user... --> send public mail to users in current area
X  mail -s -aAREA user.... --> send public mail to users in area specified
X     -Ssubject --> specify subject
X*/
Xsendmail(argc,argv)
X     int argc;
X     char **argv;
X{
X  extern char *optarg;
X  extern int optind;
X  FILE *fp;
X  char priv_mail,s[80],q,input[80],send_list[160],subject[66],marea[80];
X  AREA *msg_area;
X  char filename[40];
X  int i,ii;
X  optind=1;
X  priv_mail=1;
X  subject[0]=0;
X  msg_area=NULL; /* set for private mail */
X  while ((i=getopt(argc,argv,"S:spa:"))!=EOF)
X    {
X      switch (i)
X	{
X	case 'S': /* subject */
X	  strcpy(subject,optarg);
X	  stripquote(subject);
X	  break;
X	case 's': /* send mail */
X	  break;
SHAR_EOF
echo "End of gdxbbs part 2"
echo "File mail.c is continued in part 3"
echo "3" > @shar_seq_.tmp
exit 0