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*6015Swnj static char SccsId[] = "@(#)mail.local.c 4.6 02/28/82"; 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 104*6015Swnj bulkmail(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 399*6015Swnj bulkmail(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"; 4284461Sroot 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 } 526*6015Swnj while (--argc > 0) { 527*6015Swnj if (!sendmail(0, *++argv, truename)) 528579Sroot error++; 529*6015Swnj } 530579Sroot if (error) { 531579Sroot setuid(getuid()); 532579Sroot malf = fopen(dead, "w"); 533579Sroot if (malf == NULL) { 534579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 535579Sroot fclose(tmpf); 536579Sroot return; 537579Sroot } 538579Sroot copylet(0, malf, ZAP); 539579Sroot fclose(malf); 540579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 541579Sroot } 542579Sroot fclose(tmpf); 543579Sroot } 544579Sroot 545579Sroot sendrmt(n, name, rcmd) 546579Sroot char *name; 547579Sroot char *rcmd; 548579Sroot { 549579Sroot FILE *rmf, *popen(); 550579Sroot register char *p; 551579Sroot char rsys[64], cmd[64]; 552579Sroot register local, pid; 553579Sroot int sts; 554579Sroot 555579Sroot local = 0; 556579Sroot if (index(name, '^')) { 557579Sroot while (p = index(name, '^')) 558579Sroot *p = '!'; 559579Sroot if (strncmp(name, "researc", 7)) { 560579Sroot strcpy(rsys, "research"); 561579Sroot if (*name != '!') 562579Sroot --name; 563579Sroot goto skip; 564579Sroot } 565579Sroot } 566579Sroot if (*name=='!') 567579Sroot name++; 568579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 569579Sroot if (*name=='\0') { 570579Sroot local++; 571579Sroot break; 572579Sroot } 573579Sroot *p = '\0'; 574579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 575579Sroot fprintf(stdout, "null name\n"); 576579Sroot return(0); 577579Sroot } 578579Sroot skip: 579579Sroot if ((pid = fork()) == -1) { 580579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 581579Sroot return(0); 582579Sroot } 583579Sroot if (pid) { 584579Sroot while (wait(&sts) != pid) { 585579Sroot if (wait(&sts)==-1) 586579Sroot return(0); 587579Sroot } 588579Sroot return(!sts); 589579Sroot } 590579Sroot setuid(getuid()); 591579Sroot if (local) 592579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 593579Sroot else { 594579Sroot if (index(name+1, '!')) 595579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 596579Sroot else 597579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 598579Sroot } 599579Sroot if ((rmf=popen(cmd, "w")) == NULL) 600579Sroot exit(1); 601579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 602579Sroot pclose(rmf); 603579Sroot exit(0); 604579Sroot } 605579Sroot 606580Seric # ifndef DELIVERMAIL 607579Sroot /* 608579Sroot * Send mail on the Berkeley network. 609579Sroot * Sorry Bill, sendrmt() is so awful we just gave up. 610579Sroot */ 611579Sroot 612579Sroot sendberkmail(n, name, fromaddr) 613579Sroot char name[]; 614579Sroot char fromaddr[]; 615579Sroot { 616579Sroot char cmd[200]; 617579Sroot register FILE *cmdf; 618579Sroot 619579Sroot sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name); 620579Sroot if ((cmdf = popen(cmd, "w")) == NULL) { 621579Sroot perror(RMAIL); 622579Sroot return(0); 623579Sroot } 624579Sroot copylet(n, cmdf, ORDINARY); 625579Sroot pclose(cmdf); 626579Sroot return(9); 627579Sroot } 628580Seric # endif 629579Sroot 630579Sroot usage() 631579Sroot { 632579Sroot 633579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 634579Sroot } 635579Sroot 636*6015Swnj #include <sys/socket.h> 637*6015Swnj #include <net/in.h> 638*6015Swnj #include <wellknown.h> 639*6015Swnj struct sockaddr_in biffaddr = { AF_INET, IPPORT_BIFFUDP }; 640*6015Swnj char *localhost = "localhost"; 641*6015Swnj 642*6015Swnj sendmail(n, name, fromaddr) 643579Sroot int n; 644579Sroot char *name; 645579Sroot char *fromaddr; 646579Sroot { 647579Sroot char file[100]; 648579Sroot register char *p; 649579Sroot register mask; 650579Sroot struct passwd *pw, *getpwnam(); 651579Sroot struct stat statb; 6523666Swnj char buf[128]; 6533666Swnj int f; 654579Sroot 655580Seric # ifndef DELIVERMAIL 656579Sroot stripfx(LOCNAM1, &name); 657579Sroot stripfx(LOCNAM2, &name); 658579Sroot stripfx(LOCNAM3, &name); 659579Sroot stripfx(LOCNAM4, &name); 660579Sroot if(*name == ':')name++; /* skip colon in to-name */ 661580Seric for(p=name; *p!=':' && *p!='!' && *p!='^' &&*p!='\0'; p++); 662579Sroot /* if(*p == ':') return(sendrmt(n, name, RMAIL)); */ 663579Sroot if (*p == ':') 664579Sroot return(sendberkmail(n, name, fromaddr)); 665580Seric else if (*p=='\0' && strcmp(name, "msgs") == 0) 666580Seric return(sendrmt(n, "-s", "/usr/ucb/msgs")); 667580Seric # endif 668579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 669579Sroot ; 670579Sroot if (*p == '!'|| *p=='^') 671579Sroot return(sendrmt(n, name, 0)); 672579Sroot if ((pw = getpwnam(name)) == NULL) { 673579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 674579Sroot return(0); 675579Sroot } 676579Sroot cat(file, maildir, name); 677579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 678579Sroot strcat(file, "/"); 679579Sroot strcat(file, name); 680579Sroot } 681579Sroot mask = umask(MAILMODE); 6824459Sroot if (stat(file, &statb) >= 0 && statb.st_nlink != 1) { 6834458Sroot fprintf(stdout, "mail: %s's mail file has more than one link\n", name); 6844458Sroot return(0); 6854458Sroot } 686579Sroot malf = fopen(file, "a"); 687579Sroot umask(mask); 688579Sroot if (malf == NULL) { 689579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 690579Sroot return(0); 691579Sroot } 692579Sroot lock(file); 693*6015Swnj chown(file, pw->pw_uid, pw->pw_gid); 6943666Swnj { 695*6015Swnj f = socket(SOCK_DGRAM, 0, 0, 0); 6963666Swnj sprintf(buf, "%s@%d\n", name, ftell(malf)); 6973666Swnj } 698579Sroot copylet(n, malf, ORDINARY); 699*6015Swnj fclose(malf); 7003666Swnj if (f >= 0) { 701*6015Swnj biffaddr.sin_addr.s_addr = rhost(&localhost); 702*6015Swnj send(f, &biffaddr, buf, strlen(buf)+1); 7033666Swnj close(f); 7043666Swnj } 705579Sroot unlock(); 706579Sroot return(1); 707579Sroot } 708579Sroot 709579Sroot delete(i) 710579Sroot { 711579Sroot setsig(i, delete); 712579Sroot fprintf(stderr, "\n"); 713579Sroot if(delflg) 714579Sroot longjmp(sjbuf, 1); 715579Sroot done(); 716579Sroot } 717579Sroot 718579Sroot /* 719579Sroot * Lock the specified mail file by setting the file mailfile.lock. 720579Sroot * We must, of course, be careful to unlink the lock file by a call 721579Sroot * to unlock before we stop. The algorithm used here is to see if 722579Sroot * the lock exists, and if it does, to check its modify time. If it 723579Sroot * is older than 30 seconds, we assume error and set our own file. 724579Sroot * Otherwise, we wait for 5 seconds and try again. 725579Sroot */ 726579Sroot 727579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 728579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 729579Sroot char locktmp[30]; /* Usable lock temporary */ 730579Sroot char curlock[50]; /* Last used name of lock */ 731579Sroot int locked; /* To note that we locked it */ 732579Sroot 733579Sroot lock(file) 734579Sroot char *file; 735579Sroot { 736579Sroot register int f; 737579Sroot struct stat sbuf; 738579Sroot long curtime; 739579Sroot int statfailed; 740579Sroot 741579Sroot if (locked || flgf) 742579Sroot return(0); 743579Sroot strcpy(curlock, file); 744579Sroot strcat(curlock, maillock); 745579Sroot strcpy(locktmp, lockname); 746579Sroot mktemp(locktmp); 747579Sroot unlink(locktmp); 748579Sroot statfailed = 0; 749579Sroot for (;;) { 750579Sroot f = lock1(locktmp, curlock); 751579Sroot if (f == 0) { 752579Sroot locked = 1; 753579Sroot return(0); 754579Sroot } 755579Sroot if (stat(curlock, &sbuf) < 0) { 756579Sroot if (statfailed++ > 5) 757579Sroot return(-1); 758579Sroot sleep(5); 759579Sroot continue; 760579Sroot } 761579Sroot statfailed = 0; 762579Sroot time(&curtime); 763579Sroot if (curtime < sbuf.st_ctime + 30) { 764579Sroot sleep(5); 765579Sroot continue; 766579Sroot } 767579Sroot unlink(curlock); 768579Sroot } 769579Sroot } 770579Sroot 771579Sroot /* 772579Sroot * Remove the mail lock, and note that we no longer 773579Sroot * have it locked. 774579Sroot */ 775579Sroot 776579Sroot unlock() 777579Sroot { 778579Sroot 779579Sroot unlink(curlock); 780579Sroot locked = 0; 781579Sroot } 782579Sroot 783579Sroot /* 784579Sroot * Attempt to set the lock by creating the temporary file, 785579Sroot * then doing a link/unlink. If it fails, return -1 else 0 786579Sroot */ 787579Sroot 788579Sroot lock1(tempfile, name) 789579Sroot char tempfile[], name[]; 790579Sroot { 791579Sroot register int fd; 792579Sroot 793579Sroot fd = creat(tempfile, 0); 794579Sroot if (fd < 0) 795579Sroot return(-1); 796579Sroot close(fd); 797579Sroot if (link(tempfile, name) < 0) { 798579Sroot unlink(tempfile); 799579Sroot return(-1); 800579Sroot } 801579Sroot unlink(tempfile); 802579Sroot return(0); 803579Sroot } 804579Sroot 805579Sroot done() 806579Sroot { 807579Sroot if(locked) 808579Sroot unlock(); 809579Sroot unlink(lettmp); 810579Sroot unlink(locktmp); 811579Sroot exit(error); 812579Sroot } 813579Sroot 814579Sroot cat(to, from1, from2) 815579Sroot char *to, *from1, *from2; 816579Sroot { 817579Sroot int i, j; 818579Sroot 819579Sroot j = 0; 820579Sroot for (i=0; from1[i]; i++) 821579Sroot to[j++] = from1[i]; 822579Sroot for (i=0; from2[i]; i++) 823579Sroot to[j++] = from2[i]; 824579Sroot to[j] = 0; 825579Sroot } 826579Sroot 827579Sroot char *getarg(s, p) /* copy p... into s, update p */ 828579Sroot register char *s, *p; 829579Sroot { 830579Sroot while (*p == ' ' || *p == '\t') 831579Sroot p++; 832579Sroot if (*p == '\n' || *p == '\0') 833579Sroot return(NULL); 834579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 835579Sroot *s++ = *p++; 836579Sroot *s = '\0'; 837579Sroot return(p); 838579Sroot } 839580Seric # ifndef DELIVERMAIL 840579Sroot /* 841579Sroot stripfx(prefix string, pointer to string) 842579Sroot 843579Sroot takes a ptr to string and compares it to prefix string. 844579Sroot may be called multiple times 845579Sroot */ 846579Sroot stripfx(pfx, name) 847579Sroot char *pfx; 848579Sroot char **name; 849579Sroot { 850579Sroot register char *cp = *name; 851579Sroot 852579Sroot while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) 853579Sroot cp++, pfx++; 854579Sroot if (*cp != ':' || *pfx != 0) 855579Sroot return; 856579Sroot *name = cp; 857579Sroot } 858580Seric # endif 859