ftp.nice.ch/pub/next/unix/communication/ft_bbs.1.0.s.tar.gz#/ft_bbs-1.0/userrw.c

This is userrw.c in view mode; [Download] [Up]

/* $Id: userrw.c,v 1.2 1995/12/19 19:30:47 eilts Exp eilts $ */
#include "bbs.h"

boolean userlogin(confrecordtyp *confrecord, const char *uname)
{
  int n;
  boolean ok = FALSE;
  char path[PATH_MAX+1], username[S_STRLEN+1];
  FILE *fp;

  if (buildhelppath(path,"login",sprachensuffix[confrecord->userrecord.lang],
                    confrecord) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","userlogin",
		 "path to login too long");
    return(-1);
  }
  if ((fp=fopen(path,"r")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","userlogin",
             "cannot fopen %s: %m", path);
    return(-1);
  }
  while (fgets(path,PATH_MAX,fp) != NULL) {
    fputs(path,stdout);
  }
  fclose(fp);  
  
  n = 1;
  do {
    if (*uname == '\0' || n > 1) {
      printf("Login: ");
      fgets(username,S_STRLEN,stdin);
      username[strlen(username)-1] = '\0';
    }
    else {
      strmaxcpy(username,uname,S_STRLEN);
    }
    if (*username == '\0')  strcpy(username,NOUSER);
    
    if (getuserrecord(&(confrecord->userrecord),username,confrecord)) {
      if (*(confrecord->userrecord.passwd) == '\0') {
	ok = TRUE;
      }
      else {
        if (strncmp(confrecord->userrecord.passwd,
	    CRYPTFUNC(getpass("Password: "),confrecord->userrecord.passwd),
	    PASSCRYPTED_LEN)==0) {
          ok = TRUE;
	}
      }
    }
    if (! ok) {
      bbslog(LOG_FILE,confrecord,"Login try %i: %s\n",n,username);
    }
    n++;
  } while (n<=confrecord->maxtries && !ok);
  if (!ok) {
    return FALSE;
  }
  else {
    return TRUE;
  }
}


int usergreeting(confrecordtyp *confrecord)
{
  int n;
  char buf[PATH_MAX+1], termstr[S_STRLEN+1], c;
  FILE *fp;
  struct termios save_termios;
  ttystateenum ttystate = TTY_RESET;
  
  if (buildhelppath(buf,"greeting",sprachensuffix[confrecord->userrecord.lang],confrecord) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","usergreeting",
		 "path to greeting too long");
    return(-1);
  }
  if ((fp=fopen(buf,"r")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","usergreeting",
             "cannot fopen %s: %m", buf);
    return(-1);
  }
  while (fgets(buf,PATH_MAX,fp) != NULL) {
    fputs(buf,stdout);
  }
  fclose(fp);
  
  if (*confrecord->termtable == '\0') {
    printf(msg("usergreeting",0,confrecord->lang),confrecord->userrecord.term);
  }
  else {
    printf(msg("usergreeting",1,confrecord->lang),confrecord->userrecord.term);
  }
  do {
    fflush(stdout);
    if (*confrecord->termtable == '\0') {
      fgets(termstr,S_STRLEN,stdin);
      n = strlen(termstr);
    }
    else {
      tty_cbreak(STDIN_FILENO,&save_termios,&ttystate);
      n = 0;
      do {
        read(STDIN_FILENO,&c,1);
	if (n==0 &&  c=='?') {
          rawshowtermtable(confrecord->termtable,confrecord);
          printf(msg("usergreeting",0,confrecord->lang),
                     confrecord->userrecord.term);
	  fflush(stdout);
	}
        else if (n>0 && (c==BACKSPACE_KEY || c==DELETE_KEY)) {
          printf("\b \b");
	  fflush(stdout);
          n--;
        }
	else {
  	  write(STDOUT_FILENO,&c,1);
          termstr[n++] = c;
	}
      } while (c!=RETURN_KEY && c!=NEWLINE_KEY && n<S_STRLEN);
      tty_reset(STDIN_FILENO,&save_termios,&ttystate);
    }
    termstr[n-1] = '\0';
    if (n > 1 && ! termexists(termstr)) {
      strcpy(buf,termstr);
      lowercases(buf);
      if (termexists(buf)) {
        printf(msg("usergreeting",2,confrecord->lang),buf);
      }
      printf(msg("usergreeting",3,confrecord->lang),termstr);
    }
  } while (n > 1 && ! termexists(termstr));

  if (n > 1) {
    if (strlen(termstr)+100 > PATH_MAX) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","usergreeting",
	       "line too long");
      return(-1);
    }
    sprintf(buf,"%s %d %d",termstr, confrecord->userrecord.lines,
            confrecord->userrecord.columns);
    do_term(buf,&(confrecord->userrecord),confrecord);
  }

  return(n);
}


