|
|
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 provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)cmd2.c 5.14 (Berkeley) 6/25/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include "rcv.h" ! 25: #include <sys/wait.h> ! 26: ! 27: /* ! 28: * Mail -- a mail program ! 29: * ! 30: * More user commands. ! 31: */ ! 32: ! 33: /* ! 34: * If any arguments were given, go to the next applicable argument ! 35: * following dot, otherwise, go to the next applicable message. ! 36: * If given as first command with no arguments, print first message. ! 37: */ ! 38: ! 39: next(msgvec) ! 40: int *msgvec; ! 41: { ! 42: register struct message *mp; ! 43: register int *ip, *ip2; ! 44: int list[2], mdot; ! 45: ! 46: if (*msgvec != NULL) { ! 47: ! 48: /* ! 49: * If some messages were supplied, find the ! 50: * first applicable one following dot using ! 51: * wrap around. ! 52: */ ! 53: ! 54: mdot = dot - &message[0] + 1; ! 55: ! 56: /* ! 57: * Find the first message in the supplied ! 58: * message list which follows dot. ! 59: */ ! 60: ! 61: for (ip = msgvec; *ip != NULL; ip++) ! 62: if (*ip > mdot) ! 63: break; ! 64: if (*ip == NULL) ! 65: ip = msgvec; ! 66: ip2 = ip; ! 67: do { ! 68: mp = &message[*ip2 - 1]; ! 69: if ((mp->m_flag & MDELETED) == 0) { ! 70: dot = mp; ! 71: goto hitit; ! 72: } ! 73: if (*ip2 != NULL) ! 74: ip2++; ! 75: if (*ip2 == NULL) ! 76: ip2 = msgvec; ! 77: } while (ip2 != ip); ! 78: printf("No messages applicable\n"); ! 79: return(1); ! 80: } ! 81: ! 82: /* ! 83: * If this is the first command, select message 1. ! 84: * Note that this must exist for us to get here at all. ! 85: */ ! 86: ! 87: if (!sawcom) ! 88: goto hitit; ! 89: ! 90: /* ! 91: * Just find the next good message after dot, no ! 92: * wraparound. ! 93: */ ! 94: ! 95: for (mp = dot+1; mp < &message[msgCount]; mp++) ! 96: if ((mp->m_flag & (MDELETED|MSAVED)) == 0) ! 97: break; ! 98: if (mp >= &message[msgCount]) { ! 99: printf("At EOF\n"); ! 100: return(0); ! 101: } ! 102: dot = mp; ! 103: hitit: ! 104: /* ! 105: * Print dot. ! 106: */ ! 107: ! 108: list[0] = dot - &message[0] + 1; ! 109: list[1] = NULL; ! 110: return(type(list)); ! 111: } ! 112: ! 113: /* ! 114: * Save a message in a file. Mark the message as saved ! 115: * so we can discard when the user quits. ! 116: */ ! 117: save(str) ! 118: char str[]; ! 119: { ! 120: ! 121: return save1(str, 1, "save", saveignore); ! 122: } ! 123: ! 124: /* ! 125: * Copy a message to a file without affected its saved-ness ! 126: */ ! 127: copycmd(str) ! 128: char str[]; ! 129: { ! 130: ! 131: return save1(str, 0, "copy", saveignore); ! 132: } ! 133: ! 134: /* ! 135: * Save/copy the indicated messages at the end of the passed file name. ! 136: * If mark is true, mark the message "saved." ! 137: */ ! 138: save1(str, mark, cmd, ignore) ! 139: char str[]; ! 140: char *cmd; ! 141: struct ignoretab *ignore; ! 142: { ! 143: register int *ip; ! 144: register struct message *mp; ! 145: char *file, *disp; ! 146: int f, *msgvec; ! 147: FILE *obuf; ! 148: ! 149: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); ! 150: if ((file = snarf(str, &f)) == NOSTR) ! 151: return(1); ! 152: if (!f) { ! 153: *msgvec = first(0, MMNORM); ! 154: if (*msgvec == NULL) { ! 155: printf("No messages to %s.\n", cmd); ! 156: return(1); ! 157: } ! 158: msgvec[1] = NULL; ! 159: } ! 160: if (f && getmsglist(str, msgvec, 0) < 0) ! 161: return(1); ! 162: if ((file = expand(file)) == NOSTR) ! 163: return(1); ! 164: printf("\"%s\" ", file); ! 165: fflush(stdout); ! 166: if (access(file, 0) >= 0) ! 167: disp = "[Appended]"; ! 168: else ! 169: disp = "[New file]"; ! 170: if ((obuf = Fopen(file, "a")) == NULL) { ! 171: perror(NOSTR); ! 172: return(1); ! 173: } ! 174: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { ! 175: mp = &message[*ip - 1]; ! 176: touch(mp); ! 177: if (send(mp, obuf, ignore, NOSTR) < 0) { ! 178: perror(file); ! 179: Fclose(obuf); ! 180: return(1); ! 181: } ! 182: if (mark) ! 183: mp->m_flag |= MSAVED; ! 184: } ! 185: fflush(obuf); ! 186: if (ferror(obuf)) ! 187: perror(file); ! 188: Fclose(obuf); ! 189: printf("%s\n", disp); ! 190: return(0); ! 191: } ! 192: ! 193: /* ! 194: * Write the indicated messages at the end of the passed ! 195: * file name, minus header and trailing blank line. ! 196: */ ! 197: ! 198: swrite(str) ! 199: char str[]; ! 200: { ! 201: ! 202: return save1(str, 1, "write", ignoreall); ! 203: } ! 204: ! 205: /* ! 206: * Snarf the file from the end of the command line and ! 207: * return a pointer to it. If there is no file attached, ! 208: * just return NOSTR. Put a null in front of the file ! 209: * name so that the message list processing won't see it, ! 210: * unless the file name is the only thing on the line, in ! 211: * which case, return 0 in the reference flag variable. ! 212: */ ! 213: ! 214: char * ! 215: snarf(linebuf, flag) ! 216: char linebuf[]; ! 217: int *flag; ! 218: { ! 219: register char *cp; ! 220: ! 221: *flag = 1; ! 222: cp = strlen(linebuf) + linebuf - 1; ! 223: ! 224: /* ! 225: * Strip away trailing blanks. ! 226: */ ! 227: ! 228: while (cp > linebuf && isspace(*cp)) ! 229: cp--; ! 230: *++cp = 0; ! 231: ! 232: /* ! 233: * Now search for the beginning of the file name. ! 234: */ ! 235: ! 236: while (cp > linebuf && !isspace(*cp)) ! 237: cp--; ! 238: if (*cp == '\0') { ! 239: printf("No file specified.\n"); ! 240: return(NOSTR); ! 241: } ! 242: if (isspace(*cp)) ! 243: *cp++ = 0; ! 244: else ! 245: *flag = 0; ! 246: return(cp); ! 247: } ! 248: ! 249: /* ! 250: * Delete messages. ! 251: */ ! 252: ! 253: delete(msgvec) ! 254: int msgvec[]; ! 255: { ! 256: delm(msgvec); ! 257: return 0; ! 258: } ! 259: ! 260: /* ! 261: * Delete messages, then type the new dot. ! 262: */ ! 263: ! 264: deltype(msgvec) ! 265: int msgvec[]; ! 266: { ! 267: int list[2]; ! 268: int lastdot; ! 269: ! 270: lastdot = dot - &message[0] + 1; ! 271: if (delm(msgvec) >= 0) { ! 272: list[0] = dot - &message[0] + 1; ! 273: if (list[0] > lastdot) { ! 274: touch(dot); ! 275: list[1] = NULL; ! 276: return(type(list)); ! 277: } ! 278: printf("At EOF\n"); ! 279: } else ! 280: printf("No more messages\n"); ! 281: return(0); ! 282: } ! 283: ! 284: /* ! 285: * Delete the indicated messages. ! 286: * Set dot to some nice place afterwards. ! 287: * Internal interface. ! 288: */ ! 289: ! 290: delm(msgvec) ! 291: int *msgvec; ! 292: { ! 293: register struct message *mp; ! 294: register *ip; ! 295: int last; ! 296: ! 297: last = NULL; ! 298: for (ip = msgvec; *ip != NULL; ip++) { ! 299: mp = &message[*ip - 1]; ! 300: touch(mp); ! 301: mp->m_flag |= MDELETED|MTOUCH; ! 302: mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX); ! 303: last = *ip; ! 304: } ! 305: if (last != NULL) { ! 306: dot = &message[last-1]; ! 307: last = first(0, MDELETED); ! 308: if (last != NULL) { ! 309: dot = &message[last-1]; ! 310: return(0); ! 311: } ! 312: else { ! 313: dot = &message[0]; ! 314: return(-1); ! 315: } ! 316: } ! 317: ! 318: /* ! 319: * Following can't happen -- it keeps lint happy ! 320: */ ! 321: ! 322: return(-1); ! 323: } ! 324: ! 325: /* ! 326: * Undelete the indicated messages. ! 327: */ ! 328: ! 329: undelete(msgvec) ! 330: int *msgvec; ! 331: { ! 332: register struct message *mp; ! 333: register *ip; ! 334: ! 335: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { ! 336: mp = &message[*ip - 1]; ! 337: touch(mp); ! 338: dot = mp; ! 339: mp->m_flag &= ~MDELETED; ! 340: } ! 341: return 0; ! 342: } ! 343: ! 344: /* ! 345: * Interactively dump core on "core" ! 346: */ ! 347: ! 348: core() ! 349: { ! 350: int pid; ! 351: extern union wait wait_status; ! 352: ! 353: switch (pid = vfork()) { ! 354: case -1: ! 355: perror("fork"); ! 356: return(1); ! 357: case 0: ! 358: abort(); ! 359: _exit(1); ! 360: } ! 361: printf("Okie dokie"); ! 362: fflush(stdout); ! 363: wait_child(pid); ! 364: if (wait_status.w_coredump) ! 365: printf(" -- Core dumped.\n"); ! 366: else ! 367: printf(" -- Can't dump core.\n"); ! 368: return 0; ! 369: } ! 370: ! 371: /* ! 372: * Clobber as many bytes of stack as the user requests. ! 373: */ ! 374: clobber(argv) ! 375: char **argv; ! 376: { ! 377: register int times; ! 378: ! 379: if (argv[0] == 0) ! 380: times = 1; ! 381: else ! 382: times = (atoi(argv[0]) + 511) / 512; ! 383: clob1(times); ! 384: return 0; ! 385: } ! 386: ! 387: /* ! 388: * Clobber the stack. ! 389: */ ! 390: clob1(n) ! 391: { ! 392: char buf[512]; ! 393: register char *cp; ! 394: ! 395: if (n <= 0) ! 396: return; ! 397: for (cp = buf; cp < &buf[512]; *cp++ = 0xFF) ! 398: ; ! 399: clob1(n - 1); ! 400: } ! 401: ! 402: /* ! 403: * Add the given header fields to the retained list. ! 404: * If no arguments, print the current list of retained fields. ! 405: */ ! 406: retfield(list) ! 407: char *list[]; ! 408: { ! 409: ! 410: return ignore1(list, ignore + 1, "retained"); ! 411: } ! 412: ! 413: /* ! 414: * Add the given header fields to the ignored list. ! 415: * If no arguments, print the current list of ignored fields. ! 416: */ ! 417: igfield(list) ! 418: char *list[]; ! 419: { ! 420: ! 421: return ignore1(list, ignore, "ignored"); ! 422: } ! 423: ! 424: saveretfield(list) ! 425: char *list[]; ! 426: { ! 427: ! 428: return ignore1(list, saveignore + 1, "retained"); ! 429: } ! 430: ! 431: saveigfield(list) ! 432: char *list[]; ! 433: { ! 434: ! 435: return ignore1(list, saveignore, "ignored"); ! 436: } ! 437: ! 438: ignore1(list, tab, which) ! 439: char *list[]; ! 440: struct ignoretab *tab; ! 441: char *which; ! 442: { ! 443: char field[BUFSIZ]; ! 444: register int h; ! 445: register struct ignore *igp; ! 446: char **ap; ! 447: ! 448: if (*list == NOSTR) ! 449: return igshow(tab, which); ! 450: for (ap = list; *ap != 0; ap++) { ! 451: istrcpy(field, *ap); ! 452: if (member(field, tab)) ! 453: continue; ! 454: h = hash(field); ! 455: igp = (struct ignore *) calloc(1, sizeof (struct ignore)); ! 456: igp->i_field = calloc((unsigned) strlen(field) + 1, ! 457: sizeof (char)); ! 458: strcpy(igp->i_field, field); ! 459: igp->i_link = tab->i_head[h]; ! 460: tab->i_head[h] = igp; ! 461: tab->i_count++; ! 462: } ! 463: return 0; ! 464: } ! 465: ! 466: /* ! 467: * Print out all currently retained fields. ! 468: */ ! 469: igshow(tab, which) ! 470: struct ignoretab *tab; ! 471: char *which; ! 472: { ! 473: register int h; ! 474: struct ignore *igp; ! 475: char **ap, **ring; ! 476: int igcomp(); ! 477: ! 478: if (tab->i_count == 0) { ! 479: printf("No fields currently being %s.\n", which); ! 480: return 0; ! 481: } ! 482: ring = (char **) salloc((tab->i_count + 1) * sizeof (char *)); ! 483: ap = ring; ! 484: for (h = 0; h < HSHSIZE; h++) ! 485: for (igp = tab->i_head[h]; igp != 0; igp = igp->i_link) ! 486: *ap++ = igp->i_field; ! 487: *ap = 0; ! 488: qsort((char *) ring, tab->i_count, sizeof (char *), igcomp); ! 489: for (ap = ring; *ap != 0; ap++) ! 490: printf("%s\n", *ap); ! 491: return 0; ! 492: } ! 493: ! 494: /* ! 495: * Compare two names for sorting ignored field list. ! 496: */ ! 497: igcomp(l, r) ! 498: char **l, **r; ! 499: { ! 500: ! 501: return strcmp(*l, *r); ! 502: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.