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

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

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

#ifdef NNTPNEWS
int dgetnewsrc(const int sockd, const confrecordtyp *confrecord)
{
  int rw=0;
  SIZE_T len;
  char newsrc[PATH_MAX+1], str[S_STRLEN+1];
  FILE *fp;
  boolean no_newsrc = FALSE;
  struct stat stats;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)str,len,0);
  sprintf(newsrc,"%s/%s.newsrc",confrecord->maildir,str);
  if (stat(newsrc,&stats) < 0) {
    if (errno != ENOENT) {
      bgerror("dgetnewsrc","stat %s: %m",newsrc);
      rw = -1;
    }
    no_newsrc = TRUE;
  }
  if (no_newsrc || stats.st_size == 0) {
    len = 0;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    return rw;
  }

  if ((fp=fopen(newsrc,"r")) == NULL) {
    bgerror("dgetnewsrc","fopen newsrc file %s: %m", newsrc);
    rw = -1;
  }
  else {
    while (fgetnln(str,S_STRLEN,fp) >= 0) {
      len = strlen(str) + 1;
      sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
      sendn(sockd,(void *)str,len,0);
    }
  }
  len = 0;
  sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
  return rw;
}


int dsavenewsrc(const int sockd, const confrecordtyp *confrecord)
{
  int rw=0;
  SIZE_T len;
  char newsrc[PATH_MAX+1], scratch[PATH_MAX+1], str[S_STRLEN+1];
  FILE *sfp;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)str,len,0);
  scratchfilename(scratch,"dsnewsrc-",str,confrecord->scratchdir);
  sprintf(newsrc,"%s/%s.newsrc",confrecord->maildir,str);
  unlink(scratch);
  if ((sfp=fopen(scratch,"w")) == NULL) {
    bgerror("dsavenewsrc","fopen scratchfile %s: %m", scratch);
    sfp = fopen("/dev/null","w");
    rw = -1;
  }
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  while (len > 0) {
    recvn(sockd,(void *)str,len,0);
    fputs(str,sfp);
    putc('\n',sfp);
    recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  }
  fclose(sfp);
  if (len != 0)  rw = -1;
  if (rw == 0) {
    if ((rw=rename(scratch,newsrc)) < 0) {
      bgerror("dsavenewsrc","rename %s -> %s: %m",scratch,newsrc);
    }
    chmod(newsrc,0600);
  }
  return rw;
}


int dgetallnewsgroups(const int sockd, const bbsddbtyp *bbsddb,
                      const confrecordtyp *confrecord)
{
  int mask;
  SIZE_T len, c_len;
  char group[S_STRLEN+1], count[S_STRLEN+1], str[2*S_STRLEN+4];
  
  recvn(sockd,(void *)&mask,(SIZE_T)sizeof(int),0);
  while (getkeysbbsddb(bbsddb,NEWSGROUPS_DB,group,&len,count,&c_len,
                       confrecord) == 0) {
    if ((mask & GROUPNAME_MASK) && (mask & GROUPCOUNT_MASK)) {
      sprintf(str,"%s %s",group,count);
    }
    else if (mask & GROUPNAME_MASK) {
      strcpy(str,group);
    }
    else if (mask & GROUPCOUNT_MASK) {
      strcpy(str,count);
    }
    else {
      *str = '\0';
    }
    len = strlen(str) + 1;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    sendn(sockd,(void *)str,len,0);
  }
  len = 0;
  sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
  
  return(0);
}


int dcheckgroup(const int sockd, const bbsddbtyp *bbsddb,
                const confrecordtyp *confrecord)
{
  int n;
  SIZE_T len;
  char group[S_STRLEN+1];
  boolean grp_exists = FALSE;

  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)group,len,0);
  n = lookupbbsddb(bbsddb,group,0,NEWSGROUPS_DB,NULL,&len,confrecord);
  if (n == 0) {
    grp_exists = TRUE;
  }
  else if (n > 0)  n = 0;
  sendn(sockd,(void *)&grp_exists,sizeof(boolean),0);
  return n;
}
#endif