int rawshowtermtable(const char *termtable, const confrecordtyp *confrecord)
{
  int n;
  int znr = 0;
  char zeile[STRLEN+1], str[S_STRLEN+1], *zp[3];
  FILE *fp;

  if ((fp=fopen(termtable,"r")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","rawshowtermtable",
	      "cannot fopen %s: %m", termtable);
    return(-1);
  }
  putchar('\n');
  while (fgets(zeile,STRLEN,fp) != NULL) {
    zeile[strlen(zeile)-1] = '\0';
    n = splitstring(zp,zeile,'|',2);
    if (n>0 && *zp[0]!='\0' && *zp[0]!='#') {
      if (zp[1] == NULL)  zp[1] = "";
      if (znr > confrecord->userrecord.lines-3) {
	printf(msg("rawshowtermtable",0,confrecord->lang));
	fflush(stdout);
	read(STDIN_FILENO,str,S_STRLEN);
	putchar('\n');
	znr = 0;
      }
      printf("%-12s %s\n",zp[0],zp[1]);
      znr++;
    }
  }
  fclose(fp);
  return 0;
}


char *showmsgline(const char *fmt, ...)
{
  int y, x, k;
  static char buf[STRLEN+1];
  char str[STRLEN+1];
  va_list ap;

  getyx(stdscr,y,x);
  for (k=0; k < COLS; k++) {
    buf[k] = mvinch(LINES-1,k);
  }
  buf[k] = '\0';
  va_start(ap, fmt);
  vsprintf(str,fmt,ap);
  va_end(ap);
  move(LINES-1,0);
  clrtoeol();
  addstr(str);
  refresh();
  move(y,x);
  return buf;
}


void removemsgline(const char *buf)
{
  int y, x;

  getyx(stdscr,y,x);  
  move(LINES-1,0);
  clrtoeol();
  if (buf != NULL)  addstr(buf);
  move(y,x);
  refresh();
  return;
}


int writetouser(const confrecordtyp *confrecord, const char *fmt, ...)
{
  va_list ap;
  char str[MSG_MAX+1];
  
  va_start(ap, fmt);
  vsprintf(str,fmt,ap);
  va_end(ap);
  if (confrecord->curses_on) {
    windowtext(str," BBS: ",0,confrecord);
  }
  else {
    printf("%s",str);
  }
  return 0;
}


