114465Ssam #ifndef lint 2*17533Sralph static char sccsid[] = "@(#)mail.local.c 4.24 (Berkeley) 12/18/84"; 314465Ssam #endif 414465Ssam 516731Sralph #include <sys/types.h> 616731Sralph #include <sys/stat.h> 716731Sralph #include <sys/file.h> 816731Sralph 9579Sroot #include <ctype.h> 10579Sroot #include <stdio.h> 11579Sroot #include <pwd.h> 12579Sroot #include <utmp.h> 13579Sroot #include <signal.h> 14579Sroot #include <setjmp.h> 15579Sroot #include <sysexits.h> 16579Sroot 179978Seric #define SENDMAIL "/usr/lib/sendmail" 18579Sroot 1916731Sralph /* copylet flags */ 2016731Sralph #define REMOTE 1 /* remote mail, add rmtmsg */ 2116731Sralph #define ORDINARY 2 2216731Sralph #define ZAP 3 /* zap header and trailing empty line */ 2316731Sralph #define FORWARD 4 24579Sroot 2516731Sralph #define LSIZE 256 2616731Sralph #define MAXLET 300 /* maximum number of letters */ 2716731Sralph #define MAILMODE 0600 /* mode of created mail */ 28579Sroot 29579Sroot char line[LSIZE]; 30579Sroot char resp[LSIZE]; 31579Sroot struct let { 32579Sroot long adr; 33579Sroot char change; 34579Sroot } let[MAXLET]; 35579Sroot int nlet = 0; 36579Sroot char lfil[50]; 37579Sroot long iop, time(); 38579Sroot char *getenv(); 39579Sroot char *index(); 40579Sroot char lettmp[] = "/tmp/maXXXXX"; 41579Sroot char maildir[] = "/usr/spool/mail/"; 42579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 43579Sroot char dead[] = "dead.letter"; 44579Sroot char forwmsg[] = " forwarded\n"; 45579Sroot FILE *tmpf; 46579Sroot FILE *malf; 47579Sroot char *my_name; 48579Sroot char *getlogin(); 49579Sroot int error; 50579Sroot int changed; 51579Sroot int forward; 52579Sroot char from[] = "From "; 53579Sroot long ftell(); 5416731Sralph int delex(); 55579Sroot char *ctime(); 56579Sroot int flgf; 57579Sroot int flgp; 58579Sroot int delflg = 1; 59579Sroot int hseqno; 60579Sroot jmp_buf sjbuf; 61579Sroot int rmail; 62579Sroot 63579Sroot main(argc, argv) 64579Sroot char **argv; 65579Sroot { 66579Sroot register i; 67579Sroot 68579Sroot my_name = getlogin(); 6916731Sralph if (my_name == NULL || *my_name == '\0') { 70579Sroot struct passwd *pwent; 71579Sroot pwent = getpwuid(getuid()); 72579Sroot if (pwent==NULL) 73579Sroot my_name = "???"; 74579Sroot else 75579Sroot my_name = pwent->pw_name; 76579Sroot } 7716731Sralph if (setjmp(sjbuf)) 7816731Sralph done(); 7914912Sralph for (i=SIGHUP; i<=SIGTERM; i++) 8016731Sralph setsig(i, delex); 81*17533Sralph i = mkstemp(lettmp); 82*17533Sralph tmpf = fdopen(i, "r+w"); 83*17533Sralph if (i < 0 || tmpf == NULL) 8416731Sralph panic("mail: %s: cannot open for writing", lettmp); 8516731Sralph /* 8616731Sralph * This protects against others reading mail from temp file and 8716731Sralph * if we exit, the file will be deleted already. 8816731Sralph */ 8916731Sralph unlink(lettmp); 90579Sroot if (argv[0][0] == 'r') 91579Sroot rmail++; 92579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 93579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 94579Sroot printmail(argc, argv); 95579Sroot else 966015Swnj bulkmail(argc, argv); 97579Sroot done(); 98579Sroot } 99579Sroot 100579Sroot setsig(i, f) 101579Sroot int i; 102579Sroot int (*f)(); 103579Sroot { 10416731Sralph if (signal(i, SIG_IGN) != SIG_IGN) 105579Sroot signal(i, f); 106579Sroot } 107579Sroot 108579Sroot any(c, str) 109579Sroot register int c; 110579Sroot register char *str; 111579Sroot { 112579Sroot 113579Sroot while (*str) 114579Sroot if (c == *str++) 115579Sroot return(1); 116579Sroot return(0); 117579Sroot } 118579Sroot 119579Sroot printmail(argc, argv) 12016731Sralph char **argv; 121579Sroot { 122579Sroot int flg, i, j, print; 123579Sroot char *p, *getarg(); 124579Sroot struct stat statb; 125579Sroot 126579Sroot setuid(getuid()); 127579Sroot cat(mailfile, maildir, my_name); 12816731Sralph #ifdef notdef 129579Sroot if (stat(mailfile, &statb) >= 0 130579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 131579Sroot strcat(mailfile, "/"); 132579Sroot strcat(mailfile, my_name); 133579Sroot } 13416731Sralph #endif 13516731Sralph for (; argc > 1; argv++, argc--) { 13616731Sralph if (argv[1][0] != '-') 13716731Sralph break; 13816731Sralph switch (argv[1][1]) { 13916731Sralph 14016731Sralph case 'p': 14116731Sralph flgp++; 14216731Sralph /* fall thru... */ 14316731Sralph case 'q': 14416731Sralph delflg = 0; 14516731Sralph break; 14616731Sralph 14716731Sralph case 'f': 14816731Sralph if (argc >= 3) { 14916731Sralph strcpy(mailfile, argv[2]); 15016731Sralph argv++, argc--; 151579Sroot } 152579Sroot break; 15316731Sralph 15416731Sralph case 'b': 15516731Sralph forward = 1; 15616731Sralph break; 15716731Sralph 15816731Sralph default: 15916731Sralph panic("unknown option %c", argv[1][1]); 16016731Sralph /*NOTREACHED*/ 16116731Sralph } 162579Sroot } 163579Sroot malf = fopen(mailfile, "r"); 164579Sroot if (malf == NULL) { 16516731Sralph printf("No mail.\n"); 166579Sroot return; 167579Sroot } 16816731Sralph flock(fileno(malf), LOCK_SH); 169579Sroot copymt(malf, tmpf); 17016731Sralph fclose(malf); /* implicit unlock */ 17116731Sralph fseek(tmpf, 0, L_SET); 172579Sroot 173579Sroot changed = 0; 174579Sroot print = 1; 175579Sroot for (i = 0; i < nlet; ) { 176579Sroot j = forward ? i : nlet - i - 1; 17716731Sralph if (setjmp(sjbuf)) { 17816731Sralph print = 0; 179579Sroot } else { 180579Sroot if (print) 181579Sroot copylet(j, stdout, ORDINARY); 182579Sroot print = 1; 183579Sroot } 184579Sroot if (flgp) { 185579Sroot i++; 186579Sroot continue; 187579Sroot } 188579Sroot setjmp(sjbuf); 18916731Sralph fputs("? ", stdout); 190579Sroot fflush(stdout); 191579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 192579Sroot break; 193579Sroot switch (resp[0]) { 194579Sroot 195579Sroot default: 19616731Sralph printf("usage\n"); 197579Sroot case '?': 198579Sroot print = 0; 19916731Sralph printf("q\tquit\n"); 20016731Sralph printf("x\texit without changing mail\n"); 20116731Sralph printf("p\tprint\n"); 20216731Sralph printf("s[file]\tsave (default mbox)\n"); 20316731Sralph printf("w[file]\tsame without header\n"); 20416731Sralph printf("-\tprint previous\n"); 20516731Sralph printf("d\tdelete\n"); 20616731Sralph printf("+\tnext (no delete)\n"); 20716731Sralph printf("m user\tmail to user\n"); 20816731Sralph printf("! cmd\texecute cmd\n"); 209579Sroot break; 210579Sroot 211579Sroot case '+': 212579Sroot case 'n': 213579Sroot case '\n': 214579Sroot i++; 215579Sroot break; 216579Sroot case 'x': 217579Sroot changed = 0; 218579Sroot case 'q': 219579Sroot goto donep; 220579Sroot case 'p': 221579Sroot break; 222579Sroot case '^': 223579Sroot case '-': 224579Sroot if (--i < 0) 225579Sroot i = 0; 226579Sroot break; 227579Sroot case 'y': 228579Sroot case 'w': 229579Sroot case 's': 230579Sroot flg = 0; 231579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 232579Sroot printf("illegal\n"); 233579Sroot flg++; 234579Sroot print = 0; 235579Sroot continue; 236579Sroot } 237579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 238579Sroot p = getenv("HOME"); 23916731Sralph if (p != 0) 240579Sroot cat(resp+1, p, "/mbox"); 241579Sroot else 242579Sroot cat(resp+1, "", "mbox"); 243579Sroot } 244579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 245579Sroot malf = fopen(lfil, "a"); 246579Sroot if (malf == NULL) { 24716731Sralph printf("mail: %s: cannot append\n", 24816731Sralph lfil); 249579Sroot flg++; 250579Sroot continue; 251579Sroot } 252579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 253579Sroot fclose(malf); 254579Sroot } 255579Sroot if (flg) 256579Sroot print = 0; 257579Sroot else { 258579Sroot let[j].change = 'd'; 259579Sroot changed++; 260579Sroot i++; 261579Sroot } 262579Sroot break; 263579Sroot case 'm': 264579Sroot flg = 0; 265579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 266579Sroot i++; 267579Sroot continue; 268579Sroot } 269579Sroot if (resp[1] != ' ') { 270579Sroot printf("invalid command\n"); 271579Sroot flg++; 272579Sroot print = 0; 273579Sroot continue; 274579Sroot } 275579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 27617019Sralph if (!sendmail(j, lfil, my_name)) 277579Sroot flg++; 278579Sroot if (flg) 279579Sroot print = 0; 280579Sroot else { 281579Sroot let[j].change = 'd'; 282579Sroot changed++; 283579Sroot i++; 284579Sroot } 285579Sroot break; 286579Sroot case '!': 287579Sroot system(resp+1); 288579Sroot printf("!\n"); 289579Sroot print = 0; 290579Sroot break; 291579Sroot case 'd': 292579Sroot let[j].change = 'd'; 293579Sroot changed++; 294579Sroot i++; 295579Sroot if (resp[1] == 'q') 296579Sroot goto donep; 297579Sroot break; 298579Sroot } 299579Sroot } 300579Sroot donep: 301579Sroot if (changed) 302579Sroot copyback(); 303579Sroot } 304579Sroot 30516731Sralph /* copy temp or whatever back to /usr/spool/mail */ 30616731Sralph copyback() 307579Sroot { 30816731Sralph register i, c; 30916731Sralph int fd, new = 0, oldmask; 310579Sroot struct stat stbuf; 311579Sroot 31216731Sralph #define mask(s) (1 << ((s) - 1)) 31316731Sralph oldmask = sigblock(mask(SIGINT)|mask(SIGHUP)|mask(SIGQUIT)); 31416731Sralph #undef mask 31516731Sralph fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); 31616731Sralph if (fd >= 0) { 31716731Sralph flock(fd, LOCK_EX); 31816731Sralph malf = fdopen(fd, "r+w"); 31916731Sralph } 32016731Sralph if (fd < 0 || malf == NULL) 32116731Sralph panic("can't rewrite %s", lfil); 32216731Sralph fstat(fd, &stbuf); 323579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 32416731Sralph fseek(malf, let[nlet].adr, L_SET); 32516731Sralph fseek(tmpf, let[nlet].adr, L_SET); 32616731Sralph while ((c = getc(malf)) != EOF) 32716731Sralph putc(c, tmpf); 328579Sroot let[++nlet].adr = stbuf.st_size; 329579Sroot new = 1; 33016731Sralph fseek(malf, 0, L_SET); 331579Sroot } 33216731Sralph ftruncate(fd, 0); 333579Sroot for (i = 0; i < nlet; i++) 33416731Sralph if (let[i].change != 'd') 335579Sroot copylet(i, malf, ORDINARY); 33616731Sralph fclose(malf); /* implict unlock */ 337579Sroot if (new) 33816731Sralph printf("New mail has arrived.\n"); 33916731Sralph sigsetmask(oldmask); 340579Sroot } 341579Sroot 34216731Sralph /* copy mail (f1) to temp (f2) */ 34316731Sralph copymt(f1, f2) 34416731Sralph FILE *f1, *f2; 345579Sroot { 346579Sroot long nextadr; 347579Sroot 348579Sroot nlet = nextadr = 0; 349579Sroot let[0].adr = 0; 350579Sroot while (fgets(line, LSIZE, f1) != NULL) { 351579Sroot if (isfrom(line)) 352579Sroot let[nlet++].adr = nextadr; 353579Sroot nextadr += strlen(line); 354579Sroot fputs(line, f2); 355579Sroot } 356579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 357579Sroot } 358579Sroot 35911893Seric copylet(n, f, type) 36011893Seric FILE *f; 36111893Seric { 36211893Seric int ch; 36311893Seric long k; 36416731Sralph char hostname[32]; 36511893Seric 36616731Sralph fseek(tmpf, let[n].adr, L_SET); 367579Sroot k = let[n+1].adr - let[n].adr; 36816731Sralph while (k-- > 1 && (ch = getc(tmpf)) != '\n') 36916731Sralph if (type != ZAP) 37016731Sralph putc(ch, f); 37116731Sralph switch (type) { 37216731Sralph 37316731Sralph case REMOTE: 3746199Sroot gethostname(hostname, sizeof (hostname)); 3756199Sroot fprintf(f, " remote from %s\n", hostname); 37616731Sralph break; 37716731Sralph 37816731Sralph case FORWARD: 379579Sroot fprintf(f, forwmsg); 38016731Sralph break; 38116731Sralph 38216731Sralph case ORDINARY: 38316731Sralph putc(ch, f); 38416731Sralph break; 38516731Sralph 38617019Sralph case ZAP: 38717019Sralph break; 38817019Sralph 38916731Sralph default: 39016731Sralph panic("Bad letter type %d to copylet.", type); 39116731Sralph } 39216731Sralph while (k-- > 1) { 39316731Sralph ch = getc(tmpf); 39416731Sralph putc(ch, f); 39516731Sralph } 39616731Sralph if (type != ZAP || ch != '\n') 39716731Sralph putc(getc(tmpf), f); 398579Sroot } 399579Sroot 400579Sroot isfrom(lp) 401579Sroot register char *lp; 402579Sroot { 403579Sroot register char *p; 404579Sroot 405579Sroot for (p = from; *p; ) 406579Sroot if (*lp++ != *p++) 407579Sroot return(0); 408579Sroot return(1); 409579Sroot } 410579Sroot 4116015Swnj bulkmail(argc, argv) 412579Sroot char **argv; 413579Sroot { 414579Sroot char truename[100]; 415579Sroot int first; 416579Sroot register char *cp; 417579Sroot int gaver = 0; 418579Sroot char *newargv[1000]; 419579Sroot register char **ap; 420579Sroot register char **vp; 421579Sroot int dflag; 422579Sroot 423579Sroot dflag = 0; 42416731Sralph if (argc < 1) { 425579Sroot fprintf(stderr, "puke\n"); 42616731Sralph return; 42716731Sralph } 428579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 429579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 430579Sroot dflag++; 43116731Sralph if (!dflag) { 4329978Seric /* give it to sendmail, rah rah! */ 433579Sroot unlink(lettmp); 434579Sroot ap = newargv+1; 435579Sroot if (rmail) 436579Sroot *ap-- = "-s"; 4379978Seric *ap = "-sendmail"; 4384461Sroot setuid(getuid()); 4399978Seric execv(SENDMAIL, ap); 4409978Seric perror(SENDMAIL); 441579Sroot exit(EX_UNAVAILABLE); 442579Sroot } 443579Sroot 444579Sroot truename[0] = 0; 445579Sroot line[0] = '\0'; 446579Sroot 447579Sroot /* 448579Sroot * When we fall out of this, argv[1] should be first name, 449579Sroot * argc should be number of names + 1. 450579Sroot */ 451579Sroot 452579Sroot while (argc > 1 && *argv[1] == '-') { 453579Sroot cp = *++argv; 454579Sroot argc--; 455579Sroot switch (cp[1]) { 456579Sroot case 'r': 45716731Sralph if (argc <= 1) 458579Sroot usage(); 45915346Skarels gaver++; 46015346Skarels strcpy(truename, argv[1]); 46115346Skarels fgets(line, LSIZE, stdin); 46215346Skarels if (strcmpn("From", line, 4) == 0) 46315346Skarels line[0] = '\0'; 464579Sroot argv++; 465579Sroot argc--; 466579Sroot break; 467579Sroot 468579Sroot case 'h': 46916731Sralph if (argc <= 1) 470579Sroot usage(); 471579Sroot hseqno = atoi(argv[1]); 472579Sroot argv++; 473579Sroot argc--; 474579Sroot break; 475579Sroot 476579Sroot case 'd': 477579Sroot break; 478579Sroot 479579Sroot default: 480579Sroot usage(); 481579Sroot } 482579Sroot } 48316731Sralph if (argc <= 1) 484579Sroot usage(); 485579Sroot if (gaver == 0) 486579Sroot strcpy(truename, my_name); 487579Sroot time(&iop); 488579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 489579Sroot iop = ftell(tmpf); 49016731Sralph flgf = first = 1; 49116731Sralph for (;;) { 49216731Sralph if (first) { 49316731Sralph first = 0; 49416731Sralph if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) 49516731Sralph break; 49616731Sralph } else { 49716731Sralph if (fgets(line, LSIZE, stdin) == NULL) 49816731Sralph break; 49916731Sralph } 50016731Sralph if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) 501579Sroot break; 502579Sroot if (isfrom(line)) 50316731Sralph putc('>', tmpf); 504579Sroot fputs(line, tmpf); 505579Sroot flgf = 0; 506579Sroot } 50716731Sralph putc('\n', tmpf); 508579Sroot nlet = 1; 509579Sroot let[0].adr = 0; 510579Sroot let[1].adr = ftell(tmpf); 511579Sroot if (flgf) 512579Sroot return; 51316731Sralph while (--argc > 0) 5146015Swnj if (!sendmail(0, *++argv, truename)) 515579Sroot error++; 51610644Seric if (error && safefile(dead)) { 517579Sroot setuid(getuid()); 518579Sroot malf = fopen(dead, "w"); 519579Sroot if (malf == NULL) { 52016731Sralph printf("mail: cannot open %s\n", dead); 521579Sroot fclose(tmpf); 522579Sroot return; 523579Sroot } 524579Sroot copylet(0, malf, ZAP); 525579Sroot fclose(malf); 52616731Sralph printf("Mail saved in %s\n", dead); 527579Sroot } 528579Sroot fclose(tmpf); 529579Sroot } 530579Sroot 53117019Sralph sendrmt(n, name) 532579Sroot char *name; 533579Sroot { 534579Sroot FILE *rmf, *popen(); 535579Sroot register char *p; 536579Sroot char rsys[64], cmd[64]; 53717019Sralph register pid; 538579Sroot int sts; 539579Sroot 54017019Sralph #ifdef notdef 54117019Sralph if (any('^', name)) { 542579Sroot while (p = index(name, '^')) 543579Sroot *p = '!'; 544579Sroot if (strncmp(name, "researc", 7)) { 545579Sroot strcpy(rsys, "research"); 546579Sroot if (*name != '!') 547579Sroot --name; 548579Sroot goto skip; 549579Sroot } 550579Sroot } 55117019Sralph #endif 55217019Sralph for (p=rsys; *name!='!'; *p++ = *name++) 55317019Sralph if (*name=='\0') 55417019Sralph return(0); /* local address, no '!' */ 555579Sroot *p = '\0'; 55617019Sralph if (name[1]=='\0') { 55716731Sralph printf("null name\n"); 558579Sroot return(0); 559579Sroot } 560579Sroot skip: 561579Sroot if ((pid = fork()) == -1) { 562579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 563579Sroot return(0); 564579Sroot } 565579Sroot if (pid) { 566579Sroot while (wait(&sts) != pid) { 567579Sroot if (wait(&sts)==-1) 568579Sroot return(0); 569579Sroot } 570579Sroot return(!sts); 571579Sroot } 572579Sroot setuid(getuid()); 57317019Sralph if (any('!', name+1)) 57417019Sralph sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 57517019Sralph else 57617019Sralph sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 577579Sroot if ((rmf=popen(cmd, "w")) == NULL) 578579Sroot exit(1); 57917019Sralph copylet(n, rmf, REMOTE); 58010783Seric exit(pclose(rmf) != 0); 581579Sroot } 582579Sroot 583579Sroot usage() 584579Sroot { 585579Sroot 586579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 58715299Skarels error = EX_USAGE; 58816731Sralph done(); 589579Sroot } 590579Sroot 5916015Swnj #include <sys/socket.h> 5929226Ssam #include <netinet/in.h> 59310227Ssam #include <netdb.h> 5946015Swnj 59516731Sralph notifybiff(msg) 59616731Sralph char *msg; 59716731Sralph { 59816731Sralph static struct sockaddr_in addr; 59916731Sralph static int f = -1; 60016731Sralph 60116731Sralph if (addr.sin_family == 0) { 60216731Sralph struct hostent *hp = gethostbyname("localhost"); 60316731Sralph struct servent *sp = getservbyname("biff", "udp"); 60416731Sralph 60516731Sralph if (hp && sp) { 60616731Sralph addr.sin_family = hp->h_addrtype; 60716731Sralph bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 60816731Sralph addr.sin_port = sp->s_port; 60916731Sralph } 61016731Sralph } 61116731Sralph if (addr.sin_family) { 61216731Sralph if (f < 0) 61316731Sralph f = socket(AF_INET, SOCK_DGRAM, 0); 61416731Sralph sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); 61516731Sralph } 61616731Sralph } 61716731Sralph 6186015Swnj sendmail(n, name, fromaddr) 61916731Sralph int n; 62016731Sralph char *name, *fromaddr; 621579Sroot { 62216731Sralph char file[256]; 62316731Sralph int mask, fd; 62416731Sralph struct passwd *pw; 62516731Sralph #ifdef notdef 626579Sroot struct stat statb; 62716731Sralph #endif 6283666Swnj char buf[128]; 629579Sroot 63017019Sralph if (*name=='!') 63117019Sralph name++; 63217019Sralph if (any('!', name)) 63317019Sralph return (sendrmt(n, name)); 634579Sroot if ((pw = getpwnam(name)) == NULL) { 63516731Sralph printf("mail: can't send to %s\n", name); 636579Sroot return(0); 637579Sroot } 638579Sroot cat(file, maildir, name); 63916731Sralph #ifdef notdef 640579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 641579Sroot strcat(file, "/"); 642579Sroot strcat(file, name); 643579Sroot } 64416731Sralph #endif 64510644Seric if (!safefile(file)) 6464458Sroot return(0); 64716731Sralph fd = open(file, O_WRONLY | O_CREAT, MAILMODE); 64816731Sralph if (fd >= 0) { 64916731Sralph flock(fd, LOCK_EX); 65016731Sralph malf = fdopen(fd, "a"); 65116731Sralph } 65216731Sralph if (fd < 0 || malf == NULL) { 65316731Sralph close(fd); 65416731Sralph printf("mail: %s: cannot append\n", file); 655579Sroot return(0); 656579Sroot } 65716731Sralph fchown(fd, pw->pw_uid, pw->pw_gid); 65816731Sralph sprintf(buf, "%s@%d\n", name, ftell(malf)); 659579Sroot copylet(n, malf, ORDINARY); 6606015Swnj fclose(malf); 66116731Sralph notifybiff(buf); 662579Sroot return(1); 663579Sroot } 664579Sroot 66516731Sralph delex(i) 666579Sroot { 66716731Sralph setsig(i, delex); 66816731Sralph putc('\n', stderr); 66916731Sralph if (delflg) 670579Sroot longjmp(sjbuf, 1); 671579Sroot done(); 672579Sroot } 673579Sroot 67416731Sralph done() 675579Sroot { 676579Sroot 677579Sroot unlink(lettmp); 678579Sroot exit(error); 679579Sroot } 680579Sroot 681579Sroot cat(to, from1, from2) 68216731Sralph char *to, *from1, *from2; 683579Sroot { 68416731Sralph register char *cp, *dp; 685579Sroot 68616731Sralph cp = to; 68716731Sralph for (dp = from1; *cp = *dp++; cp++) 68816731Sralph ; 68916731Sralph for (dp = from2; *cp++ = *dp++; ) 69016731Sralph ; 691579Sroot } 692579Sroot 69316731Sralph /* copy p... into s, update p */ 69416731Sralph char * 69516731Sralph getarg(s, p) 69616731Sralph register char *s, *p; 697579Sroot { 698579Sroot while (*p == ' ' || *p == '\t') 699579Sroot p++; 700579Sroot if (*p == '\n' || *p == '\0') 701579Sroot return(NULL); 702579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 703579Sroot *s++ = *p++; 704579Sroot *s = '\0'; 705579Sroot return(p); 706579Sroot } 70710644Seric 70810644Seric safefile(f) 70910644Seric char *f; 71010644Seric { 71110644Seric struct stat statb; 71210644Seric 71310644Seric if (lstat(f, &statb) < 0) 71410644Seric return (1); 71510644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 71616731Sralph fprintf(stderr, 71716731Sralph "mail: %s has more than one link or is a symbolic link\n", 71816731Sralph f); 71910644Seric return (0); 72010644Seric } 72110644Seric return (1); 72210644Seric } 72316731Sralph 72416731Sralph panic(msg, a1, a2, a3) 72516731Sralph char *msg; 72616731Sralph { 72716731Sralph 72816731Sralph fprintf(stderr, "mail: "); 72916731Sralph fprintf(stderr, msg, a1, a2, a3); 73016731Sralph fprintf(stderr, "\n"); 73116731Sralph done(); 73216731Sralph } 733