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