|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)cmd2.c 2.11 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: #include "rcv.h" ! 6: #include <sys/stat.h> ! 7: ! 8: /* ! 9: * Mail -- a mail program ! 10: * ! 11: * More user commands. ! 12: */ ! 13: ! 14: /* ! 15: * If any arguments were given, go to the next applicable argument ! 16: * following dot, otherwise, go to the next applicable message. ! 17: * If given as first command with no arguments, print first message. ! 18: */ ! 19: ! 20: next(msgvec) ! 21: int *msgvec; ! 22: { ! 23: register struct message *mp; ! 24: register int *ip, *ip2; ! 25: int list[2], mdot; ! 26: ! 27: if (*msgvec != NULL) { ! 28: ! 29: /* ! 30: * If some messages were supplied, find the ! 31: * first applicable one following dot using ! 32: * wrap around. ! 33: */ ! 34: ! 35: mdot = dot - &message[0] + 1; ! 36: ! 37: /* ! 38: * Find the first message in the supplied ! 39: * message list which follows dot. ! 40: */ ! 41: ! 42: for (ip = msgvec; *ip != NULL; ip++) ! 43: if (*ip > mdot) ! 44: break; ! 45: if (*ip == NULL) ! 46: ip = msgvec; ! 47: ip2 = ip; ! 48: do { ! 49: mp = &message[*ip2 - 1]; ! 50: if ((mp->m_flag & MDELETED) == 0) { ! 51: dot = mp; ! 52: goto hitit; ! 53: } ! 54: if (*ip2 != NULL) ! 55: ip2++; ! 56: if (*ip2 == NULL) ! 57: ip2 = msgvec; ! 58: } while (ip2 != ip); ! 59: printf("No messages applicable\n"); ! 60: return(1); ! 61: } ! 62: ! 63: /* ! 64: * If this is the first command, select message 1. ! 65: * Note that this must exist for us to get here at all. ! 66: */ ! 67: ! 68: if (!sawcom) ! 69: goto hitit; ! 70: ! 71: /* ! 72: * Just find the next good message after dot, no ! 73: * wraparound. ! 74: */ ! 75: ! 76: for (mp = dot+1; mp < &message[msgCount]; mp++) ! 77: if ((mp->m_flag & (MDELETED|MSAVED)) == 0) ! 78: break; ! 79: if (mp >= &message[msgCount]) { ! 80: printf("At EOF\n"); ! 81: return(0); ! 82: } ! 83: dot = mp; ! 84: hitit: ! 85: /* ! 86: * Print dot. ! 87: */ ! 88: ! 89: list[0] = dot - &message[0] + 1; ! 90: list[1] = NULL; ! 91: return(type(list)); ! 92: } ! 93: ! 94: /* ! 95: * Save a message in a file. Mark the message as saved ! 96: * so we can discard when the user quits. ! 97: */ ! 98: extern int brokpipe(); ! 99: extern jmp_buf pipestop; ! 100: save(str) ! 101: char str[]; ! 102: { ! 103: ! 104: return(save1(str, 1)); ! 105: } ! 106: ! 107: /* ! 108: * Copy a message to a file without affected its saved-ness ! 109: */ ! 110: copycmd(str) ! 111: char str[]; ! 112: { ! 113: ! 114: return(save1(str, 0)); ! 115: } ! 116: ! 117: /* ! 118: * Save/copy the indicated messages at the end of the passed file name. ! 119: * If mark is true, mark the message "saved." ! 120: */ ! 121: #define PIPE2CMD 2 /* pipe to command instead of file */ ! 122: save1(str, mark) ! 123: char str[]; ! 124: { ! 125: register int *ip, mesg; ! 126: register struct message *mp; ! 127: char *file, *disp, *cmd; ! 128: int f, *msgvec, lc, t; ! 129: long cc; ! 130: FILE *obuf; ! 131: struct stat statb; ! 132: int is_pipe; ! 133: ! 134: cmd = mark ? "save" : "copy"; ! 135: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); ! 136: if ((file = snarf(str, &f)) == NOSTR) ! 137: return(1); ! 138: if (is_pipe = f & PIPE2CMD) ! 139: f &= ~PIPE2CMD; ! 140: if (!f) { ! 141: *msgvec = first(0, MMNORM); ! 142: if (*msgvec == NULL) { ! 143: printf("No messages to %s.\n", cmd); ! 144: return(1); ! 145: } ! 146: msgvec[1] = NULL; ! 147: } ! 148: if (f && getmsglist(str, msgvec, 0) < 0) ! 149: return(1); ! 150: if (!is_pipe) { ! 151: if ((file = expand(file)) == NOSTR) ! 152: return(1); ! 153: printf("\"%s\" ", file); ! 154: flush(); ! 155: if (stat(file, &statb) >= 0) ! 156: disp = "[Appended]"; ! 157: else ! 158: disp = "[New file]"; ! 159: if ((obuf = fopen(file, "a")) == NULL) { ! 160: perror(NOSTR); ! 161: return(1); ! 162: } ! 163: } else { ! 164: if (setjmp(pipestop)) { ! 165: pclose(obuf); ! 166: sigset(SIGPIPE, SIG_DFL); ! 167: printf("[broken pipe]\n"); ! 168: return(1); ! 169: } ! 170: printf("%s ", file); ! 171: flush(); ! 172: disp = "[completed]"; ! 173: if ((obuf = popen(file, "w")) == NULL) { ! 174: perror(NOSTR); ! 175: return(1); ! 176: } ! 177: sigset(SIGPIPE, brokpipe); ! 178: } ! 179: cc = 0L; ! 180: lc = 0; ! 181: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { ! 182: mesg = *ip; ! 183: touch(mesg); ! 184: mp = &message[mesg-1]; ! 185: if ((t = send(mp, obuf, 0)) < 0) { ! 186: perror(file); ! 187: if (is_pipe) { ! 188: pclose(obuf); ! 189: sigset(SIGPIPE, SIG_DFL); ! 190: } else { ! 191: fclose(obuf); ! 192: } ! 193: return(1); ! 194: } ! 195: lc += t; ! 196: cc += mp->m_size; ! 197: if (mark) ! 198: mp->m_flag |= MSAVED; ! 199: } ! 200: fflush(obuf); ! 201: if (ferror(obuf)) ! 202: perror(file); ! 203: if (is_pipe) { ! 204: pclose(obuf); ! 205: sigset(SIGPIPE, SIG_DFL); ! 206: } else { ! 207: fclose(obuf); ! 208: } ! 209: printf("%s %d/%ld\n", disp, lc, cc); ! 210: return(0); ! 211: } ! 212: ! 213: /* ! 214: * Write the indicated messages at the end of the passed ! 215: * file name, minus header and trailing blank line. ! 216: */ ! 217: ! 218: swrite(str) ! 219: char str[]; ! 220: { ! 221: register int *ip, mesg; ! 222: register struct message *mp; ! 223: register char *file, *disp; ! 224: char linebuf[BUFSIZ]; ! 225: int f, *msgvec, lc, cc, t; ! 226: FILE *obuf, *mesf; ! 227: struct stat statb; ! 228: int is_pipe; ! 229: ! 230: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); ! 231: if ((file = snarf(str, &f)) == NOSTR) ! 232: return(1); ! 233: if (is_pipe = f & PIPE2CMD) ! 234: f &= ~PIPE2CMD; ! 235: if (!f) { ! 236: *msgvec = first(0, MMNORM); ! 237: if (*msgvec == NULL) { ! 238: printf("No messages to write.\n"); ! 239: return(1); ! 240: } ! 241: msgvec[1] = NULL; ! 242: } ! 243: if (f && getmsglist(str, msgvec, 0) < 0) ! 244: return(1); ! 245: if (!is_pipe) { ! 246: if ((file = expand(file)) == NOSTR) ! 247: return(1); ! 248: printf("\"%s\" ", file); ! 249: flush(); ! 250: if (stat(file, &statb) >= 0) ! 251: disp = "[Appended]"; ! 252: else ! 253: disp = "[New file]"; ! 254: if ((obuf = fopen(file, "a")) == NULL) { ! 255: perror(NOSTR); ! 256: return(1); ! 257: } ! 258: } else { ! 259: if (setjmp(pipestop)) { ! 260: pclose(obuf); ! 261: sigset(SIGPIPE, SIG_DFL); ! 262: printf("[broken pipe]\n"); ! 263: return(1); ! 264: } ! 265: printf("%s ", file); ! 266: flush(); ! 267: disp = "[completed]"; ! 268: if ((obuf = popen(file, "w")) == NULL) { ! 269: perror(NOSTR); ! 270: return(1); ! 271: } ! 272: sigset(SIGPIPE, brokpipe); ! 273: } ! 274: cc = lc = 0; ! 275: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { ! 276: mesg = *ip; ! 277: touch(mesg); ! 278: mp = &message[mesg-1]; ! 279: mesf = setinput(mp); ! 280: t = mp->m_lines - 2; ! 281: readline(mesf, linebuf); ! 282: while (t-- > 0) { ! 283: fgets(linebuf, BUFSIZ, mesf); ! 284: fputs(linebuf, obuf); ! 285: cc += strlen(linebuf); ! 286: } ! 287: lc += mp->m_lines - 2; ! 288: mp->m_flag |= MSAVED; ! 289: } ! 290: fflush(obuf); ! 291: if (ferror(obuf)) ! 292: perror(file); ! 293: if (is_pipe) { ! 294: pclose(obuf); ! 295: sigset(SIGPIPE, SIG_DFL); ! 296: } else { ! 297: fclose(obuf); ! 298: } ! 299: printf("%s %d/%d\n", disp, lc, cc); ! 300: return(0); ! 301: } ! 302: ! 303: /* ! 304: * Snarf the file from the end of the command line and ! 305: * return a pointer to it. If there is no file attached, ! 306: * just return NOSTR. Put a null in front of the file ! 307: * name so that the message list processing won't see it, ! 308: * unless the file name is the only thing on the line, in ! 309: * which case, return 0 in the reference flag variable. ! 310: */ ! 311: ! 312: char * ! 313: snarf(linebuf, flag) ! 314: char linebuf[]; ! 315: int *flag; ! 316: { ! 317: register char *cp; ! 318: char *is_pipe = NULL; ! 319: ! 320: *flag = 1; ! 321: for (cp = linebuf; *cp; cp++) { ! 322: if (*cp == '|') { ! 323: is_pipe = cp; ! 324: break; ! 325: } ! 326: } ! 327: cp = strlen(linebuf) + linebuf - 1; ! 328: ! 329: /* ! 330: * Strip away trailing blanks. ! 331: */ ! 332: ! 333: while (*cp == ' ' && cp > linebuf) ! 334: cp--; ! 335: *++cp = 0; ! 336: ! 337: if (is_pipe) { ! 338: if (is_pipe == linebuf) ! 339: *flag = PIPE2CMD | 0; ! 340: else ! 341: *flag = PIPE2CMD | 1; ! 342: *is_pipe = 0; ! 343: cp = is_pipe; ! 344: while(any(*++cp, " \t")) ! 345: ; ! 346: } else { ! 347: /* ! 348: * Now search for the beginning of the file name. ! 349: */ ! 350: ! 351: while (cp > linebuf && !any(*cp, "\t ")) ! 352: cp--; ! 353: if (*cp == '\0') { ! 354: printf("No file specified.\n"); ! 355: return(NOSTR); ! 356: } ! 357: if (any(*cp, " \t")) ! 358: *cp++ = 0; ! 359: else ! 360: *flag = 0; ! 361: } ! 362: return(cp); ! 363: } ! 364: ! 365: /* ! 366: * Delete messages. ! 367: */ ! 368: ! 369: delete(msgvec) ! 370: int msgvec[]; ! 371: { ! 372: return(delm(msgvec)); ! 373: } ! 374: ! 375: /* ! 376: * Delete messages, then type the new dot. ! 377: */ ! 378: ! 379: deltype(msgvec) ! 380: int msgvec[]; ! 381: { ! 382: int list[2]; ! 383: int lastdot; ! 384: ! 385: lastdot = dot - &message[0] + 1; ! 386: if (delm(msgvec) >= 0) { ! 387: list[0] = dot - &message[0]; ! 388: list[0]++; ! 389: if (list[0] > lastdot) { ! 390: touch(list[0]); ! 391: list[1] = NULL; ! 392: return(type(list)); ! 393: } ! 394: printf("At EOF\n"); ! 395: return(0); ! 396: } ! 397: else { ! 398: printf("No more messages\n"); ! 399: return(0); ! 400: } ! 401: } ! 402: ! 403: /* ! 404: * Delete the indicated messages. ! 405: * Set dot to some nice place afterwards. ! 406: * Internal interface. ! 407: */ ! 408: ! 409: delm(msgvec) ! 410: int *msgvec; ! 411: { ! 412: register struct message *mp; ! 413: register *ip, mesg; ! 414: int last; ! 415: ! 416: last = NULL; ! 417: for (ip = msgvec; *ip != NULL; ip++) { ! 418: mesg = *ip; ! 419: touch(mesg); ! 420: mp = &message[mesg-1]; ! 421: mp->m_flag |= MDELETED|MTOUCH; ! 422: mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX); ! 423: last = mesg; ! 424: } ! 425: if (last != NULL) { ! 426: dot = &message[last-1]; ! 427: last = first(0, MDELETED); ! 428: if (last != NULL) { ! 429: dot = &message[last-1]; ! 430: return(0); ! 431: } ! 432: else { ! 433: dot = &message[0]; ! 434: return(-1); ! 435: } ! 436: } ! 437: ! 438: /* ! 439: * Following can't happen -- it keeps lint happy ! 440: */ ! 441: ! 442: return(-1); ! 443: } ! 444: ! 445: /* ! 446: * Undelete the indicated messages. ! 447: */ ! 448: ! 449: undelete(msgvec) ! 450: int *msgvec; ! 451: { ! 452: register struct message *mp; ! 453: register *ip, mesg; ! 454: ! 455: for (ip = msgvec; ip-msgvec < msgCount; ip++) { ! 456: mesg = *ip; ! 457: if (mesg == 0) ! 458: return; ! 459: touch(mesg); ! 460: mp = &message[mesg-1]; ! 461: dot = mp; ! 462: mp->m_flag &= ~MDELETED; ! 463: } ! 464: } ! 465: ! 466: /* ! 467: * Interactively dump core on "core" ! 468: */ ! 469: ! 470: core() ! 471: { ! 472: register int pid; ! 473: int status; ! 474: ! 475: if ((pid = vfork()) == -1) { ! 476: perror("fork"); ! 477: return(1); ! 478: } ! 479: if (pid == 0) { ! 480: sigchild(); ! 481: abort(); ! 482: _exit(1); ! 483: } ! 484: printf("Okie dokie"); ! 485: fflush(stdout); ! 486: while (wait(&status) != pid) ! 487: ; ! 488: if (status & 0200) ! 489: printf(" -- Core dumped\n"); ! 490: else ! 491: printf("\n"); ! 492: } ! 493: ! 494: /* ! 495: * Add the given header fields to the ignored list. ! 496: * If no arguments, print the current list of ignored fields. ! 497: */ ! 498: igfield(list) ! 499: char *list[]; ! 500: { ! 501: char field[BUFSIZ]; ! 502: register int h; ! 503: register struct ignore *igp; ! 504: char **ap; ! 505: ! 506: if (argcount(list) == 0) ! 507: return(igshow()); ! 508: for (ap = list; *ap != 0; ap++) { ! 509: if (isign(*ap)) ! 510: continue; ! 511: istrcpy(field, *ap); ! 512: h = hash(field); ! 513: igp = (struct ignore *) calloc(1, sizeof (struct ignore)); ! 514: igp->i_field = calloc(strlen(field) + 1, sizeof (char)); ! 515: strcpy(igp->i_field, field); ! 516: igp->i_link = ignore[h]; ! 517: ignore[h] = igp; ! 518: } ! 519: return(0); ! 520: } ! 521: ! 522: /* ! 523: * Print out all currently ignored fields. ! 524: */ ! 525: igshow() ! 526: { ! 527: register int h, count; ! 528: struct ignore *igp; ! 529: char **ap, **ring; ! 530: int igcomp(); ! 531: ! 532: count = 0; ! 533: for (h = 0; h < HSHSIZE; h++) ! 534: for (igp = ignore[h]; igp != 0; igp = igp->i_link) ! 535: count++; ! 536: if (count == 0) { ! 537: printf("No fields currently being ignored.\n"); ! 538: return(0); ! 539: } ! 540: ring = (char **) salloc((count + 1) * sizeof (char *)); ! 541: ap = ring; ! 542: for (h = 0; h < HSHSIZE; h++) ! 543: for (igp = ignore[h]; igp != 0; igp = igp->i_link) ! 544: *ap++ = igp->i_field; ! 545: *ap = 0; ! 546: qsort(ring, count, sizeof (char *), igcomp); ! 547: for (ap = ring; *ap != 0; ap++) ! 548: printf("%s\n", *ap); ! 549: return(0); ! 550: } ! 551: ! 552: /* ! 553: * Compare two names for sorting ignored field list. ! 554: */ ! 555: igcomp(l, r) ! 556: char **l, **r; ! 557: { ! 558: ! 559: return(strcmp(*l, *r)); ! 560: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.