|
|
1.1 ! root 1: #ident "@(#)fio.c 1.3 'attmail mail(1) command'" ! 2: #ident "@(#)mailx:fio.c 1.13.1.2" ! 3: /* Copyright (c) 1984 AT&T */ ! 4: /* All Rights Reserved */ ! 5: ! 6: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ ! 7: /* The copyright notice above does not evidence any */ ! 8: /* actual or intended publication of such source code. */ ! 9: ! 10: #ident "@(#)mailx:fio.c 1.13.1.1" ! 11: ! 12: #include "rcv.h" ! 13: ! 14: /* ! 15: * mailx -- a modified version of a University of California at Berkeley ! 16: * mail program ! 17: * ! 18: * File I/O. ! 19: */ ! 20: ! 21: static int getln(); ! 22: ! 23: /* ! 24: * Set up the input pointers while copying the mail file into ! 25: * /tmp. ! 26: */ ! 27: ! 28: void ! 29: setptr(ibuf) ! 30: FILE *ibuf; ! 31: { ! 32: int n, newline = 1; ! 33: int ToldUser = FALSE; ! 34: int ctf = FALSE; /* header continuation flag */ ! 35: long clen = 0; ! 36: long explicit_clen = 0; ! 37: int hdr = 0; ! 38: register char *cp; ! 39: register int l; ! 40: register long s; ! 41: off_t offset; ! 42: char linebuf[LINESIZE]; ! 43: int inhead, newmail, Odot; ! 44: short flag; ! 45: ! 46: if ( !space ) { ! 47: msgCount = 0; ! 48: offset = 0; ! 49: space = 32; ! 50: newmail = 0; ! 51: message = (struct message *)calloc(space, sizeof(struct message)); ! 52: if ( message == NULL ) { ! 53: fprintf(stderr,"calloc: insufficient memory for %d messages\n",space); ! 54: exit(1); ! 55: /* NOTREACHED */ ! 56: } ! 57: dot = message; ! 58: } else { ! 59: newmail = 1; ! 60: offset = fsize(otf); ! 61: } ! 62: s = 0L; ! 63: l = 0; ! 64: flag = MUSED|MNEW; ! 65: ! 66: while ((n = getln(linebuf, sizeof linebuf, ibuf)) > 0) { ! 67: if (!newline) { ! 68: goto putout; ! 69: } else if ((hdr = isheader (linebuf, &ctf)) == FALSE) { ! 70: ctf = FALSE; /* next line can't be cont. */ ! 71: } ! 72: ! 73: /* ! 74: bug msgCount should be checked ! 75: also, ignore anything that looks like a header line ! 76: after the header is finished!!! -- adb ! 77: */ ! 78: switch (hdr) { ! 79: case H_FROM: ! 80: ! 81: if ( (msgCount > 0) && (!newmail) ){ ! 82: message[msgCount-1].m_size = s; ! 83: message[msgCount-1].m_clen = ! 84: (explicit_clen <= 0 || clen < explicit_clen) ? ! 85: clen : explicit_clen; ! 86: /* if ( message[msgCount-1].m_text == TRUE ) { */ ! 87: message[msgCount-1].m_lines = l; ! 88: /* } else { */ ! 89: /* message[msgCount-1].m_lines = -99; */ ! 90: /* } */ ! 91: message[msgCount-1].m_flag = flag; ! 92: flag = MUSED|MNEW; ! 93: } ! 94: if ( msgCount >= space ) { ! 95: ! 96: /* Limit the speed at which the allocated space grows */ ! 97: ! 98: if ( space < 512 ) ! 99: space = space*2; ! 100: else ! 101: space += 512; ! 102: errno = 0; ! 103: Odot = dot - &(message[0]); ! 104: message = (struct message *)realloc(message,space*(sizeof( struct message))); ! 105: if ( message == NULL ) { ! 106: perror("realloc failed"); ! 107: fprintf(stderr,"realloc: insufficient memory for %d messages\n",space); ! 108: exit(1); ! 109: } ! 110: dot = &message[Odot]; ! 111: } ! 112: message[msgCount].m_block = blockof(offset); ! 113: message[msgCount].m_offset = offsetofaddr(offset); ! 114: message[msgCount].m_text = TRUE; ! 115: newmail = 0; ! 116: msgCount++; ! 117: flag = MUSED|MNEW; ! 118: inhead = 1; ! 119: s = 0L; ! 120: explicit_clen = clen = 0L; ! 121: l = 0; ! 122: ToldUser = FALSE; ! 123: break; ! 124: case H_CLEN: ! 125: if (!inhead) { ! 126: break; ! 127: } ! 128: explicit_clen = atol (strpbrk (linebuf, ":")+1); ! 129: break; ! 130: ! 131: case H_STATUS: ! 132: if (inhead && ishfield(linebuf, "status")) { ! 133: cp = hcontents(linebuf); ! 134: if (strchr(cp, 'R')) ! 135: flag |= MREAD; ! 136: if (strchr(cp, 'O')) ! 137: flag &= ~MNEW; ! 138: } ! 139: break; ! 140: default: ! 141: break; ! 142: } ! 143: if( !inhead && hdr) hdr = 0; ! 144: putout: ! 145: offset += n; ! 146: s += (long)n; ! 147: if( !hdr ) { ! 148: if( inhead ) { ! 149: inhead = 0; ! 150: if( n == 1 && linebuf[0] == '\n') ! 151: clen = -1L; /* cheat: avoid leading blank */ ! 152: } ! 153: clen += (long)n; ! 154: } ! 155: if (msgCount && message[msgCount-1].m_text == TRUE) { ! 156: message[msgCount-1].m_text = istext(linebuf,(long)n); ! 157: } ! 158: if (fwrite(linebuf,1,n,otf) != n) { ! 159: fclose(ibuf); ! 160: fflush(otf); ! 161: } else { ! 162: l++; ! 163: } ! 164: if (ferror(otf)) { ! 165: perror("/tmp"); ! 166: exit(1); ! 167: } ! 168: if (msgCount == 0) { ! 169: fclose(ibuf); ! 170: fflush(otf); ! 171: ! 172: } ! 173: newline = (linebuf[n-1] == '\n'); ! 174: ! 175: /* distribution mailx had unreachable code here -- ignore */ ! 176: } ! 177: ! 178: /* ! 179: last plus 1 ! 180: */ ! 181: ! 182: if (n == 0) { ! 183: fflush(otf); ! 184: if ( msgCount ) { ! 185: message[msgCount-1].m_size = s; ! 186: message[msgCount-1].m_clen = clen; ! 187: /* if ( message[msgCount-1].m_text == TRUE ) { */ ! 188: message[msgCount-1].m_lines = l; ! 189: /* } else { */ ! 190: /* message[msgCount-1].m_lines = -99; */ ! 191: /* } */ ! 192: message[msgCount-1].m_flag = flag; ! 193: } ! 194: flag = MUSED|MNEW; ! 195: fclose(ibuf); ! 196: fflush(otf); ! 197: return; ! 198: } ! 199: } ! 200: ! 201: /* HMF: Code from fio.c. (getln) */ ! 202: ! 203: static int ! 204: getln(line, max, f) ! 205: char *line; ! 206: int max; ! 207: FILE *f; ! 208: { ! 209: int i,ch; ! 210: for (i=0; i < max-1 && (ch=getc(f)) != EOF;) ! 211: if ((line[i++] = (char)ch) == '\n') break; ! 212: line[i] = '\0'; ! 213: return(i); ! 214: } ! 215: ! 216: /* ! 217: * Drop the passed line onto the passed output buffer. ! 218: * If a write error occurs, return -1, else the count of ! 219: * characters written, including the newline. ! 220: */ ! 221: ! 222: putline(obuf, linebuf) ! 223: FILE *obuf; ! 224: char *linebuf; ! 225: { ! 226: register int c; ! 227: ! 228: c = strlen(linebuf); ! 229: fputs(linebuf, obuf); ! 230: putc('\n', obuf); ! 231: if (ferror(obuf)) ! 232: return(-1); ! 233: return(c+1); ! 234: } ! 235: ! 236: /* ! 237: * Read up a line from the specified input into the line ! 238: * buffer. Return the number of characters read. Do not ! 239: * include the newline at the end. ! 240: */ ! 241: ! 242: readline(ibuf, linebuf) ! 243: FILE *ibuf; ! 244: char *linebuf; ! 245: { ! 246: register char *cp; ! 247: register int c; ! 248: ! 249: do { ! 250: clearerr(ibuf); ! 251: c = getc(ibuf); ! 252: for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) { ! 253: /* ! 254: if (c == 0) { ! 255: fprintf(stderr, "mailx: NUL changed to @\n"); ! 256: c = '@'; ! 257: } ! 258: */ ! 259: if (cp - linebuf < LINESIZE-2) ! 260: *cp++ = (char)c; ! 261: } ! 262: } while (ferror(ibuf) && ibuf == stdin); ! 263: *cp = 0; ! 264: if (c == EOF && cp == linebuf) ! 265: return(0); ! 266: return(cp - linebuf + 1); ! 267: } ! 268: ! 269: /* ! 270: * Return a file buffer all ready to read up the ! 271: * passed message pointer. ! 272: */ ! 273: ! 274: FILE * ! 275: setinput(mp) ! 276: register struct message *mp; ! 277: { ! 278: off_t off; ! 279: ! 280: fflush(otf); ! 281: off = mp->m_block; ! 282: off <<= 9; ! 283: off += mp->m_offset; ! 284: if (fseek(itf, off, 0) < 0) { ! 285: perror("fseek"); ! 286: panic("temporary file seek"); ! 287: } ! 288: return(itf); ! 289: } ! 290: ! 291: ! 292: /* ! 293: * Delete a file, but only if the file is a plain file. ! 294: */ ! 295: ! 296: removefile(name) ! 297: char name[]; ! 298: { ! 299: struct stat statb; ! 300: ! 301: if (stat(name, &statb) < 0) ! 302: return(-1); ! 303: if ((statb.st_mode & S_IFMT) != S_IFREG) { ! 304: errno = EISDIR; ! 305: return(-1); ! 306: } ! 307: return(unlink(name)); ! 308: } ! 309: ! 310: /* ! 311: * Terminate an editing session by attempting to write out the user's ! 312: * file from the temporary. Save any new stuff appended to the file. ! 313: */ ! 314: int ! 315: edstop() ! 316: { ! 317: register int gotcha, c; ! 318: register struct message *mp; ! 319: FILE *obuf, *ibuf, *tbuf = 0, *readstat; ! 320: FILE *lockopen(); /* adb */ ! 321: struct stat statb; ! 322: char tempname[30], *id; ! 323: ! 324: if (readonly) ! 325: return(0); ! 326: holdsigs(); ! 327: if (Tflag != NOSTR) { ! 328: if ((readstat = fopen(Tflag, "w")) == NULL) ! 329: Tflag = NOSTR; ! 330: } ! 331: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) { ! 332: if (mp->m_flag & MNEW) { ! 333: mp->m_flag &= ~MNEW; ! 334: mp->m_flag |= MSTATUS; ! 335: } ! 336: if (mp->m_flag & (MODIFY|MDELETED|MSTATUS)) ! 337: gotcha++; ! 338: if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { ! 339: if ((id = hfield("article-id", mp, addone)) != NOSTR) ! 340: fprintf(readstat, "%s\n", id); ! 341: } ! 342: } ! 343: if (Tflag != NOSTR) ! 344: fclose(readstat); ! 345: if (!gotcha || Tflag != NOSTR) ! 346: goto done; ! 347: if ((ibuf = lockopen(editfile, "r+w", 0666, -1, -1)) == NULL) { /* adb */ ! 348: perror(editfile); ! 349: relsesigs(); ! 350: longjmp(srbuf, 1); ! 351: } ! 352: /* lock(ibuf, "r+", 1); adb */ ! 353: if (fstat(fileno(ibuf), &statb) >= 0 && statb.st_size > mailsize) { ! 354: strcpy(tempname, "/tmp/mboxXXXXXX"); ! 355: mktemp(tempname); ! 356: if ((obuf = fopen(tempname, "w")) == NULL) { ! 357: perror(tempname); ! 358: lockclose(ibuf); /* adb */ ! 359: relsesigs(); ! 360: longjmp(srbuf, 1); ! 361: } ! 362: fseek(ibuf, mailsize, 0); ! 363: while ((c = getc(ibuf)) != EOF) ! 364: putc(c, obuf); ! 365: fclose(obuf); ! 366: if ((tbuf = fopen(tempname, "r")) == NULL) { ! 367: perror(tempname); ! 368: lockclose(ibuf); /* adb */ ! 369: removefile(tempname); ! 370: relsesigs(); ! 371: longjmp(srbuf, 1); ! 372: } ! 373: removefile(tempname); ! 374: } ! 375: printf("\"%s\" ", editfile); ! 376: flush(); ! 377: if ((obuf = fopen(editfile, "w")) == NULL) { ! 378: perror(editfile); ! 379: lockclose(ibuf); /* adb */ ! 380: if (tbuf) ! 381: fclose(tbuf); ! 382: relsesigs(); ! 383: longjmp(srbuf, 1); ! 384: } ! 385: c = 0; ! 386: for (mp = &message[0]; mp < &message[msgCount]; mp++) { ! 387: if ((mp->m_flag & MDELETED) != 0) ! 388: continue; ! 389: c++; ! 390: if (send(mp, obuf, 0) < 0) { ! 391: perror(editfile); ! 392: lockclose(ibuf); /* adb */ ! 393: fclose(obuf); ! 394: if (tbuf) ! 395: fclose(tbuf); ! 396: relsesigs(); ! 397: longjmp(srbuf, 1); ! 398: } ! 399: } ! 400: gotcha = (c == 0 && ibuf == NULL); ! 401: if (tbuf != NULL) { ! 402: while ((c = getc(tbuf)) != EOF) ! 403: putc(c, obuf); ! 404: fclose(tbuf); ! 405: } ! 406: fflush(obuf); ! 407: if (ferror(obuf)) { ! 408: perror(editfile); ! 409: lockclose(ibuf); /* adb */ ! 410: fclose(obuf); ! 411: relsesigs(); ! 412: longjmp(srbuf, 1); ! 413: } ! 414: if (gotcha) { ! 415: removefile(editfile); ! 416: printf("removed\n"); ! 417: } ! 418: else ! 419: printf("complete\n"); ! 420: lockclose(ibuf); /* adb */ ! 421: fclose(obuf); ! 422: flush(); ! 423: ! 424: done: ! 425: relsesigs(); ! 426: return(1); ! 427: } ! 428: ! 429: /* ! 430: * Hold signals SIGHUP - SIGQUIT. ! 431: */ ! 432: void ! 433: holdsigs() ! 434: { ! 435: sighold(SIGHUP); ! 436: sighold(SIGINT); ! 437: sighold(SIGQUIT); ! 438: } ! 439: ! 440: /* ! 441: * Release signals SIGHUP - SIGQUIT ! 442: */ ! 443: void ! 444: relsesigs() ! 445: { ! 446: sigrelse(SIGHUP); ! 447: sigrelse(SIGINT); ! 448: sigrelse(SIGQUIT); ! 449: } ! 450: ! 451: /* ! 452: * Empty the output buffer. ! 453: * (now a no-op; why was it here?) ! 454: */ ! 455: void ! 456: clrbuf(buf) ! 457: register FILE *buf; ! 458: { ! 459: /*** ! 460: buf = stdout; ! 461: buf->_ptr = buf->_base; ! 462: buf->_cnt = BUFSIZ; ! 463: ***/ (void) buf; ! 464: } ! 465: ! 466: ! 467: /* ! 468: * Flush the standard output. ! 469: */ ! 470: ! 471: void ! 472: flush() ! 473: { ! 474: fflush(stdout); ! 475: fflush(stderr); ! 476: } ! 477: ! 478: /* ! 479: * Determine the size of the file possessed by ! 480: * the passed buffer. ! 481: */ ! 482: ! 483: off_t ! 484: fsize(iob) ! 485: FILE *iob; ! 486: { ! 487: register int f; ! 488: struct stat sbuf; ! 489: ! 490: f = fileno(iob); ! 491: if (fstat(f, &sbuf) < 0) ! 492: return(0); ! 493: return(sbuf.st_size); ! 494: } ! 495: ! 496: /* ! 497: * Take a file name, possibly with shell meta characters ! 498: * in it and expand it by using "sh -c echo filename" ! 499: * Return the file name as a dynamic string. ! 500: */ ! 501: ! 502: char * ! 503: expand(name) ! 504: char name[]; ! 505: { ! 506: char xname[BUFSIZ]; ! 507: char cmdbuf[BUFSIZ]; ! 508: register pid_t pid; ! 509: register int l; ! 510: register char *cp; ! 511: int s, pivec[2]; ! 512: struct stat sbuf; ! 513: char *Shell; ! 514: ! 515: if (debug) fprintf(stderr, "expand(%s)=", name); ! 516: if (name[0] == '+') { ! 517: cp = expand(++name); ! 518: if (*cp != '/' && getfold(cmdbuf) >= 0) { ! 519: sprintf(xname, "%s/%s", cmdbuf, cp); ! 520: cp = savestr(xname); ! 521: } ! 522: if (debug) fprintf(stderr, "%s\n", cp); ! 523: return cp; ! 524: } ! 525: if (!anyof(name, "~{[*?$`'\"\\")) { ! 526: if (debug) fprintf(stderr, "%s\n", name); ! 527: return(name); ! 528: } ! 529: if (pipe(pivec) < 0) { ! 530: perror("pipe"); ! 531: return(name); ! 532: } ! 533: sprintf(cmdbuf, "echo %s", name); ! 534: if ((pid = fork()) == 0) { ! 535: sigchild(); ! 536: close(pivec[0]); ! 537: close(1); ! 538: dup(pivec[1]); ! 539: close(pivec[1]); ! 540: close(2); ! 541: if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0') ! 542: Shell = SHELL; ! 543: execlp(Shell, Shell, "-c", cmdbuf, (char *)0); ! 544: _exit(1); ! 545: } ! 546: if (pid == (pid_t)-1) { ! 547: perror("fork"); ! 548: close(pivec[0]); ! 549: close(pivec[1]); ! 550: return(NOSTR); ! 551: } ! 552: close(pivec[1]); ! 553: l = read(pivec[0], xname, BUFSIZ); ! 554: close(pivec[0]); ! 555: while (wait(&s) != pid); ! 556: ; ! 557: s &= 0377; ! 558: if (s != 0 && s != SIGPIPE) { ! 559: fprintf(stderr, "\"Echo\" failed\n"); ! 560: goto err; ! 561: } ! 562: if (l < 0) { ! 563: perror("read"); ! 564: goto err; ! 565: } ! 566: if (l == 0) { ! 567: fprintf(stderr, "\"%s\": No match\n", name); ! 568: goto err; ! 569: } ! 570: if (l == BUFSIZ) { ! 571: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); ! 572: goto err; ! 573: } ! 574: xname[l] = 0; ! 575: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) ! 576: ; ! 577: *++cp = '\0'; ! 578: if (any(' ', xname) && stat(xname, &sbuf) < 0) { ! 579: fprintf(stderr, "\"%s\": Ambiguous\n", name); ! 580: goto err; ! 581: } ! 582: if (debug) fprintf(stderr, "%s\n", xname); ! 583: return(savestr(xname)); ! 584: ! 585: err: ! 586: printf("\n"); ! 587: return(NOSTR); ! 588: } ! 589: ! 590: /* ! 591: * Determine the current folder directory name. ! 592: */ ! 593: getfold(name) ! 594: char *name; ! 595: { ! 596: char *folder; ! 597: ! 598: if ((folder = value("folder")) == NOSTR) { ! 599: strcpy(name, homedir); ! 600: return(0); ! 601: } ! 602: if ((folder = expand(folder)) == NOSTR) ! 603: return(-1); ! 604: if (*folder == '/') ! 605: strcpy(name, folder); ! 606: else ! 607: sprintf(name, "%s/%s", homedir, folder); ! 608: return(0); ! 609: } ! 610: ! 611: /* ! 612: * A nicer version of Fdopen, which allows us to fclose ! 613: * without losing the open file. ! 614: */ ! 615: ! 616: FILE * ! 617: Fdopen(fildes, mode) ! 618: char *mode; ! 619: { ! 620: register int f; ! 621: ! 622: f = dup(fildes); ! 623: if (f < 0) { ! 624: perror("dup"); ! 625: return(NULL); ! 626: } ! 627: return(fdopen(f, mode)); ! 628: } ! 629: ! 630: /* ! 631: * return the filename associated with "s". This function always ! 632: * returns a non-null string (no error checking is done on the receiving end) ! 633: */ ! 634: char * ! 635: Getf(s) ! 636: register char *s; ! 637: { ! 638: register char *cp; ! 639: static char defbuf[PATHSIZE]; ! 640: ! 641: if (((cp = value(s)) != 0) && *cp) { ! 642: return expand(cp); ! 643: } else if (strcmp(s, "MBOX")==0) { ! 644: strcpy(defbuf, Getf("HOME")); ! 645: strcat(defbuf, "/"); ! 646: strcat(defbuf, "mbox"); ! 647: return(defbuf); ! 648: } else if (strcmp(s, "DEAD")==0) { ! 649: strcpy(defbuf, Getf("HOME")); ! 650: strcat(defbuf, "/"); ! 651: strcat(defbuf, "dead.letter"); ! 652: return(defbuf); ! 653: } else if (strcmp(s, "MAILRC")==0) { ! 654: strcpy(defbuf, Getf("HOME")); ! 655: strcat(defbuf, "/"); ! 656: strcat(defbuf, ".mailrc"); ! 657: return(defbuf); ! 658: } else if (strcmp(s, "HOME")==0) { ! 659: /* no recursion allowed! */ ! 660: return("."); ! 661: } ! 662: return("DEAD"); /* "cannot happen" */ ! 663: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.