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