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 <whoami.h> 10579Sroot #include <sysexits.h> 11579Sroot 12*4461Sroot static char SccsId[] = "@(#)mail.local.c 4.5 10/03/81"; 13580Seric 14579Sroot #define DELIVERMAIL "/etc/delivermail" 15579Sroot 16579Sroot 17579Sroot /*copylet flags */ 18579Sroot /*remote mail, add rmtmsg */ 19579Sroot #define REMOTE 1 20579Sroot /* zap header and trailing empty line */ 21579Sroot #define ZAP 3 22579Sroot #define ORDINARY 2 23579Sroot #define FORWARD 4 24579Sroot #define LSIZE 256 25579Sroot #define MAXLET 300 /* maximum number of letters */ 26579Sroot #define MAILMODE (~0644) /* mode of created mail */ 27580Seric # ifndef DELIVERMAIL 28579Sroot #define RMAIL "/usr/net/bin/sendberkmail" 29579Sroot #define LOCNAM1 "csvax" 30579Sroot #define LOCNAM2 "ucbvax" 31579Sroot #define LOCNAM3 "vax" 32579Sroot #define LOCNAM4 "v" 33580Seric # endif 34579Sroot 35579Sroot char line[LSIZE]; 36579Sroot char resp[LSIZE]; 37579Sroot struct let { 38579Sroot long adr; 39579Sroot char change; 40579Sroot } let[MAXLET]; 41579Sroot int nlet = 0; 42579Sroot char lfil[50]; 43579Sroot long iop, time(); 44579Sroot char *getenv(); 45579Sroot char *index(); 46579Sroot char lettmp[] = "/tmp/maXXXXX"; 47579Sroot char maildir[] = "/usr/spool/mail/"; 48579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 49579Sroot char dead[] = "dead.letter"; 50579Sroot char *thissys = sysname; 51579Sroot char *netname = "vax"; 52579Sroot char forwmsg[] = " forwarded\n"; 53579Sroot FILE *tmpf; 54579Sroot FILE *malf; 55579Sroot char *my_name; 56579Sroot char *getlogin(); 57579Sroot struct passwd *getpwuid(); 58579Sroot int error; 59579Sroot int changed; 60579Sroot int forward; 61579Sroot char from[] = "From "; 62579Sroot long ftell(); 63579Sroot int delete(); 64579Sroot char *ctime(); 65579Sroot int flgf; 66579Sroot int flgp; 67579Sroot int delflg = 1; 68579Sroot int hseqno; 69579Sroot jmp_buf sjbuf; 70579Sroot int rmail; 71579Sroot 72579Sroot main(argc, argv) 73579Sroot char **argv; 74579Sroot { 75579Sroot register i; 76579Sroot char sobuf[BUFSIZ]; 77579Sroot 78579Sroot setbuf(stdout, sobuf); 79579Sroot mktemp(lettmp); 80579Sroot unlink(lettmp); 81579Sroot my_name = getlogin(); 82579Sroot if (my_name == NULL || strlen(my_name) == 0) { 83579Sroot struct passwd *pwent; 84579Sroot pwent = getpwuid(getuid()); 85579Sroot if (pwent==NULL) 86579Sroot my_name = "???"; 87579Sroot else 88579Sroot my_name = pwent->pw_name; 89579Sroot } 90579Sroot if(setjmp(sjbuf)) done(); 91579Sroot for (i=0; i<20; i++) 92579Sroot setsig(i, delete); 93579Sroot tmpf = fopen(lettmp, "w"); 94579Sroot if (tmpf == NULL) { 95579Sroot fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); 96579Sroot done(); 97579Sroot } 98579Sroot if (argv[0][0] == 'r') 99579Sroot rmail++; 100579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 101579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 102579Sroot printmail(argc, argv); 103579Sroot else 104579Sroot sendmail(argc, argv); 105579Sroot done(); 106579Sroot } 107579Sroot 108579Sroot setsig(i, f) 109579Sroot int i; 110579Sroot int (*f)(); 111579Sroot { 112579Sroot if(signal(i, SIG_IGN)!=SIG_IGN) 113579Sroot signal(i, f); 114579Sroot } 115579Sroot 116579Sroot any(c, str) 117579Sroot register int c; 118579Sroot register char *str; 119579Sroot { 120579Sroot 121579Sroot while (*str) 122579Sroot if (c == *str++) 123579Sroot return(1); 124579Sroot return(0); 125579Sroot } 126579Sroot 127579Sroot printmail(argc, argv) 128579Sroot char **argv; 129579Sroot { 130579Sroot int flg, i, j, print; 131579Sroot char *p, *getarg(); 132579Sroot struct stat statb; 133579Sroot 134579Sroot setuid(getuid()); 135579Sroot cat(mailfile, maildir, my_name); 136579Sroot if (stat(mailfile, &statb) >= 0 137579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 138579Sroot strcat(mailfile, "/"); 139579Sroot strcat(mailfile, my_name); 140579Sroot } 141579Sroot for (; argc>1; argv++, argc--) { 142579Sroot if (argv[1][0]=='-') { 143579Sroot if (argv[1][1]=='q') 144579Sroot delflg = 0; 145579Sroot else if (argv[1][1]=='p') { 146579Sroot flgp++; 147579Sroot delflg = 0; 148579Sroot } else if (argv[1][1]=='f') { 149579Sroot if (argc>=3) { 150579Sroot strcpy(mailfile, argv[2]); 151579Sroot argv++; 152579Sroot argc--; 153579Sroot } 154579Sroot } else if (argv[1][1]=='r') { 155579Sroot forward = 1; 156579Sroot } else if (argv[1][1]=='h') { 157579Sroot forward = 1; 158579Sroot } else { 159579Sroot fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); 160579Sroot done(); 161579Sroot } 162579Sroot } else 163579Sroot break; 164579Sroot } 165579Sroot malf = fopen(mailfile, "r"); 166579Sroot if (malf == NULL) { 167579Sroot fprintf(stdout, "No mail.\n"); 168579Sroot return; 169579Sroot } 170579Sroot lock(mailfile); 171579Sroot copymt(malf, tmpf); 172579Sroot fclose(malf); 173579Sroot fclose(tmpf); 174579Sroot unlock(); 175579Sroot tmpf = fopen(lettmp, "r"); 176579Sroot 177579Sroot changed = 0; 178579Sroot print = 1; 179579Sroot for (i = 0; i < nlet; ) { 180579Sroot j = forward ? i : nlet - i - 1; 181579Sroot if(setjmp(sjbuf)) { 182579Sroot print=0; 183579Sroot } else { 184579Sroot if (print) 185579Sroot copylet(j, stdout, ORDINARY); 186579Sroot print = 1; 187579Sroot } 188579Sroot if (flgp) { 189579Sroot i++; 190579Sroot continue; 191579Sroot } 192579Sroot setjmp(sjbuf); 193579Sroot fprintf(stdout, "? "); 194579Sroot fflush(stdout); 195579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 196579Sroot break; 197579Sroot switch (resp[0]) { 198579Sroot 199579Sroot default: 200579Sroot fprintf(stderr, "usage\n"); 201579Sroot case '?': 202579Sroot print = 0; 203579Sroot fprintf(stderr, "q\tquit\n"); 204579Sroot fprintf(stderr, "x\texit without changing mail\n"); 205579Sroot fprintf(stderr, "p\tprint\n"); 206579Sroot fprintf(stderr, "s[file]\tsave (default mbox)\n"); 207579Sroot fprintf(stderr, "w[file]\tsame without header\n"); 208579Sroot fprintf(stderr, "-\tprint previous\n"); 209579Sroot fprintf(stderr, "d\tdelete\n"); 210579Sroot fprintf(stderr, "+\tnext (no delete)\n"); 211579Sroot fprintf(stderr, "m user\tmail to user\n"); 212579Sroot fprintf(stderr, "! cmd\texecute cmd\n"); 213579Sroot break; 214579Sroot 215579Sroot case '+': 216579Sroot case 'n': 217579Sroot case '\n': 218579Sroot i++; 219579Sroot break; 220579Sroot case 'x': 221579Sroot changed = 0; 222579Sroot case 'q': 223579Sroot goto donep; 224579Sroot case 'p': 225579Sroot break; 226579Sroot case '^': 227579Sroot case '-': 228579Sroot if (--i < 0) 229579Sroot i = 0; 230579Sroot break; 231579Sroot case 'y': 232579Sroot case 'w': 233579Sroot case 's': 234579Sroot flg = 0; 235579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 236579Sroot printf("illegal\n"); 237579Sroot flg++; 238579Sroot print = 0; 239579Sroot continue; 240579Sroot } 241579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 242579Sroot p = getenv("HOME"); 243579Sroot if(p != 0) 244579Sroot cat(resp+1, p, "/mbox"); 245579Sroot else 246579Sroot cat(resp+1, "", "mbox"); 247579Sroot } 248579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 249579Sroot malf = fopen(lfil, "a"); 250579Sroot if (malf == NULL) { 251579Sroot fprintf(stdout, "mail: cannot append to %s\n", lfil); 252579Sroot flg++; 253579Sroot continue; 254579Sroot } 255579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 256579Sroot fclose(malf); 257579Sroot } 258579Sroot if (flg) 259579Sroot print = 0; 260579Sroot else { 261579Sroot let[j].change = 'd'; 262579Sroot changed++; 263579Sroot i++; 264579Sroot } 265579Sroot break; 266579Sroot case 'm': 267579Sroot flg = 0; 268579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 269579Sroot i++; 270579Sroot continue; 271579Sroot } 272579Sroot if (resp[1] != ' ') { 273579Sroot printf("invalid command\n"); 274579Sroot flg++; 275579Sroot print = 0; 276579Sroot continue; 277579Sroot } 278579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 279579Sroot if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ 280579Sroot flg++; 281579Sroot if (flg) 282579Sroot print = 0; 283579Sroot else { 284579Sroot let[j].change = 'd'; 285579Sroot changed++; 286579Sroot i++; 287579Sroot } 288579Sroot break; 289579Sroot case '!': 290579Sroot system(resp+1); 291579Sroot printf("!\n"); 292579Sroot print = 0; 293579Sroot break; 294579Sroot case 'd': 295579Sroot let[j].change = 'd'; 296579Sroot changed++; 297579Sroot i++; 298579Sroot if (resp[1] == 'q') 299579Sroot goto donep; 300579Sroot break; 301579Sroot } 302579Sroot } 303579Sroot donep: 304579Sroot if (changed) 305579Sroot copyback(); 306579Sroot } 307579Sroot 308579Sroot copyback() /* copy temp or whatever back to /usr/spool/mail */ 309579Sroot { 310579Sroot register i, n, c; 311579Sroot int new = 0; 312579Sroot struct stat stbuf; 313579Sroot 314579Sroot signal(SIGINT, SIG_IGN); 315579Sroot signal(SIGHUP, SIG_IGN); 316579Sroot signal(SIGQUIT, SIG_IGN); 317579Sroot lock(mailfile); 318579Sroot stat(mailfile, &stbuf); 319579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 320579Sroot malf = fopen(mailfile, "r"); 321579Sroot if (malf == NULL) { 322579Sroot fprintf(stdout, "mail: can't re-read %s\n", mailfile); 323579Sroot done(); 324579Sroot } 325579Sroot fseek(malf, let[nlet].adr, 0); 326579Sroot fclose(tmpf); 327579Sroot tmpf = fopen(lettmp, "a"); 328579Sroot fseek(tmpf, let[nlet].adr, 0); 329579Sroot while ((c = fgetc(malf)) != EOF) 330579Sroot fputc(c, tmpf); 331579Sroot fclose(malf); 332579Sroot fclose(tmpf); 333579Sroot tmpf = fopen(lettmp, "r"); 334579Sroot let[++nlet].adr = stbuf.st_size; 335579Sroot new = 1; 336579Sroot } 337579Sroot malf = fopen(mailfile, "w"); 338579Sroot if (malf == NULL) { 339579Sroot fprintf(stderr, "mail: can't rewrite %s\n", lfil); 340579Sroot done(); 341579Sroot } 342579Sroot n = 0; 343579Sroot for (i = 0; i < nlet; i++) 344579Sroot if (let[i].change != 'd') { 345579Sroot copylet(i, malf, ORDINARY); 346579Sroot n++; 347579Sroot } 348579Sroot fclose(malf); 349579Sroot if (new) 350579Sroot fprintf(stdout, "new mail arrived\n"); 351579Sroot unlock(); 352579Sroot } 353579Sroot 354579Sroot copymt(f1, f2) /* copy mail (f1) to temp (f2) */ 355579Sroot FILE *f1, *f2; 356579Sroot { 357579Sroot long nextadr; 358579Sroot 359579Sroot nlet = nextadr = 0; 360579Sroot let[0].adr = 0; 361579Sroot while (fgets(line, LSIZE, f1) != NULL) { 362579Sroot if (isfrom(line)) 363579Sroot let[nlet++].adr = nextadr; 364579Sroot nextadr += strlen(line); 365579Sroot fputs(line, f2); 366579Sroot } 367579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 368579Sroot } 369579Sroot 370579Sroot copylet(n, f, type) FILE *f; 371579Sroot { int ch, k; 372579Sroot fseek(tmpf, let[n].adr, 0); 373579Sroot k = let[n+1].adr - let[n].adr; 374579Sroot while(k-- > 1 && (ch=fgetc(tmpf))!='\n') 375579Sroot if(type!=ZAP) fputc(ch,f); 376579Sroot if(type==REMOTE) 377579Sroot fprintf(f, " remote from %s\n", thissys); 378579Sroot else if (type==FORWARD) 379579Sroot fprintf(f, forwmsg); 380579Sroot else if(type==ORDINARY) 381579Sroot fputc(ch,f); 382579Sroot while(k-->1) 383579Sroot fputc(ch=fgetc(tmpf), f); 384579Sroot if(type!=ZAP || ch!= '\n') 385579Sroot fputc(fgetc(tmpf), f); 386579Sroot } 387579Sroot 388579Sroot isfrom(lp) 389579Sroot register char *lp; 390579Sroot { 391579Sroot register char *p; 392579Sroot 393579Sroot for (p = from; *p; ) 394579Sroot if (*lp++ != *p++) 395579Sroot return(0); 396579Sroot return(1); 397579Sroot } 398579Sroot 399579Sroot sendmail(argc, argv) 400579Sroot char **argv; 401579Sroot { 402579Sroot char truename[100]; 403579Sroot int first; 404579Sroot register char *cp; 405579Sroot int gaver = 0; 406579Sroot # ifdef DELIVERMAIL 407579Sroot char *newargv[1000]; 408579Sroot register char **ap; 409579Sroot register char **vp; 410579Sroot int dflag; 411579Sroot 412579Sroot dflag = 0; 413579Sroot if (argc < 1) 414579Sroot fprintf(stderr, "puke\n"); 415579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 416579Sroot { 417579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 418579Sroot dflag++; 419579Sroot } 420579Sroot if (!dflag) 421579Sroot { 422579Sroot /* give it to delivermail, rah rah! */ 423579Sroot unlink(lettmp); 424579Sroot ap = newargv+1; 425579Sroot if (rmail) 426579Sroot *ap-- = "-s"; 427579Sroot *ap = "-delivermail"; 428*4461Sroot setuid(getuid()); 429579Sroot execv(DELIVERMAIL, ap); 430579Sroot perror(DELIVERMAIL); 431579Sroot exit(EX_UNAVAILABLE); 432579Sroot } 433579Sroot # endif DELIVERMAIL 434579Sroot 435579Sroot truename[0] = 0; 436579Sroot line[0] = '\0'; 437579Sroot 438579Sroot /* 439579Sroot * When we fall out of this, argv[1] should be first name, 440579Sroot * argc should be number of names + 1. 441579Sroot */ 442579Sroot 443579Sroot while (argc > 1 && *argv[1] == '-') { 444579Sroot cp = *++argv; 445579Sroot argc--; 446579Sroot switch (cp[1]) { 447579Sroot case 'r': 448579Sroot if (argc <= 0) { 449579Sroot usage(); 450579Sroot done(); 451579Sroot } 452579Sroot gaver++; 453579Sroot strcpy(truename, argv[1]); 454579Sroot fgets(line, LSIZE, stdin); 455579Sroot if (strcmpn("From", line, 4) == 0) 456579Sroot line[0] = '\0'; 457579Sroot argv++; 458579Sroot argc--; 459579Sroot break; 460579Sroot 461579Sroot case 'h': 462579Sroot if (argc <= 0) { 463579Sroot usage(); 464579Sroot done(); 465579Sroot } 466579Sroot hseqno = atoi(argv[1]); 467579Sroot argv++; 468579Sroot argc--; 469579Sroot break; 470579Sroot 471579Sroot # ifdef DELIVERMAIL 472579Sroot case 'd': 473579Sroot break; 474579Sroot # endif DELIVERMAIL 475579Sroot 476579Sroot default: 477579Sroot usage(); 478579Sroot done(); 479579Sroot } 480579Sroot } 481579Sroot if (argc <= 1) { 482579Sroot usage(); 483579Sroot done(); 484579Sroot } 485579Sroot if (gaver == 0) 486579Sroot strcpy(truename, my_name); 487579Sroot /* 488579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 489579Sroot strcpy(truename, argv[2]); 490579Sroot argc -= 2; 491579Sroot argv += 2; 492579Sroot fgets(line, LSIZE, stdin); 493579Sroot if (strcmpn("From", line, 4) == 0) 494579Sroot line[0] = '\0'; 495579Sroot } else 496579Sroot strcpy(truename, my_name); 497579Sroot */ 498579Sroot time(&iop); 499579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 500579Sroot iop = ftell(tmpf); 501579Sroot flgf = 1; 502579Sroot for (first = 1;; first = 0) { 503579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 504579Sroot break; 505579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 506579Sroot break; 507579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 508579Sroot break; 509579Sroot if (isfrom(line)) 510579Sroot fputs(">", tmpf); 511579Sroot fputs(line, tmpf); 512579Sroot flgf = 0; 513579Sroot } 514579Sroot fputs("\n", tmpf); 515579Sroot nlet = 1; 516579Sroot let[0].adr = 0; 517579Sroot let[1].adr = ftell(tmpf); 518579Sroot fclose(tmpf); 519579Sroot if (flgf) 520579Sroot return; 521579Sroot tmpf = fopen(lettmp, "r"); 522579Sroot if (tmpf == NULL) { 523579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 524579Sroot return; 525579Sroot } 526579Sroot while (--argc > 0) 527579Sroot if (!send(0, *++argv, truename)) 528579Sroot error++; 529579Sroot if (error) { 530579Sroot setuid(getuid()); 531579Sroot malf = fopen(dead, "w"); 532579Sroot if (malf == NULL) { 533579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 534579Sroot fclose(tmpf); 535579Sroot return; 536579Sroot } 537579Sroot copylet(0, malf, ZAP); 538579Sroot fclose(malf); 539579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 540579Sroot } 541579Sroot fclose(tmpf); 542579Sroot } 543579Sroot 544579Sroot sendrmt(n, name, rcmd) 545579Sroot char *name; 546579Sroot char *rcmd; 547579Sroot { 548579Sroot FILE *rmf, *popen(); 549579Sroot register char *p; 550579Sroot char rsys[64], cmd[64]; 551579Sroot register local, pid; 552579Sroot int sts; 553579Sroot 554579Sroot local = 0; 555579Sroot if (index(name, '^')) { 556579Sroot while (p = index(name, '^')) 557579Sroot *p = '!'; 558579Sroot if (strncmp(name, "researc", 7)) { 559579Sroot strcpy(rsys, "research"); 560579Sroot if (*name != '!') 561579Sroot --name; 562579Sroot goto skip; 563579Sroot } 564579Sroot } 565579Sroot if (*name=='!') 566579Sroot name++; 567579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 568579Sroot if (*name=='\0') { 569579Sroot local++; 570579Sroot break; 571579Sroot } 572579Sroot *p = '\0'; 573579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 574579Sroot fprintf(stdout, "null name\n"); 575579Sroot return(0); 576579Sroot } 577579Sroot skip: 578579Sroot if ((pid = fork()) == -1) { 579579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 580579Sroot return(0); 581579Sroot } 582579Sroot if (pid) { 583579Sroot while (wait(&sts) != pid) { 584579Sroot if (wait(&sts)==-1) 585579Sroot return(0); 586579Sroot } 587579Sroot return(!sts); 588579Sroot } 589579Sroot setuid(getuid()); 590579Sroot if (local) 591579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 592579Sroot else { 593579Sroot if (index(name+1, '!')) 594579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 595579Sroot else 596579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 597579Sroot } 598579Sroot if ((rmf=popen(cmd, "w")) == NULL) 599579Sroot exit(1); 600579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 601579Sroot pclose(rmf); 602579Sroot exit(0); 603579Sroot } 604579Sroot 605580Seric # ifndef DELIVERMAIL 606579Sroot /* 607579Sroot * Send mail on the Berkeley network. 608579Sroot * Sorry Bill, sendrmt() is so awful we just gave up. 609579Sroot */ 610579Sroot 611579Sroot sendberkmail(n, name, fromaddr) 612579Sroot char name[]; 613579Sroot char fromaddr[]; 614579Sroot { 615579Sroot char cmd[200]; 616579Sroot register FILE *cmdf; 617579Sroot 618579Sroot sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name); 619579Sroot if ((cmdf = popen(cmd, "w")) == NULL) { 620579Sroot perror(RMAIL); 621579Sroot return(0); 622579Sroot } 623579Sroot copylet(n, cmdf, ORDINARY); 624579Sroot pclose(cmdf); 625579Sroot return(9); 626579Sroot } 627580Seric # endif 628579Sroot 629579Sroot usage() 630579Sroot { 631579Sroot 632579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 633579Sroot } 634579Sroot 635579Sroot send(n, name, fromaddr) 636579Sroot int n; 637579Sroot char *name; 638579Sroot char *fromaddr; 639579Sroot { 640579Sroot char file[100]; 641579Sroot register char *p; 642579Sroot register mask; 643579Sroot struct passwd *pw, *getpwnam(); 644579Sroot struct stat statb; 6453666Swnj char buf[128]; 6463666Swnj int f; 647579Sroot 648580Seric # ifndef DELIVERMAIL 649579Sroot stripfx(LOCNAM1, &name); 650579Sroot stripfx(LOCNAM2, &name); 651579Sroot stripfx(LOCNAM3, &name); 652579Sroot stripfx(LOCNAM4, &name); 653579Sroot if(*name == ':')name++; /* skip colon in to-name */ 654580Seric for(p=name; *p!=':' && *p!='!' && *p!='^' &&*p!='\0'; p++); 655579Sroot /* if(*p == ':') return(sendrmt(n, name, RMAIL)); */ 656579Sroot if (*p == ':') 657579Sroot return(sendberkmail(n, name, fromaddr)); 658580Seric else if (*p=='\0' && strcmp(name, "msgs") == 0) 659580Seric return(sendrmt(n, "-s", "/usr/ucb/msgs")); 660580Seric # endif 661579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 662579Sroot ; 663579Sroot if (*p == '!'|| *p=='^') 664579Sroot return(sendrmt(n, name, 0)); 665579Sroot if ((pw = getpwnam(name)) == NULL) { 666579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 667579Sroot return(0); 668579Sroot } 669579Sroot cat(file, maildir, name); 670579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 671579Sroot strcat(file, "/"); 672579Sroot strcat(file, name); 673579Sroot } 674579Sroot mask = umask(MAILMODE); 6754459Sroot if (stat(file, &statb) >= 0 && statb.st_nlink != 1) { 6764458Sroot fprintf(stdout, "mail: %s's mail file has more than one link\n", name); 6774458Sroot return(0); 6784458Sroot } 679579Sroot malf = fopen(file, "a"); 6804458Sroot chown(file, pw->pw_uid, pw->pw_gid); 681579Sroot umask(mask); 682579Sroot if (malf == NULL) { 683579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 684579Sroot return(0); 685579Sroot } 686579Sroot lock(file); 6873666Swnj { 6883666Swnj f = open("/dev/mail", 1); 6893666Swnj sprintf(buf, "%s@%d\n", name, ftell(malf)); 6903666Swnj } 691579Sroot copylet(n, malf, ORDINARY); 6923666Swnj if (f >= 0) { 6933666Swnj write(f, buf, strlen(buf)+1); 6943666Swnj close(f); 6953666Swnj } 696579Sroot fclose(malf); 697579Sroot unlock(); 698579Sroot return(1); 699579Sroot } 700579Sroot 701579Sroot delete(i) 702579Sroot { 703579Sroot setsig(i, delete); 704579Sroot fprintf(stderr, "\n"); 705579Sroot if(delflg) 706579Sroot longjmp(sjbuf, 1); 707579Sroot done(); 708579Sroot } 709579Sroot 710579Sroot /* 711579Sroot * Lock the specified mail file by setting the file mailfile.lock. 712579Sroot * We must, of course, be careful to unlink the lock file by a call 713579Sroot * to unlock before we stop. The algorithm used here is to see if 714579Sroot * the lock exists, and if it does, to check its modify time. If it 715579Sroot * is older than 30 seconds, we assume error and set our own file. 716579Sroot * Otherwise, we wait for 5 seconds and try again. 717579Sroot */ 718579Sroot 719579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 720579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 721579Sroot char locktmp[30]; /* Usable lock temporary */ 722579Sroot char curlock[50]; /* Last used name of lock */ 723579Sroot int locked; /* To note that we locked it */ 724579Sroot 725579Sroot lock(file) 726579Sroot char *file; 727579Sroot { 728579Sroot register int f; 729579Sroot struct stat sbuf; 730579Sroot long curtime; 731579Sroot int statfailed; 732579Sroot 733579Sroot if (locked || flgf) 734579Sroot return(0); 735579Sroot strcpy(curlock, file); 736579Sroot strcat(curlock, maillock); 737579Sroot strcpy(locktmp, lockname); 738579Sroot mktemp(locktmp); 739579Sroot unlink(locktmp); 740579Sroot statfailed = 0; 741579Sroot for (;;) { 742579Sroot f = lock1(locktmp, curlock); 743579Sroot if (f == 0) { 744579Sroot locked = 1; 745579Sroot return(0); 746579Sroot } 747579Sroot if (stat(curlock, &sbuf) < 0) { 748579Sroot if (statfailed++ > 5) 749579Sroot return(-1); 750579Sroot sleep(5); 751579Sroot continue; 752579Sroot } 753579Sroot statfailed = 0; 754579Sroot time(&curtime); 755579Sroot if (curtime < sbuf.st_ctime + 30) { 756579Sroot sleep(5); 757579Sroot continue; 758579Sroot } 759579Sroot unlink(curlock); 760579Sroot } 761579Sroot } 762579Sroot 763579Sroot /* 764579Sroot * Remove the mail lock, and note that we no longer 765579Sroot * have it locked. 766579Sroot */ 767579Sroot 768579Sroot unlock() 769579Sroot { 770579Sroot 771579Sroot unlink(curlock); 772579Sroot locked = 0; 773579Sroot } 774579Sroot 775579Sroot /* 776579Sroot * Attempt to set the lock by creating the temporary file, 777579Sroot * then doing a link/unlink. If it fails, return -1 else 0 778579Sroot */ 779579Sroot 780579Sroot lock1(tempfile, name) 781579Sroot char tempfile[], name[]; 782579Sroot { 783579Sroot register int fd; 784579Sroot 785579Sroot fd = creat(tempfile, 0); 786579Sroot if (fd < 0) 787579Sroot return(-1); 788579Sroot close(fd); 789579Sroot if (link(tempfile, name) < 0) { 790579Sroot unlink(tempfile); 791579Sroot return(-1); 792579Sroot } 793579Sroot unlink(tempfile); 794579Sroot return(0); 795579Sroot } 796579Sroot 797579Sroot done() 798579Sroot { 799579Sroot if(locked) 800579Sroot unlock(); 801579Sroot unlink(lettmp); 802579Sroot unlink(locktmp); 803579Sroot exit(error); 804579Sroot } 805579Sroot 806579Sroot cat(to, from1, from2) 807579Sroot char *to, *from1, *from2; 808579Sroot { 809579Sroot int i, j; 810579Sroot 811579Sroot j = 0; 812579Sroot for (i=0; from1[i]; i++) 813579Sroot to[j++] = from1[i]; 814579Sroot for (i=0; from2[i]; i++) 815579Sroot to[j++] = from2[i]; 816579Sroot to[j] = 0; 817579Sroot } 818579Sroot 819579Sroot char *getarg(s, p) /* copy p... into s, update p */ 820579Sroot register char *s, *p; 821579Sroot { 822579Sroot while (*p == ' ' || *p == '\t') 823579Sroot p++; 824579Sroot if (*p == '\n' || *p == '\0') 825579Sroot return(NULL); 826579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 827579Sroot *s++ = *p++; 828579Sroot *s = '\0'; 829579Sroot return(p); 830579Sroot } 831580Seric # ifndef DELIVERMAIL 832579Sroot /* 833579Sroot stripfx(prefix string, pointer to string) 834579Sroot 835579Sroot takes a ptr to string and compares it to prefix string. 836579Sroot may be called multiple times 837579Sroot */ 838579Sroot stripfx(pfx, name) 839579Sroot char *pfx; 840579Sroot char **name; 841579Sroot { 842579Sroot register char *cp = *name; 843579Sroot 844579Sroot while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) 845579Sroot cp++, pfx++; 846579Sroot if (*cp != ':' || *pfx != 0) 847579Sroot return; 848579Sroot *name = cp; 849579Sroot } 850580Seric # endif 851