int dlistmessages(const int sockd, const confrecordtyp *confrecord)
{
  int rw=0;
  SIZE_T len;
  char mbox[PATH_MAX+1], str[STRLEN+1], hdrlines[3*STRLEN+4], *hdrbuf;
  FILE *fp;
  boolean no_mbox = FALSE;
  mailheadertyp mailhdr;
  struct stat stats;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)str,len,0);
  sprintf(mbox,"%s/%s",confrecord->maildir,str);
  if (stat(mbox,&stats) < 0) {
    if (errno != ENOENT) {
      bgerror("dlistmessages","stat %s: %m",mbox);
      rw = -1;
    }
    no_mbox = TRUE;
  }
  if (no_mbox || stats.st_size == 0) {
    len = 0;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    return rw;
  }

  if ((fp=fopen(mbox,"r")) == NULL) {
    bgerror("dlistmessages","fopen mailbox %s: %m", mbox);
    rw = -1;
  }
  else {
    fgetnln(str,6,fp);
    do {
      if (testmailbegin(str) &&
          (hdrbuf=parsemailheader(&mailhdr,fp,confrecord)) != NULL) {
        if (strlen(mailhdr.from) + strlen(mailhdr.subject) +
            strlen(mailhdr.msg_id) < 3*STRLEN) {
  	  sprintf(hdrlines,"%s\n%s\n%s",mailhdr.from,mailhdr.subject,
                  mailhdr.msg_id);
        }
        else {
          strcpy(hdrlines,"");
        }
        len = strlen(hdrlines) + 1;
	sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
	sendn(sockd,(void *)hdrlines,len,0);
        free(hdrbuf);
      }
    } while(fgetnln(str,6,fp) >= 0);
    fclose(fp);
  }
  len = 0;
  sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
  return rw;
}


int dremovemessage(const int sockd, const confrecordtyp *confrecord)
{
  int k, nr, rw=0;
  char mbox[PATH_MAX+1], scratch[PATH_MAX+1], sstr[6], zeile[STRLEN+1],
       msg_id[STRLEN+1];
  char *hdrbuf = NULL;
  SIZE_T len;
  boolean found = FALSE;
  FILE *fp, *sfp;
  mailheadertyp mailhdr;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)zeile,len,0);
  sprintf(mbox,"%s/%s",confrecord->maildir,zeile);
  recvn(sockd,(void *)&nr,sizeof(int),0);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)msg_id,len,0);
  if ((fp=fopen(mbox,"r")) == NULL) {
    bgerror("dremovemessage","fopen mailbox %s: %m", mbox);
    return -1;
  }
  scratchfilename(scratch,zeile,NULL,confrecord->maildir);
  if ((sfp=fopen(scratch,"w")) == NULL) {
    bgerror("dremovemessage","fopen scratchfile %s: %m", scratch);
    fclose(fp);
    return -1;
  }
  k = 0;
  while (fgetnln(zeile,STRLEN,fp) >= 0) {
    strmaxcpy(sstr,zeile,5);
    if (testmailbegin(sstr)) {
      if (k == nr) {
	if ((hdrbuf=parsemailheader(&mailhdr,fp,confrecord)) == NULL) {
	  bgerror("dremovemessage","corrupt mailheader");
	  break;
	}
	if (strcmp(msg_id,mailhdr.msg_id) == 0 || *msg_id == '\0') {
	  found = TRUE;
	}
	else {
	  bgerror("dremovemessage","Mailbox mismatch: Nr. %d != MsgId %s",
		  nr,msg_id);
	}
	if (hdrbuf != NULL)  free(hdrbuf);
	break;
      }
      k++;
    }
    fputs(zeile,sfp);
    putc('\n',sfp);
  }
  if (found) {
    while ((k=fgetnln(zeile,STRLEN,fp)) >= 0) {
      strmaxcpy(sstr,zeile,5);
      if (testmailbegin(sstr))  break;
    }
    if (k >= 0) {
      do {
        fputs(zeile,sfp);
        putc('\n',sfp);
      } while (fgetnln(zeile,STRLEN,fp) >= 0);
    }
  }
  fclose(sfp);
  fclose(fp);
  if (found) {
    rename(scratch,mbox);
    chmod(mbox,0600);
  }
  else {
    unlink(scratch);
    bgerror("dremovemessage","Message Nr. %d not found",nr,msg_id);
    rw = -1;
  }
  return rw;
}


