|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 15286 (0x3bb6) Types: TextFile Names: »binmail.c,v«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« └─⟦f9e35cd84⟧ └─⟦this⟧ »sendmail/binmail/RCS/binmail.c,v«
head 4.36; branch 4.36.0; access ; symbols UICSO:4.36.0 VANILLA:4.36; locks ; strict; comment @ * @; 4.36 date 90.11.30.14.14.06; author paul; state Exp; branches 4.36.0.1; next ; 4.36.0.1 date 90.11.30.14.22.29; author paul; state Exp; branches ; next ; desc @@ 4.36 log @Sendmail V5.65 distribution @ text @#ifndef lint static char sccsid[] = "@@(#)delivermail.c 4.36 (Berkeley) 4/21/89"; #endif #include <sys/param.h> #include <sys/stat.h> #include <sys/file.h> #include <ctype.h> #include <stdio.h> #include <pwd.h> #include <utmp.h> #include <signal.h> #include <setjmp.h> #include <sysexits.h> #include "pathnames.h" /* copylet flags */ #define REMOTE 1 /* remote mail, add rmtmsg */ #define ORDINARY 2 #define ZAP 3 /* zap header and trailing empty line */ #define FORWARD 4 #define LSIZE 256 #define MAXLET 300 /* maximum number of letters */ #define MAILMODE 0600 /* mode of created mail */ char line[LSIZE]; char resp[LSIZE]; struct let { long adr; char change; } let[MAXLET]; int nlet = 0; char lfil[50]; long iop, time(); char *getenv(); char *index(); char lettmp[] = _PATH_TMP; char maildir[] = _PATH_MAILDIR; char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; char dead[] = "dead.letter"; char forwmsg[] = " forwarded\n"; FILE *tmpf; FILE *malf; char my_name[60]; char *getlogin(); int error; int changed; int forward; char from[] = "From "; long ftell(); int delex(); char *ctime(); int flgf; int flgp; int delflg = 1; int hseqno; jmp_buf sjbuf; int rmail; main(argc, argv) char **argv; { register int i; char *name; struct passwd *pwent; if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || getuid() != pwent->pw_uid) pwent = getpwuid(getuid()); strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1); if (setjmp(sjbuf)) done(); for (i=SIGHUP; i<=SIGTERM; i++) setsig(i, delex); i = mkstemp(lettmp); tmpf = fdopen(i, "r+"); if (i < 0 || tmpf == NULL) panic("mail: %s: cannot open for writing", lettmp); /* * This protects against others reading mail from temp file and * if we exit, the file will be deleted already. */ unlink(lettmp); if (argv[0][0] == 'r') rmail++; if (argv[0][0] != 'r' && /* no favors for rmail*/ (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) printmail(argc, argv); else bulkmail(argc, argv); done(); } setsig(i, f) int i; int (*f)(); { if (signal(i, SIG_IGN) != SIG_IGN) signal(i, f); } any(c, str) register int c; register char *str; { while (*str) if (c == *str++) return(1); return(0); } printmail(argc, argv) char **argv; { int flg, i, j, print; char *p, *getarg(); struct stat statb; setuid(getuid()); cat(mailfile, maildir, my_name); #ifdef notdef if (stat(mailfile, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { strcat(mailfile, "/"); strcat(mailfile, my_name); } #endif for (; argc > 1; argv++, argc--) { if (argv[1][0] != '-') break; switch (argv[1][1]) { case 'p': flgp++; /* fall thru... */ case 'q': delflg = 0; break; case 'f': if (argc >= 3) { strcpy(mailfile, argv[2]); argv++, argc--; } break; case 'b': forward = 1; break; default: panic("unknown option %c", argv[1][1]); /*NOTREACHED*/ } } malf = fopen(mailfile, "r"); if (malf == NULL) { printf("No mail.\n"); return; } flock(fileno(malf), LOCK_SH); copymt(malf, tmpf); fclose(malf); /* implicit unlock */ fseek(tmpf, 0L, L_SET); changed = 0; print = 1; for (i = 0; i < nlet; ) { j = forward ? i : nlet - i - 1; if (setjmp(sjbuf)) { print = 0; } else { if (print) copylet(j, stdout, ORDINARY); print = 1; } if (flgp) { i++; continue; } setjmp(sjbuf); fputs("? ", stdout); 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("w[file]\tsame without header\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("illegal\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) { printf("mail: %s: cannot append\n", lfil); flg++; continue; } copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 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 command\n"); flg++; print = 0; continue; } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) if (!sendmail(j, lfil, my_name)) flg++; 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(); } /* copy temp or whatever back to /usr/spool/mail */ copyback() { register int i, c; long oldmask; int fd, new = 0; struct stat stbuf; oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT)); fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); if (fd >= 0) { flock(fd, LOCK_EX); malf = fdopen(fd, "r+"); } if (fd < 0 || malf == NULL) panic("can't rewrite %s", lfil); fstat(fd, &stbuf); if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ fseek(malf, let[nlet].adr, L_SET); fseek(tmpf, let[nlet].adr, L_SET); while ((c = getc(malf)) != EOF) putc(c, tmpf); let[++nlet].adr = stbuf.st_size; new = 1; fseek(malf, 0L, L_SET); } ftruncate(fd, 0L); for (i = 0; i < nlet; i++) if (let[i].change != 'd') copylet(i, malf, ORDINARY); fclose(malf); /* implict unlock */ if (new) printf("New mail has arrived.\n"); sigsetmask(oldmask); } /* copy mail (f1) to temp (f2) */ copymt(f1, 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; nextadr += strlen(line); fputs(line, f2); } let[nlet].adr = nextadr; /* last plus 1 */ } copylet(n, f, type) FILE *f; { int ch; long k; char hostname[MAXHOSTNAMELEN]; fseek(tmpf, let[n].adr, L_SET); k = let[n+1].adr - let[n].adr; while (k-- > 1 && (ch = getc(tmpf)) != '\n') if (type != ZAP) putc(ch, f); switch (type) { case REMOTE: gethostname(hostname, sizeof (hostname)); fprintf(f, " remote from %s\n", hostname); break; case FORWARD: fprintf(f, forwmsg); break; case ORDINARY: putc(ch, f); break; case ZAP: break; default: panic("Bad letter type %d to copylet.", type); } while (k-- > 1) { ch = getc(tmpf); putc(ch, f); } if (type != ZAP || ch != '\n') putc(getc(tmpf), f); } isfrom(lp) register char *lp; { register char *p; for (p = from; *p; ) if (*lp++ != *p++) return(0); return(1); } bulkmail(argc, argv) char **argv; { char *truename; int first; register char *cp; char *newargv[1000]; register char **ap; register char **vp; int dflag; dflag = 0; delflg = 0; if (argc < 1) { fprintf(stderr, "puke\n"); return; } for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) if (ap[0][0] == '-' && ap[0][1] == 'd') dflag++; if (!dflag) { /* give it to sendmail, rah rah! */ unlink(lettmp); ap = newargv+1; if (rmail) *ap-- = "-s"; *ap = "-sendmail"; setuid(getuid()); execv(_PATH_SENDMAIL, ap); perror(_PATH_SENDMAIL); exit(EX_UNAVAILABLE); } truename = 0; line[0] = '\0'; /* * When we fall out of this, argv[1] should be first name, * argc should be number of names + 1. */ while (argc > 1 && *argv[1] == '-') { cp = *++argv; argc--; switch (cp[1]) { case 'r': if (argc <= 1) usage(); truename = argv[1]; fgets(line, LSIZE, stdin); if (strncmp("From", line, 4) == 0) line[0] = '\0'; argv++; argc--; break; case 'h': if (argc <= 1) usage(); hseqno = atoi(argv[1]); argv++; argc--; break; case 'd': break; default: usage(); } } if (argc <= 1) usage(); if (truename == 0) truename = my_name; time(&iop); fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); iop = ftell(tmpf); flgf = first = 1; for (;;) { if (first) { first = 0; if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) break; } else { if (fgets(line, LSIZE, stdin) == NULL) break; } if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) break; if (isfrom(line)) putc('>', tmpf); fputs(line, tmpf); flgf = 0; } putc('\n', tmpf); nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); if (flgf) return; while (--argc > 0) if (!sendmail(0, *++argv, truename)) error++; if (error && safefile(dead)) { setuid(getuid()); malf = fopen(dead, "w"); if (malf == NULL) { printf("mail: cannot open %s\n", dead); fclose(tmpf); return; } copylet(0, malf, ZAP); fclose(malf); printf("Mail saved in %s\n", dead); } fclose(tmpf); } sendrmt(n, name) char *name; { FILE *rmf, *popen(); register char *p; char rsys[64], cmd[64]; register pid; int sts; #ifdef notdef if (any('^', name)) { while (p = index(name, '^')) *p = '!'; if (strncmp(name, "researc", 7)) { strcpy(rsys, "research"); if (*name != '!') --name; goto skip; } } #endif for (p=rsys; *name!='!'; *p++ = *name++) if (*name=='\0') return(0); /* local address, no '!' */ *p = '\0'; if (name[1]=='\0') { printf("null name\n"); return(0); } skip: if ((pid = fork()) == -1) { fprintf(stderr, "mail: can't create proc for remote\n"); return(0); } if (pid) { while (wait(&sts) != pid) { if (wait(&sts)==-1) return(0); } return(!sts); } setuid(getuid()); if (any('!', name+1)) (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); else (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); if ((rmf=popen(cmd, "w")) == NULL) exit(1); copylet(n, rmf, REMOTE); exit(pclose(rmf) != 0); } usage() { fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); error = EX_USAGE; done(); } #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> notifybiff(msg) char *msg; { static struct sockaddr_in addr; static int f = -1; if (addr.sin_family == 0) { struct hostent *hp = gethostbyname("localhost"); struct servent *sp = getservbyname("biff", "udp"); if (hp && sp) { addr.sin_family = hp->h_addrtype; bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); addr.sin_port = sp->s_port; } } if (addr.sin_family) { if (f < 0) f = socket(AF_INET, SOCK_DGRAM, 0); if (f >= 0) sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); } } sendmail(n, name, fromaddr) int n; char *name, *fromaddr; { char file[256]; int mask, fd; struct passwd *pw; #ifdef notdef struct stat statb; #endif char buf[128]; if (*name=='!') name++; if (any('!', name)) return (sendrmt(n, name)); if ((pw = getpwnam(name)) == NULL) { printf("mail: can't send to %s\n", name); return(0); } cat(file, maildir, name); #ifdef notdef if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { strcat(file, "/"); strcat(file, name); } #endif if (!safefile(file)) return(0); fd = open(file, O_WRONLY | O_CREAT, MAILMODE); if (fd >= 0) { flock(fd, LOCK_EX); malf = fdopen(fd, "a"); } if (fd < 0 || malf == NULL) { close(fd); printf("mail: %s: cannot append\n", file); return(0); } fchown(fd, pw->pw_uid, pw->pw_gid); (void)sprintf(buf, "%s@@%ld\n", name, ftell(malf)); copylet(n, malf, ORDINARY); fclose(malf); notifybiff(buf); return(1); } delex(i) { if (i != SIGINT) { setsig(i, SIG_DFL); sigsetmask(sigblock(0L) &~ sigmask(i)); } putc('\n', stderr); if (delflg) longjmp(sjbuf, 1); if (error == 0) error = i; done(); } done() { unlink(lettmp); exit(error); } cat(to, from1, from2) char *to, *from1, *from2; { register char *cp, *dp; cp = to; for (dp = from1; *cp = *dp++; cp++) ; for (dp = from2; *cp++ = *dp++; ) ; } /* copy p... into s, update p */ char * getarg(s, 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); } safefile(f) char *f; { struct stat statb; if (lstat(f, &statb) < 0) return (1); if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f); return (0); } return (1); } panic(msg, a1, a2, a3) char *msg; { fprintf(stderr, "mail: "); fprintf(stderr, msg, a1, a2, a3); fprintf(stderr, "\n"); done(); } @ 4.36.0.1 log @Date: Fri, 23 Nov 90 14:44:41 +1300 To: "Paul Pomes, UofIllinois-CSO" <paul@@uxc.cso.uiuc.edu> From: Andy.Linton@@comp.vuw.ac.nz Subject: locking in /bin/mail (with the details (:-)) X-Mailer: XMH (using mh 6.7) We use the LCK_BEL locking in 'mh' as we have the spool directory mounted via NFS. The flock (real or emulated) is not good enough and results in races which unfortunately end up in "dead heats" at times. @ text @a120 4 #if defined(MH_LCK_BEL) int lk_fd; extern int lkopen(), lkclose(); #endif /* MH_LCK_BEL */ a158 7 #if defined(LOCKF_FLOCK) /* * We can't get a lock on a file that * isn't opened for writing - sigh! */ malf = fopen(mailfile, "r+"); #else a159 1 #endif /* LOCKF_FLOCK */ a163 3 #if defined(MH_LCK_BEL) lk_fd = lkopen(mailfile, O_RDONLY); #endif /* MH_LCK_BEL */ a166 3 #if defined(MH_LCK_BEL) (void) lkclose(lk_fd, mailfile); #endif /* MH_LCK_BEL */ a307 4 #if defined(MH_LCK_BEL) int lk_fd; extern int lkopen(), lkclose(); #endif /* MH_LCK_BEL */ d312 2 a313 5 #if defined(MH_LCK_BEL) lk_fd = lkopen(mailfile, O_RDWR); #endif /* MH_LCK_BEL */ flock(fd, LOCK_EX); malf = fdopen(fd, "r+"); a331 3 #if defined(MH_LCK_BEL) (void) lkclose(lk_fd, mailfile); #endif /* MH_LCK_BEL */ a623 4 #if defined(MH_LCK_BEL) int lk_fd; extern int lkopen(), lkclose(); #endif /* MH_LCK_BEL */ d644 2 a645 5 #if defined(MH_LCK_BEL) lk_fd = lkopen(mailfile, O_RDWR); #endif /* MH_LCK_BEL */ flock(fd, LOCK_EX); malf = fdopen(fd, "a"); a655 4 #if defined(MH_LCK_BEL) (void) lkclose(lk_fd, mailfile); #endif /* MH_LCK_BEL */ @