#ifdef USE_EDIT
int readfromuser(char str[], const char *defaultstr, const int mlen,
                 const boolean echo, const confrecordtyp *confrecord)
{
  int seq[100], seqanz, n, k, x_p, y_p, x_0, x_off, step, cols, ltag, rtag;
  SIZE_T spos, slen = 0;
  static int p=0, len=0;
  char c, *sp, tgetentbuf[TGETENTBUF];
  const char *term = NULL;
  static char tkbuf[1024], inbuf[INBUFLEN];
  boolean termsequenz;
  static termks termkeys[] = {
    {"kr", NULL, Curright},
    {"kl", NULL, Curleft},
    {"kr", "\006", Curright},
    {"kl", "\002", Curleft},
    {"kr", "\033[C", Curright},
    {"kl", "\033[D", Curleft},
    {"", (char *)0, Nocmd}
  };

  if (term == NULL) {
    term = confrecord->userrecord.term;
    n = tgetent(tgetentbuf,term);
    if (n < 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readfromuser",
               "cannot open terminal database");
      return(-1);
    }
    else if (n == 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readfromuser",
               "%s: unknown terminal type",term);
      return(-1);
    }
    sp = tkbuf;
    for (n=0; *termkeys[n].id; n++) {
      if (termkeys[n].sequenz == NULL) {
        if ((termkeys[n].sequenz=tgetstr(termkeys[n].id,&sp)) == NULL) {
          errormsg(E_LOGFILE,confrecord,"bbs","readfromuser",
                   "%s: not capable of %s",term,termkeys[n].id);
        }
      }
    }
  }

  cols = confrecord->userrecord.columns;
  getyx(stdscr,y_p,x_0);
  ltag = 0;
  rtag = 0;
  x_off = 0;
  if (defaultstr != NULL) {
    strmaxcpy(str,defaultstr,mlen);
    slen = strlen(str);
    step = cols / 2;
    for (n=slen+x_0; n > cols-2; n -= step)  x_off += step;
    if (x_off > 0) {
      ltag = 1;
      addch('<');
    }
    for (k=x_off+ltag; k < slen; k++) {
      addch(str[k]);
    }
  }
  spos = slen;
  getyx(stdscr,y_p,x_p);
  do {
    refresh();
    termsequenz = FALSE;
    for (k=0,seqanz=0; *termkeys[k].id; k++)  {
      if (termkeys[k].sequenz != NULL)  seq[seqanz++] = k;
    }
    n = 0;
    do {
      if (p == len) {
        len = read(STDIN_FILENO,inbuf,INBUFLEN);
        p = 0;
      }
      c = inbuf[p++];
      for (k=0; k<seqanz; k++) {
        if (c != termkeys[seq[k]].sequenz[n]) {
          seq[k] = seq[--seqanz];
          k--;
        }
      }
      if (seqanz == 1) {
        if (termkeys[seq[0]].sequenz[n+1] == '\0')  {
          termsequenz = TRUE;
        }
      }
      else if (seqanz > 0 && ! termsequenz && n == 0 && p == len) {
        len = waitread(STDIN_FILENO,inbuf,INBUFLEN,KEYBOARDIN_SEQ_DELAY);
        p = 0;
        if (len == 0)  seqanz = 0;
      }
    n++;
    } while (! termsequenz && seqanz > 0 && len >= 0);
    
    if (len < 0)  return -1;
    if (termsequenz) {
      switch (termkeys[seq[0]].cmd) {
      case Curleft:
        if (spos > 0) {
          move(y_p,--x_p);
          spos--;
        }
        break;
      case Curright:
        if (spos < slen) {
          move(y_p,++x_p);
          spos++;
        }
        break;
      case Nocmd:
        break;
      }
    }
    else {
      switch (c) {
      case BACKSPACE_KEY:
      case DELETE_KEY:
        if (spos > 0) {
          mvdelch(y_p,--x_p);
          slen--;
          spos--;
          for (k=spos; k<slen; k++)  str[k] = str[k+1];
          k = x_off + cols - x_0 - 1 - rtag;
          if (k < slen) {
            mvaddch(y_p,cols-1-rtag,str[k]);
            if (rtag > 0)  addch('>');
            move(y_p,x_p);
          }
         }
        break;
      case LINE_START:
        x_p -= spos;
        move(y_p,x_p);
        spos = 0;
        break;
      case LINE_END:
        x_p += slen - spos;
        move(y_p,x_p);
        spos = slen;
        break;
      case KILL_LINE:
        clrtoeol();
        slen = spos;
        break;
      case  RETURN_KEY:
      case  NEWLINE_KEY:
        break;
      case  ESCAPE_KEY:
        slen = 0;
        break;
      default:
        if (slen >= mlen)  break;
        if (echo) {
          insch(c);
        }
        else {
          insch(' ');
        }
        if (rtag > 0)  mvaddch(y_p,cols-1,'>');
        move(y_p,++x_p);
        for (k=slen; k>spos; k--)  str[k] = str[k-1];
        str[spos++] = c;
        slen++;
      }
    }
    if (x_p > cols - 2) {
      step = cols / 2;
    }
    else if (x_off > 0 && x_p < x_0+2) {
      step = -cols / 2;
    }
    else {
      step = 0;
    }
    if (step != 0) {
      x_off += step;
      move(y_p,x_0);
      clrtoeol();
      if (x_off > 0) {
        ltag = 1;
        addch('<');
      }
      else {
        ltag = 0;
      }
      if (slen > x_off+cols-x_0) {
        rtag = 1;
        mvaddch(y_p,cols-1,'>');
        move(y_p,x_0+ltag);
      }
      else {
        rtag = 0;
      }
      for (k=x_off+ltag; k < slen && k < x_off+cols-x_0-rtag; k++) {
        addch(str[k]);
      }
      x_p -= step;
      move(y_p,x_p);
    }
  } while (c !=  RETURN_KEY && c != NEWLINE_KEY && c != ESCAPE_KEY);
  str[slen] = '\0';
  return(slen);
}

