11224Skas # 21224Skas 31224Skas #include "rcv.h" 41224Skas #include <sys/stat.h> 51224Skas 61224Skas /* 71224Skas * Mail -- a mail program 81224Skas * 91224Skas * More user commands. 101224Skas */ 111224Skas 12*4493Skurt static char *SccsId = "@(#)cmd2.c 2.3 10/13/81"; 131224Skas 141224Skas /* 151224Skas * If any arguments were given, go to the next applicable argument 161224Skas * following dot, otherwise, go to the next applicable message. 171224Skas * If given as first command with no arguments, print first message. 181224Skas */ 191224Skas 201224Skas next(msgvec) 211224Skas int *msgvec; 221224Skas { 231224Skas register struct message *mp; 241224Skas register int *ip, *ip2; 251224Skas int list[2], mdot; 261224Skas 271224Skas if (*msgvec != NULL) { 281224Skas 291224Skas /* 301224Skas * If some messages were supplied, find the 311224Skas * first applicable one following dot using 321224Skas * wrap around. 331224Skas */ 341224Skas 351224Skas mdot = dot - &message[0] + 1; 361470Skas 371470Skas /* 381470Skas * Find the first message in the supplied 391470Skas * message list which follows dot. 401470Skas */ 411470Skas 421224Skas for (ip = msgvec; *ip != NULL; ip++) 431224Skas if (*ip > mdot) 441224Skas break; 451224Skas if (*ip == NULL) 461224Skas ip = msgvec; 471224Skas ip2 = ip; 481224Skas do { 491224Skas mp = &message[*ip2 - 1]; 501224Skas if ((mp->m_flag & MDELETED) == 0) { 511224Skas dot = mp; 521224Skas goto hitit; 531224Skas } 541470Skas if (*ip2 != NULL) 551470Skas ip2++; 561470Skas if (*ip2 == NULL) 571470Skas ip2 = msgvec; 581224Skas } while (ip2 != ip); 591224Skas printf("No messages applicable\n"); 601224Skas return(1); 611224Skas } 621224Skas 631224Skas /* 641224Skas * If this is the first command, select message 1. 651224Skas * Note that this must exist for us to get here at all. 661224Skas */ 671224Skas 681481Skas if (!sawcom) 691224Skas goto hitit; 701224Skas 711224Skas /* 721224Skas * Just find the next good message after dot, no 731224Skas * wraparound. 741224Skas */ 751224Skas 761224Skas for (mp = dot+1; mp < &message[msgCount]; mp++) 771224Skas if ((mp->m_flag & (MDELETED|MSAVED)) == 0) 781224Skas break; 791224Skas if (mp >= &message[msgCount]) { 801224Skas printf("At EOF\n"); 811224Skas return(0); 821224Skas } 831224Skas dot = mp; 841224Skas hitit: 851224Skas /* 861224Skas * Print dot. 871224Skas */ 881224Skas 891224Skas list[0] = dot - &message[0] + 1; 901224Skas list[1] = NULL; 911224Skas return(type(list)); 921224Skas } 931224Skas 941224Skas /* 951224Skas * Save the indicated messages at the end of the passed file name. 961224Skas */ 971224Skas 981224Skas save(str) 991224Skas char str[]; 1001224Skas { 1011224Skas register int *ip, mesg; 1021224Skas register struct message *mp; 1031224Skas char *file, *disp; 1041224Skas int f, *msgvec, lc, cc, t; 1051224Skas FILE *obuf; 1061224Skas struct stat statb; 1071224Skas 1081224Skas msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 1091224Skas if ((file = snarf(str, &f)) == NOSTR) 1101224Skas return(1); 1111224Skas if (!f) { 1121224Skas *msgvec = first(0, MMNORM); 1131224Skas if (*msgvec == NULL) { 1141224Skas printf("No messages to save.\n"); 1151224Skas return(1); 1161224Skas } 1171224Skas msgvec[1] = NULL; 1181224Skas } 1191224Skas if (f && getmsglist(str, msgvec, 0) < 0) 1201224Skas return(1); 1211224Skas if ((file = expand(file)) == NOSTR) 1221224Skas return(1); 1231224Skas printf("\"%s\" ", file); 1241224Skas flush(); 1251224Skas if (stat(file, &statb) >= 0) 1261224Skas disp = "[Appended]"; 1271224Skas else 1281224Skas disp = "[New file]"; 1291224Skas if ((obuf = fopen(file, "a")) == NULL) { 1301224Skas perror(NOSTR); 1311224Skas return(1); 1321224Skas } 1331224Skas cc = lc = 0; 1341224Skas for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 1351224Skas mesg = *ip; 1361224Skas touch(mesg); 1371224Skas mp = &message[mesg-1]; 1381224Skas if ((t = send(mp, obuf)) < 0) { 1391224Skas perror(file); 1401224Skas fclose(obuf); 1411224Skas return(1); 1421224Skas } 1431224Skas lc += t; 1441224Skas cc += msize(mp); 1451224Skas mp->m_flag |= MSAVED; 1461224Skas } 1471224Skas fflush(obuf); 1481224Skas if (ferror(obuf)) 1491224Skas perror(file); 1501224Skas fclose(obuf); 1511224Skas printf("%s %d/%d\n", disp, lc, cc); 1521224Skas return(0); 1531224Skas } 1541224Skas 1551224Skas /* 1561224Skas * Write the indicated messages at the end of the passed 1571224Skas * file name, minus header and trailing blank line. 1581224Skas */ 1591224Skas 1601224Skas swrite(str) 1611224Skas char str[]; 1621224Skas { 1631224Skas register int *ip, mesg; 1641224Skas register struct message *mp; 1651224Skas register char *file, *disp; 1661224Skas char linebuf[BUFSIZ]; 1671224Skas int f, *msgvec, lc, cc, t; 1681224Skas FILE *obuf, *mesf; 1691224Skas struct stat statb; 1701224Skas 1711224Skas msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 1721224Skas if ((file = snarf(str, &f)) == NOSTR) 1731224Skas return(1); 1741224Skas if ((file = expand(file)) == NOSTR) 1751224Skas return(1); 1761224Skas if (!f) { 1771224Skas *msgvec = first(0, MMNORM); 1781224Skas if (*msgvec == NULL) { 1791224Skas printf("No messages to write.\n"); 1801224Skas return(1); 1811224Skas } 1821224Skas msgvec[1] = NULL; 1831224Skas } 1841224Skas if (f && getmsglist(str, msgvec, 0) < 0) 1851224Skas return(1); 1861224Skas printf("\"%s\" ", file); 1871224Skas flush(); 1881224Skas if (stat(file, &statb) >= 0) 1891224Skas disp = "[Appended]"; 1901224Skas else 1911224Skas disp = "[New file]"; 1921224Skas if ((obuf = fopen(file, "a")) == NULL) { 1931224Skas perror(NOSTR); 1941224Skas return(1); 1951224Skas } 1961224Skas cc = lc = 0; 1971224Skas for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 1981224Skas mesg = *ip; 1991224Skas touch(mesg); 2001224Skas mp = &message[mesg-1]; 2011224Skas mesf = setinput(mp); 2021224Skas t = mp->m_lines - 2; 2031224Skas readline(mesf, linebuf); 2041224Skas while (t-- > 0) { 2051224Skas fgets(linebuf, BUFSIZ, mesf); 2061224Skas fputs(linebuf, obuf); 2071224Skas cc += strlen(linebuf); 2081224Skas } 2091224Skas lc += mp->m_lines - 2; 2101224Skas mp->m_flag |= MSAVED; 2111224Skas } 2121224Skas fflush(obuf); 2131224Skas if (ferror(obuf)) 2141224Skas perror(file); 2151224Skas fclose(obuf); 2161224Skas printf("%s %d/%d\n", disp, lc, cc); 2171224Skas return(0); 2181224Skas } 2191224Skas 2201224Skas /* 2211224Skas * Snarf the file from the end of the command line and 2221224Skas * return a pointer to it. If there is no file attached, 2231224Skas * just return NOSTR. Put a null in front of the file 2241224Skas * name so that the message list processing won't see it, 2251224Skas * unless the file name is the only thing on the line, in 2261224Skas * which case, return 0 in the reference flag variable. 2271224Skas */ 2281224Skas 2291224Skas char * 2301224Skas snarf(linebuf, flag) 2311224Skas char linebuf[]; 2321224Skas int *flag; 2331224Skas { 2341224Skas register char *cp; 2351224Skas 2361224Skas *flag = 1; 2371224Skas cp = strlen(linebuf) + linebuf - 1; 2381224Skas 2391224Skas /* 2401224Skas * Strip away trailing blanks. 2411224Skas */ 2421224Skas 2431224Skas while (*cp == ' ' && cp > linebuf) 2441224Skas cp--; 2451224Skas *++cp = 0; 2461224Skas 2471224Skas /* 2481224Skas * Now search for the beginning of the file name. 2491224Skas */ 2501224Skas 2511224Skas while (cp > linebuf && !any(*cp, "\t ")) 2521224Skas cp--; 2531224Skas if (*cp == '\0') { 2541224Skas printf("No file specified.\n"); 2551224Skas return(NOSTR); 2561224Skas } 2571224Skas if (any(*cp, " \t")) 2581224Skas *cp++ = 0; 2591224Skas else 2601224Skas *flag = 0; 2611224Skas return(cp); 2621224Skas } 2631224Skas 2641224Skas /* 2651224Skas * Delete messages. 2661224Skas */ 2671224Skas 2681224Skas delete(msgvec) 2691224Skas int msgvec[]; 2701224Skas { 2711224Skas return(delm(msgvec)); 2721224Skas } 2731224Skas 2741224Skas /* 2751224Skas * Delete messages, then type the new dot. 2761224Skas */ 2771224Skas 2781224Skas deltype(msgvec) 2791224Skas int msgvec[]; 2801224Skas { 2811224Skas int list[2]; 282*4493Skurt int lastdot; 2831224Skas 284*4493Skurt lastdot = dot - &message[0] + 1; 2851224Skas if (delm(msgvec) >= 0) { 2861224Skas list[0] = dot - &message[0]; 2871224Skas list[0]++; 288*4493Skurt if (list[0] > lastdot) { 289*4493Skurt touch(list[0]); 290*4493Skurt list[1] = NULL; 291*4493Skurt return(type(list)); 292*4493Skurt } 293*4493Skurt printf("At EOF\n"); 294*4493Skurt return(0); 2951224Skas } 2961224Skas else { 2971224Skas printf("No more messages\n"); 2981224Skas return(0); 2991224Skas } 3001224Skas } 3011224Skas 3021224Skas /* 3031224Skas * Delete the indicated messages. 3041224Skas * Set dot to some nice place afterwards. 3051224Skas * Internal interface. 3061224Skas */ 3071224Skas 3081224Skas delm(msgvec) 3091224Skas int *msgvec; 3101224Skas { 3111224Skas register struct message *mp; 3121224Skas register *ip, mesg; 3131224Skas int last; 3141224Skas 3151224Skas last = NULL; 3161224Skas for (ip = msgvec; *ip != NULL; ip++) { 3171224Skas mesg = *ip; 3181224Skas touch(mesg); 3191224Skas mp = &message[mesg-1]; 3203319Skas mp->m_flag |= MDELETED|MTOUCH; 3213319Skas mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX); 3221224Skas last = mesg; 3231224Skas } 3241224Skas if (last != NULL) { 3251224Skas dot = &message[last-1]; 3261224Skas last = first(0, MDELETED); 3271224Skas if (last != NULL) { 3281224Skas dot = &message[last-1]; 3291224Skas return(0); 3301224Skas } 3311224Skas else { 3321224Skas dot = &message[0]; 3331224Skas return(-1); 3341224Skas } 3351224Skas } 3361224Skas 3371224Skas /* 3381224Skas * Following can't happen -- it keeps lint happy 3391224Skas */ 3401224Skas 3411224Skas return(-1); 3421224Skas } 3431224Skas 3441224Skas /* 3451224Skas * Undelete the indicated messages. 3461224Skas */ 3471224Skas 3481224Skas undelete(msgvec) 3491224Skas int *msgvec; 3501224Skas { 3511224Skas register struct message *mp; 3521224Skas register *ip, mesg; 3531224Skas 3541224Skas for (ip = msgvec; ip-msgvec < msgCount; ip++) { 3551224Skas mesg = *ip; 3561224Skas if (mesg == 0) 3571224Skas return; 3581224Skas touch(mesg); 3591224Skas mp = &message[mesg-1]; 3601224Skas dot = mp; 3611224Skas mp->m_flag &= ~MDELETED; 3621224Skas } 3631224Skas } 3641224Skas 3651224Skas /* 3661224Skas * Interactively dump core on "core" 3671224Skas */ 3681224Skas 3691224Skas core() 3701224Skas { 3711224Skas register int pid; 3721224Skas int status; 3731224Skas 3741224Skas if ((pid = vfork()) == -1) { 3751224Skas perror("fork"); 3761224Skas return(1); 3771224Skas } 3781224Skas if (pid == 0) { 3791224Skas abort(); 3801224Skas _exit(1); 3811224Skas } 3821224Skas printf("Okie dokie"); 3831224Skas fflush(stdout); 3841224Skas while (wait(&status) != pid) 3851224Skas ; 3861224Skas if (status & 0200) 3871224Skas printf(" -- Core dumped\n"); 3881224Skas else 3891224Skas printf("\n"); 3901224Skas } 3914340Skurt 3924340Skurt /* 3934340Skurt * Clobber as many bytes of stack as the user requests. 3944340Skurt */ 3954340Skurt clobber(argv) 3964340Skurt char **argv; 3974340Skurt { 3984340Skurt register int times; 3994340Skurt 4004340Skurt if (argv[0] == 0) 4014340Skurt times = 1; 4024340Skurt else 4034340Skurt times = (atoi(argv[0]) + 511) / 512; 4044340Skurt clobber1(times); 4054340Skurt } 4064340Skurt 4074340Skurt /* 4084340Skurt * Clobber the stack. 4094340Skurt */ 4104340Skurt clobber1(n) 4114340Skurt { 4124340Skurt char buf[512]; 4134340Skurt register char *cp; 4144340Skurt 4154340Skurt if (n <= 0) 4164340Skurt return; 4174340Skurt for (cp = buf; cp < &buf[512]; *cp++ = 0xFF) 4184340Skurt ; 4194340Skurt clobber1(n - 1); 4204340Skurt } 421