1579Sroot #include <ctype.h> 2579Sroot #include <stdio.h> 3579Sroot #include <pwd.h> 4579Sroot #include <utmp.h> 5579Sroot #include <signal.h> 6579Sroot #include <sys/types.h> 7579Sroot #include <sys/stat.h> 8579Sroot #include <setjmp.h> 9579Sroot #include <sysexits.h> 10579Sroot 11*11893Seric static char SccsId[] = "@(#)mail.local.c 4.14 04/10/83"; 12580Seric 139978Seric #define SENDMAIL "/usr/lib/sendmail" 14579Sroot 15579Sroot 16579Sroot /*copylet flags */ 17579Sroot /*remote mail, add rmtmsg */ 18579Sroot #define REMOTE 1 19579Sroot /* zap header and trailing empty line */ 20579Sroot #define ZAP 3 21579Sroot #define ORDINARY 2 22579Sroot #define FORWARD 4 23579Sroot #define LSIZE 256 24579Sroot #define MAXLET 300 /* maximum number of letters */ 25579Sroot #define MAILMODE (~0644) /* mode of created mail */ 26579Sroot 27579Sroot char line[LSIZE]; 28579Sroot char resp[LSIZE]; 29579Sroot struct let { 30579Sroot long adr; 31579Sroot char change; 32579Sroot } let[MAXLET]; 33579Sroot int nlet = 0; 34579Sroot char lfil[50]; 35579Sroot long iop, time(); 36579Sroot char *getenv(); 37579Sroot char *index(); 38579Sroot char lettmp[] = "/tmp/maXXXXX"; 39579Sroot char maildir[] = "/usr/spool/mail/"; 40579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 41579Sroot char dead[] = "dead.letter"; 42579Sroot char *netname = "vax"; 43579Sroot char forwmsg[] = " forwarded\n"; 44579Sroot FILE *tmpf; 45579Sroot FILE *malf; 46579Sroot char *my_name; 47579Sroot char *getlogin(); 48579Sroot struct passwd *getpwuid(); 49579Sroot int error; 50579Sroot int changed; 51579Sroot int forward; 52579Sroot char from[] = "From "; 53579Sroot long ftell(); 54579Sroot int delete(); 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 char sobuf[BUFSIZ]; 68579Sroot 69579Sroot setbuf(stdout, sobuf); 70579Sroot mktemp(lettmp); 71579Sroot unlink(lettmp); 72579Sroot my_name = getlogin(); 73579Sroot if (my_name == NULL || strlen(my_name) == 0) { 74579Sroot struct passwd *pwent; 75579Sroot pwent = getpwuid(getuid()); 76579Sroot if (pwent==NULL) 77579Sroot my_name = "???"; 78579Sroot else 79579Sroot my_name = pwent->pw_name; 80579Sroot } 81579Sroot if(setjmp(sjbuf)) done(); 82579Sroot for (i=0; i<20; i++) 83579Sroot setsig(i, delete); 84579Sroot tmpf = fopen(lettmp, "w"); 85579Sroot if (tmpf == NULL) { 86579Sroot fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); 87579Sroot done(); 88579Sroot } 89579Sroot if (argv[0][0] == 'r') 90579Sroot rmail++; 91579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 92579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 93579Sroot printmail(argc, argv); 94579Sroot else 956015Swnj bulkmail(argc, argv); 96579Sroot done(); 97579Sroot } 98579Sroot 99579Sroot setsig(i, f) 100579Sroot int i; 101579Sroot int (*f)(); 102579Sroot { 103579Sroot if(signal(i, SIG_IGN)!=SIG_IGN) 104579Sroot signal(i, f); 105579Sroot } 106579Sroot 107579Sroot any(c, str) 108579Sroot register int c; 109579Sroot register char *str; 110579Sroot { 111579Sroot 112579Sroot while (*str) 113579Sroot if (c == *str++) 114579Sroot return(1); 115579Sroot return(0); 116579Sroot } 117579Sroot 118579Sroot printmail(argc, argv) 119579Sroot char **argv; 120579Sroot { 121579Sroot int flg, i, j, print; 122579Sroot char *p, *getarg(); 123579Sroot struct stat statb; 124579Sroot 125579Sroot setuid(getuid()); 126579Sroot cat(mailfile, maildir, my_name); 127579Sroot if (stat(mailfile, &statb) >= 0 128579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 129579Sroot strcat(mailfile, "/"); 130579Sroot strcat(mailfile, my_name); 131579Sroot } 132579Sroot for (; argc>1; argv++, argc--) { 133579Sroot if (argv[1][0]=='-') { 134579Sroot if (argv[1][1]=='q') 135579Sroot delflg = 0; 136579Sroot else if (argv[1][1]=='p') { 137579Sroot flgp++; 138579Sroot delflg = 0; 139579Sroot } else if (argv[1][1]=='f') { 140579Sroot if (argc>=3) { 141579Sroot strcpy(mailfile, argv[2]); 142579Sroot argv++; 143579Sroot argc--; 144579Sroot } 145579Sroot } else if (argv[1][1]=='r') { 146579Sroot forward = 1; 147579Sroot } else if (argv[1][1]=='h') { 148579Sroot forward = 1; 149579Sroot } else { 150579Sroot fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); 151579Sroot done(); 152579Sroot } 153579Sroot } else 154579Sroot break; 155579Sroot } 156579Sroot malf = fopen(mailfile, "r"); 157579Sroot if (malf == NULL) { 158579Sroot fprintf(stdout, "No mail.\n"); 159579Sroot return; 160579Sroot } 161579Sroot lock(mailfile); 162579Sroot copymt(malf, tmpf); 163579Sroot fclose(malf); 164579Sroot fclose(tmpf); 165579Sroot unlock(); 166579Sroot tmpf = fopen(lettmp, "r"); 167579Sroot 168579Sroot changed = 0; 169579Sroot print = 1; 170579Sroot for (i = 0; i < nlet; ) { 171579Sroot j = forward ? i : nlet - i - 1; 172579Sroot if(setjmp(sjbuf)) { 173579Sroot print=0; 174579Sroot } else { 175579Sroot if (print) 176579Sroot copylet(j, stdout, ORDINARY); 177579Sroot print = 1; 178579Sroot } 179579Sroot if (flgp) { 180579Sroot i++; 181579Sroot continue; 182579Sroot } 183579Sroot setjmp(sjbuf); 184579Sroot fprintf(stdout, "? "); 185579Sroot fflush(stdout); 186579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 187579Sroot break; 188579Sroot switch (resp[0]) { 189579Sroot 190579Sroot default: 191579Sroot fprintf(stderr, "usage\n"); 192579Sroot case '?': 193579Sroot print = 0; 194579Sroot fprintf(stderr, "q\tquit\n"); 195579Sroot fprintf(stderr, "x\texit without changing mail\n"); 196579Sroot fprintf(stderr, "p\tprint\n"); 197579Sroot fprintf(stderr, "s[file]\tsave (default mbox)\n"); 198579Sroot fprintf(stderr, "w[file]\tsame without header\n"); 199579Sroot fprintf(stderr, "-\tprint previous\n"); 200579Sroot fprintf(stderr, "d\tdelete\n"); 201579Sroot fprintf(stderr, "+\tnext (no delete)\n"); 202579Sroot fprintf(stderr, "m user\tmail to user\n"); 203579Sroot fprintf(stderr, "! cmd\texecute cmd\n"); 204579Sroot break; 205579Sroot 206579Sroot case '+': 207579Sroot case 'n': 208579Sroot case '\n': 209579Sroot i++; 210579Sroot break; 211579Sroot case 'x': 212579Sroot changed = 0; 213579Sroot case 'q': 214579Sroot goto donep; 215579Sroot case 'p': 216579Sroot break; 217579Sroot case '^': 218579Sroot case '-': 219579Sroot if (--i < 0) 220579Sroot i = 0; 221579Sroot break; 222579Sroot case 'y': 223579Sroot case 'w': 224579Sroot case 's': 225579Sroot flg = 0; 226579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 227579Sroot printf("illegal\n"); 228579Sroot flg++; 229579Sroot print = 0; 230579Sroot continue; 231579Sroot } 232579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 233579Sroot p = getenv("HOME"); 234579Sroot if(p != 0) 235579Sroot cat(resp+1, p, "/mbox"); 236579Sroot else 237579Sroot cat(resp+1, "", "mbox"); 238579Sroot } 239579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 240579Sroot malf = fopen(lfil, "a"); 241579Sroot if (malf == NULL) { 242579Sroot fprintf(stdout, "mail: cannot append to %s\n", lfil); 243579Sroot flg++; 244579Sroot continue; 245579Sroot } 246579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 247579Sroot fclose(malf); 248579Sroot } 249579Sroot if (flg) 250579Sroot print = 0; 251579Sroot else { 252579Sroot let[j].change = 'd'; 253579Sroot changed++; 254579Sroot i++; 255579Sroot } 256579Sroot break; 257579Sroot case 'm': 258579Sroot flg = 0; 259579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 260579Sroot i++; 261579Sroot continue; 262579Sroot } 263579Sroot if (resp[1] != ' ') { 264579Sroot printf("invalid command\n"); 265579Sroot flg++; 266579Sroot print = 0; 267579Sroot continue; 268579Sroot } 269579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 270579Sroot if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ 271579Sroot flg++; 272579Sroot if (flg) 273579Sroot print = 0; 274579Sroot else { 275579Sroot let[j].change = 'd'; 276579Sroot changed++; 277579Sroot i++; 278579Sroot } 279579Sroot break; 280579Sroot case '!': 281579Sroot system(resp+1); 282579Sroot printf("!\n"); 283579Sroot print = 0; 284579Sroot break; 285579Sroot case 'd': 286579Sroot let[j].change = 'd'; 287579Sroot changed++; 288579Sroot i++; 289579Sroot if (resp[1] == 'q') 290579Sroot goto donep; 291579Sroot break; 292579Sroot } 293579Sroot } 294579Sroot donep: 295579Sroot if (changed) 296579Sroot copyback(); 297579Sroot } 298579Sroot 299579Sroot copyback() /* copy temp or whatever back to /usr/spool/mail */ 300579Sroot { 301579Sroot register i, n, c; 302579Sroot int new = 0; 303579Sroot struct stat stbuf; 304579Sroot 305579Sroot signal(SIGINT, SIG_IGN); 306579Sroot signal(SIGHUP, SIG_IGN); 307579Sroot signal(SIGQUIT, SIG_IGN); 308579Sroot lock(mailfile); 309579Sroot stat(mailfile, &stbuf); 310579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 311579Sroot malf = fopen(mailfile, "r"); 312579Sroot if (malf == NULL) { 313579Sroot fprintf(stdout, "mail: can't re-read %s\n", mailfile); 314579Sroot done(); 315579Sroot } 316579Sroot fseek(malf, let[nlet].adr, 0); 317579Sroot fclose(tmpf); 318579Sroot tmpf = fopen(lettmp, "a"); 319579Sroot fseek(tmpf, let[nlet].adr, 0); 320579Sroot while ((c = fgetc(malf)) != EOF) 321579Sroot fputc(c, tmpf); 322579Sroot fclose(malf); 323579Sroot fclose(tmpf); 324579Sroot tmpf = fopen(lettmp, "r"); 325579Sroot let[++nlet].adr = stbuf.st_size; 326579Sroot new = 1; 327579Sroot } 328579Sroot malf = fopen(mailfile, "w"); 329579Sroot if (malf == NULL) { 330579Sroot fprintf(stderr, "mail: can't rewrite %s\n", lfil); 331579Sroot done(); 332579Sroot } 333579Sroot n = 0; 334579Sroot for (i = 0; i < nlet; i++) 335579Sroot if (let[i].change != 'd') { 336579Sroot copylet(i, malf, ORDINARY); 337579Sroot n++; 338579Sroot } 339579Sroot fclose(malf); 340579Sroot if (new) 341579Sroot fprintf(stdout, "new mail arrived\n"); 342579Sroot unlock(); 343579Sroot } 344579Sroot 345579Sroot copymt(f1, f2) /* copy mail (f1) to temp (f2) */ 346579Sroot FILE *f1, *f2; 347579Sroot { 348579Sroot long nextadr; 349579Sroot 350579Sroot nlet = nextadr = 0; 351579Sroot let[0].adr = 0; 352579Sroot while (fgets(line, LSIZE, f1) != NULL) { 353579Sroot if (isfrom(line)) 354579Sroot let[nlet++].adr = nextadr; 355579Sroot nextadr += strlen(line); 356579Sroot fputs(line, f2); 357579Sroot } 358579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 359579Sroot } 360579Sroot 361*11893Seric copylet(n, f, type) 362*11893Seric FILE *f; 363*11893Seric { 364*11893Seric int ch; 365*11893Seric long k; 366*11893Seric 367579Sroot fseek(tmpf, let[n].adr, 0); 368579Sroot k = let[n+1].adr - let[n].adr; 369579Sroot while(k-- > 1 && (ch=fgetc(tmpf))!='\n') 370579Sroot if(type!=ZAP) fputc(ch,f); 3716199Sroot if(type==REMOTE) { 3726199Sroot char hostname[32]; 3736199Sroot gethostname(hostname, sizeof (hostname)); 3746199Sroot fprintf(f, " remote from %s\n", hostname); 3756199Sroot } else if (type==FORWARD) 376579Sroot fprintf(f, forwmsg); 377579Sroot else if(type==ORDINARY) 378579Sroot fputc(ch,f); 379579Sroot while(k-->1) 380579Sroot fputc(ch=fgetc(tmpf), f); 381579Sroot if(type!=ZAP || ch!= '\n') 382579Sroot fputc(fgetc(tmpf), f); 383579Sroot } 384579Sroot 385579Sroot isfrom(lp) 386579Sroot register char *lp; 387579Sroot { 388579Sroot register char *p; 389579Sroot 390579Sroot for (p = from; *p; ) 391579Sroot if (*lp++ != *p++) 392579Sroot return(0); 393579Sroot return(1); 394579Sroot } 395579Sroot 3966015Swnj bulkmail(argc, argv) 397579Sroot char **argv; 398579Sroot { 399579Sroot char truename[100]; 400579Sroot int first; 401579Sroot register char *cp; 402579Sroot int gaver = 0; 403579Sroot char *newargv[1000]; 404579Sroot register char **ap; 405579Sroot register char **vp; 406579Sroot int dflag; 407579Sroot 408579Sroot dflag = 0; 409579Sroot if (argc < 1) 410579Sroot fprintf(stderr, "puke\n"); 411579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 412579Sroot { 413579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 414579Sroot dflag++; 415579Sroot } 416579Sroot if (!dflag) 417579Sroot { 4189978Seric /* give it to sendmail, rah rah! */ 419579Sroot unlink(lettmp); 420579Sroot ap = newargv+1; 421579Sroot if (rmail) 422579Sroot *ap-- = "-s"; 4239978Seric *ap = "-sendmail"; 4244461Sroot setuid(getuid()); 4259978Seric execv(SENDMAIL, ap); 4269978Seric perror(SENDMAIL); 427579Sroot exit(EX_UNAVAILABLE); 428579Sroot } 429579Sroot 430579Sroot truename[0] = 0; 431579Sroot line[0] = '\0'; 432579Sroot 433579Sroot /* 434579Sroot * When we fall out of this, argv[1] should be first name, 435579Sroot * argc should be number of names + 1. 436579Sroot */ 437579Sroot 438579Sroot while (argc > 1 && *argv[1] == '-') { 439579Sroot cp = *++argv; 440579Sroot argc--; 441579Sroot switch (cp[1]) { 442579Sroot case 'r': 443579Sroot if (argc <= 0) { 444579Sroot usage(); 445579Sroot done(); 446579Sroot } 447579Sroot gaver++; 448579Sroot strcpy(truename, argv[1]); 449579Sroot fgets(line, LSIZE, stdin); 450579Sroot if (strcmpn("From", line, 4) == 0) 451579Sroot line[0] = '\0'; 452579Sroot argv++; 453579Sroot argc--; 454579Sroot break; 455579Sroot 456579Sroot case 'h': 457579Sroot if (argc <= 0) { 458579Sroot usage(); 459579Sroot done(); 460579Sroot } 461579Sroot hseqno = atoi(argv[1]); 462579Sroot argv++; 463579Sroot argc--; 464579Sroot break; 465579Sroot 466579Sroot case 'd': 467579Sroot break; 468579Sroot 469579Sroot default: 470579Sroot usage(); 471579Sroot done(); 472579Sroot } 473579Sroot } 474579Sroot if (argc <= 1) { 475579Sroot usage(); 476579Sroot done(); 477579Sroot } 478579Sroot if (gaver == 0) 479579Sroot strcpy(truename, my_name); 480579Sroot /* 481579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 482579Sroot strcpy(truename, argv[2]); 483579Sroot argc -= 2; 484579Sroot argv += 2; 485579Sroot fgets(line, LSIZE, stdin); 486579Sroot if (strcmpn("From", line, 4) == 0) 487579Sroot line[0] = '\0'; 488579Sroot } else 489579Sroot strcpy(truename, my_name); 490579Sroot */ 491579Sroot time(&iop); 492579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 493579Sroot iop = ftell(tmpf); 494579Sroot flgf = 1; 495579Sroot for (first = 1;; first = 0) { 496579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 497579Sroot break; 498579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 499579Sroot break; 500579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 501579Sroot break; 502579Sroot if (isfrom(line)) 503579Sroot fputs(">", tmpf); 504579Sroot fputs(line, tmpf); 505579Sroot flgf = 0; 506579Sroot } 507579Sroot fputs("\n", tmpf); 508579Sroot nlet = 1; 509579Sroot let[0].adr = 0; 510579Sroot let[1].adr = ftell(tmpf); 511579Sroot fclose(tmpf); 512579Sroot if (flgf) 513579Sroot return; 514579Sroot tmpf = fopen(lettmp, "r"); 515579Sroot if (tmpf == NULL) { 516579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 517579Sroot return; 518579Sroot } 5196015Swnj while (--argc > 0) { 5206015Swnj if (!sendmail(0, *++argv, truename)) 521579Sroot error++; 5226015Swnj } 52310644Seric if (error && safefile(dead)) { 524579Sroot setuid(getuid()); 525579Sroot malf = fopen(dead, "w"); 526579Sroot if (malf == NULL) { 527579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 528579Sroot fclose(tmpf); 529579Sroot return; 530579Sroot } 531579Sroot copylet(0, malf, ZAP); 532579Sroot fclose(malf); 533579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 534579Sroot } 535579Sroot fclose(tmpf); 536579Sroot } 537579Sroot 538579Sroot sendrmt(n, name, rcmd) 539579Sroot char *name; 540579Sroot char *rcmd; 541579Sroot { 542579Sroot FILE *rmf, *popen(); 543579Sroot register char *p; 544579Sroot char rsys[64], cmd[64]; 545579Sroot register local, pid; 546579Sroot int sts; 547579Sroot 548579Sroot local = 0; 549579Sroot if (index(name, '^')) { 550579Sroot while (p = index(name, '^')) 551579Sroot *p = '!'; 552579Sroot if (strncmp(name, "researc", 7)) { 553579Sroot strcpy(rsys, "research"); 554579Sroot if (*name != '!') 555579Sroot --name; 556579Sroot goto skip; 557579Sroot } 558579Sroot } 559579Sroot if (*name=='!') 560579Sroot name++; 561579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 562579Sroot if (*name=='\0') { 563579Sroot local++; 564579Sroot break; 565579Sroot } 566579Sroot *p = '\0'; 567579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 568579Sroot fprintf(stdout, "null name\n"); 569579Sroot return(0); 570579Sroot } 571579Sroot skip: 572579Sroot if ((pid = fork()) == -1) { 573579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 574579Sroot return(0); 575579Sroot } 576579Sroot if (pid) { 577579Sroot while (wait(&sts) != pid) { 578579Sroot if (wait(&sts)==-1) 579579Sroot return(0); 580579Sroot } 581579Sroot return(!sts); 582579Sroot } 583579Sroot setuid(getuid()); 584579Sroot if (local) 585579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 586579Sroot else { 587579Sroot if (index(name+1, '!')) 588579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 589579Sroot else 590579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 591579Sroot } 592579Sroot if ((rmf=popen(cmd, "w")) == NULL) 593579Sroot exit(1); 594579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 59510783Seric exit(pclose(rmf) != 0); 596579Sroot } 597579Sroot 598579Sroot usage() 599579Sroot { 600579Sroot 601579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 602579Sroot } 603579Sroot 6046015Swnj #include <sys/socket.h> 6059226Ssam #include <netinet/in.h> 60610227Ssam #include <netdb.h> 60710227Ssam struct sockaddr_in biffaddr; 6086015Swnj 6096015Swnj sendmail(n, name, fromaddr) 610579Sroot int n; 611579Sroot char *name; 612579Sroot char *fromaddr; 613579Sroot { 614579Sroot char file[100]; 615579Sroot register char *p; 616579Sroot register mask; 617579Sroot struct passwd *pw, *getpwnam(); 618579Sroot struct stat statb; 6193666Swnj char buf[128]; 6203666Swnj int f; 62110227Ssam struct hostent *hp = NULL; 62210227Ssam struct servent *sp = NULL; 623579Sroot 624579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 625579Sroot ; 626579Sroot if (*p == '!'|| *p=='^') 627579Sroot return(sendrmt(n, name, 0)); 628579Sroot if ((pw = getpwnam(name)) == NULL) { 629579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 630579Sroot return(0); 631579Sroot } 632579Sroot cat(file, maildir, name); 633579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 634579Sroot strcat(file, "/"); 635579Sroot strcat(file, name); 636579Sroot } 637579Sroot mask = umask(MAILMODE); 63810644Seric if (!safefile(file)) 6394458Sroot return(0); 640*11893Seric lock(file); 641579Sroot malf = fopen(file, "a"); 642579Sroot umask(mask); 643579Sroot if (malf == NULL) { 644*11893Seric unlock(); 645579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 646579Sroot return(0); 647579Sroot } 6486015Swnj chown(file, pw->pw_uid, pw->pw_gid); 6493666Swnj { 65010227Ssam hp = gethostbyname("localhost"); 65110227Ssam sp = getservbyname("biff", "udp"); 65210227Ssam if (hp && sp) { 65310227Ssam f = socket(AF_INET, SOCK_DGRAM, 0, 0); 65410227Ssam sprintf(buf, "%s@%d\n", name, ftell(malf)); 65510227Ssam } 6563666Swnj } 657579Sroot copylet(n, malf, ORDINARY); 6586015Swnj fclose(malf); 65910227Ssam if (hp && sp) { 66010227Ssam biffaddr.sin_family = hp->h_addrtype; 66110227Ssam bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length); 66210227Ssam biffaddr.sin_port = sp->s_port; 6639226Ssam sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr)); 6643666Swnj close(f); 6653666Swnj } 666579Sroot unlock(); 667579Sroot return(1); 668579Sroot } 669579Sroot 670579Sroot delete(i) 671579Sroot { 672579Sroot setsig(i, delete); 673579Sroot fprintf(stderr, "\n"); 674579Sroot if(delflg) 675579Sroot longjmp(sjbuf, 1); 676579Sroot done(); 677579Sroot } 678579Sroot 679579Sroot /* 680579Sroot * Lock the specified mail file by setting the file mailfile.lock. 681579Sroot * We must, of course, be careful to unlink the lock file by a call 682579Sroot * to unlock before we stop. The algorithm used here is to see if 683579Sroot * the lock exists, and if it does, to check its modify time. If it 684579Sroot * is older than 30 seconds, we assume error and set our own file. 685579Sroot * Otherwise, we wait for 5 seconds and try again. 686579Sroot */ 687579Sroot 688579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 689579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 690579Sroot char locktmp[30]; /* Usable lock temporary */ 691579Sroot char curlock[50]; /* Last used name of lock */ 692579Sroot int locked; /* To note that we locked it */ 693579Sroot 694579Sroot lock(file) 695579Sroot char *file; 696579Sroot { 697579Sroot register int f; 698579Sroot struct stat sbuf; 699579Sroot long curtime; 700579Sroot int statfailed; 701579Sroot 702579Sroot if (locked || flgf) 703579Sroot return(0); 704579Sroot strcpy(curlock, file); 705579Sroot strcat(curlock, maillock); 706579Sroot strcpy(locktmp, lockname); 707579Sroot mktemp(locktmp); 708579Sroot unlink(locktmp); 709579Sroot statfailed = 0; 710579Sroot for (;;) { 711579Sroot f = lock1(locktmp, curlock); 712579Sroot if (f == 0) { 713579Sroot locked = 1; 714579Sroot return(0); 715579Sroot } 716579Sroot if (stat(curlock, &sbuf) < 0) { 717579Sroot if (statfailed++ > 5) 718579Sroot return(-1); 719579Sroot sleep(5); 720579Sroot continue; 721579Sroot } 722579Sroot statfailed = 0; 723579Sroot time(&curtime); 724579Sroot if (curtime < sbuf.st_ctime + 30) { 725579Sroot sleep(5); 726579Sroot continue; 727579Sroot } 728579Sroot unlink(curlock); 729579Sroot } 730579Sroot } 731579Sroot 732579Sroot /* 733579Sroot * Remove the mail lock, and note that we no longer 734579Sroot * have it locked. 735579Sroot */ 736579Sroot 737579Sroot unlock() 738579Sroot { 739579Sroot 740579Sroot unlink(curlock); 741579Sroot locked = 0; 742579Sroot } 743579Sroot 744579Sroot /* 745579Sroot * Attempt to set the lock by creating the temporary file, 746579Sroot * then doing a link/unlink. If it fails, return -1 else 0 747579Sroot */ 748579Sroot 749579Sroot lock1(tempfile, name) 750579Sroot char tempfile[], name[]; 751579Sroot { 752579Sroot register int fd; 753579Sroot 754579Sroot fd = creat(tempfile, 0); 755579Sroot if (fd < 0) 756579Sroot return(-1); 757579Sroot close(fd); 758579Sroot if (link(tempfile, name) < 0) { 759579Sroot unlink(tempfile); 760579Sroot return(-1); 761579Sroot } 762579Sroot unlink(tempfile); 763579Sroot return(0); 764579Sroot } 765579Sroot 766579Sroot done() 767579Sroot { 768579Sroot if(locked) 769579Sroot unlock(); 770579Sroot unlink(lettmp); 771579Sroot unlink(locktmp); 772579Sroot exit(error); 773579Sroot } 774579Sroot 775579Sroot cat(to, from1, from2) 776579Sroot char *to, *from1, *from2; 777579Sroot { 778579Sroot int i, j; 779579Sroot 780579Sroot j = 0; 781579Sroot for (i=0; from1[i]; i++) 782579Sroot to[j++] = from1[i]; 783579Sroot for (i=0; from2[i]; i++) 784579Sroot to[j++] = from2[i]; 785579Sroot to[j] = 0; 786579Sroot } 787579Sroot 788579Sroot char *getarg(s, p) /* copy p... into s, update p */ 789579Sroot register char *s, *p; 790579Sroot { 791579Sroot while (*p == ' ' || *p == '\t') 792579Sroot p++; 793579Sroot if (*p == '\n' || *p == '\0') 794579Sroot return(NULL); 795579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 796579Sroot *s++ = *p++; 797579Sroot *s = '\0'; 798579Sroot return(p); 799579Sroot } 80010644Seric 80110644Seric safefile(f) 80210644Seric char *f; 80310644Seric { 80410644Seric struct stat statb; 80510644Seric 80610644Seric if (lstat(f, &statb) < 0) 80710644Seric return (1); 80810644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 80910644Seric fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f); 81010644Seric return (0); 81110644Seric } 81210644Seric return (1); 81310644Seric } 814