1*579Sroot #include <ctype.h> 2*579Sroot #include <stdio.h> 3*579Sroot #include <pwd.h> 4*579Sroot #include <utmp.h> 5*579Sroot #include <signal.h> 6*579Sroot #include <sys/types.h> 7*579Sroot #include <sys/stat.h> 8*579Sroot #include <setjmp.h> 9*579Sroot #include <whoami.h> 10*579Sroot #include <sysexits.h> 11*579Sroot 12*579Sroot #define DELIVERMAIL "/etc/delivermail" 13*579Sroot 14*579Sroot 15*579Sroot /*copylet flags */ 16*579Sroot /*remote mail, add rmtmsg */ 17*579Sroot #define REMOTE 1 18*579Sroot /* zap header and trailing empty line */ 19*579Sroot #define ZAP 3 20*579Sroot #define ORDINARY 2 21*579Sroot #define FORWARD 4 22*579Sroot #define LSIZE 256 23*579Sroot #define MAXLET 300 /* maximum number of letters */ 24*579Sroot #define MAILMODE (~0644) /* mode of created mail */ 25*579Sroot #define RMAIL "/usr/net/bin/sendberkmail" 26*579Sroot #define LOCNAM1 "csvax" 27*579Sroot #define LOCNAM2 "ucbvax" 28*579Sroot #define LOCNAM3 "vax" 29*579Sroot #define LOCNAM4 "v" 30*579Sroot 31*579Sroot char line[LSIZE]; 32*579Sroot char resp[LSIZE]; 33*579Sroot struct let { 34*579Sroot long adr; 35*579Sroot char change; 36*579Sroot } let[MAXLET]; 37*579Sroot int nlet = 0; 38*579Sroot char lfil[50]; 39*579Sroot long iop, time(); 40*579Sroot char *getenv(); 41*579Sroot char *index(); 42*579Sroot char lettmp[] = "/tmp/maXXXXX"; 43*579Sroot char maildir[] = "/usr/spool/mail/"; 44*579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 45*579Sroot char dead[] = "dead.letter"; 46*579Sroot char *thissys = sysname; 47*579Sroot char *netname = "vax"; 48*579Sroot char forwmsg[] = " forwarded\n"; 49*579Sroot FILE *tmpf; 50*579Sroot FILE *malf; 51*579Sroot char *my_name; 52*579Sroot char *getlogin(); 53*579Sroot struct passwd *getpwuid(); 54*579Sroot int error; 55*579Sroot int changed; 56*579Sroot int forward; 57*579Sroot char from[] = "From "; 58*579Sroot long ftell(); 59*579Sroot int delete(); 60*579Sroot char *ctime(); 61*579Sroot int flgf; 62*579Sroot int flgp; 63*579Sroot int delflg = 1; 64*579Sroot int hseqno; 65*579Sroot jmp_buf sjbuf; 66*579Sroot int rmail; 67*579Sroot 68*579Sroot main(argc, argv) 69*579Sroot char **argv; 70*579Sroot { 71*579Sroot register i; 72*579Sroot char sobuf[BUFSIZ]; 73*579Sroot 74*579Sroot setbuf(stdout, sobuf); 75*579Sroot mktemp(lettmp); 76*579Sroot unlink(lettmp); 77*579Sroot my_name = getlogin(); 78*579Sroot if (my_name == NULL || strlen(my_name) == 0) { 79*579Sroot struct passwd *pwent; 80*579Sroot pwent = getpwuid(getuid()); 81*579Sroot if (pwent==NULL) 82*579Sroot my_name = "???"; 83*579Sroot else 84*579Sroot my_name = pwent->pw_name; 85*579Sroot } 86*579Sroot if(setjmp(sjbuf)) done(); 87*579Sroot for (i=0; i<20; i++) 88*579Sroot setsig(i, delete); 89*579Sroot tmpf = fopen(lettmp, "w"); 90*579Sroot if (tmpf == NULL) { 91*579Sroot fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); 92*579Sroot done(); 93*579Sroot } 94*579Sroot if (argv[0][0] == 'r') 95*579Sroot rmail++; 96*579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 97*579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 98*579Sroot printmail(argc, argv); 99*579Sroot else 100*579Sroot sendmail(argc, argv); 101*579Sroot done(); 102*579Sroot } 103*579Sroot 104*579Sroot setsig(i, f) 105*579Sroot int i; 106*579Sroot int (*f)(); 107*579Sroot { 108*579Sroot if(signal(i, SIG_IGN)!=SIG_IGN) 109*579Sroot signal(i, f); 110*579Sroot } 111*579Sroot 112*579Sroot any(c, str) 113*579Sroot register int c; 114*579Sroot register char *str; 115*579Sroot { 116*579Sroot 117*579Sroot while (*str) 118*579Sroot if (c == *str++) 119*579Sroot return(1); 120*579Sroot return(0); 121*579Sroot } 122*579Sroot 123*579Sroot printmail(argc, argv) 124*579Sroot char **argv; 125*579Sroot { 126*579Sroot int flg, i, j, print; 127*579Sroot char *p, *getarg(); 128*579Sroot struct stat statb; 129*579Sroot 130*579Sroot setuid(getuid()); 131*579Sroot cat(mailfile, maildir, my_name); 132*579Sroot if (stat(mailfile, &statb) >= 0 133*579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 134*579Sroot strcat(mailfile, "/"); 135*579Sroot strcat(mailfile, my_name); 136*579Sroot } 137*579Sroot for (; argc>1; argv++, argc--) { 138*579Sroot if (argv[1][0]=='-') { 139*579Sroot if (argv[1][1]=='q') 140*579Sroot delflg = 0; 141*579Sroot else if (argv[1][1]=='p') { 142*579Sroot flgp++; 143*579Sroot delflg = 0; 144*579Sroot } else if (argv[1][1]=='f') { 145*579Sroot if (argc>=3) { 146*579Sroot strcpy(mailfile, argv[2]); 147*579Sroot argv++; 148*579Sroot argc--; 149*579Sroot } 150*579Sroot } else if (argv[1][1]=='r') { 151*579Sroot forward = 1; 152*579Sroot } else if (argv[1][1]=='h') { 153*579Sroot forward = 1; 154*579Sroot } else { 155*579Sroot fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); 156*579Sroot done(); 157*579Sroot } 158*579Sroot } else 159*579Sroot break; 160*579Sroot } 161*579Sroot malf = fopen(mailfile, "r"); 162*579Sroot if (malf == NULL) { 163*579Sroot fprintf(stdout, "No mail.\n"); 164*579Sroot return; 165*579Sroot } 166*579Sroot lock(mailfile); 167*579Sroot copymt(malf, tmpf); 168*579Sroot fclose(malf); 169*579Sroot fclose(tmpf); 170*579Sroot unlock(); 171*579Sroot tmpf = fopen(lettmp, "r"); 172*579Sroot 173*579Sroot changed = 0; 174*579Sroot print = 1; 175*579Sroot for (i = 0; i < nlet; ) { 176*579Sroot j = forward ? i : nlet - i - 1; 177*579Sroot if(setjmp(sjbuf)) { 178*579Sroot print=0; 179*579Sroot } else { 180*579Sroot if (print) 181*579Sroot copylet(j, stdout, ORDINARY); 182*579Sroot print = 1; 183*579Sroot } 184*579Sroot if (flgp) { 185*579Sroot i++; 186*579Sroot continue; 187*579Sroot } 188*579Sroot setjmp(sjbuf); 189*579Sroot fprintf(stdout, "? "); 190*579Sroot fflush(stdout); 191*579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 192*579Sroot break; 193*579Sroot switch (resp[0]) { 194*579Sroot 195*579Sroot default: 196*579Sroot fprintf(stderr, "usage\n"); 197*579Sroot case '?': 198*579Sroot print = 0; 199*579Sroot fprintf(stderr, "q\tquit\n"); 200*579Sroot fprintf(stderr, "x\texit without changing mail\n"); 201*579Sroot fprintf(stderr, "p\tprint\n"); 202*579Sroot fprintf(stderr, "s[file]\tsave (default mbox)\n"); 203*579Sroot fprintf(stderr, "w[file]\tsame without header\n"); 204*579Sroot fprintf(stderr, "-\tprint previous\n"); 205*579Sroot fprintf(stderr, "d\tdelete\n"); 206*579Sroot fprintf(stderr, "+\tnext (no delete)\n"); 207*579Sroot fprintf(stderr, "m user\tmail to user\n"); 208*579Sroot fprintf(stderr, "! cmd\texecute cmd\n"); 209*579Sroot break; 210*579Sroot 211*579Sroot case '+': 212*579Sroot case 'n': 213*579Sroot case '\n': 214*579Sroot i++; 215*579Sroot break; 216*579Sroot case 'x': 217*579Sroot changed = 0; 218*579Sroot case 'q': 219*579Sroot goto donep; 220*579Sroot case 'p': 221*579Sroot break; 222*579Sroot case '^': 223*579Sroot case '-': 224*579Sroot if (--i < 0) 225*579Sroot i = 0; 226*579Sroot break; 227*579Sroot case 'y': 228*579Sroot case 'w': 229*579Sroot case 's': 230*579Sroot flg = 0; 231*579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 232*579Sroot printf("illegal\n"); 233*579Sroot flg++; 234*579Sroot print = 0; 235*579Sroot continue; 236*579Sroot } 237*579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 238*579Sroot p = getenv("HOME"); 239*579Sroot if(p != 0) 240*579Sroot cat(resp+1, p, "/mbox"); 241*579Sroot else 242*579Sroot cat(resp+1, "", "mbox"); 243*579Sroot } 244*579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 245*579Sroot malf = fopen(lfil, "a"); 246*579Sroot if (malf == NULL) { 247*579Sroot fprintf(stdout, "mail: cannot append to %s\n", lfil); 248*579Sroot flg++; 249*579Sroot continue; 250*579Sroot } 251*579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 252*579Sroot fclose(malf); 253*579Sroot } 254*579Sroot if (flg) 255*579Sroot print = 0; 256*579Sroot else { 257*579Sroot let[j].change = 'd'; 258*579Sroot changed++; 259*579Sroot i++; 260*579Sroot } 261*579Sroot break; 262*579Sroot case 'm': 263*579Sroot flg = 0; 264*579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 265*579Sroot i++; 266*579Sroot continue; 267*579Sroot } 268*579Sroot if (resp[1] != ' ') { 269*579Sroot printf("invalid command\n"); 270*579Sroot flg++; 271*579Sroot print = 0; 272*579Sroot continue; 273*579Sroot } 274*579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 275*579Sroot if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ 276*579Sroot flg++; 277*579Sroot if (flg) 278*579Sroot print = 0; 279*579Sroot else { 280*579Sroot let[j].change = 'd'; 281*579Sroot changed++; 282*579Sroot i++; 283*579Sroot } 284*579Sroot break; 285*579Sroot case '!': 286*579Sroot system(resp+1); 287*579Sroot printf("!\n"); 288*579Sroot print = 0; 289*579Sroot break; 290*579Sroot case 'd': 291*579Sroot let[j].change = 'd'; 292*579Sroot changed++; 293*579Sroot i++; 294*579Sroot if (resp[1] == 'q') 295*579Sroot goto donep; 296*579Sroot break; 297*579Sroot } 298*579Sroot } 299*579Sroot donep: 300*579Sroot if (changed) 301*579Sroot copyback(); 302*579Sroot } 303*579Sroot 304*579Sroot copyback() /* copy temp or whatever back to /usr/spool/mail */ 305*579Sroot { 306*579Sroot register i, n, c; 307*579Sroot int new = 0; 308*579Sroot struct stat stbuf; 309*579Sroot 310*579Sroot signal(SIGINT, SIG_IGN); 311*579Sroot signal(SIGHUP, SIG_IGN); 312*579Sroot signal(SIGQUIT, SIG_IGN); 313*579Sroot lock(mailfile); 314*579Sroot stat(mailfile, &stbuf); 315*579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 316*579Sroot malf = fopen(mailfile, "r"); 317*579Sroot if (malf == NULL) { 318*579Sroot fprintf(stdout, "mail: can't re-read %s\n", mailfile); 319*579Sroot done(); 320*579Sroot } 321*579Sroot fseek(malf, let[nlet].adr, 0); 322*579Sroot fclose(tmpf); 323*579Sroot tmpf = fopen(lettmp, "a"); 324*579Sroot fseek(tmpf, let[nlet].adr, 0); 325*579Sroot while ((c = fgetc(malf)) != EOF) 326*579Sroot fputc(c, tmpf); 327*579Sroot fclose(malf); 328*579Sroot fclose(tmpf); 329*579Sroot tmpf = fopen(lettmp, "r"); 330*579Sroot let[++nlet].adr = stbuf.st_size; 331*579Sroot new = 1; 332*579Sroot } 333*579Sroot malf = fopen(mailfile, "w"); 334*579Sroot if (malf == NULL) { 335*579Sroot fprintf(stderr, "mail: can't rewrite %s\n", lfil); 336*579Sroot done(); 337*579Sroot } 338*579Sroot n = 0; 339*579Sroot for (i = 0; i < nlet; i++) 340*579Sroot if (let[i].change != 'd') { 341*579Sroot copylet(i, malf, ORDINARY); 342*579Sroot n++; 343*579Sroot } 344*579Sroot fclose(malf); 345*579Sroot if (new) 346*579Sroot fprintf(stdout, "new mail arrived\n"); 347*579Sroot unlock(); 348*579Sroot } 349*579Sroot 350*579Sroot copymt(f1, f2) /* copy mail (f1) to temp (f2) */ 351*579Sroot FILE *f1, *f2; 352*579Sroot { 353*579Sroot long nextadr; 354*579Sroot 355*579Sroot nlet = nextadr = 0; 356*579Sroot let[0].adr = 0; 357*579Sroot while (fgets(line, LSIZE, f1) != NULL) { 358*579Sroot if (isfrom(line)) 359*579Sroot let[nlet++].adr = nextadr; 360*579Sroot nextadr += strlen(line); 361*579Sroot fputs(line, f2); 362*579Sroot } 363*579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 364*579Sroot } 365*579Sroot 366*579Sroot copylet(n, f, type) FILE *f; 367*579Sroot { int ch, k; 368*579Sroot fseek(tmpf, let[n].adr, 0); 369*579Sroot k = let[n+1].adr - let[n].adr; 370*579Sroot while(k-- > 1 && (ch=fgetc(tmpf))!='\n') 371*579Sroot if(type!=ZAP) fputc(ch,f); 372*579Sroot if(type==REMOTE) 373*579Sroot fprintf(f, " remote from %s\n", thissys); 374*579Sroot else if (type==FORWARD) 375*579Sroot fprintf(f, forwmsg); 376*579Sroot else if(type==ORDINARY) 377*579Sroot fputc(ch,f); 378*579Sroot while(k-->1) 379*579Sroot fputc(ch=fgetc(tmpf), f); 380*579Sroot if(type!=ZAP || ch!= '\n') 381*579Sroot fputc(fgetc(tmpf), f); 382*579Sroot } 383*579Sroot 384*579Sroot isfrom(lp) 385*579Sroot register char *lp; 386*579Sroot { 387*579Sroot register char *p; 388*579Sroot 389*579Sroot for (p = from; *p; ) 390*579Sroot if (*lp++ != *p++) 391*579Sroot return(0); 392*579Sroot return(1); 393*579Sroot } 394*579Sroot 395*579Sroot sendmail(argc, argv) 396*579Sroot char **argv; 397*579Sroot { 398*579Sroot char truename[100]; 399*579Sroot int first; 400*579Sroot register char *cp; 401*579Sroot int gaver = 0; 402*579Sroot # ifdef DELIVERMAIL 403*579Sroot char *newargv[1000]; 404*579Sroot register char **ap; 405*579Sroot register char **vp; 406*579Sroot int dflag; 407*579Sroot 408*579Sroot dflag = 0; 409*579Sroot if (argc < 1) 410*579Sroot fprintf(stderr, "puke\n"); 411*579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 412*579Sroot { 413*579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 414*579Sroot dflag++; 415*579Sroot } 416*579Sroot if (!dflag) 417*579Sroot { 418*579Sroot /* give it to delivermail, rah rah! */ 419*579Sroot unlink(lettmp); 420*579Sroot ap = newargv+1; 421*579Sroot if (rmail) 422*579Sroot *ap-- = "-s"; 423*579Sroot *ap = "-delivermail"; 424*579Sroot execv(DELIVERMAIL, ap); 425*579Sroot perror(DELIVERMAIL); 426*579Sroot exit(EX_UNAVAILABLE); 427*579Sroot } 428*579Sroot # endif DELIVERMAIL 429*579Sroot 430*579Sroot truename[0] = 0; 431*579Sroot line[0] = '\0'; 432*579Sroot 433*579Sroot /* 434*579Sroot * When we fall out of this, argv[1] should be first name, 435*579Sroot * argc should be number of names + 1. 436*579Sroot */ 437*579Sroot 438*579Sroot while (argc > 1 && *argv[1] == '-') { 439*579Sroot cp = *++argv; 440*579Sroot argc--; 441*579Sroot switch (cp[1]) { 442*579Sroot case 'r': 443*579Sroot if (argc <= 0) { 444*579Sroot usage(); 445*579Sroot done(); 446*579Sroot } 447*579Sroot gaver++; 448*579Sroot strcpy(truename, argv[1]); 449*579Sroot fgets(line, LSIZE, stdin); 450*579Sroot if (strcmpn("From", line, 4) == 0) 451*579Sroot line[0] = '\0'; 452*579Sroot argv++; 453*579Sroot argc--; 454*579Sroot break; 455*579Sroot 456*579Sroot case 'h': 457*579Sroot if (argc <= 0) { 458*579Sroot usage(); 459*579Sroot done(); 460*579Sroot } 461*579Sroot hseqno = atoi(argv[1]); 462*579Sroot argv++; 463*579Sroot argc--; 464*579Sroot break; 465*579Sroot 466*579Sroot # ifdef DELIVERMAIL 467*579Sroot case 'd': 468*579Sroot break; 469*579Sroot # endif DELIVERMAIL 470*579Sroot 471*579Sroot default: 472*579Sroot usage(); 473*579Sroot done(); 474*579Sroot } 475*579Sroot } 476*579Sroot if (argc <= 1) { 477*579Sroot usage(); 478*579Sroot done(); 479*579Sroot } 480*579Sroot if (gaver == 0) 481*579Sroot strcpy(truename, my_name); 482*579Sroot /* 483*579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 484*579Sroot strcpy(truename, argv[2]); 485*579Sroot argc -= 2; 486*579Sroot argv += 2; 487*579Sroot fgets(line, LSIZE, stdin); 488*579Sroot if (strcmpn("From", line, 4) == 0) 489*579Sroot line[0] = '\0'; 490*579Sroot } else 491*579Sroot strcpy(truename, my_name); 492*579Sroot */ 493*579Sroot time(&iop); 494*579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 495*579Sroot iop = ftell(tmpf); 496*579Sroot flgf = 1; 497*579Sroot for (first = 1;; first = 0) { 498*579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 499*579Sroot break; 500*579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 501*579Sroot break; 502*579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 503*579Sroot break; 504*579Sroot if (isfrom(line)) 505*579Sroot fputs(">", tmpf); 506*579Sroot fputs(line, tmpf); 507*579Sroot flgf = 0; 508*579Sroot } 509*579Sroot fputs("\n", tmpf); 510*579Sroot nlet = 1; 511*579Sroot let[0].adr = 0; 512*579Sroot let[1].adr = ftell(tmpf); 513*579Sroot fclose(tmpf); 514*579Sroot if (flgf) 515*579Sroot return; 516*579Sroot tmpf = fopen(lettmp, "r"); 517*579Sroot if (tmpf == NULL) { 518*579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 519*579Sroot return; 520*579Sroot } 521*579Sroot while (--argc > 0) 522*579Sroot if (!send(0, *++argv, truename)) 523*579Sroot error++; 524*579Sroot if (error) { 525*579Sroot setuid(getuid()); 526*579Sroot malf = fopen(dead, "w"); 527*579Sroot if (malf == NULL) { 528*579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 529*579Sroot fclose(tmpf); 530*579Sroot return; 531*579Sroot } 532*579Sroot copylet(0, malf, ZAP); 533*579Sroot fclose(malf); 534*579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 535*579Sroot } 536*579Sroot fclose(tmpf); 537*579Sroot } 538*579Sroot 539*579Sroot sendrmt(n, name, rcmd) 540*579Sroot char *name; 541*579Sroot char *rcmd; 542*579Sroot { 543*579Sroot FILE *rmf, *popen(); 544*579Sroot register char *p; 545*579Sroot char rsys[64], cmd[64]; 546*579Sroot register local, pid; 547*579Sroot int sts; 548*579Sroot 549*579Sroot local = 0; 550*579Sroot if (index(name, '^')) { 551*579Sroot while (p = index(name, '^')) 552*579Sroot *p = '!'; 553*579Sroot if (strncmp(name, "researc", 7)) { 554*579Sroot strcpy(rsys, "research"); 555*579Sroot if (*name != '!') 556*579Sroot --name; 557*579Sroot goto skip; 558*579Sroot } 559*579Sroot } 560*579Sroot if (*name=='!') 561*579Sroot name++; 562*579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 563*579Sroot if (*name=='\0') { 564*579Sroot local++; 565*579Sroot break; 566*579Sroot } 567*579Sroot *p = '\0'; 568*579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 569*579Sroot fprintf(stdout, "null name\n"); 570*579Sroot return(0); 571*579Sroot } 572*579Sroot skip: 573*579Sroot if ((pid = fork()) == -1) { 574*579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 575*579Sroot return(0); 576*579Sroot } 577*579Sroot if (pid) { 578*579Sroot while (wait(&sts) != pid) { 579*579Sroot if (wait(&sts)==-1) 580*579Sroot return(0); 581*579Sroot } 582*579Sroot return(!sts); 583*579Sroot } 584*579Sroot setuid(getuid()); 585*579Sroot if (local) 586*579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 587*579Sroot else { 588*579Sroot if (index(name+1, '!')) 589*579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 590*579Sroot else 591*579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 592*579Sroot } 593*579Sroot if ((rmf=popen(cmd, "w")) == NULL) 594*579Sroot exit(1); 595*579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 596*579Sroot pclose(rmf); 597*579Sroot exit(0); 598*579Sroot } 599*579Sroot 600*579Sroot /* 601*579Sroot * Send mail on the Berkeley network. 602*579Sroot * Sorry Bill, sendrmt() is so awful we just gave up. 603*579Sroot */ 604*579Sroot 605*579Sroot sendberkmail(n, name, fromaddr) 606*579Sroot char name[]; 607*579Sroot char fromaddr[]; 608*579Sroot { 609*579Sroot char cmd[200]; 610*579Sroot register FILE *cmdf; 611*579Sroot 612*579Sroot sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name); 613*579Sroot if ((cmdf = popen(cmd, "w")) == NULL) { 614*579Sroot perror(RMAIL); 615*579Sroot return(0); 616*579Sroot } 617*579Sroot copylet(n, cmdf, ORDINARY); 618*579Sroot pclose(cmdf); 619*579Sroot return(9); 620*579Sroot } 621*579Sroot 622*579Sroot usage() 623*579Sroot { 624*579Sroot 625*579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 626*579Sroot } 627*579Sroot 628*579Sroot send(n, name, fromaddr) 629*579Sroot int n; 630*579Sroot char *name; 631*579Sroot char *fromaddr; 632*579Sroot { 633*579Sroot char file[100]; 634*579Sroot register char *p; 635*579Sroot register mask; 636*579Sroot struct passwd *pw, *getpwnam(); 637*579Sroot struct stat statb; 638*579Sroot 639*579Sroot stripfx(LOCNAM1, &name); 640*579Sroot stripfx(LOCNAM2, &name); 641*579Sroot stripfx(LOCNAM3, &name); 642*579Sroot stripfx(LOCNAM4, &name); 643*579Sroot if(*name == ':')name++; /* skip colon in to-name */ 644*579Sroot for(p=name; *p!=':' &&*p!='\0'; p++); 645*579Sroot /* if(*p == ':') return(sendrmt(n, name, RMAIL)); */ 646*579Sroot if (*p == ':') 647*579Sroot return(sendberkmail(n, name, fromaddr)); 648*579Sroot else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs")); 649*579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 650*579Sroot ; 651*579Sroot if (*p == '!'|| *p=='^') 652*579Sroot return(sendrmt(n, name, 0)); 653*579Sroot if ((pw = getpwnam(name)) == NULL) { 654*579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 655*579Sroot return(0); 656*579Sroot } 657*579Sroot cat(file, maildir, name); 658*579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 659*579Sroot strcat(file, "/"); 660*579Sroot strcat(file, name); 661*579Sroot } 662*579Sroot mask = umask(MAILMODE); 663*579Sroot malf = fopen(file, "a"); 664*579Sroot umask(mask); 665*579Sroot if (malf == NULL) { 666*579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 667*579Sroot return(0); 668*579Sroot } 669*579Sroot lock(file); 670*579Sroot chown(file, pw->pw_uid, pw->pw_gid); 671*579Sroot copylet(n, malf, ORDINARY); 672*579Sroot fclose(malf); 673*579Sroot unlock(); 674*579Sroot return(1); 675*579Sroot } 676*579Sroot 677*579Sroot delete(i) 678*579Sroot { 679*579Sroot setsig(i, delete); 680*579Sroot fprintf(stderr, "\n"); 681*579Sroot if(delflg) 682*579Sroot longjmp(sjbuf, 1); 683*579Sroot done(); 684*579Sroot } 685*579Sroot 686*579Sroot /* 687*579Sroot * Lock the specified mail file by setting the file mailfile.lock. 688*579Sroot * We must, of course, be careful to unlink the lock file by a call 689*579Sroot * to unlock before we stop. The algorithm used here is to see if 690*579Sroot * the lock exists, and if it does, to check its modify time. If it 691*579Sroot * is older than 30 seconds, we assume error and set our own file. 692*579Sroot * Otherwise, we wait for 5 seconds and try again. 693*579Sroot */ 694*579Sroot 695*579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 696*579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 697*579Sroot char locktmp[30]; /* Usable lock temporary */ 698*579Sroot char curlock[50]; /* Last used name of lock */ 699*579Sroot int locked; /* To note that we locked it */ 700*579Sroot 701*579Sroot lock(file) 702*579Sroot char *file; 703*579Sroot { 704*579Sroot register int f; 705*579Sroot struct stat sbuf; 706*579Sroot long curtime; 707*579Sroot int statfailed; 708*579Sroot 709*579Sroot if (locked || flgf) 710*579Sroot return(0); 711*579Sroot strcpy(curlock, file); 712*579Sroot strcat(curlock, maillock); 713*579Sroot strcpy(locktmp, lockname); 714*579Sroot mktemp(locktmp); 715*579Sroot unlink(locktmp); 716*579Sroot statfailed = 0; 717*579Sroot for (;;) { 718*579Sroot f = lock1(locktmp, curlock); 719*579Sroot if (f == 0) { 720*579Sroot locked = 1; 721*579Sroot return(0); 722*579Sroot } 723*579Sroot if (stat(curlock, &sbuf) < 0) { 724*579Sroot if (statfailed++ > 5) 725*579Sroot return(-1); 726*579Sroot sleep(5); 727*579Sroot continue; 728*579Sroot } 729*579Sroot statfailed = 0; 730*579Sroot time(&curtime); 731*579Sroot if (curtime < sbuf.st_ctime + 30) { 732*579Sroot sleep(5); 733*579Sroot continue; 734*579Sroot } 735*579Sroot unlink(curlock); 736*579Sroot } 737*579Sroot } 738*579Sroot 739*579Sroot /* 740*579Sroot * Remove the mail lock, and note that we no longer 741*579Sroot * have it locked. 742*579Sroot */ 743*579Sroot 744*579Sroot unlock() 745*579Sroot { 746*579Sroot 747*579Sroot unlink(curlock); 748*579Sroot locked = 0; 749*579Sroot } 750*579Sroot 751*579Sroot /* 752*579Sroot * Attempt to set the lock by creating the temporary file, 753*579Sroot * then doing a link/unlink. If it fails, return -1 else 0 754*579Sroot */ 755*579Sroot 756*579Sroot lock1(tempfile, name) 757*579Sroot char tempfile[], name[]; 758*579Sroot { 759*579Sroot register int fd; 760*579Sroot 761*579Sroot fd = creat(tempfile, 0); 762*579Sroot if (fd < 0) 763*579Sroot return(-1); 764*579Sroot close(fd); 765*579Sroot if (link(tempfile, name) < 0) { 766*579Sroot unlink(tempfile); 767*579Sroot return(-1); 768*579Sroot } 769*579Sroot unlink(tempfile); 770*579Sroot return(0); 771*579Sroot } 772*579Sroot 773*579Sroot done() 774*579Sroot { 775*579Sroot if(locked) 776*579Sroot unlock(); 777*579Sroot unlink(lettmp); 778*579Sroot unlink(locktmp); 779*579Sroot exit(error); 780*579Sroot } 781*579Sroot 782*579Sroot cat(to, from1, from2) 783*579Sroot char *to, *from1, *from2; 784*579Sroot { 785*579Sroot int i, j; 786*579Sroot 787*579Sroot j = 0; 788*579Sroot for (i=0; from1[i]; i++) 789*579Sroot to[j++] = from1[i]; 790*579Sroot for (i=0; from2[i]; i++) 791*579Sroot to[j++] = from2[i]; 792*579Sroot to[j] = 0; 793*579Sroot } 794*579Sroot 795*579Sroot char *getarg(s, p) /* copy p... into s, update p */ 796*579Sroot register char *s, *p; 797*579Sroot { 798*579Sroot while (*p == ' ' || *p == '\t') 799*579Sroot p++; 800*579Sroot if (*p == '\n' || *p == '\0') 801*579Sroot return(NULL); 802*579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 803*579Sroot *s++ = *p++; 804*579Sroot *s = '\0'; 805*579Sroot return(p); 806*579Sroot } 807*579Sroot /* 808*579Sroot stripfx(prefix string, pointer to string) 809*579Sroot 810*579Sroot takes a ptr to string and compares it to prefix string. 811*579Sroot may be called multiple times 812*579Sroot */ 813*579Sroot stripfx(pfx, name) 814*579Sroot char *pfx; 815*579Sroot char **name; 816*579Sroot { 817*579Sroot register char *cp = *name; 818*579Sroot 819*579Sroot while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) 820*579Sroot cp++, pfx++; 821*579Sroot if (*cp != ':' || *pfx != 0) 822*579Sroot return; 823*579Sroot *name = cp; 824*579Sroot } 825