#else

int readfromuser(char str[], const char *defaultstr, const int mlen,
                 const boolean echo, const confrecordtyp *confrecord)
{
  int k = 0;
  int n, p;
  SIZE_T nchars;
  char c, junkbuf[10];

  if (defaultstr != NULL) {
    strmaxcpy(str,defaultstr,mlen);
    k = strlen(str);
    addstr(str);
  }
  do {
    refresh();
    c = bbsgetch(TRUE);
    if (c == ESCAPE_KEY) {
/*
#if defined(FIONREAD) && ! defined (NO_TV_USEC)
      usleep(200000);
      if (ioctl(STDIN_FILENO,FIONREAD,&nchars) >= 0) {
        if (nchars > 0) {
          read(STDIN_FILENO,junkbuf,10);
	  continue;          
        }
      }
      if (c == ESCAPE_KEY) {
        str[0] = '\0';
        return(0);
      }
#else
*/
      str[0] = '\0';
      return(0);
/*
#endif
*/
    }
    if (k>0 && (c==BACKSPACE_KEY || c==DELETE_KEY)) {
      getyx(stdscr,n,p);
      mvdelch(n,--p);
      k--;
    }
    else {
      if (echo) {
        addch(c);
      }
      else {
        addch(' ');
      }
      str[k++] = c;
    }
  } while (c!=RETURN_KEY && c!=NEWLINE_KEY && k<mlen);
  if (c==RETURN_KEY || c==NEWLINE_KEY)  k--;    
  str[k] = '\0';
  return(k);
}
#endif


#ifdef USE_EDIT
char bbsgetch(const boolean no_escapesequenz)
{
  static int p=0, len=0;
  static char inbuf[100];
  char c;
  
  do {
    if (p == len) {
      len = read(STDIN_FILENO,inbuf,100);
      p = 0;
    }
    c = inbuf[p++];
    if (c == ESCAPE_KEY && no_escapesequenz && p == len) {
      len = waitread(STDIN_FILENO,inbuf,100,KEYBOARDIN_SEQ_DELAY);
      p = 0;
    }
  } while (c == ESCAPE_KEY && len > 0);
  return c;
}

#else

char bbsgetch(const boolean no_escapesequenz)
{
  static int p=0, len=0;
  static char inbuf[100];
  
  if (p == len) {
    len = read(STDIN_FILENO,inbuf,100);
    p = 0;
  }
  return inbuf[p++];
}
#endif


#ifndef NO_TV_USEC
char waitonkeypress(boolean minwait)
{
  char c;
  double t;

  if (minwait) {
    t = microtime();
    do {
      c = bbsgetch(TRUE);
    } while(microtime()-t < KEYTIME);
  }
  else {
    c = bbsgetch(TRUE);
  }
  return(c);
}
#else
char waitonkeypress(boolean minwait)
{
  return bbsgetch(TRUE);
}
#endif


