Annotation of 43BSDReno/contrib/mh/support/pop/smtpd.c, revision 1.1

1.1     ! root        1: /* smtpd.c - the stub SMTP server for POP client hosts */
        !             2: 
        !             3: 
        !             4: /* Author:     Marshall T. Rose        <MRose@NRTC>    (MTR)
        !             5:                Northrop Research and Technology Center
        !             6:                One Research park
        !             7:                Palos Verdes Peninsula, CA  90274
        !             8:                213/377-4811
        !             9: 
        !            10:    Date:       Wed May 15 00:04:12 1985
        !            11:  */
        !            12: 
        !            13: #include <errno.h>
        !            14: #include <signal.h>
        !            15: #include <stdio.h>
        !            16: #include <strings.h>
        !            17: #include <syslog.h>
        !            18: #include <sys/types.h>
        !            19: #include <sys/file.h>
        !            20: #include <sys/ioctl.h>
        !            21: #include <sys/socket.h>
        !            22: #include <sys/wait.h>
        !            23: #include <netinet/in.h>
        !            24: #include <netdb.h>
        !            25: #include <arpa/inet.h>
        !            26: 
        !            27: 
        !            28: #define        NOTOK   (-1)
        !            29: #define        OK      0
        !            30: 
        !            31: /*  */
        !            32: 
        !            33: extern int  errno;
        !            34: extern char *sys_siglist[];
        !            35: 
        !            36: 
        !            37: int  debug = 0;
        !            38: static int  nbits = ((sizeof (int)) * 8);
        !            39: static int  options = 0;
        !            40: 
        !            41: 
        !            42: char *myname = "smtpd";
        !            43: char myhost[BUFSIZ];
        !            44: static char *myprotocol = "tcp";
        !            45: static char *myservice = "smtp";
        !            46: 
        !            47: static struct sockaddr_in   in_socket;
        !            48: static struct sockaddr_in  *isock = &in_socket;
        !            49: 
        !            50: static char *smtphost;
        !            51: static struct sockaddr_in   sm_socket;
        !            52: static struct sockaddr_in  *msock = &sm_socket;
        !            53: 
        !            54: 
        !            55: void   chldser ();
        !            56: void   adios (), advise ();
        !            57: 
        !            58: /*  */
        !            59: 
        !            60: /* ARGSUSED */
        !            61: 
        !            62: main (argc, argv, envp)
        !            63: int     argc;
        !            64: char  **argv,
        !            65:       **envp;
        !            66: {
        !            67:     int     fd,
        !            68:             sd;
        !            69:     struct servent *sp;
        !            70:     struct sockaddr_in  out_socket,
        !            71:                        *osock = &out_socket;
        !            72: 
        !            73:     if ((sp = getservbyname (myservice, myprotocol)) == NULL)
        !            74:        adios (NULL, "%s/%s: unknown service", myprotocol, myservice);
        !            75:     isock -> sin_family = AF_INET;
        !            76:     isock -> sin_port = sp -> s_port;
        !            77:     isock -> sin_addr.s_addr = INADDR_ANY;
        !            78:     arginit (argv);
        !            79:     envinit ();
        !            80:     msock -> sin_port = isock -> sin_port;
        !            81: 
        !            82: #ifdef RESTART
        !            83:     for (;;) {
        !            84:        char    reason[BUFSIZ];
        !            85:        union wait status;
        !            86: 
        !            87:        switch (fork ()) {
        !            88:            case NOTOK: 
        !            89:                sleep (5);
        !            90:                continue;
        !            91: 
        !            92:            case OK: 
        !            93:                break;
        !            94: 
        !            95:            default: 
        !            96:                sleep (60);
        !            97:                (void) wait3 (&status, 0, NULL);
        !            98:                if (WIFEXITED (status))
        !            99:                    (void) sprintf (reason, "exit=0%o", status.w_retcode);
        !           100:                else
        !           101:                    if (WIFSIGNALED (status))
        !           102:                        (void) sprintf (reason, "signal=%s%s",
        !           103:                                status.w_termsig < NSIG
        !           104:                                ? sys_siglist[status.w_termsig] : "unknown",
        !           105:                                status.w_coredump ? " (core dumped)" : NULL);
        !           106:                    else
        !           107:                        (void) strcpy (reason, "stopped(!!)");
        !           108:                advise (NULL, LOG_WARNING, "%s/%s server has terminated -- %s",
        !           109:                        sp -> s_proto, sp -> s_name, reason);
        !           110:                continue;
        !           111:        }
        !           112:        break;
        !           113:     }
        !           114: 
        !           115:     closelog ();
        !           116:     openlog (myname, LOG_PID);
        !           117:     advise (NULL, LOG_INFO, "restart");
        !           118: #endif RESTART
        !           119: 
        !           120: /*  */
        !           121: 
        !           122:     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
        !           123:        adios ("socket", "unable to create");
        !           124:     if (options & SO_DEBUG)
        !           125:        if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0) == NOTOK)
        !           126:            advise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
        !           127:     if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == NOTOK)
        !           128:        advise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
        !           129:     if (bind (sd, isock, sizeof *isock) == NOTOK)
        !           130:        adios ("socket", "unable to bind");
        !           131: 
        !           132:     (void) signal (SIGCHLD, chldser);
        !           133:     (void) listen (sd, SOMAXCONN);
        !           134:     for (;;) {
        !           135:        int     i = sizeof *osock;
        !           136: 
        !           137:        if ((fd = accept (sd, osock, &i)) == NOTOK) {
        !           138:            if (errno != EINTR)
        !           139:                advise ("socket", LOG_WARNING,
        !           140:                    "unable to accept connection on");
        !           141:            continue;
        !           142:        }
        !           143:        switch (fork ()) {
        !           144:            case OK: 
        !           145:                (void) close (sd);
        !           146:                (void) signal (SIGCHLD, SIG_DFL);
        !           147:                server (fd, osock);
        !           148:                _exit (0);
        !           149: 
        !           150:            case NOTOK: 
        !           151:                advise ("socket", LOG_WARNING,
        !           152:                    "no forks, so rejecting connection on");
        !           153:            default: 
        !           154:                (void) close (fd);
        !           155:        }
        !           156:     }
        !           157: }
        !           158: 
        !           159: /*  */
        !           160: 
        !           161: static server (fd, sin)
        !           162: int    fd;
        !           163: struct sockaddr_in *sin;
        !           164: {
        !           165:     int     sd;
        !           166:     u_short port;
        !           167:     char    buffer[BUFSIZ];
        !           168:     struct hostent *hp;
        !           169:     struct in_addr *addr;
        !           170: 
        !           171:     closelog ();
        !           172:     openlog (myname, LOG_PID);
        !           173:     port = ntohs (sin -> sin_port);
        !           174:     addr = &sin -> sin_addr;
        !           175:     advise (NULL, LOG_INFO, "servicing %s/%d",
        !           176:            (hp = gethostbyaddr (addr, sizeof *addr, sin -> sin_family))
        !           177:            ? hp -> h_name : inet_ntoa (*addr), port);
        !           178: 
        !           179:     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK
        !           180:            || connect (sd, msock, sizeof *msock) == NOTOK) {
        !           181:        advise (smtphost, LOG_WARNING,
        !           182:                sd != NOTOK ? "unable to connect to" : "socket failed for");
        !           183:        sprintf (buffer, "451 No %s/%s service available, try %s--%s\r\n",
        !           184:                myprotocol, myservice, smtphost, "you might get lucky");
        !           185:        write (fd, buffer, strlen (buffer));
        !           186:        return;
        !           187:     }
        !           188: 
        !           189:     advise (NULL, LOG_INFO, "connected to %s", smtphost);
        !           190:     shuffle (fd, sd);
        !           191: }
        !           192: 
        !           193: /*  */
        !           194: 
        !           195: shuffle (fd, sd)
        !           196: int    fd,
        !           197:        sd;
        !           198: {
        !           199:     int     cc,
        !           200:             ibits,
        !           201:             obits,
        !           202:             on,
        !           203:             scc,
        !           204:             fcc;
        !           205:     char   *sbp,
        !           206:             sibuf[BUFSIZ],
        !           207:            *fbp,
        !           208:             fibuf[BUFSIZ];
        !           209: 
        !           210:     on = 1;
        !           211:     ioctl (fd, FIONBIO, &on);
        !           212:     ioctl (sd, FIONBIO, &on);
        !           213: 
        !           214:     for (fcc = scc = 0;;) {
        !           215:        ibits = obits = 0;
        !           216:        if (fcc)
        !           217:            obits |= 1 << sd;
        !           218:        else
        !           219:            ibits |= 1 << fd;
        !           220:        if (scc)
        !           221:            obits |= 1 << fd;
        !           222:        else
        !           223:            ibits |= 1 << sd;
        !           224:        if (fcc < 0 && scc < 0)
        !           225:            break;
        !           226: 
        !           227:        select (nbits, &ibits, &obits, NULL, NULL);
        !           228: 
        !           229:        if (ibits == 0 && obits == 0) {
        !           230:            sleep (5);
        !           231:            continue;
        !           232:        }
        !           233: 
        !           234:        if (ibits & (1 << fd)) {
        !           235:            fcc = read (fd, fibuf, sizeof fibuf);
        !           236:            if (fcc < 0 && errno == EWOULDBLOCK)
        !           237:                fcc = 0;
        !           238:            else {
        !           239:                if (fcc <= 0)
        !           240:                    break;
        !           241:                fbp = fibuf;
        !           242:            }
        !           243:        }
        !           244:        if (ibits & (1 << sd)) {
        !           245:            scc = read (sd, sibuf, sizeof sibuf);
        !           246:            if (scc < 0 && errno == EWOULDBLOCK)
        !           247:                scc = 0;
        !           248:            else {
        !           249:                if (scc <= 0)
        !           250:                    break;
        !           251:                sbp = sibuf;
        !           252:            }
        !           253:        }
        !           254: 
        !           255:        if ((obits & (1 << fd)) && scc > 0) {
        !           256:            cc = write (fd, sbp, scc);
        !           257:            if (cc > 0)
        !           258:                scc -= cc, sbp += cc;
        !           259:        }
        !           260:        if ((obits & (1 << sd)) && fcc > 0) {
        !           261:            cc = write (sd, fbp, fcc);
        !           262:            if (cc > 0)
        !           263:                fcc -= cc, fbp += cc;
        !           264:        }
        !           265:     }
        !           266: 
        !           267:     advise (NULL, LOG_INFO, "terminating: fcc=%d scc=%d errno=%d",
        !           268:            fcc, scc, errno);
        !           269: }
        !           270: 
        !           271: /*  */
        !           272: 
        !           273: /* set options and isock -> sin_port here... */
        !           274: 
        !           275: static arginit (vec)
        !           276: char   **vec;
        !           277: {
        !           278:     struct hostent *hp;
        !           279: 
        !           280:     if (myname = rindex (*vec, '/'))
        !           281:        myname++;
        !           282:     if (myname == NULL || *myname == NULL)
        !           283:        myname = *vec;
        !           284: 
        !           285:     (void) gethostname (myhost, sizeof myhost);
        !           286:     if (hp = gethostbyname (myhost))
        !           287:        (void) strcpy (myhost, hp -> h_name);
        !           288:     nbits = getdtablesize ();
        !           289: 
        !           290:     if ((smtphost = *++vec) == NULL)
        !           291:        adios (NULL, "usage: %s server-host", myname);
        !           292:     if ((hp = gethostbyname (smtphost)) == NULL)
        !           293:        adios (NULL," %s: unknown host");
        !           294:     bzero ((char *) msock, sizeof *msock);
        !           295:     msock -> sin_family = hp -> h_addrtype;
        !           296:     bcopy (hp -> h_addr, (char *) &msock -> sin_addr, hp -> h_length);
        !           297: }
        !           298: 
        !           299: /*  */
        !           300: 
        !           301: static  envinit () {
        !           302:     int     i,
        !           303:             sd;
        !           304: 
        !           305:     if (!(debug = isatty (2))) {
        !           306:        for (i = 0; i < 5; i++) {
        !           307:            switch (fork ()) {
        !           308:                case NOTOK: 
        !           309:                    sleep (5);
        !           310:                    continue;
        !           311: 
        !           312:                case OK: 
        !           313:                    break;
        !           314: 
        !           315:                default: 
        !           316:                    _exit (0);
        !           317:            }
        !           318:            break;
        !           319:        }
        !           320: 
        !           321:        (void) chdir ("/");
        !           322: 
        !           323:        if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
        !           324:            adios ("/dev/null", "unable to read");
        !           325:        if (sd != 0)
        !           326:            (void) dup2 (sd, 0), (void) close (sd);
        !           327:        (void) dup2 (0, 1);
        !           328:        (void) dup2 (0, 2);
        !           329: 
        !           330:        if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
        !           331:            (void) ioctl (sd, TIOCNOTTY, NULL);
        !           332:            (void) close (sd);
        !           333:        }
        !           334:     }
        !           335: 
        !           336:     for (sd = 3; sd < nbits; sd++)
        !           337:        (void) close (sd);
        !           338: 
        !           339:     (void) signal (SIGPIPE, SIG_IGN);
        !           340: 
        !           341:     openlog (myname, LOG_PID);
        !           342:     advise (NULL, LOG_INFO, "starting");
        !           343: }
        !           344: 
        !           345: /*  */
        !           346: 
        !           347: /* ARGSUSED */
        !           348: 
        !           349: static void chldser (sig, code, sc)
        !           350: int    sig;
        !           351: long    code;
        !           352: struct sigcontext *sc;
        !           353: {
        !           354:     union wait status;
        !           355: 
        !           356:     while (wait3 (&status, WNOHANG, NULL) > 0)
        !           357:        continue;
        !           358: }
        !           359: 
        !           360: /*  */
        !           361: 
        !           362: /* VARARGS */
        !           363: 
        !           364: void   adios (what, fmt, a, b, c, d)
        !           365: char   *what,
        !           366:        *fmt,
        !           367:        *a,
        !           368:        *b,
        !           369:        *c,
        !           370:        *d;
        !           371: {
        !           372:     advise (what, LOG_SALERT, fmt, a, b, c, d);
        !           373:     _exit (1);
        !           374: }
        !           375: 
        !           376: 
        !           377: /* VARARGS */
        !           378: 
        !           379: void   advise (what, code, fmt, a, b, c, d)
        !           380: char   *what,
        !           381:        *fmt,
        !           382:        *a,
        !           383:        *b,
        !           384:        *c,
        !           385:        *d;
        !           386: int    code;
        !           387: {
        !           388:     char    buffer[BUFSIZ];
        !           389: 
        !           390:     if (what) {
        !           391:        sprintf (buffer, fmt, a, b, c, d);
        !           392:        syslog (code, "%s %s: %m", buffer, what);
        !           393:     }
        !           394:     else
        !           395:        syslog (code, fmt, a, b, c, d);
        !           396: 
        !           397:     if (debug) {
        !           398:        fprintf (stderr, "[%d] ", code);
        !           399:        fprintf (stderr, fmt, a, b, c, d);
        !           400:        if (what)
        !           401:            (void) fputc (' ', stderr), perror (what);
        !           402:        else
        !           403:            (void) fputc ('\n', stderr);
        !           404:        (void) fflush (stderr);
        !           405:     }
        !           406: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.