1: # 2: 3: #include "rcv.h" 4: #include <sys/stat.h> 5: 6: /* 7: * Mail -- a mail program 8: * 9: * More user commands. 10: */ 11: 12: static char *SccsId = "@(#)cmd2.c 2.10 10/21/82"; 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: save(str) 99: char str[]; 100: { 101: 102: return(save1(str, 1)); 103: } 104: 105: /* 106: * Copy a message to a file without affected its saved-ness 107: */ 108: copycmd(str) 109: char str[]; 110: { 111: 112: return(save1(str, 0)); 113: } 114: 115: /* 116: * Save/copy the indicated messages at the end of the passed file name. 117: * If mark is true, mark the message "saved." 118: */ 119: save1(str, mark) 120: char str[]; 121: { 122: register int *ip, mesg; 123: register struct message *mp; 124: char *file, *disp, *cmd; 125: int f, *msgvec, lc, t; 126: long cc; 127: FILE *obuf; 128: struct stat statb; 129: 130: cmd = mark ? "save" : "copy"; 131: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 132: if ((file = snarf(str, &f)) == NOSTR) 133: return(1); 134: if (!f) { 135: *msgvec = first(0, MMNORM); 136: if (*msgvec == NULL) { 137: printf("No messages to %s.\n", cmd); 138: return(1); 139: } 140: msgvec[1] = NULL; 141: } 142: if (f && getmsglist(str, msgvec, 0) < 0) 143: return(1); 144: if ((file = expand(file)) == NOSTR) 145: return(1); 146: printf("\"%s\" ", file); 147: flush(); 148: if (stat(file, &statb) >= 0) 149: disp = "[Appended]"; 150: else 151: disp = "[New file]"; 152: if ((obuf = fopen(file, "a")) == NULL) { 153: perror(NOSTR); 154: return(1); 155: } 156: cc = 0L; 157: lc = 0; 158: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 159: mesg = *ip; 160: touch(mesg); 161: mp = &message[mesg-1]; 162: if ((t = send(mp, obuf, 0)) < 0) { 163: perror(file); 164: fclose(obuf); 165: return(1); 166: } 167: lc += t; 168: cc += mp->m_size; 169: if (mark) 170: mp->m_flag |= MSAVED; 171: } 172: fflush(obuf); 173: if (ferror(obuf)) 174: perror(file); 175: fclose(obuf); 176: printf("%s %d/%ld\n", disp, lc, cc); 177: return(0); 178: } 179: 180: /* 181: * Write the indicated messages at the end of the passed 182: * file name, minus header and trailing blank line. 183: */ 184: 185: swrite(str) 186: char str[]; 187: { 188: register int *ip, mesg; 189: register struct message *mp; 190: register char *file, *disp; 191: char linebuf[BUFSIZ]; 192: int f, *msgvec, lc, cc, t; 193: FILE *obuf, *mesf; 194: struct stat statb; 195: 196: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 197: if ((file = snarf(str, &f)) == NOSTR) 198: return(1); 199: if ((file = expand(file)) == NOSTR) 200: return(1); 201: if (!f) { 202: *msgvec = first(0, MMNORM); 203: if (*msgvec == NULL) { 204: printf("No messages to write.\n"); 205: return(1); 206: } 207: msgvec[1] = NULL; 208: } 209: if (f && getmsglist(str, msgvec, 0) < 0) 210: return(1); 211: printf("\"%s\" ", file); 212: flush(); 213: if (stat(file, &statb) >= 0) 214: disp = "[Appended]"; 215: else 216: disp = "[New file]"; 217: if ((obuf = fopen(file, "a")) == NULL) { 218: perror(NOSTR); 219: return(1); 220: } 221: cc = lc = 0; 222: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 223: mesg = *ip; 224: touch(mesg); 225: mp = &message[mesg-1]; 226: mesf = setinput(mp); 227: t = mp->m_lines - 2; 228: readline(mesf, linebuf); 229: while (t-- > 0) { 230: fgets(linebuf, BUFSIZ, mesf); 231: fputs(linebuf, obuf); 232: cc += strlen(linebuf); 233: } 234: lc += mp->m_lines - 2; 235: mp->m_flag |= MSAVED; 236: } 237: fflush(obuf); 238: if (ferror(obuf)) 239: perror(file); 240: fclose(obuf); 241: printf("%s %d/%d\n", disp, lc, cc); 242: return(0); 243: } 244: 245: /* 246: * Snarf the file from the end of the command line and 247: * return a pointer to it. If there is no file attached, 248: * just return NOSTR. Put a null in front of the file 249: * name so that the message list processing won't see it, 250: * unless the file name is the only thing on the line, in 251: * which case, return 0 in the reference flag variable. 252: */ 253: 254: char * 255: snarf(linebuf, flag) 256: char linebuf[]; 257: int *flag; 258: { 259: register char *cp; 260: 261: *flag = 1; 262: cp = strlen(linebuf) + linebuf - 1; 263: 264: /* 265: * Strip away trailing blanks. 266: */ 267: 268: while (*cp == ' ' && cp > linebuf) 269: cp--; 270: *++cp = 0; 271: 272: /* 273: * Now search for the beginning of the file name. 274: */ 275: 276: while (cp > linebuf && !any(*cp, "\t ")) 277: cp--; 278: if (*cp == '\0') { 279: printf("No file specified.\n"); 280: return(NOSTR); 281: } 282: if (any(*cp, " \t")) 283: *cp++ = 0; 284: else 285: *flag = 0; 286: return(cp); 287: } 288: 289: /* 290: * Delete messages. 291: */ 292: 293: delete(msgvec) 294: int msgvec[]; 295: { 296: return(delm(msgvec)); 297: } 298: 299: /* 300: * Delete messages, then type the new dot. 301: */ 302: 303: deltype(msgvec) 304: int msgvec[]; 305: { 306: int list[2]; 307: int lastdot; 308: 309: lastdot = dot - &message[0] + 1; 310: if (delm(msgvec) >= 0) { 311: list[0] = dot - &message[0]; 312: list[0]++; 313: if (list[0] > lastdot) { 314: touch(list[0]); 315: list[1] = NULL; 316: return(type(list)); 317: } 318: printf("At EOF\n"); 319: return(0); 320: } 321: else { 322: printf("No more messages\n"); 323: return(0); 324: } 325: } 326: 327: /* 328: * Delete the indicated messages. 329: * Set dot to some nice place afterwards. 330: * Internal interface. 331: */ 332: 333: delm(msgvec) 334: int *msgvec; 335: { 336: register struct message *mp; 337: register *ip, mesg; 338: int last; 339: 340: last = NULL; 341: for (ip = msgvec; *ip != NULL; ip++) { 342: mesg = *ip; 343: touch(mesg); 344: mp = &message[mesg-1]; 345: mp->m_flag |= MDELETED|MTOUCH; 346: mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX); 347: last = mesg; 348: } 349: if (last != NULL) { 350: dot = &message[last-1]; 351: last = first(0, MDELETED); 352: if (last != NULL) { 353: dot = &message[last-1]; 354: return(0); 355: } 356: else { 357: dot = &message[0]; 358: return(-1); 359: } 360: } 361: 362: /* 363: * Following can't happen -- it keeps lint happy 364: */ 365: 366: return(-1); 367: } 368: 369: /* 370: * Undelete the indicated messages. 371: */ 372: 373: undelete(msgvec) 374: int *msgvec; 375: { 376: register struct message *mp; 377: register *ip, mesg; 378: 379: for (ip = msgvec; ip-msgvec < msgCount; ip++) { 380: mesg = *ip; 381: if (mesg == 0) 382: return; 383: touch(mesg); 384: mp = &message[mesg-1]; 385: dot = mp; 386: mp->m_flag &= ~MDELETED; 387: } 388: } 389: 390: /* 391: * Interactively dump core on "core" 392: */ 393: 394: core() 395: { 396: register int pid; 397: int status; 398: 399: if ((pid = vfork()) == -1) { 400: perror("fork"); 401: return(1); 402: } 403: if (pid == 0) { 404: sigchild(); 405: abort(); 406: _exit(1); 407: } 408: printf("Okie dokie"); 409: fflush(stdout); 410: while (wait(&status) != pid) 411: ; 412: if (status & 0200) 413: printf(" -- Core dumped\n"); 414: else 415: printf("\n"); 416: } 417: 418: /* 419: * Clobber as many bytes of stack as the user requests. 420: */ 421: clobber(argv) 422: char **argv; 423: { 424: register int times; 425: 426: if (argv[0] == 0) 427: times = 1; 428: else 429: times = (atoi(argv[0]) + 511) / 512; 430: clob1(times); 431: } 432: 433: /* 434: * Clobber the stack. 435: */ 436: clob1(n) 437: { 438: char buf[512]; 439: register char *cp; 440: 441: if (n <= 0) 442: return; 443: for (cp = buf; cp < &buf[512]; *cp++ = 0xFF) 444: ; 445: clob1(n - 1); 446: } 447: 448: /* 449: * Add the given header fields to the ignored list. 450: * If no arguments, print the current list of ignored fields. 451: */ 452: igfield(list) 453: char *list[]; 454: { 455: char field[BUFSIZ]; 456: register int h; 457: register struct ignore *igp; 458: char **ap; 459: 460: if (argcount(list) == 0) 461: return(igshow()); 462: for (ap = list; *ap != 0; ap++) { 463: if (isign(*ap)) 464: continue; 465: istrcpy(field, *ap); 466: h = hash(field); 467: igp = (struct ignore *) calloc(1, sizeof (struct ignore)); 468: igp->i_field = calloc(strlen(field) + 1, sizeof (char)); 469: strcpy(igp->i_field, field); 470: igp->i_link = ignore[h]; 471: ignore[h] = igp; 472: } 473: return(0); 474: } 475: 476: /* 477: * Print out all currently ignored fields. 478: */ 479: igshow() 480: { 481: register int h, count; 482: struct ignore *igp; 483: char **ap, **ring; 484: int igcomp(); 485: 486: count = 0; 487: for (h = 0; h < HSHSIZE; h++) 488: for (igp = ignore[h]; igp != 0; igp = igp->i_link) 489: count++; 490: if (count == 0) { 491: printf("No fields currently being ignored.\n"); 492: return(0); 493: } 494: ring = (char **) salloc((count + 1) * sizeof (char *)); 495: ap = ring; 496: for (h = 0; h < HSHSIZE; h++) 497: for (igp = ignore[h]; igp != 0; igp = igp->i_link) 498: *ap++ = igp->i_field; 499: *ap = 0; 500: qsort(ring, count, sizeof (char *), igcomp); 501: for (ap = ring; *ap != 0; ap++) 502: printf("%s\n", *ap); 503: return(0); 504: } 505: 506: /* 507: * Compare two names for sorting ignored field list. 508: */ 509: igcomp(l, r) 510: char **l, **r; 511: { 512: 513: return(strcmp(*l, *r)); 514: }