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

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

/* $Id$ */
#include "bbs.h"

boolean bbsdaemon = FALSE;
SIGSET_T old_blocksigset;
sigmaskstatusenum blocksigsetstatus = SIGMASK_UNSET;

extern char **environ;

int main(int argc, char *argv[], char *envp[])
  /*
  Zum Empfangen von externer E-Mail (sendmail -> BBS-mailbox)
  */
{
  int infd, sockd, n, k, rknown, anz, rw[MAXARGS];
  SIZE_T msgsize, len;
#ifdef BBSMAILNAME
  SIZE_T envlen;
#endif
  SSIZE_T bytes;
  char c, conffile[PATH_MAX+1], file[PATH_MAX+1], recipient[S_STRLEN+1],
       bstr[BEFSTRLEN+1], rstr[ARG_MAX+1], *splits[MAXARGS+1], *msgbuf, *bp;
  boolean argserror = FALSE;
  confrecordtyp confrecord;
  extern int optind, opterr, optopt;
  extern char *optarg;

  *recipient = '\0';
  if ((bp=getenv("TZ")) != NULL) {
    strncpy(recipient,bp,S_STRLEN);
  }
#ifdef BBSMAILNAME
  /* Speicher vom alten Environment fuer setproctitle recyclen */
  envlen = 0;
  for (n=0; n<argc; n++)  envlen += strlen(argv[n]);
  for (n=0; envp[n]!=NULL; n++)  envlen += strlen(envp[n]);
#endif
  environ[0] = (char *)NULL;
  if (*recipient != '\0')  mdefenv("TZ",recipient);
  mputenv("EDITOR=/bin/false");
  openlog("bbsmail",LOG_PID,LOG_BBS);
  strcpy(conffile,CONFFILE);
  *recipient = '\0';
  strcpy(file,"-");
  /* Optionen verarbeiten */
  opterr = FALSE;
  while ((c = getopt(argc, argv, "c:f:")) != EOF) {
    switch (c) {
    case 'c':
      strmaxcpy(conffile,optarg,PATH_MAX);
      break;
    case 'f':
      strmaxcpy(file,optarg,PATH_MAX);
      break;
    case '?':
      fprintf(stderr,"bbsmail: unrecognized option: -%c\n", optopt);
      errormsg(E_LOGFILE,&confrecord,"bbsmail","bbsmail",
               "unrecognized option: -%c",optopt);
      argserror = TRUE;
    }
  }
  anz = 0;
  *rstr = '\0';
  while (optind < argc) {
    anz++;
    strmaxcat(rstr,argv[optind++],ARG_MAX-1);
    strcat(rstr,",");
  }
  if (anz == 0) {
    argserror = TRUE;
    bgerror("bbsmail","no recipients given");
    fprintf(stderr,"no recipients given\n");
    argserror = TRUE;
  }

#ifdef BBSMAILNAME
  /* alten Programmtitel loeschen */
  argv[0][envlen-2] = '\0';
  for (n=0; n<envlen-2; n++)  argv[0][n] = ' ';
#endif

  if (readconffile(&confrecord,conffile) < 0) {
    bgerror("bbsmail","cannot read conffile %s",conffile);
    fprintf(stderr,"cannot read conffile %s\n",conffile);
    exit(EX_UNAVAILABLE);
  }
  confrecord.curses_on = FALSE;
  if (startbbsd(&confrecord,conffile) < 0) {
    bgerror("bbsmail","starting bbsd failed");
    fprintf(stderr,"starting bbsd failed\n");
    exit(EX_OSERR);
  }


  if (strcmp(file,"-") == 0) {
#ifdef FIONREAD
    if (isatty(STDIN_FILENO) && ioctl(STDIN_FILENO,FIONREAD,&msgsize) < 0) {
      errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail","ioctl: %m");
      exit(EX_OSERR);
    }
    for (k=0; msgsize == 0 && k < 20; k++) {
      usleep(100000);
      if (ioctl(STDIN_FILENO,FIONREAD,&msgsize) < 0) {
        errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail","ioctl: %m");
        exit(EX_OSERR);
      }
    }
    if (msgsize == 0) {
      errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail",
              "no input on stdin");
      exit(EX_NOINPUT);
    }
#endif
    infd = STDIN_FILENO;
  }
  else {
    if ((infd=open(file,O_RDONLY)) < 0) {
      errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail",
               "open %s: %m",file);
      exit(EX_NOINPUT);
    }
  }
  if (argserror) {
    errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail",
         "usage: bbsmail [-c conffile] [-f file] recipient1 recipient2 ...");
    exit(EX_USAGE);
  }

  if ((msgbuf=(char *)malloc(ALLOCSTEPSIZE)) == NULL) {
    errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail","malloc: %m");
    exit(EX_OSERR);
  }
  n = 1;
  bp = msgbuf;
  while ((bytes=readn(infd,msgbuf+(n-1)*ALLOCSTEPSIZE,ALLOCSTEPSIZE)) ==
         ALLOCSTEPSIZE) {
    n++;
    bp += ALLOCSTEPSIZE;
    if ((msgbuf=(char *)realloc((void *)msgbuf,n*ALLOCSTEPSIZE)) == NULL) {
      errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail","realloc: %m");
      exit(EX_OSERR);
    }
  }
  if (bytes < 0) {
    errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail","readn: %m");
    exit(EX_IOERR);
  }
  close(infd);
  msgsize = (n-1) * ALLOCSTEPSIZE + bytes;

  anz = splitstring(splits,rstr,',',MAXARGS);
  for (k=0; k<anz; k++) {
    if ((sockd=connect2bbsd(&confrecord))<0) {
      errormsg(E_LOGFILE|E_USER,&confrecord,"bbsmail","bbsmail",
               "connection to daemon failed");
      exit(EX_SOFTWARE);
    }
    sprintf(bstr,"#%2d\n",DO_RECEIVEMAIL);
    sendn(sockd,(void *)bstr,(SIZE_T)BEFSTRLEN,0);
#ifdef BBSMAILNAME
    setproctitle(argv,envlen,"checking recipient %s",splits[k]);
#endif
    len = strlen(splits[k]) + 1;
    sendn(sockd,(void *)&len,sizeof(SIZE_T),0);
    sendn(sockd,(void *)splits[k],len,0);
    recvn(sockd,(void *)&rknown,(SIZE_T)sizeof(int),0);
    if (rknown == 0) {
#ifdef BBSMAILNAME
      setproctitle(argv,envlen,"deliver %s",splits[k]);
#endif
      sendn(sockd,(void *)&msgsize,sizeof(SIZE_T),0);
      sendn(sockd,(void *)msgbuf,msgsize,0);
    }
    recvn(sockd,(void *)&n,(SIZE_T)sizeof(int),0);
    unconnect2bbsd(sockd,&confrecord);
    bbslog(LOG_FILE,&confrecord,"bbsmail: delivering mail to %s: %s", 
           splits[k],n==0?"ok":"failed");
    if (n == 0) {
      rw[k] = EX_OK;
    }
    else {
      rw[k] = EX_SOFTWARE;
      n = EX_NOUSER;
    }
    if (rknown != 0) {
      rw[k] = EX_NOUSER;
      n = EX_NOUSER;
    }      
  }
  if (n != 0) {
    for (k=0; k<anz; k++) {
      switch (rw[k]) {
      case EX_OK:
        fprintf(stderr,"Delivery to %s: OK\n",splits[k]);
	break;
      case EX_NOUSER:
        fprintf(stderr,"User %s: not known at BBS\n",splits[k]);
	break;
      default:
        fprintf(stderr,"Delivery to %s: FAILED by internal BBS error\n",
	        splits[k]);
      }
    }
  }
  free(msgbuf);
  closelog();
  return n;
}


