|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)fio.c 2.16 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: #include "rcv.h" ! 6: #include <sys/stat.h> ! 7: #include <errno.h> ! 8: ! 9: /* ! 10: * Mail -- a mail program ! 11: * ! 12: * File I/O. ! 13: */ ! 14: ! 15: /* ! 16: * Set up the input pointers while copying the mail file into ! 17: * /tmp. ! 18: */ ! 19: ! 20: setptr(ibuf) ! 21: FILE *ibuf; ! 22: { ! 23: register int c; ! 24: register char *cp, *cp2; ! 25: register int count, l; ! 26: long s; ! 27: off_t offset; ! 28: char linebuf[LINESIZE]; ! 29: char wbuf[LINESIZE]; ! 30: int maybe, mestmp, flag, inhead; ! 31: struct message this; ! 32: extern char tempSet[]; ! 33: ! 34: if ((mestmp = opentemp(tempSet)) < 0) ! 35: exit(1); ! 36: msgCount = 0; ! 37: offset = 0; ! 38: s = 0L; ! 39: l = 0; ! 40: maybe = 1; ! 41: flag = MUSED|MNEW; ! 42: for (;;) { ! 43: cp = linebuf; ! 44: c = getc(ibuf); ! 45: while (c != EOF && c != '\n') { ! 46: if (cp - linebuf >= LINESIZE - 1) { ! 47: ungetc(c, ibuf); ! 48: *cp = 0; ! 49: break; ! 50: } ! 51: *cp++ = c; ! 52: c = getc(ibuf); ! 53: } ! 54: *cp = 0; ! 55: if (cp == linebuf && c == EOF) { ! 56: this.m_flag = flag; ! 57: flag = MUSED|MNEW; ! 58: this.m_offset = offsetof(offset); ! 59: this.m_block = blockof(offset); ! 60: this.m_size = s; ! 61: this.m_lines = l; ! 62: if (append(&this, mestmp)) { ! 63: perror(tempSet); ! 64: exit(1); ! 65: } ! 66: fclose(ibuf); ! 67: makemessage(mestmp); ! 68: close(mestmp); ! 69: return; ! 70: } ! 71: count = cp - linebuf + 1; ! 72: for (cp = linebuf; *cp;) ! 73: putc(*cp++, otf); ! 74: putc('\n', otf); ! 75: if (ferror(otf)) { ! 76: perror("/tmp"); ! 77: exit(1); ! 78: } ! 79: if (maybe && linebuf[0] == 'F' && ishead(linebuf)) { ! 80: msgCount++; ! 81: this.m_flag = flag; ! 82: flag = MUSED|MNEW; ! 83: inhead = 1; ! 84: this.m_block = blockof(offset); ! 85: this.m_offset = offsetof(offset); ! 86: this.m_size = s; ! 87: this.m_lines = l; ! 88: s = 0L; ! 89: l = 0; ! 90: if (append(&this, mestmp)) { ! 91: perror(tempSet); ! 92: exit(1); ! 93: } ! 94: } ! 95: if (linebuf[0] == 0) ! 96: inhead = 0; ! 97: if (inhead && index(linebuf, ':')) { ! 98: cp = linebuf; ! 99: cp2 = wbuf; ! 100: while (isalpha(*cp)) ! 101: *cp2++ = *cp++; ! 102: *cp2 = 0; ! 103: if (icequal(wbuf, "status")) { ! 104: cp = index(linebuf, ':'); ! 105: if (index(cp, 'R')) ! 106: flag |= MREAD; ! 107: if (index(cp, 'O')) ! 108: flag &= ~MNEW; ! 109: inhead = 0; ! 110: } ! 111: } ! 112: offset += count; ! 113: s += (long) count; ! 114: l++; ! 115: maybe = 0; ! 116: if (linebuf[0] == 0) ! 117: maybe = 1; ! 118: } ! 119: } ! 120: ! 121: /* ! 122: * Drop the passed line onto the passed output buffer. ! 123: * If a write error occurs, return -1, else the count of ! 124: * characters written, including the newline. ! 125: */ ! 126: ! 127: putline(obuf, linebuf) ! 128: FILE *obuf; ! 129: char *linebuf; ! 130: { ! 131: register int c; ! 132: ! 133: c = strlen(linebuf); ! 134: fputs(linebuf, obuf); ! 135: putc('\n', obuf); ! 136: if (ferror(obuf)) ! 137: return(-1); ! 138: return(c+1); ! 139: } ! 140: ! 141: /* ! 142: * Quickly read a line from the specified input into the line ! 143: * buffer; return characters read. ! 144: */ ! 145: ! 146: freadline(ibuf, linebuf) ! 147: register FILE *ibuf; ! 148: register char *linebuf; ! 149: { ! 150: register int c; ! 151: register char *cp; ! 152: ! 153: c = getc(ibuf); ! 154: cp = linebuf; ! 155: while (c != '\n' && c != EOF) { ! 156: if (c == 0) { ! 157: c = getc(ibuf); ! 158: continue; ! 159: } ! 160: if (cp - linebuf >= BUFSIZ-1) { ! 161: *cp = 0; ! 162: return(cp - linebuf + 1); ! 163: } ! 164: *cp++ = c; ! 165: c = getc(ibuf); ! 166: } ! 167: if (c == EOF && cp == linebuf) ! 168: return(0); ! 169: *cp = 0; ! 170: return(cp - linebuf + 1); ! 171: } ! 172: ! 173: /* ! 174: * Read up a line from the specified input into the line ! 175: * buffer. Return the number of characters read. Do not ! 176: * include the newline at the end. ! 177: */ ! 178: ! 179: readline(ibuf, linebuf) ! 180: FILE *ibuf; ! 181: char *linebuf; ! 182: { ! 183: register char *cp; ! 184: register int c; ! 185: ! 186: do { ! 187: clearerr(ibuf); ! 188: c = getc(ibuf); ! 189: for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) { ! 190: if (c == 0) ! 191: continue; ! 192: if (cp - linebuf < LINESIZE-2) ! 193: *cp++ = c; ! 194: } ! 195: } while (ferror(ibuf) && ibuf == stdin); ! 196: *cp = 0; ! 197: if (c == EOF && cp == linebuf) ! 198: return(0); ! 199: return(cp - linebuf + 1); ! 200: } ! 201: ! 202: /* ! 203: * Return a file buffer all ready to read up the ! 204: * passed message pointer. ! 205: */ ! 206: ! 207: FILE * ! 208: setinput(mp) ! 209: register struct message *mp; ! 210: { ! 211: off_t off; ! 212: ! 213: fflush(otf); ! 214: off = mp->m_block; ! 215: off <<= 9; ! 216: off += mp->m_offset; ! 217: if (fseek(itf, off, 0) < 0) { ! 218: perror("fseek"); ! 219: panic("temporary file seek"); ! 220: } ! 221: return(itf); ! 222: } ! 223: ! 224: /* ! 225: * Take the data out of the passed ghost file and toss it into ! 226: * a dynamically allocated message structure. ! 227: */ ! 228: ! 229: makemessage(f) ! 230: { ! 231: register struct message *m; ! 232: register char *mp; ! 233: register count; ! 234: ! 235: mp = calloc((unsigned) (msgCount + 1), sizeof *m); ! 236: if (mp == NOSTR) { ! 237: printf("Insufficient memory for %d messages\n", msgCount); ! 238: exit(1); ! 239: } ! 240: if (message != (struct message *) 0) ! 241: cfree((char *) message); ! 242: message = (struct message *) mp; ! 243: dot = message; ! 244: lseek(f, 0L, 0); ! 245: while (count = read(f, mp, BUFSIZ)) ! 246: mp += count; ! 247: for (m = &message[0]; m < &message[msgCount]; m++) { ! 248: m->m_size = (m+1)->m_size; ! 249: m->m_lines = (m+1)->m_lines; ! 250: m->m_flag = (m+1)->m_flag; ! 251: } ! 252: message[msgCount].m_size = 0L; ! 253: message[msgCount].m_lines = 0; ! 254: } ! 255: ! 256: /* ! 257: * Append the passed message descriptor onto the temp file. ! 258: * If the write fails, return 1, else 0 ! 259: */ ! 260: ! 261: append(mp, f) ! 262: struct message *mp; ! 263: { ! 264: if (write(f, (char *) mp, sizeof *mp) != sizeof *mp) ! 265: return(1); ! 266: return(0); ! 267: } ! 268: ! 269: /* ! 270: * Delete a file, but only if the file is a plain file. ! 271: */ ! 272: ! 273: remove(name) ! 274: char name[]; ! 275: { ! 276: struct stat statb; ! 277: extern int errno; ! 278: ! 279: if (stat(name, &statb) < 0) ! 280: return(-1); ! 281: if ((statb.st_mode & S_IFMT) != S_IFREG) { ! 282: errno = EISDIR; ! 283: return(-1); ! 284: } ! 285: return(unlink(name)); ! 286: } ! 287: ! 288: /* ! 289: * Terminate an editing session by attempting to write out the user's ! 290: * file from the temporary. Save any new stuff appended to the file. ! 291: */ ! 292: edstop() ! 293: { ! 294: register int gotcha, c; ! 295: register struct message *mp; ! 296: FILE *obuf, *ibuf, *readstat; ! 297: struct stat statb; ! 298: char tempname[30], *id; ! 299: int (*sigs[3])(); ! 300: ! 301: if (readonly) ! 302: return; ! 303: holdsigs(); ! 304: if (Tflag != NOSTR) { ! 305: if ((readstat = fopen(Tflag, "w")) == NULL) ! 306: Tflag = NOSTR; ! 307: } ! 308: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) { ! 309: if (mp->m_flag & MNEW) { ! 310: mp->m_flag &= ~MNEW; ! 311: mp->m_flag |= MSTATUS; ! 312: } ! 313: if (mp->m_flag & (MODIFY|MDELETED|MSTATUS)) ! 314: gotcha++; ! 315: if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { ! 316: if ((id = hfield("article-id", mp)) != NOSTR) ! 317: fprintf(readstat, "%s\n", id); ! 318: } ! 319: } ! 320: if (Tflag != NOSTR) ! 321: fclose(readstat); ! 322: if (!gotcha || Tflag != NOSTR) ! 323: goto done; ! 324: ibuf = NULL; ! 325: if (stat(editfile, &statb) >= 0 && statb.st_size > mailsize) { ! 326: strcpy(tempname, "/tmp/mboxXXXXXX"); ! 327: mktemp(tempname); ! 328: if ((obuf = fopen(tempname, "w")) == NULL) { ! 329: perror(tempname); ! 330: relsesigs(); ! 331: reset(0); ! 332: } ! 333: if ((ibuf = fopen(editfile, "r")) == NULL) { ! 334: perror(editfile); ! 335: fclose(obuf); ! 336: remove(tempname); ! 337: relsesigs(); ! 338: reset(0); ! 339: } ! 340: fseek(ibuf, mailsize, 0); ! 341: while ((c = getc(ibuf)) != EOF) ! 342: putc(c, obuf); ! 343: fclose(ibuf); ! 344: fclose(obuf); ! 345: if ((ibuf = fopen(tempname, "r")) == NULL) { ! 346: perror(tempname); ! 347: remove(tempname); ! 348: relsesigs(); ! 349: reset(0); ! 350: } ! 351: remove(tempname); ! 352: } ! 353: printf("\"%s\" ", editfile); ! 354: flush(); ! 355: if ((obuf = fopen(editfile, "r+")) == NULL) { ! 356: perror(editfile); ! 357: relsesigs(); ! 358: reset(0); ! 359: } ! 360: trunc(obuf); ! 361: c = 0; ! 362: for (mp = &message[0]; mp < &message[msgCount]; mp++) { ! 363: if ((mp->m_flag & MDELETED) != 0) ! 364: continue; ! 365: c++; ! 366: if (send(mp, obuf, 0) < 0) { ! 367: perror(editfile); ! 368: relsesigs(); ! 369: reset(0); ! 370: } ! 371: } ! 372: gotcha = (c == 0 && ibuf == NULL); ! 373: if (ibuf != NULL) { ! 374: while ((c = getc(ibuf)) != EOF) ! 375: putc(c, obuf); ! 376: fclose(ibuf); ! 377: } ! 378: fflush(obuf); ! 379: if (ferror(obuf)) { ! 380: perror(editfile); ! 381: relsesigs(); ! 382: reset(0); ! 383: } ! 384: fclose(obuf); ! 385: if (gotcha) { ! 386: remove(editfile); ! 387: printf("removed\n"); ! 388: } ! 389: else ! 390: printf("complete\n"); ! 391: flush(); ! 392: ! 393: done: ! 394: relsesigs(); ! 395: } ! 396: ! 397: static int sigdepth = 0; /* depth of holdsigs() */ ! 398: static int sigmask = 0; ! 399: /* ! 400: * Hold signals SIGHUP - SIGQUIT. ! 401: */ ! 402: holdsigs() ! 403: { ! 404: register int i; ! 405: ! 406: if (sigdepth++ == 0) ! 407: sigmask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)); ! 408: } ! 409: ! 410: /* ! 411: * Release signals SIGHUP - SIGQUIT ! 412: */ ! 413: relsesigs() ! 414: { ! 415: register int i; ! 416: ! 417: if (--sigdepth == 0) ! 418: sigsetmask(sigmask); ! 419: } ! 420: ! 421: /* ! 422: * Empty the output buffer. ! 423: */ ! 424: ! 425: clrbuf(buf) ! 426: register FILE *buf; ! 427: { ! 428: ! 429: buf = stdout; ! 430: buf->_ptr = buf->_base; ! 431: buf->_cnt = BUFSIZ; ! 432: } ! 433: ! 434: /* ! 435: * Open a temp file by creating, closing, unlinking, and ! 436: * reopening. Return the open file descriptor. ! 437: */ ! 438: ! 439: opentemp(file) ! 440: char file[]; ! 441: { ! 442: register int f; ! 443: ! 444: if ((f = creat(file, 0600)) < 0) { ! 445: perror(file); ! 446: return(-1); ! 447: } ! 448: close(f); ! 449: if ((f = open(file, 2)) < 0) { ! 450: perror(file); ! 451: remove(file); ! 452: return(-1); ! 453: } ! 454: remove(file); ! 455: return(f); ! 456: } ! 457: ! 458: /* ! 459: * Flush the standard output. ! 460: */ ! 461: ! 462: flush() ! 463: { ! 464: fflush(stdout); ! 465: fflush(stderr); ! 466: } ! 467: ! 468: /* ! 469: * Determine the size of the file possessed by ! 470: * the passed buffer. ! 471: */ ! 472: ! 473: off_t ! 474: fsize(iob) ! 475: FILE *iob; ! 476: { ! 477: register int f; ! 478: struct stat sbuf; ! 479: ! 480: f = fileno(iob); ! 481: if (fstat(f, &sbuf) < 0) ! 482: return(0); ! 483: return(sbuf.st_size); ! 484: } ! 485: ! 486: /* ! 487: * Take a file name, possibly with shell meta characters ! 488: * in it and expand it by using "sh -c echo filename" ! 489: * Return the file name as a dynamic string. ! 490: */ ! 491: ! 492: char * ! 493: expand(name) ! 494: char name[]; ! 495: { ! 496: char xname[BUFSIZ]; ! 497: char cmdbuf[BUFSIZ]; ! 498: register int pid, l, rc; ! 499: register char *cp, *Shell; ! 500: int s, pivec[2], (*sigint)(); ! 501: struct stat sbuf; ! 502: ! 503: if (name[0] == '+' && getfold(cmdbuf) >= 0) { ! 504: sprintf(xname, "%s/%s", cmdbuf, name + 1); ! 505: return(expand(savestr(xname))); ! 506: } ! 507: if (!anyof(name, "~{[*?$`'\"\\")) ! 508: return(name); ! 509: if (pipe(pivec) < 0) { ! 510: perror("pipe"); ! 511: return(name); ! 512: } ! 513: sprintf(cmdbuf, "echo %s", name); ! 514: if ((pid = vfork()) == 0) { ! 515: sigchild(); ! 516: Shell = value("SHELL"); ! 517: if (Shell == NOSTR) ! 518: Shell = SHELL; ! 519: close(pivec[0]); ! 520: close(1); ! 521: dup(pivec[1]); ! 522: close(pivec[1]); ! 523: close(2); ! 524: execl(Shell, Shell, "-c", cmdbuf, 0); ! 525: _exit(1); ! 526: } ! 527: if (pid == -1) { ! 528: perror("fork"); ! 529: close(pivec[0]); ! 530: close(pivec[1]); ! 531: return(NOSTR); ! 532: } ! 533: close(pivec[1]); ! 534: l = read(pivec[0], xname, BUFSIZ); ! 535: close(pivec[0]); ! 536: while (wait(&s) != pid); ! 537: ; ! 538: s &= 0377; ! 539: if (s != 0 && s != SIGPIPE) { ! 540: fprintf(stderr, "\"Echo\" failed\n"); ! 541: goto err; ! 542: } ! 543: if (l < 0) { ! 544: perror("read"); ! 545: goto err; ! 546: } ! 547: if (l == 0) { ! 548: fprintf(stderr, "\"%s\": No match\n", name); ! 549: goto err; ! 550: } ! 551: if (l == BUFSIZ) { ! 552: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); ! 553: goto err; ! 554: } ! 555: xname[l] = 0; ! 556: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) ! 557: ; ! 558: *++cp = '\0'; ! 559: if (any(' ', xname) && stat(xname, &sbuf) < 0) { ! 560: fprintf(stderr, "\"%s\": Ambiguous\n", name); ! 561: goto err; ! 562: } ! 563: return(savestr(xname)); ! 564: ! 565: err: ! 566: return(NOSTR); ! 567: } ! 568: ! 569: /* ! 570: * Determine the current folder directory name. ! 571: */ ! 572: getfold(name) ! 573: char *name; ! 574: { ! 575: char *folder; ! 576: ! 577: if ((folder = value("folder")) == NOSTR) ! 578: return(-1); ! 579: if (*folder == '/') ! 580: strcpy(name, folder); ! 581: else ! 582: sprintf(name, "%s/%s", homedir, folder); ! 583: return(0); ! 584: } ! 585: ! 586: /* ! 587: * A nicer version of Fdopen, which allows us to fclose ! 588: * without losing the open file. ! 589: */ ! 590: ! 591: FILE * ! 592: Fdopen(fildes, mode) ! 593: char *mode; ! 594: { ! 595: register int f; ! 596: FILE *fdopen(); ! 597: ! 598: f = dup(fildes); ! 599: if (f < 0) { ! 600: perror("dup"); ! 601: return(NULL); ! 602: } ! 603: return(fdopen(f, mode)); ! 604: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.