|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: #include <sys/stat.h> ! 5: #include <errno.h> ! 6: ! 7: /* ! 8: * Mail -- a mail program ! 9: * ! 10: * File I/O. ! 11: */ ! 12: ! 13: /* ! 14: * Set up the input pointers while copying the mail file into ! 15: * /tmp. ! 16: */ ! 17: ! 18: setptr(ibuf) ! 19: FILE *ibuf; ! 20: { ! 21: register int count, s, l; ! 22: off_t offset; ! 23: char linebuf[LINESIZE]; ! 24: int maybe, mestmp, flag; ! 25: struct message this; ! 26: extern char tempSet[]; ! 27: ! 28: if ((mestmp = opentemp(tempSet)) < 0) ! 29: exit(1); ! 30: msgCount = 0; ! 31: offset = 0; ! 32: s = 0; ! 33: l = 0; ! 34: maybe = 1; ! 35: flag = MUSED; ! 36: if (value("hold") != NOSTR) ! 37: flag = MPRESERVE|MUSED; ! 38: for (;;) { ! 39: if ((count = readline(ibuf, linebuf)) == 0) { ! 40: this.m_flag = flag; ! 41: this.m_offset = offsetof(offset); ! 42: this.m_block = blockof(offset); ! 43: this.m_size = s; ! 44: this.m_lines = l; ! 45: if (append(&this, mestmp)) { ! 46: perror(tempSet); ! 47: exit(1); ! 48: } ! 49: fclose(ibuf); ! 50: makemessage(mestmp); ! 51: close(mestmp); ! 52: return; ! 53: } ! 54: if (putline(otf, linebuf) < 0) { ! 55: perror("/tmp"); ! 56: exit(1); ! 57: } ! 58: if (maybe && ishead(linebuf)) { ! 59: msgCount++; ! 60: this.m_flag = flag; ! 61: this.m_block = blockof(offset); ! 62: this.m_offset = offsetof(offset); ! 63: this.m_size = s; ! 64: this.m_lines = l; ! 65: s = 0; ! 66: l = 0; ! 67: if (append(&this, mestmp)) { ! 68: perror(tempSet); ! 69: exit(1); ! 70: } ! 71: } ! 72: offset += count; ! 73: s += count; ! 74: l++; ! 75: maybe = 0; ! 76: if (linebuf[0] == 0) ! 77: maybe = 1; ! 78: } ! 79: } ! 80: ! 81: /* ! 82: * Drop the passed line onto the passed output buffer. ! 83: * If a write error occurs, return -1, else the count of ! 84: * characters written, including the newline. ! 85: */ ! 86: ! 87: putline(obuf, linebuf) ! 88: FILE *obuf; ! 89: char *linebuf; ! 90: { ! 91: register int c; ! 92: ! 93: c = strlen(linebuf); ! 94: fputs(linebuf, obuf); ! 95: putc('\n', obuf); ! 96: if (ferror(obuf)) ! 97: return(-1); ! 98: return(c+1); ! 99: } ! 100: ! 101: /* ! 102: * Read up a line from the specified input into the line ! 103: * buffer. Return the number of characters read. Do not ! 104: * include the newline at the end. ! 105: */ ! 106: ! 107: readline(ibuf, linebuf) ! 108: FILE *ibuf; ! 109: char *linebuf; ! 110: { ! 111: register char *cp; ! 112: register int c; ! 113: ! 114: do { ! 115: clearerr(ibuf); ! 116: c = getc(ibuf); ! 117: for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) { ! 118: if (c == 0) ! 119: continue; ! 120: if (cp - linebuf < LINESIZE-2) ! 121: *cp++ = c; ! 122: } ! 123: } while (ferror(ibuf) && ibuf == stdin); ! 124: *cp = 0; ! 125: if (c == EOF && cp == linebuf) ! 126: return(0); ! 127: return(cp - linebuf + 1); ! 128: } ! 129: ! 130: /* ! 131: * Return a file buffer all ready to read up the ! 132: * passed message pointer. ! 133: */ ! 134: ! 135: FILE * ! 136: setinput(mp) ! 137: register struct message *mp; ! 138: { ! 139: off_t off; ! 140: ! 141: fflush(otf); ! 142: off = mp->m_block; ! 143: off <<= 9; ! 144: off += mp->m_offset; ! 145: if (fseek(itf, off, 0) < 0) { ! 146: perror("fseek"); ! 147: panic("temporary file seek"); ! 148: } ! 149: return(itf); ! 150: } ! 151: ! 152: /* ! 153: * Take the data out of the passed ghost file and toss it into ! 154: * a dynamically allocated message structure. ! 155: */ ! 156: ! 157: makemessage(f) ! 158: { ! 159: register struct message *m; ! 160: register char *mp; ! 161: register count; ! 162: ! 163: mp = calloc((unsigned) (msgCount + 1), sizeof *m); ! 164: if (mp == NOSTR) { ! 165: printf("Insufficient memory for %d messages\n", msgCount); ! 166: exit(1); ! 167: } ! 168: message = (struct message *) mp; ! 169: dot = message; ! 170: lseek(f, 0L, 0); ! 171: while (count = read(f, mp, BUFSIZ)) ! 172: mp += count; ! 173: for (m = &message[0]; m < &message[msgCount]; m++) { ! 174: m->m_size = (m+1)->m_size; ! 175: m->m_lines = (m+1)->m_lines; ! 176: } ! 177: message[msgCount].m_size = 0; ! 178: message[msgCount].m_lines = 0; ! 179: } ! 180: ! 181: /* ! 182: * Append the passed message descriptor onto the temp file. ! 183: * If the write fails, return 1, else 0 ! 184: */ ! 185: ! 186: append(mp, f) ! 187: struct message *mp; ! 188: { ! 189: if (write(f, (char *) mp, sizeof *mp) != sizeof *mp) ! 190: return(1); ! 191: return(0); ! 192: } ! 193: ! 194: /* ! 195: * Delete a file, but only if the file is a plain file. ! 196: */ ! 197: ! 198: remove(name) ! 199: char name[]; ! 200: { ! 201: struct stat statb; ! 202: extern int errno; ! 203: ! 204: if (stat(name, &statb) < 0) ! 205: return(-1); ! 206: if ((statb.st_mode & S_IFMT) != S_IFREG) { ! 207: errno = EISDIR; ! 208: return(-1); ! 209: } ! 210: return(unlink(name)); ! 211: } ! 212: ! 213: /* ! 214: * Terminate an editing session by attempting to write out the user's ! 215: * file from the temporary. ! 216: */ ! 217: ! 218: edstop() ! 219: { ! 220: register int gotcha, c; ! 221: register struct message *mp; ! 222: FILE *obuf; ! 223: ! 224: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) ! 225: if (mp->m_flag & (MODIFY|MDELETED)) { ! 226: gotcha++; ! 227: break; ! 228: } ! 229: if (!gotcha) ! 230: return; ! 231: printf("\"%s\" ", editfile); ! 232: flush(); ! 233: if ((obuf = fopen(editfile, "w")) == NULL) { ! 234: perror(editfile); ! 235: reset(0); ! 236: } ! 237: c = 0; ! 238: for (mp = &message[0]; mp < &message[msgCount]; mp++) { ! 239: if ((mp->m_flag & MDELETED) != 0) ! 240: continue; ! 241: c++; ! 242: if (send(mp, obuf) < 0) { ! 243: perror(editfile); ! 244: reset(0); ! 245: } ! 246: } ! 247: fflush(obuf); ! 248: if (ferror(obuf)) { ! 249: perror(editfile); ! 250: reset(0); ! 251: } ! 252: if (c == 0) { ! 253: remove(editfile); ! 254: printf("removed\n"); ! 255: } ! 256: else ! 257: printf("complete\n"); ! 258: flush(); ! 259: } ! 260: ! 261: /* ! 262: * Empty the output buffer. ! 263: */ ! 264: ! 265: clrbuf(buf) ! 266: register FILE *buf; ! 267: { ! 268: ! 269: buf = stdout; ! 270: buf->_ptr = buf->_base; ! 271: buf->_cnt = BUFSIZ; ! 272: } ! 273: ! 274: /* ! 275: * Open a temp file by creating, closing, unlinking, and ! 276: * reopening. Return the open file descriptor. ! 277: */ ! 278: ! 279: opentemp(file) ! 280: char file[]; ! 281: { ! 282: register int f; ! 283: ! 284: if ((f = creat(file, 0600)) < 0) { ! 285: perror(file); ! 286: return(-1); ! 287: } ! 288: close(f); ! 289: if ((f = open(file, 2)) < 0) { ! 290: perror(file); ! 291: remove(file); ! 292: return(-1); ! 293: } ! 294: remove(file); ! 295: return(f); ! 296: } ! 297: ! 298: /* ! 299: * Flush the standard output. ! 300: */ ! 301: ! 302: flush() ! 303: { ! 304: fflush(stdout); ! 305: fflush(stderr); ! 306: } ! 307: ! 308: /* ! 309: * Determine the size of the file possessed by ! 310: * the passed buffer. ! 311: */ ! 312: ! 313: off_t ! 314: fsize(iob) ! 315: FILE *iob; ! 316: { ! 317: register int f; ! 318: struct stat sbuf; ! 319: ! 320: f = fileno(iob); ! 321: if (fstat(f, &sbuf) < 0) ! 322: return(0); ! 323: return(sbuf.st_size); ! 324: } ! 325: ! 326: /* ! 327: * Take a file name, possibly with shell meta characters ! 328: * in it and expand it by using "sh -c echo filename" ! 329: * Return the file name as a dynamic string. ! 330: */ ! 331: ! 332: char * ! 333: expand(name) ! 334: char name[]; ! 335: { ! 336: char xname[BUFSIZ]; ! 337: char cmdbuf[BUFSIZ]; ! 338: register int pid, l, rc; ! 339: register char *cp, *Shell; ! 340: int s, pivec[2], (*sigint)(); ! 341: struct stat sbuf; ! 342: ! 343: if (!anyof(name, "~{[*?$`'\"\\")) ! 344: return(name); ! 345: /* sigint = signal(SIGINT, SIG_IGN); */ ! 346: if (pipe(pivec) < 0) { ! 347: perror("pipe"); ! 348: /* signal(SIGINT, sigint) */ ! 349: return(name); ! 350: } ! 351: sprintf(cmdbuf, "echo %s", name); ! 352: if ((pid = vfork()) == 0) { ! 353: Shell = value("SHELL"); ! 354: if (Shell == NOSTR) ! 355: Shell = SHELL; ! 356: close(pivec[0]); ! 357: close(1); ! 358: dup(pivec[1]); ! 359: close(pivec[1]); ! 360: close(2); ! 361: execl(Shell, Shell, "-c", cmdbuf, 0); ! 362: _exit(1); ! 363: } ! 364: if (pid == -1) { ! 365: perror("fork"); ! 366: close(pivec[0]); ! 367: close(pivec[1]); ! 368: return(NOSTR); ! 369: } ! 370: close(pivec[1]); ! 371: l = read(pivec[0], xname, BUFSIZ); ! 372: close(pivec[0]); ! 373: while (wait(&s) != pid); ! 374: ; ! 375: s &= 0377; ! 376: if (s != 0 && s != SIGPIPE) { ! 377: fprintf(stderr, "\"Echo\" failed\n"); ! 378: goto err; ! 379: } ! 380: if (l < 0) { ! 381: perror("read"); ! 382: goto err; ! 383: } ! 384: if (l == 0) { ! 385: fprintf(stderr, "\"%s\": No match\n", name); ! 386: goto err; ! 387: } ! 388: if (l == BUFSIZ) { ! 389: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); ! 390: goto err; ! 391: } ! 392: xname[l] = 0; ! 393: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) ! 394: ; ! 395: *++cp = '\0'; ! 396: if (any(' ', xname) && stat(xname, &sbuf) < 0) { ! 397: fprintf(stderr, "\"%s\": Ambiguous\n", name); ! 398: goto err; ! 399: } ! 400: /* signal(SIGINT, sigint) */ ! 401: return(savestr(xname)); ! 402: ! 403: err: ! 404: /* signal(SIGINT, sigint); */ ! 405: return(NOSTR); ! 406: } ! 407: ! 408: /* ! 409: * A nicer version of Fdopen, which allows us to fclose ! 410: * without losing the open file. ! 411: */ ! 412: ! 413: FILE * ! 414: Fdopen(fildes, mode) ! 415: char *mode; ! 416: { ! 417: register int f; ! 418: FILE *fdopen(); ! 419: ! 420: f = dup(fildes); ! 421: if (f < 0) { ! 422: perror("dup"); ! 423: return(NULL); ! 424: } ! 425: return(fdopen(f, mode)); ! 426: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.