char getkeyonprompt(const char *prompt, const char *keyset,
                    const boolean maptoupper, const boolean autozmodem,
		    const char *helpcontext, const confrecordtyp *confrecord)
{
  int errs = 0;
  char key;
  const char *cp='\0', bell=BELL_KEY;
#ifndef NO_TV_USEC
  boolean zmodem;
#endif

  move(LINES-1,0);
  clrtoeol();
  standout();
  addstr(prompt);
  standend();
  do {
    refresh();
    do {
#ifndef NO_TV_USEC
      if (autozmodem && confrecord->userrecord.autozmodem &&
          confrecord->userrecord.protokoll == ZMODEMPROTO) {
        key = autoz_getch_c(&zmodem,TRUE);
        if (zmodem) {
          bbslog(LOG_FILE,confrecord,"AutoZmodem");
          return(AUTOZDETECTED);
        }
      }
      else {
        key =  waitonkeypress(TRUE);
      }
#else
      key =  waitonkeypress(TRUE);
#endif
      if (maptoupper && islower(key)) key = toupper(key);
      if (key == CHELP_KEY) {
        writehelptouser(helpcontext,confrecord);
      }
    } while (key == CHELP_KEY);
    if (*keyset != '\0') {
      for (cp=keyset; key!=*cp && *cp!='\0'; cp++) ;
    }
    if (errs > 2) {
      move(LINES-1,0);
      clrtoeol();
      standout();
      if (helpcontext==NULL || *helpcontext=='\0') {
        addstr(msg("getkeyonprompt",0,confrecord->userrecord.lang));
      }
      else {
        addstr(msg("getkeyonprompt",1,confrecord->userrecord.lang));
      }
      standend();
      errs = 0;
    }
    if (*keyset != '\0' && key != *cp && key != ESCAPE_KEY) {
      if (key == RETURN_KEY || key == NEWLINE_KEY)  touchwin(stdscr);
      writen(STDERR_FILENO,(void *)&bell,(SIZE_T)sizeof(char));
      errs++;
    }
  } while (*keyset != '\0' && key != *cp && key != ESCAPE_KEY);
/*
  invertpromptkeys(prompt);
  move(LINES-1,COLS-1);
  refresh();
*/
  return key;
}


void invertpromptkeys(const char *prompt)
{
  int k;
  const char *sp;

  for (k=0,sp=prompt; *sp; k++,sp++) {
    if (*sp == '[') {
      move(LINES-1,k);
      do {
        k++;
        addch(*sp++);
      } while (*sp && *sp != ']');
    }
  }
}


int pagerstep(const char key)
{
  switch (key) {
  case BACKSPACE_KEY:
  case DELETE_KEY:
    return(-2);
    break;
  case SPACE_KEY:
    return(2);
    break;
  }
  return(0);
}


int pagerquit(const char key)
{
  switch (key) {
  case QUIT_KEY:
  case QUIT_L_KEY:
    return(1);
    break;
  case ESCAPE_KEY:
    return(-1);
    break;
  }
  return(0);
}


#ifndef NO_TV_USEC
char autoz_getch_c(boolean *zmodem, const boolean scan)
{
  double t1, t2;
  static const char zmsig[] = "**\030B00";
  static const char *pcp, *cp;
  static char c;
  static boolean playback = FALSE;
  
  if (playback) {
    if (pcp != cp) {
      return(*pcp++);
    }
    else {
      playback = FALSE;
      return(c);
    }
  }
  
  if (scan) {
    *zmodem = FALSE;
    t2 = microtime();

    do {
      t1 = t2;
      c = bbsgetch(TRUE);
      t2 = microtime();
    } while ((c != *zmsig) && (t2-t1<KEYTIME));
    if (c != *zmsig) return c;
    cp = zmsig;
    cp++;
    c = bbsgetch(FALSE);
    while (c == *cp) {
      if (*++cp == '\0') break;
      c = bbsgetch(FALSE);
    }
    if (*cp == '\0') {
      *zmodem = TRUE;
      return(c);
    }
    else {
      playback = TRUE;
      pcp = zmsig;
      return(*pcp++);
    }
  }

  return bbsgetch(TRUE);
}
#endif


int tty_cbreak(int fd, struct termios *save_termios, ttystateenum *ttystate)
{
  struct termios buf;
  
  if (tcgetattr(fd, save_termios) < 0) {
    return -1;
  }
  buf = *save_termios;
  buf.c_lflag &= ~(ECHO | ICANON);
  buf.c_cc[VMIN] = 1;
  buf.c_cc[VTIME] = 0;
  if (tcsetattr(fd, TCSAFLUSH, &buf) < 0) {
    return -1;
  }
  *ttystate = TTY_RAW;
  return 0;
}


int tty_raw(int fd, struct termios *save_termios, ttystateenum *ttystate)
{
  struct termios buf;

  if (tcgetattr(fd, save_termios) < 0) {
    return -1;
  }
  buf = *save_termios;
  buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
  buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
  buf.c_cflag &= ~(CSIZE | PARENB);
  buf.c_cflag |= CS8;
  buf.c_oflag &= ~(OPOST);
  buf.c_cc[VMIN] = 1;
  buf.c_cc[VTIME] = 0;
  if (tcsetattr(fd, TCSAFLUSH, &buf) < 0) {
    return -1;
  }
  *ttystate = TTY_RAW;
  return 0;
}