int dgetmessage(const int sockd, const confrecordtyp *confrecord)
{
  int nr, k, rw=0;
  char mbox[PATH_MAX+1], str[STRLEN+1], name[STRLEN+1], msg_id[STRLEN+1];
  char *hdrbuf = NULL;
  SIZE_T len;
  boolean found = FALSE;
  FILE *fp, *sfp;
  mailheadertyp mailhdr;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)name,len,0);
  recvn(sockd,(void *)&nr,sizeof(int),0);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)msg_id,len,0);
  sprintf(mbox,"%s/%s",confrecord->maildir,name);
  if ((fp=fopen(mbox,"r")) == NULL) {
    bgerror("dgetmessage","fopen mailbox %s: %m", mbox);
    len = 0;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    return -1;
  }
  k = 0;
  while (fgetnln(str,STRLEN,fp) >= 0) {
    if (testmailbegin(str)) {
      if (k == nr) {
        if ((hdrbuf=parsemailheader(&mailhdr,fp,confrecord)) == NULL) {
          bgerror("dgetmessage","corrupt mailheader");
	  break;
	}
        if (strcmp(msg_id,mailhdr.msg_id) == 0 || *msg_id == '\0') {
          found = TRUE;
        }
        else {
          bgerror("dgetmessage","Mailbox mismatch: Nr. %d != MsgId %s",
                  nr,msg_id);
        }
	break;
      }
      k++;
    }
  }
  if (found) {
    scratchfilename(mbox,"dgm-",name,confrecord->scratchdir);
    unlink(mbox);
    len = strlen(mbox) + 1;
    if ((sfp=fopen(mbox,"w")) == NULL) {
      bgerror("dgetmessage","fopen scratchfile %s: %m", mbox);
      rw = -1;
    }
    fprintf(sfp,"From: %s\n",mailhdr.from);
    fprintf(sfp,"Subject: %s\n",mailhdr.subject);
    fprintf(sfp,"Date: %s\n",mailhdr.date);
    fprint_mailheaderline(mailhdr.to,"To",sfp);
    if (*mailhdr.cc != '\0') {
      fprint_mailheaderline(mailhdr.to,"Cc",sfp);
    }
    if (*mailhdr.reply_to != '\0')  fprintf(sfp,"Reply_To: %s\n",
                                            mailhdr.reply_to);
    putc('\n',sfp);
    while (fgetnln(str,STRLEN,fp) >= 0 && strncmp(str,"From ",5) != 0) {
      fputs(str,sfp);
      putc('\n',sfp);
    }
    if (sfp != NULL)  fclose(sfp);
    chmod(mbox,0444);
  }
  else {
    len = 0;
    rw = -1;
  }
  fclose(fp);
  sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
  if (len > 0) {
    sendn(sockd,(void *)&mbox,len,0);
  }
  if (hdrbuf != NULL)  free(hdrbuf);
  return rw;
}


int dsendmessage(const int sockd, const bbsddbtyp *bbsddb,
                 const confrecordtyp *confrecord)
{
  int k, n, rw=0;
  char *sp, *splits[MAXARGS+1], mbox[PATH_MAX+1], scratch[PATH_MAX+1],
       name[S_STRLEN+1], realname[S_STRLEN+1], from[2*S_STRLEN+4],
       subject[STRLEN+1], addr[ARG_MAX+1], astr[ARG_MAX+1], msgstr[S_STRLEN+1];
  static char c1 = 'A'-1;
  SIZE_T len;
  SSIZE_T bytes;
  FILE *sfp, *mboxfp;

  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)&from,len,0);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)&addr,len,0);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)&subject,len,0);
  parseaddrline(name,realname,from);
  scratchfilename(scratch,"dsm-",name,confrecord->scratchdir);
  unlink(scratch);
  if ((sfp=fopen(scratch,"w+")) == NULL) {
    bgerror("dsendmessage","fopen scratchfile %s: %m", scratch);
    sfp = fopen("/dev/null","w+");
    rw = -1;
  }
  unlink(scratch);
  sp = gettime();
  fprintf(sfp,"From %s %s\n",name,sp);
  fprintf(sfp,"Date: %s\n",sp);
  fprintf(sfp,"From: %s\n",from);
  fprintf(sfp,"Subject: %s\n",subject);
  strcpy(astr,addr);
  if (fprint_mailheaderline(astr,"To",sfp) < 1) {
    bgerror("dsendmessage","no recipients given");
    rw = -1;
  }
  splitstring(splits,addr,',',MAXARGS);
  gethostname(mbox,PATH_MAX);
  c1++;
  if (c1 > 'Z')  c1 = 'A';
  fprintf(sfp,"Message-Id: <%ld.%c@%s>\n\n",(long)time((TIME_T)0),c1,mbox);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  bytes = 0;
  while (bytes >= 0 && len > 0) {
    bytes = len > PATH_MAX ? PATH_MAX : len;
    bytes = recvn(sockd,(void *)mbox,(SIZE_T)bytes,0);
    for (k=0,sp=mbox; k<bytes; k++,sp++)  putc(*sp,sfp);
    len -= bytes;
  }
  if (bytes < 0)  rw = -1;
  
  for (k=0; splits[k] != NULL; k++) {
    parseaddrline(name,realname,splits[k]);
    if (lookupbbsddb(bbsddb,name,0,USERNAME_DB,NULL,&len,confrecord) > 0) {
      sprintf(msgstr,"Sendmessage: BBS-User %s unknown",name);
      n = (int)strlen(msgstr) + 1;
      sendn(sockd,(void *)&n,sizeof(int),0);
      sendn(sockd,(void *)msgstr,(SIZE_T)n,0);
      continue;
    }
    sprintf(mbox,"%s/%s",confrecord->maildir,name);
    if ((mboxfp=fopen(mbox,"a")) == NULL) {
      bgerror("dsendmessage","fopen mailbox %s: %m", mbox);
      rw = -1;
      n = 1;
      sendn(sockd,(void *)&n,sizeof(int),0);
      continue;
    }
    chmod(mbox,0600);
    rewind(sfp);
    from_quotestream(FALSE,sfp,mboxfp);
    putc('\n',mboxfp);
    putc('\n',mboxfp);
    fclose(mboxfp);
    n = 1;
    sendn(sockd,(void *)&n,sizeof(int),0);
  }
  fclose(sfp);

  return rw;
}