int startbbsd(const confrecordtyp *confrecord, const char *conffile)
{
  PID_T dpid;
  int status;
  
  if ((dpid=testdaemon(confrecord->bbsdpidpath,confrecord)) < 0) {
    unlink(confrecord->sockpath);
  }
  /* dpid enthaelt die Pid des Daemons, wenn > 0 */
  if (dpid <= 0) {
    if ((dpid=fork())<0) {
      errormsg(E_SYSLOG|E_CONSOLE,confrecord,"bbsmail","startbbsd",
               "fork: %m");
      return(-1);
    }
    if (dpid==0) {
      execl(confrecord->bbsdpath,"bbsd","-d","-c",conffile,
            "-p",confrecord->bbsdpath,NULL);
      errormsg(E_SYSLOG|E_CONSOLE,confrecord,"bbsmail","startbbsd",
               "execl %s: %m",confrecord->bbsdpath);
      exit(-1);
    }
    while (wait(&status)!=dpid);
    if (!WIFEXITED(status)) {
      errormsg(E_SYSLOG|E_CONSOLE,confrecord,"bbsmail","startbbsd",
               "starting bbsd failed: %d",status);
      return(-1);
    }
    if (WIFEXITED(status) && WEXITSTATUS(status)!=0) {
      errormsg(E_SYSLOG|E_CONSOLE,confrecord,"bbsmail","startbbsd",
               "bbsd exited with %i",WEXITSTATUS(status));
      return(-1);
    }
  }
  return 0;
}

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