#include <stdio.h> #include <pwd.h> #include <utmp.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <sys/timeb.h> #include <setjmp.h> #include <ctype.h> #include <dir.h> #define SMTP "/usr/lib/uucp/smtp" /*copylet flags */ /*remote mail, add rmtmsg */ #define REMOTE 1 #define INTERNET 4 /* zap header and trailing empty line */ #define ZAP 3 #define ORDINARY 2 #define SENDING 5 #define LSIZE 256 #define MAXLET 1000 /* maximum number of letters */ #define MAILMODE (~0644) /* mode of created mail */ #define FLIST "/etc/forwardlist" #define TMPNAME "/tmp/maXXXXX" /* definitions for inet gateways */ struct igateway { char *id; /* network identifier */ char *addr; /* address translation */ char *via; /* machine that talks to gateway */ char *cmd; /* command for gateway */ }; struct igateway igates[] = { "arpa_or_csnet", ".csnet-relay", "research", "/usr/mmdf/lib/mail", "csnet", ".csnet.csnet-relay", "research", "/usr/mmdf/lib/mail", "arpa", ".arpa.csnet-relay", "research", "/usr/mmdf/lib/mail", "acsnet", "", "research", "/usr/ACSnet/bin/inject", }; #define NIGATES 4 unsigned int igate; /* offset into igates (csnet by default) */ char line[LSIZE]; char resp[LSIZE]; struct let { long adr; char change; } let[MAXLET]; int nlet = 0; char lfil[50]; char *stringin(); FILE *popen(); char *getenv(); char tmpname[] = TMPNAME; char lettmp[sizeof(TMPNAME)]; char maildir[] = "/usr/spool/mail/"; char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx"; char dead[] = "dead.letter"; char whoami[] = "/etc/whoami"; #define FRWRD "Forward to " char *thissys = ""; FILE *tmpf; FILE *malf; char *my_name; char real_name[512]; char *getlogin(); struct passwd *getpwuid(); char *strchr(); int error; int changed; int forward; int onatty; char from[] = "From "; long ftell(); int delete(); int savdead(); int (*saveint)(); int (*setsig())(); char *strcpy(); char *strcat(); char *mktemp(); char *ctime(); long time(); int flgf; int flgp; int delflg = 1; int rflg; int frominet; int normtf; jmp_buf sjbuf; char dev[] = "/dev/"; void lock(), unlock(); main(argc, argv) char **argv; { static char sobuf[BUFSIZ]; char wsysname[32]; int f; char *prog; char *basename(); if (argc == 2 && (argv[1][0] == '-' && argv[1][1]=='n')) { struct stat s; char *ttyname(); char *p; fstat(2,&s); setgid(getgid()); setuid(getuid()); if ((p = ttyname(2)) && *p) chmod(p, s.st_mode ^ S_IEXEC); exit(0); } prog = basename(argv[0]); normtf = prog[0]=='r'; frominet = prog[0]=='c'; rflg = prog[0]=='r' || frominet; setbuf(stdout, sobuf); strcpy(lettmp, tmpname); mktemp(lettmp); unlink(lettmp); my_name = getlogin(); if (my_name==NULL) my_name = "daemon"; f = open(whoami, 0); if (f>=0) { wsysname[0] = '\0'; read(f, wsysname, 32); if (strchr(wsysname, '\n')) { *strchr(wsysname, '\n') = '\0'; thissys = wsysname; } close(f); } if(*thissys == 0) fprintf(stderr, "mail: bad data from %s\n", whoami); if(setjmp(sjbuf)) done(); setsig(SIGINT, delete); setsig(SIGHUP, delete); setsig(SIGKILL, delete); tmpf = fopen(lettmp, "w"); if (tmpf == NULL) { fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); done(); } chmod(lettmp, 0600); chown(lettmp, getuid(), getgid()); if( !rflg && /* no favors for rmail*/ (argc == 1 || (argv[1][0] == '-' && argv[1][1]!='R'))) printmail(argc, argv); else sendmail(argc, argv); done(); } char * basename(file) char *file; { char *base; char *strrchr(); if ((base = strrchr(file, '/')) != NULL) base++; /* past '/' */ else base = file; return (base); } int (*setsig(i, f))() int i; int (*f)(); { register int (*rc)(); if ((rc = signal(i, SIG_IGN))!=SIG_IGN) signal(i, f); return(rc); } sig_ign() { signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); } printmail(argc, argv) char **argv; { int flg, i, j, print; struct stat stbuf; char *p, *getarg(); char fbuf[256]; FILE *pipf; setgid(getgid()); setuid(getuid()); cat(mailfile, maildir, my_name); for (; argc>1; argv++, argc--) { if (argv[1][0]=='-') { if (argv[1][1]=='p') { flgp++; delflg = 0; } else if (argv[1][1]=='f') { if (argc>=3) { strcpy(mailfile, argv[2]); argv++; argc--; } } else if (argv[1][1]=='r') { forward = 1; } else { fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); done(); } } else break; } if (stat(mailfile, &stbuf) < 0 || stbuf.st_size == 0L) { printf("No mail.\n"); return; } malf = fopen(mailfile, "r"); if (malf == NULL) { fprintf(stderr, "mail: cannot read %s.\n", mailfile); return; } lock(mailfile); if(areforwarding(mailfile, fbuf)) { printf("Your mail is being forwarded to "); fseek(malf, (long)(sizeof(FRWRD) - 1), 0); fgets(fbuf, sizeof(fbuf), malf); printf("%s", fbuf); if(getc(malf) != EOF) printf("and your mailbox contains extra stuff\n"); unlock(); return; } copymt(malf, tmpf); fclose(malf); fclose(tmpf); unlock(); tmpf = fopen(lettmp, "r"); changed = 0; print = 1; for (i = 0; i < nlet; ) { j = forward ? i : nlet - i - 1; if(setjmp(sjbuf) == 0) { if (print) copylet(j, stdout, ORDINARY, (char *)NULL); print = 1; } if (flgp) { i++; continue; } setjmp(sjbuf); printf("? "); fflush(stdout); if (fgets(resp, LSIZE, stdin) == NULL) break; switch (resp[0]) { default: printf("usage\n"); case '?': print = 0; printf("q\tquit\n"); printf("x\texit without changing mail\n"); printf("p\tprint\n"); printf("s[file]\tsave (default mbox)\n"); printf("-\tprint previous\n"); printf("d\tdelete\n"); printf("+\tnext (no delete)\n"); printf("m user\tmail to user\n"); printf("! cmd\texecute cmd\n"); break; case '+': case 'n': case '\n': i++; break; case 'x': changed = 0; case 'q': goto donep; case 'p': break; case '^': case '-': if (--i < 0) i = 0; break; case 'y': case 'w': case 's': flg = 0; if (resp[1] != '\n' && resp[1] != ' ') { printf("invalid\n"); flg++; print = 0; continue; } if (resp[1] == '\n' || resp[1] == '\0') { p = getenv("HOME"); if(p != 0) cat(resp+1, p, "/mbox"); else cat(resp+1, "", "mbox"); } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { malf = fopen(lfil, "a"); if (malf == NULL) { fprintf(stderr, "mail: cannot append to %s\n", lfil); flg++; continue; } copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY, (char *)NULL); fclose(malf); } if (flg) print = 0; else { let[j].change = 'd'; changed++; i++; } break; case 'm': flg = 0; if (resp[1] == '\n' || resp[1] == '\0') { i++; continue; } if (resp[1] != ' ') { printf("invalid\n"); flg++; print = 0; continue; } strcpy(fbuf, "mail "); strcat(fbuf, resp+1); /* fork so that mail becomes super-user again */ pipf = popen(fbuf, "w"); if(pipf == NULL) { fprintf(stderr, "mail: can't fork to remail\n"); flg++; continue; } copylet(j, pipf, SENDING, (char *)NULL); flg |= pclose(pipf); if (flg) print = 0; else { let[j].change = 'd'; changed++; i++; } break; case '!': system(resp+1); printf("!\n"); print = 0; break; case 'd': let[j].change = 'd'; changed++; i++; if (resp[1] == 'q') goto donep; break; } } donep: if (changed) copyback(); } copyback() /* copy temp or whatever back to /usr/spool/mail */ { register i, c; register int new = 0; struct stat stbuf; sig_ign(); lock(mailfile); stat(mailfile, &stbuf); if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ malf = fopen(mailfile, "r"); if (malf == NULL) { fprintf(stderr, "mail: can't re-read %s\n", mailfile); done(); } fseek(malf, let[nlet].adr, 0); fclose(tmpf); tmpf = fopen(lettmp, "a"); fseek(tmpf, let[nlet].adr, 0); while ((c = fgetc(malf)) != EOF) fputc(c, tmpf); fclose(malf); fclose(tmpf); tmpf = fopen(lettmp, "r"); let[++nlet].adr = stbuf.st_size; new = 1; } malf = fopen(mailfile, "w"); if (malf == NULL) { fprintf(stderr, "mail: can't rewrite %s\n", mailfile); done(); } for (i = 0; i < nlet; i++) if (let[i].change != 'd') { copylet(i, malf, ORDINARY, (char *)NULL); } fclose(malf); if (new) printf("new mail arrived\n"); unlock(); } copymt(f1, f2) /* copy mail (f1) to temp (f2) */ FILE *f1, *f2; { long nextadr; nlet = nextadr = 0; let[0].adr = 0; while (fgets(line, LSIZE, f1) != NULL) { if (isfrom(line)) { let[nlet++].adr = nextadr; if (nlet > MAXLET) { fprintf (stderr, "mail: too many letters\n"); unlock(); exit(1); } } nextadr += strlen(line); fputs(line, f2); } let[nlet].adr = nextadr; /* last plus 1 */ } copylet(n, f, type, postmark) FILE *f; char *postmark; { long k; register ch; char *inetheader(); fseek(tmpf, let[n].adr, 0); k = let[n+1].adr - let[n].adr; if (postmark && type != ZAP) { if (type == INTERNET) postmark = inetheader (postmark); fputs(postmark, f); if (type==REMOTE) fprintf(f, " remote from %s", thissys); fputc('\n', f); } while (k>0) { ch = fgetc(tmpf); if (ch == EOF) break; fputc(ch, f); k--; } } areforwarding(s, sendto) char *s, *sendto; { FILE *fd; char fbuf[64], *p, *sp; fd = fopen(s, "r"); if(fd == NULL) return(0); fbuf[0] = '\0'; fgets(fbuf, sizeof(fbuf), fd); if (p = stringin(FRWRD, fbuf)) { while (*p == ' ') p++; sp = sendto; while (*p && *p!='\n') *sp++ = *p++; *sp = '\0'; fclose(fd); return(*sendto != 0); } fclose(fd); return(0); } isfrom(lp) register char *lp; { return(strncmp(lp, from, 5)==0); } sendmail(argc, argv) char **argv; { char *asctime(); struct timeb timbuf; struct tm *bp, *localtime(); char *tp, *zp, postmark[512]; char *timezone(); int rrrflg=0; long newpost(); while (argv[1][0]=='-') { switch(argv[1][1]) { case 'R': /* return receipt */ rrrflg = 1; } argc--; argv++; } ftime(&timbuf); bp = localtime(&timbuf.time); tp = asctime(bp); zp = timezone(timbuf.timezone, bp->tm_isdst); onatty = isatty(0); sprintf(postmark, "%s%s %.16s %.3s %.4s%s",from, my_name, tp, zp, tp+20, rrrflg?" (RRR)":""); flgf = 1; saveint = setsig(SIGINT, savdead); while (fgets(line, LSIZE, stdin) != NULL) { if (line[0] == '.' && line[1] == '\n' && onatty) break; if (isfrom(line)) fputs(">", tmpf); fputs(line, tmpf); flgf = 0; } setsig(SIGINT, saveint); if (line[0]!='\n' && error==0) fputs("\n", tmpf); nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); fclose(tmpf); if (flgf) return; tmpf = fopen(lettmp, "r"); if (tmpf == NULL) { fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); return; } let[0].adr = newpost(postmark); if (error == 0) while (--argc > 0) { if (!send(0, *++argv, 0, postmark)) error++; } if (error && onatty) { setgid(getgid()); setuid(getuid()); malf = fopen(dead, "w"); if (malf == NULL) { fprintf(stderr, "mail: cannot open %s\n", dead); fclose(tmpf); return; } copylet(0, malf, ZAP, (char *)NULL); fclose(malf); printf("Mail saved in %s\n", dead); } fclose(tmpf); } long newpost(pm) char *pm; { long inetpost(), unixpost(); if (frominet) return inetpost(pm); else return unixpost(pm); } long inetpost(pm) char *pm; { char line[512], date[64], *lp; /* get default source and date */ lp = strchr(pm+5, ' '); strcpy(date, lp); /* RFC 822 (or similar) */ /* construct the "From " line from the "From: " line */ while (fgets(line, sizeof(line), tmpf) != NULL) { line[strlen(line)-1] = '\0'; /* pick up from field */ if (strncmp("From: ", line, 6) == 0) { lp = strchr(line+6, ' '); if (lp) *lp = '\0'; sprintf(pm, "From %s", line+6); } /* pick up date field */ if (strncmp("Date: ", line, 6) == 0) strcpy(date, line+5); /* stop if we're out of header */ if (strchr(line, ':') == NULL && line[0] != ' ' && line[0] != '\t') break; } strcpy(real_name, pm+5); strcat(pm, date); return(0); } long unixpost(pm) char *pm; { long n = 0; char line[512], *cp, *lp; char rmtlist[512]; /* UNIX mail */ /* construct the "From " line from the existing ones */ rmtlist[0] = '\0'; while (fgets(line, sizeof(line), tmpf) != NULL) { /* stop if we run out of header */ if (stringin("From ", line)==NULL && stringin(">From ", line)==NULL) break; if ((cp = stringin(" remote from ", line))==NULL) break; /* get name of remote system and add to rmtlist */ line[strlen(line)-1] = '\0'; if (okrmt(cp) && n==0) normtf = 0; *(cp - sizeof(" remote from ") + 1) = '\0'; strcpy(pm, line[0] == '>' ? line + 1 : line); strcat(rmtlist, cp); strcat(rmtlist, "!"); n = ftell(tmpf); } /* tack sender's name and date onto the list of remote machines */ strcpy(line, pm); sprintf(pm, "From %s%s", rmtlist, line+5); if ((cp = strchr(line+5, ' ')) != NULL) *cp = '\0'; sprintf(real_name, "%s%s", rmtlist, line+5); return(n); } char * stringin(str, line) char *str, *line; { register char *sp, *lp; while (*line) { sp = str; lp = line++; for (;;) { if (*sp != *lp) { if (*sp=='\0') return(lp); break; } sp++; lp++; } } return(NULL); } /* * Return nonzero if forwarding is allowed to the system * named in the string at "cp". If we can't read the file * which contains the systems, assume blanket forwarding. */ okrmt(cp) char *cp; { register FILE *fp; char buf[20]; /* try to open the file; allow forwarding on failure */ fp = fopen (FLIST, "r"); if (fp == NULL) return 1; /* one iteration per system name in the file */ while (fgets (buf, sizeof buf, fp) != NULL) { buf[strlen(buf)-1] = '\0'; if (strcmp (buf, cp) == 0) { /* found it, allow forwarding */ fclose (fp); return 1; } } /* didn't find it, prohibit forwarding */ fclose (fp); return 0; } savdead() { setsig(SIGINT, saveint); error++; } sendrmt(n, name, postmark) char *name, *postmark; { FILE *rmf; register char *p, *q, *rmtid; char cmd[512], buf[512]; static forked; strcpy(buf, name); rmtid = strchr(name, '!'); if (rmtid == NULL || rmtid[1]=='\0') { fprintf(stderr, "mail: bad remote name\n"); return(0); } *rmtid++ = '\0'; if (normtf) for (p = q = &buf[0]; (p = strchr(q, '!')) && p[1] != '\0'; q = p + 1) { *p = '\0'; if (!okrmt(q)) { *--rmtid = '!'; refuse(n, name, postmark, "forwarding to this system disallowed"); return(1); } } if(onatty & !forked) { /* fork off remote send to avoid user tedium */ int p = fork(); if(p == 0) { sig_ign(); forked = 1; } else if(p != -1) exit(0); } if(access(SMTP, 0) != -1){ sprintf(cmd, "exec %s %s %s", SMTP, name, rmtid); if((rmf = popen(cmd, "w")) != NULL){ copylet(n, rmf, REMOTE, postmark); if(pclose(rmf) == 0) return(1); } } sprintf(cmd, "exec /usr/bin/uux - -a %s %s!rmail \\(%s\\)", real_name, name, rmtid); if ((rmf=popen(cmd, "w")) == NULL) { fprintf(stderr, "mail: can't pipe to uux\n"); exit(1); } copylet(n, rmf, REMOTE, postmark); *--rmtid = '!'; logsend(name, postmark, "remote"); return(pclose(rmf)==0); } send(n, name, level, postmark) /* send letter n to name */ int n; char *name, *postmark; { char file[512]; register mask; struct passwd *pw, *getpwnam(); struct stat stbuf; char sendto[256]; char inetaddr[256]; int exists; if(level > 20) { fprintf(stderr, "mail: unbounded forwarding\n"); return(0); } if (strcmp(name, "-") == 0) return(1); if (strchr(name, '!')) return(sendrmt(n, name, postmark)); if (strchr(name, '/')) { fprintf(stderr, "mail: illegal name %s\n", name); return(0); } cat(file, maildir, name); if(areforwarding(file, sendto)) { int rf, sval; rf = normtf; normtf = 0; /* to permit transshipping */ sval = send(n, sendto, level+1, postmark); normtf = rf; return(sval); } exists = stat(file, &stbuf); if ((pw = getpwnam(name)) == NULL) { if (exists < 0) { (void)strcpy (inetaddr, name); if (isinet(inetaddr)) { if (strcmp (thissys, igates[igate].via) == 0) { (void)inetgateaddr(inetaddr); return(sendinet(n,inetaddr,postmark)); } else { (void)strcpy (sendto, igates[igate].via); (void)strcat (sendto, "!"); (void)strcat (sendto, name); return(sendrmt(n, sendto, postmark)); } } if (rflg) { refuse(n, name, postmark, "addressee unknown"); return(1); } fprintf(stderr, "mail: can't send to %s\n", name); return(0); } } else { stbuf.st_uid = pw->pw_uid; stbuf.st_gid = pw->pw_gid; } mask = umask(MAILMODE); lock(file); malf = fopen(file, "a"); umask(mask); if (malf == NULL) { fprintf(stderr, "mail: cannot append to %s\n", file); return(0); } if (exists < 0) chown(file, stbuf.st_uid, stbuf.st_gid); copylet(n, malf, SENDING, postmark); fclose(malf); unlock(); logsend(name, postmark, "delivered"); notify(name); /* let him know it right away! */ return(1); } notify(name) char *name; { struct utmp entry; FILE *f; if ((f = fopen("/etc/utmp", "r")) == NULL) return; while (fread((char *)&entry, sizeof(entry), 1, f) == 1) { if (strncmp(name, entry.ut_name, sizeof(entry.ut_name)) == 0) blurb(entry.ut_line); } fclose(f); } blurb(tty) char *tty; { FILE *f = NULL; struct stat s; int blurbtime(); char devtty[32]; cat(devtty, dev, tty); signal(SIGALRM, blurbtime); alarm(30); stat(devtty, &s); if (s.st_mode & S_IEXEC) /* notify only if enabled */ if ((f = fopen(devtty, "w")) != NULL) { fprintf(f, "\r\n[%s: mail from %s]\r\n\7", thissys, real_name[0]?real_name: my_name); } if (f) fclose(f); alarm(0); } blurbtime() { } refuse(n, name, postmark, reason) char *name, *postmark, *reason; { FILE *pf; char cbuf[256], *cp; cp = strchr(postmark+5, ' '); if (cp == NULL) return; *cp = '\0'; sprintf(cbuf, "PATH=/bin:/usr/bin mail %s", postmark+5); *cp = ' '; if ((pf = popen(cbuf, "w")) == NULL) return; fprintf(pf, "Mail to %s failed: %s. Message was:\n", name, reason); copylet(n, pf, SENDING, postmark); pclose(pf); } delete(i) { setsig(i, delete); fprintf(stderr, "\n"); if(delflg) longjmp(sjbuf, 1); done(); } done() { unlock(); unlink(lettmp); exit(error); } #define LOCKPREFIX "/tmp/L." char lockname[DIRSIZ+sizeof(LOCKPREFIX)]; /* Lock the given file. The parameter "file" must contain at least one '/'. */ void lock(file) char *file; { # define TMPLNAME "/tmp/mlXXXXX" # define LOCKPREFIX "/tmp/L." char tmplname[sizeof(TMPLNAME)]; struct stat stbuf; int fd; /* return if we are already in the middle of a lock */ if (*lockname != '\0' || flgf) return; /* create a temporary file */ strcpy(tmplname, TMPLNAME); mktemp(tmplname); if ((fd=creat(tmplname, 0444))<0) return; close(fd); /* Make a link to it with the lock file name. This will fail only * if it already exists. */ strcpy(lockname, LOCKPREFIX); strcat(lockname, strrchr(file, '/')+1); lockname[DIRSIZ+sizeof("/tmp/")-1] = '\0'; while (link(tmplname, lockname) < 0) { long now; /* File is already locked. Break it if the lock is old. */ sleep(2); now = time((long *)0); if (stat(lockname, &stbuf)==0 && stbuf.st_ctime+60 < now) { if (stat(file, &stbuf)==0 && stbuf.st_mtime+60 >= now) continue; fprintf(stderr, "mail: breaking lock\n"); unlink(lockname); } } unlink(tmplname); return; } void unlock() { if (*lockname != '\0') unlink(lockname); *lockname = '\0'; } cat(to, from1, from2) char *to, *from1, *from2; { strcpy(to, from1); strcat(to, from2); } char *getarg(s, p) /* copy p... into s, update p */ register char *s, *p; { while (*p == ' ' || *p == '\t') p++; if (*p == '\n' || *p == '\0') return(NULL); while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') *s++ = *p++; *s = '\0'; return(p); } /* is this an internet address (characterized by "@" or ".") */ isinet(string) char *string; { char *rindex(); return rindex(string, '@') != 0 || rindex(string, '.') != 0; } /* add any gateway info to the address */ inetgateaddr(string) char *string; { char *at, *dot; char *rindex(); /* find last "." or "@" */ at = rindex (string, '@'); if (at != 0) dot = rindex (at + 1, '.'); else dot = rindex (string, '.'); if (dot != 0) at = dot; for (igate=0; igate<NIGATES; igate++) { if (istrcmp(at+1, igates[igate].id) == 0) { strcpy(at, igates[igate].addr); break; } } if (igate == NIGATES) { igate = 0; /* csnet or arpa, we really don't know */ strcat(string, igates[igate].addr); } } /* case insensitive strcmp */ istrcmp(p1, p2) char *p1, *p2; { do { if (tolower(*p1) != tolower(*p2)) return *p1 - *p2; p2++; } while (*p1++ != 0); return 0; } /* log a mail transmission */ logsend (to, pm, tag) char *to; /* receiver */ char *pm; /* the postmark */ char *tag; /* type of mail */ { # include <grp.h> # define LOGFILE "/usr/spool/mail/mail.log" # define LOGTEMP "/usr/spool/mail/mail.tmp" char buf[BUFSIZ]; int out, in; long len; struct stat sbuf; struct group sysgroup; struct group *getgrnam(); lock(LOGFILE); /* append to log */ if (stat(LOGFILE, &sbuf) < 0) { out = creat(LOGFILE, 0660); } else if (sbuf.st_size < 32000) { out = open(LOGFILE, 2); } else { out = creat(LOGTEMP, 0660); in = open(LOGFILE, 0); if (out >= 0 && in >= 0 && lseek(in, -4000L, 2) >= 0) { while ((len = read(in, buf, BUFSIZ)) > 0) (void)write(out, buf, len); close(in); close(out); unlink(LOGFILE); link(LOGTEMP, LOGFILE); unlink(LOGTEMP); } else { close(in); close(out); } out = open(LOGFILE, 2); } sprintf (buf, "%s %s %s\n", tag, to, pm); (void)lseek(out, 0, 2); (void)write(out, buf, strlen(buf)); close(out); unlock (); } /* * Stuff for INTERNET headers */ char * inetheader (pm) char *pm; { static char buf[256]; char *sender, *date; char *field[6]; int i; /* skip the old from field */ pm += strlen (from); /* skip over the sender */ for(sender=pm; !isspace(*sender) && *sender!=NULL; sender++) ; date = *sender == '\0' ? sender : sender+1; /* reverse the path and replace '!'s with '.'s */ (void)strcpy (buf, "From: "); while (sender >= pm) { for (*sender = NULL; sender >= pm && *sender != '!'; sender--) ; (void)strcat (buf, sender + 1); (void)strcat (buf, "."); } (void)strcat (buf, "btl."); /* change an asctime date to an INTERNET style one (yech!) */ /* parse the old date */ for (i = 0; i < 6; i++) { for (; isspace(*date) || *date==',' || *date=='-'; date++) ; field[i] = date; for (; !isspace(*date) && *date!=',' && *date!='-' && *date!='\0'; date++) ; if (*date != '\0') *date++ = '\0'; } /* output the arpa type format */ pm = buf + strlen (buf) - 1; sprintf (pm, "\nDate: %s %s %s %s %s\n", field[2], field[1], field[5], field[3], field[4]); return buf; } sendinet(n, name, postmark) char *name, *postmark; { FILE *rmf; char cmd[512], buf[512]; static forked; if (normtf) { refuse(n, name, postmark, "forwarding to this system disallowed"); return(1); } if(onatty & !forked) { int p = fork(); if(p == 0) { sig_ign(); forked = 1; } else if(p != -1) exit(0); } #ifndef DEBUG sprintf(cmd, "exec %s %s", igates[igate].cmd, name); #else sprintf(cmd, "echo %s %s; cat", igates[igate].cmd, name); #endif DEBUG if ((rmf=popen(cmd, "w")) == NULL) { fprintf(stderr, "mail: can't pipe to %s\n", igates[igate].cmd); exit(1); } copylet(n, rmf, INTERNET, postmark); logsend(name, postmark, igates[igate].id); return(pclose(rmf)==0); }