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