Annotation of researchv10no/cmd/nupas/smtp/smtp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * smtp -- client, send mail to remote smtp server
        !             3:  * TODO:
        !             4:  *     allow partial delivery to multiple recipients when only some
        !             5:  *             fail (maybe)
        !             6:  *     send stuff from cmds.h instead of hard-coded here
        !             7:  */
        !             8: 
        !             9: #define        USAGE "usage: %s [-u] [-H helohost] [-d domain] [-a addr] [-f] [-D] [-L loglevel] sender targethost recip1 recip2 ...\n"
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include <ctype.h>
        !            13: #include <sysexits.h>
        !            14: #include "addrformat.h"
        !            15: #include "smtp.h"
        !            16: #include "string.h"
        !            17: #include "aux.h"
        !            18: #include "sys.h"
        !            19: 
        !            20: #ifndef DIALER
        !            21: #define DIALER         "tcp"
        !            22: #endif
        !            23: 
        !            24: #ifndef SERVNAME
        !            25: #define SERVNAME       "smtp"          /* service we wanna talk to */
        !            26: #endif
        !            27: 
        !            28: char *progname;
        !            29: int debug;
        !            30: char *helohost;
        !            31: int kludgepause = 0;
        !            32: 
        !            33: char *strcat(), *strcpy();
        !            34: extern char *convertaddr();
        !            35: extern int ipcdebug;
        !            36: extern char *ipcpath();
        !            37: 
        !            38: static int errno;
        !            39: static char errstr[128];
        !            40: 
        !            41: char *convertto();
        !            42: 
        !            43: /*
        !            44:  * main - parse arguments and handle options
        !            45:  */
        !            46: main(argc, argv)
        !            47: int argc;
        !            48: char *argv[];
        !            49: {
        !            50:        register int c;
        !            51:        int errflg = 0;
        !            52:        int unixformat = 0;
        !            53:        int filter = 0;
        !            54:        char *domain = 0;
        !            55:        char *sender = 0;
        !            56:        char *host = 0;
        !            57:        char *addr = 0;
        !            58:        namelist *recips, *newname(), *appendname();
        !            59:        FILE *sfi, *sfo;
        !            60:        string *replyaddr=s_new();
        !            61:        string *hh;
        !            62: 
        !            63:        extern int optind;
        !            64:        extern char *optarg;
        !            65: 
        !            66:        umask(2);
        !            67: 
        !            68:        progname = argv[0];
        !            69:        Openlog("smtp", LOG_PID, LOG_SMTP);
        !            70:        setlogmask(LOG_UPTO(DEFAULT_LOG_LEVEL));
        !            71:        while ((c = getopt(argc, argv, "ga:uDd:H:fL:K")) != EOF)
        !            72:                switch (c) {
        !            73:                case 'a':       addr = optarg;          break;
        !            74:                case 'u':       unixformat++;           break;
        !            75:                case 'D':       debug++;  ipcdebug++;   break;
        !            76:                case 'd':       domain = optarg;        break;
        !            77:                case 'H':       helohost = optarg;      break;
        !            78:                case 'f':       filter++;               break;
        !            79:                case 'K':       kludgepause++;          break;
        !            80:                case 'L':       setloglevel(optarg);    break;
        !            81:                case '?':
        !            82:                default:
        !            83:                        errflg++;
        !            84:                        break;
        !            85:                }
        !            86:        if (errflg || (argc - optind) < 3) {
        !            87:                (void) fprintf(stderr, USAGE, progname);
        !            88:                Syslog(LOG_WARNING, "SMTP illegal usage.");
        !            89:                bomb(EX_USAGE);
        !            90:        }
        !            91: 
        !            92:        /*
        !            93:         *  figure out what to call ourselves
        !            94:         */
        !            95:        if (helohost==NULL)
        !            96:                helohost=s_to_c(s_copy(sysname_read()));
        !            97: 
        !            98:        /*
        !            99:         *  if there is no domain in the helo host name
        !           100:         *  and we the -d option is specified, domainify
        !           101:         *  the helo host
        !           102:         */
        !           103:        if(strchr(helohost, '.')==0 && domain){
        !           104:                hh = s_copy(helohost);
        !           105:                s_append(hh, domain);
        !           106:                helohost = s_to_c(hh);
        !           107:        }
        !           108: 
        !           109:        /*
        !           110:         *  put our address onto the reply address
        !           111:         */
        !           112:        if(strchr(argv[optind], '!')==0 || !domain){
        !           113:                s_append(replyaddr, helohost);
        !           114:                s_append(replyaddr, "!");
        !           115:                s_append(replyaddr, argv[optind]);
        !           116:        } else {
        !           117:                s_append(replyaddr, argv[optind]);
        !           118:        }
        !           119:        optind++;
        !           120: 
        !           121:        /*
        !           122:         *  convert the arguments to 822 form
        !           123:         */
        !           124:        sender = convertaddr(s_to_c(replyaddr), domain, SOURCEROUTE);
        !           125:        host = argv[optind++];
        !           126:        recips = newname(convertto(argv[optind++], unixformat, host));
        !           127:        for (; optind < argc; optind++)
        !           128:                recips = appendname(recips, convertto(argv[optind], unixformat, host));
        !           129: 
        !           130:        /*
        !           131:         * run as a filter
        !           132:         */
        !           133:        if ( filter ) {
        !           134:                do_data(unixformat, stdin, stdout, sender, recips, domain);
        !           135:                exit(0);
        !           136:        }
        !           137: 
        !           138:        /*
        !           139:         *  open connection
        !           140:         */
        !           141:        setup(addr ? addr : host, &sfi, &sfo);
        !           142: 
        !           143:        /*
        !           144:         *  hold the conversation
        !           145:         */
        !           146:        converse(unixformat, sender, recips, domain, sfi, sfo, stdin);
        !           147:        /* converse terminates with the appropriate exit code */
        !           148: }
        !           149: 
        !           150: namelist *
        !           151: newname(s)
        !           152:        char *s;
        !           153: {
        !           154:        namelist *np;
        !           155: 
        !           156:        np = (namelist *)malloc(sizeof(namelist));
        !           157:        if (np == NULL) {
        !           158:                Syslog(LOG_WARNING, "could not alloc (newname)");
        !           159:                bomb(1);
        !           160:        }
        !           161:        np->name = s;
        !           162:        np->next = NULL;
        !           163:        return np;
        !           164: }
        !           165: 
        !           166: /* could add at beginning, but let's maintain original order */
        !           167: namelist *
        !           168: appendname(nl, s)
        !           169:        char *s;
        !           170:        namelist *nl;
        !           171: {
        !           172:        register namelist *tl;
        !           173: 
        !           174:        if (nl == NULL)
        !           175:                bomb(1);        /* shouldn't happen */
        !           176:        for (tl=nl; tl->next!=NULL; tl=tl->next)
        !           177:                ;
        !           178:        tl->next = newname(s);
        !           179:        return nl;
        !           180: }
        !           181: 
        !           182: /*
        !           183:  *  convert a destination address to outgoing format
        !           184:  *
        !           185:  *     if unixformat, just leave it alone
        !           186:  *
        !           187:  *     if not add the destination host name.
        !           188:  */
        !           189: char *
        !           190: convertto(recip, unixformat, desthost)
        !           191:        char *recip;
        !           192:        char *desthost;
        !           193: {
        !           194:        static string *buf;
        !           195: 
        !           196:        if(unixformat)
        !           197:                return recip;
        !           198:        
        !           199:        buf = s_reset(buf);
        !           200:        s_append(buf, desthost);
        !           201:        s_append(buf, "!");
        !           202:        s_append(buf, recip);
        !           203:        return convertaddr(s_to_c(buf), 0, SOURCEROUTE);
        !           204: }
        !           205: 
        !           206: 
        !           207: /*
        !           208:  * setup -- setup tcp/ip connection to/from server
        !           209:  */
        !           210: setup(host, sfip, sfop)
        !           211:        char *host;
        !           212:        FILE **sfip, **sfop;
        !           213: {
        !           214:        int s;
        !           215:        char *path;
        !           216:        int localerr;
        !           217: 
        !           218:        path = ipcpath(host, DIALER, SERVNAME);
        !           219:        Syslog(LOG_DEBUG, "Opening connection to %s\n", path);
        !           220:        if ((s = ipcopen(path, "")) < 0) {
        !           221:                extern int ipcerrno;
        !           222:                extern char syserrstr[];
        !           223: 
        !           224:                char errbuf[256];
        !           225:                sprintf(errbuf, "SMTP connect error to %s", host);
        !           226:                ipcperror(errbuf);
        !           227:                Syslog(LOG_INFO, "%s: %s\n", errbuf, syserrstr);
        !           228:                bomb(ipcerrno);
        !           229:        }
        !           230: 
        !           231:        if (((*sfip = fdopen(s, "r")) == (FILE *) NULL) ||
        !           232:            ((*sfop = fdopen(s, "w")) == (FILE *) NULL)) {
        !           233:                perror("setup - fdopen");
        !           234:                Syslog(LOG_INFO, "setup - fdopen");
        !           235:                bomb(EX_IOERR);
        !           236:        }
        !           237: }
        !           238: 
        !           239: 
        !           240: /*
        !           241:  * bomb(code) - exit program, map smtp error code into mailsystem code
        !           242:  * Codes with EX_ are from <sysexits.h>
        !           243:  * Lines with FOO are placeholders until we decrypt more appropriate codes.
        !           244:  */
        !           245: bomb(code)
        !           246: int code;
        !           247: {
        !           248:        switch(code) {
        !           249:        case 451:                       /* some temporary error */
        !           250:                exit(EX_TEMPFAIL);      /* try later */
        !           251:                /*NOTREACHED*/
        !           252:        case 554:                       /* syntax error in address */
        !           253:        case 501:                       /* data format error */
        !           254:                exit(EX_DATAERR);
        !           255:                /*NOTREACHED*/
        !           256:        case 550:                       /* no such user */
        !           257:                exit(EX_NOUSER);
        !           258:                /*NOTREACHED*/
        !           259:        case EX_USAGE:
        !           260:        case EX_DATAERR:
        !           261:        case EX_NOINPUT:
        !           262:        case EX_NOUSER:
        !           263:        case EX_NOHOST:
        !           264:        case EX_UNAVAILABLE:
        !           265:        case EX_SOFTWARE:
        !           266:        case EX_OSERR:
        !           267:        case EX_OSFILE:
        !           268:        case EX_CANTCREAT:
        !           269:        case EX_IOERR:
        !           270:        case EX_TEMPFAIL:
        !           271:        case EX_PROTOCOL:
        !           272:        case EX_NOPERM:
        !           273:                exit(code);
        !           274:                /*NOTREACHED*/
        !           275:        default:                        /* can't happen? */
        !           276:                if ((code >= 400) && (code <= 499))
        !           277:                        exit(EX_TEMPFAIL);
        !           278:                else {
        !           279:                        Syslog(LOG_WARNING, "SMTP protocol error %d\n", code);
        !           280:                        exit(EX_PROTOCOL);      /* unknown error */
        !           281:                }
        !           282:        }
        !           283: }

unix.superglobalmegacorp.com

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