int dreceivemail(const int sockd, const bbsddbtyp *bbsddb,
                 const confrecordtyp *confrecord)
{
  int k, z, rw = 0;
  SIZE_T len;
  SSIZE_T bytes;
  char *sp, recipient[S_STRLEN+1], mbox[PATH_MAX+1], scratch[PATH_MAX+1];
  FILE *sfp, *mboxfp;
  
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  recvn(sockd,(void *)recipient,len,0);
  z = lookupbbsddb(bbsddb,recipient,0,USERNAME_DB,NULL,&len,confrecord);
  sendn(sockd,(void *)&z,sizeof(int),0);
  if (z != 0) {
    bgerror("dreceivemail","recipient %s not found",recipient);
    return -1;
  }

  scratchfilename(scratch,"drecm-",recipient,confrecord->scratchdir);
  unlink(scratch);
  if ((sfp=fopen(scratch,"w+")) == NULL) {
    bgerror("dreceivemail","fopen scratchfile %s: %m", scratch);
    sfp = fopen("/dev/null","w+");
    rw = -1;
  }
  unlink(scratch);
  recvn(sockd,(void *)&len,sizeof(SIZE_T),0);
  bytes = 0;
  while (bytes >= 0 && len > 0) {
    bytes = len > PATH_MAX ? PATH_MAX : len;
    bytes = recvn(sockd,(void *)mbox,(SIZE_T)bytes,0);
    for (k=0,sp=mbox; k<bytes; k++,sp++)  putc(*sp,sfp);
    len -= bytes;
  }
  if (bytes < 0)  rw = -1;

  sprintf(mbox,"%s/%s",confrecord->maildir,recipient);
  if ((mboxfp=fopen(mbox,"a")) == NULL) {
    bgerror("dreceivemail","fopen mailbox %s: %m", mbox);
    mboxfp = fopen("/dev/null","w");
    rw = -1;
  }
  chmod(mbox,0600);
  rewind(sfp);
  from_quotestream(FALSE,sfp,mboxfp);
  putc('\n',mboxfp);
  putc('\n',mboxfp);
  fclose(mboxfp);
  fclose(sfp);
  return rw;
}


int dgetallusernames(const int sockd, const bbsddbtyp *bbsddb,
                     const confrecordtyp *confrecord)
{
  int mask;
  SIZE_T len, r_len;
  char name[S_STRLEN+1], realname[S_STRLEN+1], str[2*S_STRLEN+4];
  
  recvn(sockd,(void *)&mask,(SIZE_T)sizeof(int),0);
  while (getkeysbbsddb(bbsddb,USERNAME_DB,name,&len,realname,&r_len,
                       confrecord) == 0) {
    if (r_len == 0)  *realname = '\0';
    if ((mask & USERNAME_MASK) && (mask & REALNAME_MASK)) {
      sprintf(str,"%s <%s>",realname,name);
    }
    else if (mask & USERNAME_MASK) {
      strcpy(str,name);
    }
    else if (mask & REALNAME_MASK) {
      strcpy(str,realname);
    }
    else {
      *str = '\0';
    }
    len = strlen(str) + 1;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    sendn(sockd,(void *)str,len,0);
  }
  len = 0;
  sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
  
  return(0);
}


int dsendstatustodaemon(sessionrecordtyp sessionrecords[],
                        const confrecordtyp *confrecord, const int sockd)
{
  int n, status;
  PID_T pid, spid;
  
  if (recvn(sockd,(void *)&pid,(SIZE_T)sizeof(PID_T),0)<0 ||
      recvn(sockd,(void *)&status,(SIZE_T)sizeof(int),0)<0 ) {
    bgerror("dsendstatustodaemon","recv: %m");
    return(-1);
  }
  n = -1;
  do {
    n++;
    spid = sessionrecords[n].pid;
  } while (pid!=spid && spid!=0);
  if (spid == 0) {
    bgerror("dsendstatustodaemon","cannot found user %ld",(long)pid);
    return(-1);
  }
  sessionrecords[n].status = status;
  return(0);
}


