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