int tty_reset(int fd, struct termios *save_termios, ttystateenum *ttystate)
{
  if (*ttystate != TTY_CBREAK && *ttystate != TTY_RAW) {
    return 0;
  }
  if (tcsetattr(fd, TCSAFLUSH, save_termios) < 0) {
    return -1;
  }
  *ttystate = TTY_RESET;
  return 0;
}


void linerecodeout(const char *cp, const char *mmp, OFF_T stsize,
                   const char cascii, const SIZE_T mlen)
{
  SIZE_T k, len = 0;
  char str[3];

  while (*cp!='\n' && len<mlen && (OFF_T)(cp-mmp)<stsize) {
    if (*cp=='\r' && *(cp+sizeof(char))=='\n') {
      cp++;
    }
    else {
      recode(str,*cp,cascii);
      k = strlen(str);
      if (k == 1) {
        addch(*str);
      }
      else {
        addstr(str);
      }
      len += k;
      cp++;
    }
  }
  if (len < mlen)  addch('\n');
}


void writehelptouser(const char *helpcontext, const confrecordtyp *confrecord)
{
  int lang;

  if (helpcontext == NULL)  return;
  lang = confrecord->userrecord.lang;
  if (*helpcontext == '\0') {
    writetouser(confrecord,msg("writehelptouser",0,lang));
  }
  else if (strcmp(helpcontext,"dir") == 0) {
    writetouser(confrecord,msg("writehelptouser",2,lang));
  }
  else if (strcmp(helpcontext,"cd") == 0) {
    writetouser(confrecord,msg("writehelptouser",3,lang));
  }
  else if (strcmp(helpcontext,"show") == 0) {
    writetouser(confrecord,msg("writehelptouser",4,lang));
  }
  else if (strcmp(helpcontext,"get") == 0) {
    writetouser(confrecord,msg("writehelptouser",5,lang));
  }
  else if (strcmp(helpcontext,"lang") == 0) {
    writetouser(confrecord,msg("writehelptouser",6,lang));
  }
  else if (strcmp(helpcontext,"proto") == 0) {
    writetouser(confrecord,msg("writehelptouser",7,lang));
  }
  else if (strcmp(helpcontext,"autoz") == 0) {
    writetouser(confrecord,msg("writehelptouser",8,lang));
  }
  else if (strcmp(helpcontext,"dironcd") == 0) {
    writetouser(confrecord,msg("writehelptouser",9,lang));
  }
  else if (strcmp(helpcontext,"talk") == 0) {
    writetouser(confrecord,msg("writehelptouser",10,lang));
  }
  else if (strcmp(helpcontext,"selectterm") == 0) {
    writetouser(confrecord,msg("writehelptouser",11,lang));
  }
  else if (strcmp(helpcontext,"sendmessage") == 0) {
    writetouser(confrecord,msg("writehelptouser",12,lang));
  }
  else if (strcmp(helpcontext,"msgbrowser_select") == 0) {
    writetouser(confrecord,msg("writehelptouser",13,lang));
  }
  else if (strcmp(helpcontext,"msgbrowser_menu") == 0) {
    writetouser(confrecord,msg("writehelptouser",14,lang));
  }
  else if (strcmp(helpcontext,"newsbrowser_grpselect") == 0) {
    writetouser(confrecord,msg("writehelptouser",15,lang));
  }
  else if (strcmp(helpcontext,"newsbrowser_artselect") == 0) {
    writetouser(confrecord,msg("writehelptouser",16,lang));
  }
  else if (strcmp(helpcontext,"newsbrowser_doselect") == 0) {
    writetouser(confrecord,msg("writehelptouser",17,lang));
  }
  else if (strcmp(helpcontext,"newsbrowser_subscribe") == 0) {
    writetouser(confrecord,msg("writehelptouser",18,lang));
  }
  else if (strcmp(helpcontext,"subscribenewsgroups") == 0) {
    writetouser(confrecord,msg("writehelptouser",19,lang));
  }
  else if (strcmp(helpcontext,"charset") == 0) {
    writetouser(confrecord,msg("writehelptouser",20,lang));
  }
  else {
    writetouser(confrecord,msg("writehelptouser",1,lang));
  }
  return;  
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.