int diniconnecttouser(sessionrecordtyp sessionrecords[],
                      const confrecordtyp *confrecord, const int sockd)
  /*
  Socket fuer talk einrichten
  Returnwerte: 1, wenn Partner besetzt
               0, wenn Partner frei
	      <0 bei Fehler
  */
{
  PID_T inipid, recpid, pid;
  int n;
  boolean inifound, recfound;
  char path[TALKSOCKNAMELEN+1];

  if (recvn(sockd,(void *)&inipid,(SIZE_T)sizeof(PID_T),0)<0 ||
      recvn(sockd,(void *)&recpid,(SIZE_T)sizeof(PID_T),0)<0 ) {
    bgerror("diniconnecttouser","recv: %m");
    return(-1);
  }

  n = 0;
  inifound = FALSE;
  recfound = FALSE;
  do {
    pid = sessionrecords[n].pid;
    if (pid == inipid) {
      sessionrecords[n].talking_to = recpid;
      inifound = TRUE;
    }
    else if (pid == recpid) {
      if (sessionrecords[n].talking_to > 0) {
	return(1);
      }
      sessionrecords[n].talking_to = inipid;
      recfound = TRUE;
    }
    n++;
  } while (!(inifound && recfound) && pid!=0);
  if (pid == 0) {
    bgerror("diniconnecttouser","cannot found both parties");
    return(-1);
  }
  n = 0;
  sendn(sockd,(void *)&n,(SIZE_T)sizeof(int),0);
  sprintf(path,"talk-%ld-%ld",(long)inipid,(long)recpid);
  sendn(sockd,(void *)path,(SIZE_T)TALKSOCKNAMELEN,0);
  
  return(0);
}


int dabortconnecttouser(sessionrecordtyp sessionrecords[],
                        const confrecordtyp *confrecord, const int sockd)
{
  PID_T inipid, recpid, pid;
  int n;
  boolean inifound, recfound;

  if (recvn(sockd,(void *)&inipid,(SIZE_T)sizeof(PID_T),0)<0 ||
      recvn(sockd,(void *)&recpid,(SIZE_T)sizeof(PID_T),0)<0 ) {
    bgerror("dabortconnecttouser","recv: %m");
    return(-1);
  }
  n = 0;
  inifound = FALSE;
  recfound = FALSE;
  do {
    pid = sessionrecords[n].pid;
    if (pid == inipid) {
      sessionrecords[n].talking_to = 0;
      inifound = TRUE;
    }
    else if (pid == recpid) {
      sessionrecords[n].talking_to = 0;
      recfound = TRUE;
    }
    n++;
  } while (!(inifound && recfound) && pid!=0);
  if (pid == 0) {
    bgerror("dabortconnecttouser","cannot found both parties %ld and %ld",
            (long)inipid,(long)recpid);
    return(-1);
  }  
  return(0);
}



int dremconnecttouser(const sessionrecordtyp sessionrecords[],
                      const confrecordtyp *confrecord, const int sockd)
  /*
  Returnwerte: 1, wenn Partner besetzt
               0, wenn Partner frei
	      <0 bei Fehler
  */
{
  PID_T rempid;
  int n, snr;
  boolean inifound;
  char path[TALKSOCKNAMELEN+1];

  if (recvn(sockd,(void *)&rempid,(SIZE_T)sizeof(PID_T),0) < 0) {
    bgerror("dremconnecttouser","recv: %m");
    return(-1);
  }

  snr = 0;
  inifound = FALSE;
  while (sessionrecords[snr].pid!=0 && !inifound) {
    if (rempid == sessionrecords[snr].talking_to) {
      inifound = TRUE;
    }
    else {
      snr++;
    }    
  }
  if (! inifound) {
    bgerror("dremconnecttouser","cannot found caller %ld",(long)rempid);
    return(-1);
  }
  n = 0;
  sendn(sockd,(void *)&n,(SIZE_T)sizeof(int),0);
  sprintf(path,"talk-%ld-%ld",(long)sessionrecords[snr].pid,(long)rempid);
  sendn(sockd,(void *)path,(SIZE_T)TALKSOCKNAMELEN,0);
  sendn(sockd,(void *)&(sessionrecords[snr]),(SIZE_T)sizeof(sessionrecordtyp),0);
  
  return(0);
}


