Annotation of researchv10no/cmd/nupas/smtp/smtp.c, revision 1.1.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.