|
|
1.1 ! root 1: /* ! 2: * The code that passes an individual message to the mail system. ! 3: */ ! 4: ! 5: #include "mail.h" ! 6: ! 7: #define SITENAMELEN 32 /* max length of sitename */ ! 8: #define NODENAME "/etc/uucpname" ! 9: #define DOMAINNAME "/etc/domain" ! 10: char domain [64]; ! 11: ! 12: extern char *strtok(); ! 13: static char **allist; ! 14: static char **tolist; ! 15: static char **cclist = NULL; ! 16: ! 17: char mysite[SITENAMELEN]; /* this host's uucpname */ ! 18: ! 19: extern char *temp; ! 20: extern int myuid; /* User-id of mail user */ ! 21: extern int mygid; /* Group-id of mail user */ ! 22: extern char cmdname[]; /* Command for x{en,de}code filter */ ! 23: /* and for tail recursion to uumail */ ! 24: /* and for editor recursion */ ! 25: extern char *editname; /* name of editor */ ! 26: extern char *askcc; /* Ask for CC: list? (YES/NO) */ ! 27: extern int callmexmail; /* Xmail modifier present */ ! 28: extern char wrerr[]; ! 29: extern char myname[]; /* User name */ ! 30: extern char myfullname[]; /* full user name */ ! 31: extern int mflag; /* `You have mail.' message to recipient */ ! 32: extern int verbflag; /* verbose flag */ ! 33: extern char templ[]; /* Temp file name template */ ! 34: extern char mydead[]; /* $HOME/dead.letter */ ! 35: extern char mysig[]; ! 36: extern char nosave[]; ! 37: extern int callmermail; ! 38: ! 39: static int eflag; /* Edit this mail */ ! 40: static int senderr; ! 41: struct tm *tp; ! 42: char toerr[] = "Cannot create temporary file\n"; ! 43: char header[BUFSIZ]; /* Message header */ ! 44: char boxname[256]; /* Destination mailbox */ ! 45: char remotefrom [32]; /* "remote from uucp" */ ! 46: ! 47: char nosend[] = "Can't send mail to '%s'\n"; ! 48: char nopubk[] = "Can't send xmail to '%s'\n"; ! 49: static int fromtty; ! 50: ! 51: /* ! 52: * Send the message found on ! 53: * the file pointer to the list ! 54: * of people (argv style) with ! 55: * a NULL pointer at the end. ! 56: * The message is copied to a temp-file ! 57: * from position `start' to `end' (or EOF). ! 58: */ ! 59: send2(fp, users, start, end, asksubj) ! 60: FILE *fp; ! 61: register char **users; ! 62: fsize_t start, end; ! 63: int asksubj; ! 64: { ! 65: char **getcc(), **listpp; ! 66: FILE *xfp, *tfp, *sigfp; ! 67: time_t curtime; ! 68: ! 69: uucpname(); ! 70: domainname(); ! 71: senderr = 0; ! 72: temp = templ; ! 73: ! 74: fromtty = isatty(fileno(stdin)); ! 75: if ((tfp = fopen(temp, "w")) != NULL) { ! 76: fclose(tfp); ! 77: if ((tfp = fopen(temp, "r+w")) == NULL) ! 78: merr(toerr); ! 79: } else ! 80: merr(toerr); ! 81: chown(temp, myuid, mygid); ! 82: unlink(temp); ! 83: temp = NULL; ! 84: fseek(fp, start, 0); ! 85: end -= start; ! 86: ! 87: eflag = 0; ! 88: if (fromtty && asksubj && !callmermail) { ! 89: fprintf(stdout, "Subject: "); ! 90: fflush(stdout); ! 91: if (fgets(msgline, NLINE, fp) != NULL) { ! 92: if (strlen(msgline) > 1) ! 93: fprintf(tfp, "Subject: %s", msgline); ! 94: } ! 95: } ! 96: ! 97: if (intcheck()) { ! 98: fclose(tfp); ! 99: return(1); ! 100: } ! 101: ! 102: for (;;) { ! 103: if (fgets(msgline, NLINE, fp) == NULL) ! 104: break; ! 105: if (fp == stdin) ! 106: if ((strcmp(".\n", msgline)==0)) ! 107: break; ! 108: else if ((strcmp("?\n", msgline)==0)) { ! 109: eflag = 1; ! 110: break; ! 111: } ! 112: fputs(msgline, tfp); ! 113: if ( (end-=strlen(msgline)) <= 0 ) ! 114: break; ! 115: } ! 116: ! 117: if (intcheck()) { ! 118: fclose(tfp); ! 119: return(1); ! 120: } ! 121: ! 122: ! 123: if (!callmermail && (sigfp = fopen(mysig, "r")) != NULL) { ! 124: fputs("\n", tfp); ! 125: while (fgets(msgline, NLINE, sigfp) != NULL) ! 126: fputs(msgline, tfp); ! 127: fclose(sigfp); ! 128: } ! 129: ! 130: ! 131: /* ! 132: * Now, see if user wants to edit the message ! 133: */ ! 134: ! 135: if (eflag) { ! 136: xfp = tfp; ! 137: temp = templ; ! 138: if ((tfp = fopen(temp, "wr")) == NULL) ! 139: merr(toerr); ! 140: chown(temp, myuid, mygid); ! 141: mcopy(xfp, tfp, (fsize_t)0, (fsize_t)MAXLONG, 0); ! 142: fclose(xfp); ! 143: sprintf(cmdname, "exec %s %s", editname, templ); ! 144: system(cmdname); ! 145: unlink(temp); ! 146: temp = NULL; ! 147: } ! 148: ! 149: /* ! 150: * if empty message, bug out. ! 151: */ ! 152: ! 153: if (ftell(tfp) == 0) { ! 154: fclose(tfp); ! 155: return(1); ! 156: } ! 157: ! 158: /* ! 159: * Now see if a copy list is requested. ! 160: */ ! 161: ! 162: tolist = users; ! 163: cclist = (askcc && fromtty && !callmermail) ? getcc(): NULL; ! 164: allist = listcat(tolist, cclist); ! 165: ! 166: if ( verbflag ) { ! 167: mmsg( ! 168: "Recipient List:\n\n"); ! 169: for (listpp=allist; *listpp != NULL; listpp++) ! 170: mmsg("\t%s\n", *listpp); ! 171: } ! 172: ! 173: /* ! 174: * Now send the message. ! 175: */ ! 176: ! 177: time(&curtime); ! 178: tp = localtime(&curtime); ! 179: ! 180: if (callmexmail){ ! 181: xsend(allist, tfp); ! 182: }else{ ! 183: usend(allist, tfp); ! 184: } ! 185: ! 186: return( senderr ); ! 187: } ! 188: ! 189: usend(users, tfp) ! 190: char **users; ! 191: FILE *tfp; ! 192: { ! 193: FILE *xfp; ! 194: char *name; ! 195: char **ulist, **listpp; ! 196: char command[CMDLINE]; ! 197: char *arpadate(); ! 198: FILE *popen(); ! 199: ! 200: logdump("Date: %s From: %s!%s (%s)\n", ! 201: arpadate(tp), mysite, myname, myfullname); ! 202: for (ulist = users; (name=*ulist) != NULL; ulist++) ! 203: logdump("To: \"%s\"\n", name); ! 204: ! 205: /* Build the command line to the delivery program. */ ! 206: if ( callmexmail ) { ! 207: strcpy(command, XDELIVER); /* usually "/bin/rxmail" */ ! 208: } else { ! 209: strcpy(command, DELIVER); /* usually "/bin/rmail" */ ! 210: } /* if ( callmexmail ) */ ! 211: ! 212: /* Add the list of recipients to the command line. */ ! 213: ! 214: for (listpp = users; *listpp != NULL; listpp++) { ! 215: strcat(command, " "); ! 216: strcat(command, *listpp); ! 217: } ! 218: ! 219: /* NB: I think there may be a security problem ! 220: here, since popen ought to exec $SHELL. Check this. */ ! 221: /* Now actually call the mail delivery agent. */ ! 222: ! 223: ! 224: if ( (xfp = popen(command, "w")) == NULL ) { ! 225: /* Report a send error and return. */ ! 226: } ! 227: ! 228: /* Pump the headers into the delivery agent. */ ! 229: ! 230: build_header(xfp); ! 231: ! 232: /* Pump the message into the delivery agent. */ ! 233: ! 234: rewind(tfp); ! 235: mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0); ! 236: ! 237: fclose(xfp); ! 238: fclose(tfp); ! 239: } ! 240: ! 241: xsend(users, tfp) char **users; FILE *tfp; ! 242: { ! 243: register char **ulist; ! 244: register char *cp; ! 245: register struct passwd *pwp; ! 246: FILE *xfp; ! 247: ! 248: for (ulist = users; *ulist!=NULL; ulist++) { ! 249: rewind(tfp); ! 250: sprintf(boxname, "%s%s", SPOOLDIR, *ulist); ! 251: sprintf(cmdname, "xencode %s >> %s", *ulist, boxname); ! 252: if (index(*ulist, '!') != NULL ! 253: || (pwp = getpwnam(*ulist)) == NULL) { ! 254: mmsg(nosend, *ulist); ! 255: continue; ! 256: } ! 257: if (xaccess(*ulist) == 0) { ! 258: mmsg(nopubk, *ulist); ! 259: continue; ! 260: } ! 261: mlock(pwp->pw_uid); ! 262: if ((xfp = fopen(boxname, "a")) == NULL) { ! 263: mmsg(nosend, *ulist); ! 264: munlock(); ! 265: continue; ! 266: } ! 267: chown(boxname, pwp->pw_uid, pwp->pw_gid); ! 268: fprintf(xfp, "From xmail %s %s\n", cp, ! 269: tzname[tp->tm_isdst ? 1 : 0]); ! 270: fclose(xfp); ! 271: if ((xfp = popen(cmdname, "w")) == NULL) { ! 272: mmsg("Can't pipe to xencode\n"); ! 273: continue; ! 274: } ! 275: if (fwrite(header, strlen(header), 1, xfp) != 1 ! 276: || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0)) { ! 277: merr(wrerr, cmdname); ! 278: } ! 279: pclose(xfp); ! 280: munlock(); ! 281: } ! 282: fclose(tfp); ! 283: } ! 284: ! 285: uucpname() ! 286: { ! 287: FILE *uufile; ! 288: ! 289: if (NULL == (uufile = fopen(NODENAME, "r"))) { ! 290: strcpy(mysite, "<unknown>"); ! 291: return; ! 292: } ! 293: fgets(mysite, sizeof mysite, uufile); ! 294: mysite[strlen(mysite) - 1] = '\0'; /* remove '\n' */ ! 295: fclose(uufile); ! 296: return; ! 297: } ! 298: ! 299: domainname() ! 300: { ! 301: FILE *domfile; ! 302: if((domfile = fopen(DOMAINNAME, "r")) == NULL) { ! 303: strcpy(domain, ".UNKNOWN"); ! 304: return; ! 305: } ! 306: fgets(domain, sizeof domain, domfile); ! 307: domain [strlen(domain) - 1] = '\0'; ! 308: fclose (domfile); ! 309: return; ! 310: } ! 311: ! 312: char * ! 313: arpadate(tp) ! 314: struct tm *tp; ! 315: { ! 316: static char arpabuf [64]; ! 317: static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; ! 318: sprintf(arpabuf, "%d %c%c%c %d %02d:%02d:%02d", ! 319: tp->tm_mday, ! 320: months[tp->tm_mon * 3], ! 321: months[tp->tm_mon * 3 + 1], ! 322: months[tp->tm_mon * 3 + 2], ! 323: tp->tm_year, ! 324: tp->tm_hour, tp->tm_min, tp->tm_sec); ! 325: return arpabuf; ! 326: } ! 327: ! 328: char * ! 329: msgid(tp) ! 330: struct tm *tp; ! 331: { ! 332: static char msgidbuf [32]; ! 333: sprintf(msgidbuf, "%02d%02d%02d%02d%02d", ! 334: tp->tm_year, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); ! 335: return msgidbuf; ! 336: } ! 337: ! 338: build_header(xfp) ! 339: FILE *xfp; ! 340: { ! 341: char **ulist; ! 342: int processid; ! 343: ! 344: /* Generate a Message-Id. */ ! 345: processid = getpid(); ! 346: sprintf(header, "Message-Id: <%s.AA%d.V%s@%s.%s>\n", ! 347: msgid(tp), processid, revnop(), mysite, domain); ! 348: if (fwrite(header, strlen(header), 1, xfp) != 1) ! 349: return 0; ! 350: ! 351: /* generate Date: and From: lines. */ ! 352: sprintf(header, "Date: %s\nFrom: %s@%s.%s (%s)\n", ! 353: arpadate(tp), myname, mysite, domain, myfullname); ! 354: if (fwrite(header, strlen(header), 1, xfp) != 1) ! 355: return 0; ! 356: ! 357: /* Generate the full To: lines. We just spit addresses out ! 358: verbatum, with no cleanup. */ ! 359: strcpy(header, "To:"); ! 360: for (ulist=tolist; *ulist != NULL; ulist++) { ! 361: strcat(header, " "); ! 362: strcat(header, *ulist); ! 363: } ! 364: strcat(header, "\n"); ! 365: if (fwrite(header, strlen(header), 1, xfp) != 1) ! 366: return 0; ! 367: ! 368: /* Generate a Cc: line if needed. */ ! 369: if (cclist[0] != NULL) { ! 370: strcpy(header, "Cc:"); ! 371: for (ulist=cclist; *ulist != NULL; ulist++) { ! 372: strcat(header, " "); ! 373: strcat(header, *ulist); ! 374: } ! 375: strcat(header, "\n"); ! 376: if (fwrite(header, strlen(header), 1, xfp) != 1) ! 377: return 0; ! 378: } ! 379: return 1; ! 380: } ! 381:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.