int dputinlog(const int logfilefd, const int sockd)
  /*
  Logtext vom Client empfangen und in Logfile schreiben
  */
{
  SIZE_T nleft, nanz, n;
  SSIZE_T nread;
  char buf[BUFSIZE];
  
  if (recvn(sockd,(void *)&n,(SIZE_T)sizeof(SIZE_T),0)<0) {
    bgerror("dputinlog","recv: %m");
    return(-1);
  }
  nleft = n;
  while (nleft > 0) {
    nanz = nleft > BUFSIZE ? BUFSIZE : nleft;
    if ((nread=recvn(sockd,(void *)buf,nanz,0)) < 0) {
      return(-1);
    }
    if ((nread=writen(logfilefd,(void *)buf,(SIZE_T)nread)) < 0) {
      return(-1);
    }
    nleft -= (SIZE_T)nread;
  }
  return (int)n;
}


int dgetsessions(sessionrecordtyp sessionrecords[], const int sockd)
  /*
  Clients auf Existenz pruefen und sessionrecords senden
  */
{
  int k, n;
  
  n = rmdeadsessions(sessionrecords);
  for (k=0; k<n; k++) {
    sendn(sockd,(void *)&(sessionrecords[k]),(SIZE_T)sizeof(sessionrecordtyp),0);
  }
  sendn(sockd,(void *)&(sessionrecords[n]),(SIZE_T)sizeof(sessionrecordtyp),0);
  return n;
}


int daddsession(sessionrecordtyp sessionrecords[], const int sockd)
  /*
  sessionrecord vom Client empfangen und in sessionrecords speichern
  */
{
  int k=0;
  sessionrecordtyp sr;

  if (recvn(sockd,(void *)&sr,(SIZE_T)sizeof(sessionrecordtyp),0) !=
          (SSIZE_T)sizeof(sessionrecordtyp)) {
    bgerror("daddsession","recv: %m");
    return -1;
  }
  while (sessionrecords[k].pid!=0) {
    k++;
  }
  cpysr(&(sessionrecords[k]), &sr);
  sessionrecords[k].talking_to = 0;
  sessionrecords[++k].pid = 0;
  return 0;
}


int dremovesession(sessionrecordtyp sessionrecords[], const int sockd)
  /*
  Pid vom Client empfangen und zugehoerige session entfernen
  */
{
  PID_T pid;
  int k=0;
  
  if (recvn(sockd,(void *)&pid,(SIZE_T)sizeof(PID_T),0) !=
          (SSIZE_T)sizeof(PID_T)) {
    bgerror("dremovesession","recv: %m");
    return -1;
  }
  while (sessionrecords[k].pid!=pid && sessionrecords[k].pid!=0) {
    k++;
  }
  while (sessionrecords[k].pid!=0) {
    cpysr(&(sessionrecords[k]), &(sessionrecords[k+1]));
    k++;
  }
  return 0;
}


int dgetuserrecord(const int sockd, const confrecordtyp *confrecord)
  /*
  Usernamen vom Client empfangen, dazugehoerigen Record aus dem Userfile
  lesen und an den Client senden.
  Wird kein passender Userrecord gefunden, so wird 1 zuruckgegeben und
  userrecord.user==NOUSER
  */
{
  int g=1, znr=1, z=2;
  char zeile[PATH_MAX+S_STRLEN+1], username[S_STRLEN+1], *key, *arg;
  userrecordtyp userrecord;
  FILE *fd;
  
  /* Defaultwerte */
  strcpy(userrecord.name,NOUSER);
  strcpy(userrecord.passwd,NOPASSWORD);
  strcpy(userrecord.realname,"");
  userrecord.loglevel = DEFLOGLEVEL;
  userrecord.seclevel = HIGHSECURITY;
  strcpy(userrecord.permittions,"");
  userrecord.kermitok = DEFKERMITOK;
  userrecord.protokoll = ZMODEMPROTO;
  userrecord.autozmodem = DEFAUTOZMODEM;
  userrecord.fullist_on_cd = DEFFULLIST;
  strcpy(userrecord.home,DEFHOME);
  strcpy(userrecord.uploaddir,DEFUPLOADDIR);
  strcpy(userrecord.shell,NOSHELL);
  strcpy(userrecord.path,NOPATH);
  strcpy(userrecord.term,DEFTERM);
  userrecord.lines = DEFLINES;
  userrecord.columns = DEFCOLUMNS;
  userrecord.lang = DEFLANGUAGE;
  strcpy(userrecord.charset,DEFCHARSET);

  if (recvn(sockd,(void *)username,(SIZE_T)S_STRLEN,0)<0) {
    bgerror("dgetuserrecord","recv: %m");
    return -1;
  }
  
  if ((fd=fopen(confrecord->usersfile,"r"))==NULL) {
    bgerror("dgetuserrecord","fopen %s: %m",confrecord->usersfile);
    return -1;
  }
  do {
    z = fgetnln(zeile,PATH_MAX+S_STRLEN,fd);
    znr++;
    if (z>=PATH_MAX+S_STRLEN) {
      bgerror("dgetuserrecord","line %i too long",znr);
      fclose(fd);
      return -1;
    }
    if (z>0 && zeile[0]!='#') {
      split2key_arg(zeile,&key,&arg);
      lowercases(key);
      if (strncmp("user",key,4) != 0) {
	bgerror("dgetuserrecord","line %i: 'User:' must be first entry in any record",znr);
	fclose(fd);
	return -1;
      }
      if ((g=strcmp(arg,username))!=0) {
	do {
	  z = fgetnln(zeile,PATH_MAX,fd);
	  znr++;
	} while (z>=0 && z<PATH_MAX && zeile[0]!='$');
      }
    }
  } while (z>=0 && z<PATH_MAX && g!=0);
    
  if (g==0) {
    strcpy(userrecord.name,username);
    do {
      z = fgetnln(zeile,PATH_MAX,fd);
      znr++;
      if (z<0 && z>=PATH_MAX) {
	bgerror("dgetuserrecord","error in userfile %s, line %i",
		confrecord->usersfile, znr);
	fclose(fd);
	return -1;
      }
      split2key_arg(zeile,&key,&arg);
      lowercases(key);
      if (*key=='\0' || *key=='#') {
	/* */
      }
      else if (strncmp("pass",key,4)==0) {
	strcpy(userrecord.passwd,arg);
      }
      else if (strncmp("real",key,4)==0) {
	strcpy(userrecord.realname,arg);
      }
      else if (strncmp("loglevel",key,4)==0) {
	userrecord.loglevel = atoi(arg);
      }
      else if (strncmp("seclevel",key,4)==0) {
	userrecord.seclevel = atoi(arg);
      }
      else if (strncmp("perm",key,4)==0) {
	strcpy(userrecord.permittions,arg);
      }
      else if (strncmp("kermitok",key,4)==0) {
	userrecord.kermitok = atoi(arg);
      }
      else if (strncmp("protokoll",key,4)==0) {
	userrecord.protokoll = atoi(arg);
      }
      else if (strncmp("autozmodem",key,5)==0) {
	userrecord.autozmodem = atoi(arg);
      }
      else if (strncmp("fullist_on_cd",key,8)==0) {
        userrecord.fullist_on_cd = atoi(arg);
      }
      else if (strncmp("home",key,4)==0) {
	strcpy(userrecord.home,arg);
      }
      else if (strncmp("upload",key,4)==0) {
	strcpy(userrecord.uploaddir,arg);
      }
      else if (strncmp("shell",key,4)==0) {
	strcpy(userrecord.shell,arg);
      }
      else if (strncmp("path",key,4)==0) {
	strcpy(userrecord.path,arg);
      }
      else if (strncmp("term",key,4)==0) {
	strcpy(userrecord.term,arg);
      }
      else if (strncmp("lines",key,4)==0) {
	userrecord.lines = atoi(arg);
      }
      else if (strncmp("columns",key,4)==0) {
	userrecord.columns = atoi(arg);
      }
      else if (strncmp("lang",key,4)==0) {
	userrecord.lang = atoi(arg);
      }
      else if (strncmp("char",key,4)==0) {
	strcpy(userrecord.charset,arg);
      }
    } while (zeile[0] != '$');
    z = 0;
  }
  else {
    z = 1;
  }
  fclose(fd);
  sendn(sockd,(char *)&userrecord,sizeof(userrecordtyp),0);
  return z;
}


int dsaveuserrecord(const int sockd, const confrecordtyp *confrecord)
  /*
  Empfaengt vom Client einen Userrecord und speichert ihn im Userfile ab
  */
{
  int k;
  char zeile[PATH_MAX+S_STRLEN+1], tempfile[PATH_MAX+1],
      str[PATH_MAX+S_STRLEN+1], *username, *key, *arg, *sp;
  userrecordtyp userrecord;
  FILE *infd, *outfd;
  
  if (recvn(sockd,(char *)&userrecord,sizeof(userrecordtyp),0)<0) {
    bgerror("dsaveuserrecord","recvn: %m");
    return -1;
  }
  
  if ((infd=fopen(confrecord->usersfile,"r"))==NULL) {
    bgerror("dsaveuserrecord","fopen %s: %m",confrecord->usersfile);
    return -1;
  }
  sprintf(tempfile,"%s-%ld",confrecord->usersfile,(long)getpid());
  if ((outfd=fopen(tempfile,"w"))==NULL) {
    bgerror("dsaveuserrecord","fopen %s: %m",tempfile);
    fclose(infd);
    return -1;
  }
  
  username = userrecord.name;
  do {
    if(fgetnln(zeile,PATH_MAX+S_STRLEN,infd)<0) {
      fclose(infd);
      return -1;
    }
    strmaxcpy(str,zeile,STRLEN);
    split2key_arg(str,&key,&arg);
    if (strcmp(arg,username) == 0)  break;
    if (fprintf(outfd,"%s\n",zeile)<0) {
      bgerror("dsaveuserrecord","fprintf: %m");
      fclose(infd);
      return -1;
    }
  } while (TRUE);
  do {
    strcpy(str,zeile);
    split2key_arg(zeile,&key,&arg);
    lowercases(key);
    sp = strchr(str,'#');
    if (sp != NULL && sp > str) {
      do {
	sp--;
      } while (sp > str && (*sp == ' ' || *sp == '\t'));
      sp++;
    }
    else {
      sp = "";
    }
    if (*arg == '\0' && *sp == ' ')  sp++;
    if (strncmp("user",key,4)==0) {
      fprintf(outfd,"User: %s%s\n",username,sp);
    }
    else if (strncmp("pass",key,4)==0) {
      fprintf(outfd,"Password: %s%s\n",userrecord.passwd,sp);
    }
    else if (strncmp("real",key,4)==0) {
      fprintf(outfd,"Realname: \"%s\"%s\n",userrecord.realname,sp);
    }
    else if (strncmp("loglevel",key,4)==0) {
      fprintf(outfd,"Loglevel: %d%s\n",userrecord.loglevel,sp);
    }
    else if (strncmp("seclevel",key,4)==0) {
      fprintf(outfd,"Seclevel: %d%s\n",userrecord.seclevel,sp);
    }
    else if (strncmp("perm",key,4)==0) {
      fprintf(outfd,"Permittions: %s%s\n",userrecord.permittions,sp);
    }
    else if (strncmp("kermitok",key,4)==0) {
      fprintf(outfd,"Kermitok: %d%s\n",userrecord.kermitok,sp);
    }
    else if (strncmp("protokoll",key,4)==0) {
      fprintf(outfd,"Protokoll: %d%s\n",userrecord.protokoll,sp);
    }
    else if (strncmp("autozmodem",key,5)==0) {
      fprintf(outfd,"Autozmodem: %d%s\n",userrecord.autozmodem,sp);
    }
    else if (strncmp("fullist_on_cd",key,8)==0) {
      fprintf(outfd,"Fullist_on_cd: %d%s\n",userrecord.fullist_on_cd,sp);
    }
    else if (strncmp("home",key,4)==0) {
      fprintf(outfd,"Home: %s%s\n",userrecord.home,sp);
    }
    else if (strncmp("upload",key,4)==0) {
      fprintf(outfd,"Uploaddir: %s%s\n",userrecord.uploaddir,sp);
    }
    else if (strncmp("shell",key,4)==0) {
      fprintf(outfd,"Shell: %s%s\n",userrecord.shell,sp);
    }
    else if (strncmp("path",key,4)==0) {
      fprintf(outfd,"Path: %s%s\n",userrecord.path,sp);
    }
    else if (strncmp("term",key,4)==0) {
      fprintf(outfd,"Term: %s%s\n",userrecord.term,sp);
    }
    else if (strncmp("lines",key,4)==0) {
      fprintf(outfd,"Lines: %d%s\n",userrecord.lines,sp);
    }
    else if (strncmp("columns",key,4)==0) {
      fprintf(outfd,"Columns: %d%s\n",userrecord.columns,sp);
    }
    else if (strncmp("lang",key,4)==0) {
      fprintf(outfd,"Lang: %d%s\n",userrecord.lang,sp);
    }
    else if (strncmp("char",key,4)==0) {
      fprintf(outfd,"Charset: %s%s\n",userrecord.charset,sp);
    }
    if(fgetnln(zeile,PATH_MAX+S_STRLEN,infd)<0) {
      fclose(infd);
      return -1;
    }
  } while(zeile[0]!='$');
  if (fprintf(outfd,"$\n")<0) {
    bgerror("dsaveuserrecord","fprintf: %m");
    fclose(infd);
    return -1;
  }
  while ((k=fgetnln(zeile,PATH_MAX+S_STRLEN,infd))>=0) {
    if (fprintf(outfd,"%s\n",zeile)<0) {
      bgerror("dsaveuserrecord","fprintf: %m");
      fclose(infd);
      return -1;
    }
  }
  fclose(infd);
  k = -1;
  if (fclose(outfd)>=0) {
    if (unlink(confrecord->usersfile)==0) {
      k = rename(tempfile,confrecord->usersfile);
    }
  }
  return k;
}

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