19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 359b50d902SRodney W. Grimes static char sccsid[] = "@(#)collect.c 8.2 (Berkeley) 4/19/94"; 369b50d902SRodney W. Grimes #endif /* not lint */ 379b50d902SRodney W. Grimes 389b50d902SRodney W. Grimes /* 399b50d902SRodney W. Grimes * Mail -- a mail program 409b50d902SRodney W. Grimes * 419b50d902SRodney W. Grimes * Collect input from standard input, handling 429b50d902SRodney W. Grimes * ~ escapes. 439b50d902SRodney W. Grimes */ 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes #include "rcv.h" 469b50d902SRodney W. Grimes #include "extern.h" 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes /* 499b50d902SRodney W. Grimes * Read a message from standard output and return a read file to it 509b50d902SRodney W. Grimes * or NULL on error. 519b50d902SRodney W. Grimes */ 529b50d902SRodney W. Grimes 539b50d902SRodney W. Grimes /* 549b50d902SRodney W. Grimes * The following hokiness with global variables is so that on 559b50d902SRodney W. Grimes * receipt of an interrupt signal, the partial message can be salted 569b50d902SRodney W. Grimes * away on dead.letter. 579b50d902SRodney W. Grimes */ 589b50d902SRodney W. Grimes 599b50d902SRodney W. Grimes static sig_t saveint; /* Previous SIGINT value */ 609b50d902SRodney W. Grimes static sig_t savehup; /* Previous SIGHUP value */ 619b50d902SRodney W. Grimes static sig_t savetstp; /* Previous SIGTSTP value */ 629b50d902SRodney W. Grimes static sig_t savettou; /* Previous SIGTTOU value */ 639b50d902SRodney W. Grimes static sig_t savettin; /* Previous SIGTTIN value */ 649b50d902SRodney W. Grimes static FILE *collf; /* File for saving away */ 659b50d902SRodney W. Grimes static int hadintr; /* Have seen one SIGINT so far */ 669b50d902SRodney W. Grimes 679b50d902SRodney W. Grimes static jmp_buf colljmp; /* To get back to work */ 689b50d902SRodney W. Grimes static int colljmp_p; /* whether to long jump */ 699b50d902SRodney W. Grimes static jmp_buf collabort; /* To end collection with error */ 709b50d902SRodney W. Grimes 719b50d902SRodney W. Grimes FILE * 729b50d902SRodney W. Grimes collect(hp, printheaders) 739b50d902SRodney W. Grimes struct header *hp; 749b50d902SRodney W. Grimes int printheaders; 759b50d902SRodney W. Grimes { 769b50d902SRodney W. Grimes FILE *fbuf; 779b50d902SRodney W. Grimes int lc, cc, escape, eofcount; 789b50d902SRodney W. Grimes register int c, t; 799b50d902SRodney W. Grimes char linebuf[LINESIZE], *cp; 809b50d902SRodney W. Grimes extern char tempMail[]; 819b50d902SRodney W. Grimes char getsub; 829b50d902SRodney W. Grimes int omask; 839b50d902SRodney W. Grimes void collint(), collhup(), collstop(); 849b50d902SRodney W. Grimes 859b50d902SRodney W. Grimes collf = NULL; 869b50d902SRodney W. Grimes /* 879b50d902SRodney W. Grimes * Start catching signals from here, but we're still die on interrupts 889b50d902SRodney W. Grimes * until we're in the main loop. 899b50d902SRodney W. Grimes */ 909b50d902SRodney W. Grimes omask = sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); 919b50d902SRodney W. Grimes if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) 929b50d902SRodney W. Grimes signal(SIGINT, collint); 939b50d902SRodney W. Grimes if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) 949b50d902SRodney W. Grimes signal(SIGHUP, collhup); 959b50d902SRodney W. Grimes savetstp = signal(SIGTSTP, collstop); 969b50d902SRodney W. Grimes savettou = signal(SIGTTOU, collstop); 979b50d902SRodney W. Grimes savettin = signal(SIGTTIN, collstop); 989b50d902SRodney W. Grimes if (setjmp(collabort) || setjmp(colljmp)) { 999b50d902SRodney W. Grimes rm(tempMail); 1009b50d902SRodney W. Grimes goto err; 1019b50d902SRodney W. Grimes } 1029b50d902SRodney W. Grimes sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP))); 1039b50d902SRodney W. Grimes 1049b50d902SRodney W. Grimes noreset++; 1059b50d902SRodney W. Grimes if ((collf = Fopen(tempMail, "w+")) == NULL) { 1069b50d902SRodney W. Grimes perror(tempMail); 1079b50d902SRodney W. Grimes goto err; 1089b50d902SRodney W. Grimes } 1099b50d902SRodney W. Grimes unlink(tempMail); 1109b50d902SRodney W. Grimes 1119b50d902SRodney W. Grimes /* 1129b50d902SRodney W. Grimes * If we are going to prompt for a subject, 1139b50d902SRodney W. Grimes * refrain from printing a newline after 1149b50d902SRodney W. Grimes * the headers (since some people mind). 1159b50d902SRodney W. Grimes */ 1169b50d902SRodney W. Grimes t = GTO|GSUBJECT|GCC|GNL; 1179b50d902SRodney W. Grimes getsub = 0; 1189b50d902SRodney W. Grimes if (hp->h_subject == NOSTR && value("interactive") != NOSTR && 1199b50d902SRodney W. Grimes (value("ask") != NOSTR || value("asksub") != NOSTR)) 1209b50d902SRodney W. Grimes t &= ~GNL, getsub++; 1219b50d902SRodney W. Grimes if (printheaders) { 1229b50d902SRodney W. Grimes puthead(hp, stdout, t); 1239b50d902SRodney W. Grimes fflush(stdout); 1249b50d902SRodney W. Grimes } 1259b50d902SRodney W. Grimes if ((cp = value("escape")) != NOSTR) 1269b50d902SRodney W. Grimes escape = *cp; 1279b50d902SRodney W. Grimes else 1289b50d902SRodney W. Grimes escape = ESCAPE; 1299b50d902SRodney W. Grimes eofcount = 0; 1309b50d902SRodney W. Grimes hadintr = 0; 1319b50d902SRodney W. Grimes 1329b50d902SRodney W. Grimes if (!setjmp(colljmp)) { 1339b50d902SRodney W. Grimes if (getsub) 1349b50d902SRodney W. Grimes grabh(hp, GSUBJECT); 1359b50d902SRodney W. Grimes } else { 1369b50d902SRodney W. Grimes /* 1379b50d902SRodney W. Grimes * Come here for printing the after-signal message. 1389b50d902SRodney W. Grimes * Duplicate messages won't be printed because 1399b50d902SRodney W. Grimes * the write is aborted if we get a SIGTTOU. 1409b50d902SRodney W. Grimes */ 1419b50d902SRodney W. Grimes cont: 1429b50d902SRodney W. Grimes if (hadintr) { 1439b50d902SRodney W. Grimes fflush(stdout); 1449b50d902SRodney W. Grimes fprintf(stderr, 1459b50d902SRodney W. Grimes "\n(Interrupt -- one more to kill letter)\n"); 1469b50d902SRodney W. Grimes } else { 1479b50d902SRodney W. Grimes printf("(continue)\n"); 1489b50d902SRodney W. Grimes fflush(stdout); 1499b50d902SRodney W. Grimes } 1509b50d902SRodney W. Grimes } 1519b50d902SRodney W. Grimes for (;;) { 1529b50d902SRodney W. Grimes colljmp_p = 1; 1539b50d902SRodney W. Grimes c = readline(stdin, linebuf, LINESIZE); 1549b50d902SRodney W. Grimes colljmp_p = 0; 1559b50d902SRodney W. Grimes if (c < 0) { 1569b50d902SRodney W. Grimes if (value("interactive") != NOSTR && 1579b50d902SRodney W. Grimes value("ignoreeof") != NOSTR && ++eofcount < 25) { 1589b50d902SRodney W. Grimes printf("Use \".\" to terminate letter\n"); 1599b50d902SRodney W. Grimes continue; 1609b50d902SRodney W. Grimes } 1619b50d902SRodney W. Grimes break; 1629b50d902SRodney W. Grimes } 1639b50d902SRodney W. Grimes eofcount = 0; 1649b50d902SRodney W. Grimes hadintr = 0; 1659b50d902SRodney W. Grimes if (linebuf[0] == '.' && linebuf[1] == '\0' && 1669b50d902SRodney W. Grimes value("interactive") != NOSTR && 1679b50d902SRodney W. Grimes (value("dot") != NOSTR || value("ignoreeof") != NOSTR)) 1689b50d902SRodney W. Grimes break; 1699b50d902SRodney W. Grimes if (linebuf[0] != escape || value("interactive") == NOSTR) { 1709b50d902SRodney W. Grimes if (putline(collf, linebuf) < 0) 1719b50d902SRodney W. Grimes goto err; 1729b50d902SRodney W. Grimes continue; 1739b50d902SRodney W. Grimes } 1749b50d902SRodney W. Grimes c = linebuf[1]; 1759b50d902SRodney W. Grimes switch (c) { 1769b50d902SRodney W. Grimes default: 1779b50d902SRodney W. Grimes /* 1789b50d902SRodney W. Grimes * On double escape, just send the single one. 1799b50d902SRodney W. Grimes * Otherwise, it's an error. 1809b50d902SRodney W. Grimes */ 1819b50d902SRodney W. Grimes if (c == escape) { 1829b50d902SRodney W. Grimes if (putline(collf, &linebuf[1]) < 0) 1839b50d902SRodney W. Grimes goto err; 1849b50d902SRodney W. Grimes else 1859b50d902SRodney W. Grimes break; 1869b50d902SRodney W. Grimes } 1879b50d902SRodney W. Grimes printf("Unknown tilde escape.\n"); 1889b50d902SRodney W. Grimes break; 1899b50d902SRodney W. Grimes case 'C': 1909b50d902SRodney W. Grimes /* 1919b50d902SRodney W. Grimes * Dump core. 1929b50d902SRodney W. Grimes */ 1939b50d902SRodney W. Grimes core(); 1949b50d902SRodney W. Grimes break; 1959b50d902SRodney W. Grimes case '!': 1969b50d902SRodney W. Grimes /* 1979b50d902SRodney W. Grimes * Shell escape, send the balance of the 1989b50d902SRodney W. Grimes * line to sh -c. 1999b50d902SRodney W. Grimes */ 2009b50d902SRodney W. Grimes shell(&linebuf[2]); 2019b50d902SRodney W. Grimes break; 2029b50d902SRodney W. Grimes case ':': 2039b50d902SRodney W. Grimes /* 2049b50d902SRodney W. Grimes * Escape to command mode, but be nice! 2059b50d902SRodney W. Grimes */ 2069b50d902SRodney W. Grimes execute(&linebuf[2], 1); 2079b50d902SRodney W. Grimes goto cont; 2089b50d902SRodney W. Grimes case '.': 2099b50d902SRodney W. Grimes /* 2109b50d902SRodney W. Grimes * Simulate end of file on input. 2119b50d902SRodney W. Grimes */ 2129b50d902SRodney W. Grimes goto out; 2139b50d902SRodney W. Grimes case 'q': 2149b50d902SRodney W. Grimes /* 2159b50d902SRodney W. Grimes * Force a quit of sending mail. 2169b50d902SRodney W. Grimes * Act like an interrupt happened. 2179b50d902SRodney W. Grimes */ 2189b50d902SRodney W. Grimes hadintr++; 2199b50d902SRodney W. Grimes collint(SIGINT); 2209b50d902SRodney W. Grimes exit(1); 2219b50d902SRodney W. Grimes case 'h': 2229b50d902SRodney W. Grimes /* 2239b50d902SRodney W. Grimes * Grab a bunch of headers. 2249b50d902SRodney W. Grimes */ 2259b50d902SRodney W. Grimes grabh(hp, GTO|GSUBJECT|GCC|GBCC); 2269b50d902SRodney W. Grimes goto cont; 2279b50d902SRodney W. Grimes case 't': 2289b50d902SRodney W. Grimes /* 2299b50d902SRodney W. Grimes * Add to the To list. 2309b50d902SRodney W. Grimes */ 2319b50d902SRodney W. Grimes hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO)); 2329b50d902SRodney W. Grimes break; 2339b50d902SRodney W. Grimes case 's': 2349b50d902SRodney W. Grimes /* 2359b50d902SRodney W. Grimes * Set the Subject list. 2369b50d902SRodney W. Grimes */ 2379b50d902SRodney W. Grimes cp = &linebuf[2]; 2389b50d902SRodney W. Grimes while (isspace(*cp)) 2399b50d902SRodney W. Grimes cp++; 2409b50d902SRodney W. Grimes hp->h_subject = savestr(cp); 2419b50d902SRodney W. Grimes break; 2429b50d902SRodney W. Grimes case 'c': 2439b50d902SRodney W. Grimes /* 2449b50d902SRodney W. Grimes * Add to the CC list. 2459b50d902SRodney W. Grimes */ 2469b50d902SRodney W. Grimes hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC)); 2479b50d902SRodney W. Grimes break; 2489b50d902SRodney W. Grimes case 'b': 2499b50d902SRodney W. Grimes /* 2509b50d902SRodney W. Grimes * Add stuff to blind carbon copies list. 2519b50d902SRodney W. Grimes */ 2529b50d902SRodney W. Grimes hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); 2539b50d902SRodney W. Grimes break; 2549b50d902SRodney W. Grimes case 'd': 2559b50d902SRodney W. Grimes strcpy(linebuf + 2, getdeadletter()); 2569b50d902SRodney W. Grimes /* fall into . . . */ 2579b50d902SRodney W. Grimes case 'r': 2589b50d902SRodney W. Grimes /* 2599b50d902SRodney W. Grimes * Invoke a file: 2609b50d902SRodney W. Grimes * Search for the file name, 2619b50d902SRodney W. Grimes * then open it and copy the contents to collf. 2629b50d902SRodney W. Grimes */ 2639b50d902SRodney W. Grimes cp = &linebuf[2]; 2649b50d902SRodney W. Grimes while (isspace(*cp)) 2659b50d902SRodney W. Grimes cp++; 2669b50d902SRodney W. Grimes if (*cp == '\0') { 2679b50d902SRodney W. Grimes printf("Interpolate what file?\n"); 2689b50d902SRodney W. Grimes break; 2699b50d902SRodney W. Grimes } 2709b50d902SRodney W. Grimes cp = expand(cp); 2719b50d902SRodney W. Grimes if (cp == NOSTR) 2729b50d902SRodney W. Grimes break; 2739b50d902SRodney W. Grimes if (isdir(cp)) { 2749b50d902SRodney W. Grimes printf("%s: Directory\n", cp); 2759b50d902SRodney W. Grimes break; 2769b50d902SRodney W. Grimes } 2779b50d902SRodney W. Grimes if ((fbuf = Fopen(cp, "r")) == NULL) { 2789b50d902SRodney W. Grimes perror(cp); 2799b50d902SRodney W. Grimes break; 2809b50d902SRodney W. Grimes } 2819b50d902SRodney W. Grimes printf("\"%s\" ", cp); 2829b50d902SRodney W. Grimes fflush(stdout); 2839b50d902SRodney W. Grimes lc = 0; 2849b50d902SRodney W. Grimes cc = 0; 2859b50d902SRodney W. Grimes while (readline(fbuf, linebuf, LINESIZE) >= 0) { 2869b50d902SRodney W. Grimes lc++; 2879b50d902SRodney W. Grimes if ((t = putline(collf, linebuf)) < 0) { 2889b50d902SRodney W. Grimes Fclose(fbuf); 2899b50d902SRodney W. Grimes goto err; 2909b50d902SRodney W. Grimes } 2919b50d902SRodney W. Grimes cc += t; 2929b50d902SRodney W. Grimes } 2939b50d902SRodney W. Grimes Fclose(fbuf); 2949b50d902SRodney W. Grimes printf("%d/%d\n", lc, cc); 2959b50d902SRodney W. Grimes break; 2969b50d902SRodney W. Grimes case 'w': 2979b50d902SRodney W. Grimes /* 2989b50d902SRodney W. Grimes * Write the message on a file. 2999b50d902SRodney W. Grimes */ 3009b50d902SRodney W. Grimes cp = &linebuf[2]; 3019b50d902SRodney W. Grimes while (*cp == ' ' || *cp == '\t') 3029b50d902SRodney W. Grimes cp++; 3039b50d902SRodney W. Grimes if (*cp == '\0') { 3049b50d902SRodney W. Grimes fprintf(stderr, "Write what file!?\n"); 3059b50d902SRodney W. Grimes break; 3069b50d902SRodney W. Grimes } 3079b50d902SRodney W. Grimes if ((cp = expand(cp)) == NOSTR) 3089b50d902SRodney W. Grimes break; 3099b50d902SRodney W. Grimes rewind(collf); 3109b50d902SRodney W. Grimes exwrite(cp, collf, 1); 3119b50d902SRodney W. Grimes break; 3129b50d902SRodney W. Grimes case 'm': 3139b50d902SRodney W. Grimes case 'M': 3149b50d902SRodney W. Grimes case 'f': 3159b50d902SRodney W. Grimes case 'F': 3169b50d902SRodney W. Grimes /* 3179b50d902SRodney W. Grimes * Interpolate the named messages, if we 3189b50d902SRodney W. Grimes * are in receiving mail mode. Does the 3199b50d902SRodney W. Grimes * standard list processing garbage. 3209b50d902SRodney W. Grimes * If ~f is given, we don't shift over. 3219b50d902SRodney W. Grimes */ 3229b50d902SRodney W. Grimes if (forward(linebuf + 2, collf, c) < 0) 3239b50d902SRodney W. Grimes goto err; 3249b50d902SRodney W. Grimes goto cont; 3259b50d902SRodney W. Grimes case '?': 3269b50d902SRodney W. Grimes if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) { 3279b50d902SRodney W. Grimes perror(_PATH_TILDE); 3289b50d902SRodney W. Grimes break; 3299b50d902SRodney W. Grimes } 3309b50d902SRodney W. Grimes while ((t = getc(fbuf)) != EOF) 3319b50d902SRodney W. Grimes (void) putchar(t); 3329b50d902SRodney W. Grimes Fclose(fbuf); 3339b50d902SRodney W. Grimes break; 3349b50d902SRodney W. Grimes case 'p': 3359b50d902SRodney W. Grimes /* 3369b50d902SRodney W. Grimes * Print out the current state of the 3379b50d902SRodney W. Grimes * message without altering anything. 3389b50d902SRodney W. Grimes */ 3399b50d902SRodney W. Grimes rewind(collf); 3409b50d902SRodney W. Grimes printf("-------\nMessage contains:\n"); 3419b50d902SRodney W. Grimes puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); 3429b50d902SRodney W. Grimes while ((t = getc(collf)) != EOF) 3439b50d902SRodney W. Grimes (void) putchar(t); 3449b50d902SRodney W. Grimes goto cont; 3459b50d902SRodney W. Grimes case '|': 3469b50d902SRodney W. Grimes /* 3479b50d902SRodney W. Grimes * Pipe message through command. 3489b50d902SRodney W. Grimes * Collect output as new message. 3499b50d902SRodney W. Grimes */ 3509b50d902SRodney W. Grimes rewind(collf); 3519b50d902SRodney W. Grimes mespipe(collf, &linebuf[2]); 3529b50d902SRodney W. Grimes goto cont; 3539b50d902SRodney W. Grimes case 'v': 3549b50d902SRodney W. Grimes case 'e': 3559b50d902SRodney W. Grimes /* 3569b50d902SRodney W. Grimes * Edit the current message. 3579b50d902SRodney W. Grimes * 'e' means to use EDITOR 3589b50d902SRodney W. Grimes * 'v' means to use VISUAL 3599b50d902SRodney W. Grimes */ 3609b50d902SRodney W. Grimes rewind(collf); 3619b50d902SRodney W. Grimes mesedit(collf, c); 3629b50d902SRodney W. Grimes goto cont; 3639b50d902SRodney W. Grimes } 3649b50d902SRodney W. Grimes } 3659b50d902SRodney W. Grimes goto out; 3669b50d902SRodney W. Grimes err: 3679b50d902SRodney W. Grimes if (collf != NULL) { 3689b50d902SRodney W. Grimes Fclose(collf); 3699b50d902SRodney W. Grimes collf = NULL; 3709b50d902SRodney W. Grimes } 3719b50d902SRodney W. Grimes out: 3729b50d902SRodney W. Grimes if (collf != NULL) 3739b50d902SRodney W. Grimes rewind(collf); 3749b50d902SRodney W. Grimes noreset--; 3759b50d902SRodney W. Grimes sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); 3769b50d902SRodney W. Grimes signal(SIGINT, saveint); 3779b50d902SRodney W. Grimes signal(SIGHUP, savehup); 3789b50d902SRodney W. Grimes signal(SIGTSTP, savetstp); 3799b50d902SRodney W. Grimes signal(SIGTTOU, savettou); 3809b50d902SRodney W. Grimes signal(SIGTTIN, savettin); 3819b50d902SRodney W. Grimes sigsetmask(omask); 3829b50d902SRodney W. Grimes return collf; 3839b50d902SRodney W. Grimes } 3849b50d902SRodney W. Grimes 3859b50d902SRodney W. Grimes /* 3869b50d902SRodney W. Grimes * Write a file, ex-like if f set. 3879b50d902SRodney W. Grimes */ 3889b50d902SRodney W. Grimes int 3899b50d902SRodney W. Grimes exwrite(name, fp, f) 3909b50d902SRodney W. Grimes char name[]; 3919b50d902SRodney W. Grimes FILE *fp; 3929b50d902SRodney W. Grimes int f; 3939b50d902SRodney W. Grimes { 3949b50d902SRodney W. Grimes register FILE *of; 3959b50d902SRodney W. Grimes register int c; 3969b50d902SRodney W. Grimes long cc; 3979b50d902SRodney W. Grimes int lc; 3989b50d902SRodney W. Grimes struct stat junk; 3999b50d902SRodney W. Grimes 4009b50d902SRodney W. Grimes if (f) { 4019b50d902SRodney W. Grimes printf("\"%s\" ", name); 4029b50d902SRodney W. Grimes fflush(stdout); 4039b50d902SRodney W. Grimes } 4049b50d902SRodney W. Grimes if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) { 4059b50d902SRodney W. Grimes if (!f) 4069b50d902SRodney W. Grimes fprintf(stderr, "%s: ", name); 4079b50d902SRodney W. Grimes fprintf(stderr, "File exists\n"); 4089b50d902SRodney W. Grimes return(-1); 4099b50d902SRodney W. Grimes } 4109b50d902SRodney W. Grimes if ((of = Fopen(name, "w")) == NULL) { 4119b50d902SRodney W. Grimes perror(NOSTR); 4129b50d902SRodney W. Grimes return(-1); 4139b50d902SRodney W. Grimes } 4149b50d902SRodney W. Grimes lc = 0; 4159b50d902SRodney W. Grimes cc = 0; 4169b50d902SRodney W. Grimes while ((c = getc(fp)) != EOF) { 4179b50d902SRodney W. Grimes cc++; 4189b50d902SRodney W. Grimes if (c == '\n') 4199b50d902SRodney W. Grimes lc++; 4209b50d902SRodney W. Grimes (void) putc(c, of); 4219b50d902SRodney W. Grimes if (ferror(of)) { 4229b50d902SRodney W. Grimes perror(name); 4239b50d902SRodney W. Grimes Fclose(of); 4249b50d902SRodney W. Grimes return(-1); 4259b50d902SRodney W. Grimes } 4269b50d902SRodney W. Grimes } 4279b50d902SRodney W. Grimes Fclose(of); 4289b50d902SRodney W. Grimes printf("%d/%ld\n", lc, cc); 4299b50d902SRodney W. Grimes fflush(stdout); 4309b50d902SRodney W. Grimes return(0); 4319b50d902SRodney W. Grimes } 4329b50d902SRodney W. Grimes 4339b50d902SRodney W. Grimes /* 4349b50d902SRodney W. Grimes * Edit the message being collected on fp. 4359b50d902SRodney W. Grimes * On return, make the edit file the new temp file. 4369b50d902SRodney W. Grimes */ 4379b50d902SRodney W. Grimes void 4389b50d902SRodney W. Grimes mesedit(fp, c) 4399b50d902SRodney W. Grimes FILE *fp; 4409b50d902SRodney W. Grimes int c; 4419b50d902SRodney W. Grimes { 4429b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 4439b50d902SRodney W. Grimes FILE *nf = run_editor(fp, (off_t)-1, c, 0); 4449b50d902SRodney W. Grimes 4459b50d902SRodney W. Grimes if (nf != NULL) { 4469b50d902SRodney W. Grimes fseek(nf, 0L, 2); 4479b50d902SRodney W. Grimes collf = nf; 4489b50d902SRodney W. Grimes Fclose(fp); 4499b50d902SRodney W. Grimes } 4509b50d902SRodney W. Grimes (void) signal(SIGINT, sigint); 4519b50d902SRodney W. Grimes } 4529b50d902SRodney W. Grimes 4539b50d902SRodney W. Grimes /* 4549b50d902SRodney W. Grimes * Pipe the message through the command. 4559b50d902SRodney W. Grimes * Old message is on stdin of command; 4569b50d902SRodney W. Grimes * New message collected from stdout. 4579b50d902SRodney W. Grimes * Sh -c must return 0 to accept the new message. 4589b50d902SRodney W. Grimes */ 4599b50d902SRodney W. Grimes void 4609b50d902SRodney W. Grimes mespipe(fp, cmd) 4619b50d902SRodney W. Grimes FILE *fp; 4629b50d902SRodney W. Grimes char cmd[]; 4639b50d902SRodney W. Grimes { 4649b50d902SRodney W. Grimes FILE *nf; 4659b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 4669b50d902SRodney W. Grimes extern char tempEdit[]; 4679b50d902SRodney W. Grimes char *shell; 4689b50d902SRodney W. Grimes 4699b50d902SRodney W. Grimes if ((nf = Fopen(tempEdit, "w+")) == NULL) { 4709b50d902SRodney W. Grimes perror(tempEdit); 4719b50d902SRodney W. Grimes goto out; 4729b50d902SRodney W. Grimes } 4739b50d902SRodney W. Grimes (void) unlink(tempEdit); 4749b50d902SRodney W. Grimes /* 4759b50d902SRodney W. Grimes * stdin = current message. 4769b50d902SRodney W. Grimes * stdout = new message. 4779b50d902SRodney W. Grimes */ 4789b50d902SRodney W. Grimes if ((shell = value("SHELL")) == NOSTR) 4799b50d902SRodney W. Grimes shell = _PATH_CSHELL; 4809b50d902SRodney W. Grimes if (run_command(shell, 4819b50d902SRodney W. Grimes 0, fileno(fp), fileno(nf), "-c", cmd, NOSTR) < 0) { 4829b50d902SRodney W. Grimes (void) Fclose(nf); 4839b50d902SRodney W. Grimes goto out; 4849b50d902SRodney W. Grimes } 4859b50d902SRodney W. Grimes if (fsize(nf) == 0) { 4869b50d902SRodney W. Grimes fprintf(stderr, "No bytes from \"%s\" !?\n", cmd); 4879b50d902SRodney W. Grimes (void) Fclose(nf); 4889b50d902SRodney W. Grimes goto out; 4899b50d902SRodney W. Grimes } 4909b50d902SRodney W. Grimes /* 4919b50d902SRodney W. Grimes * Take new files. 4929b50d902SRodney W. Grimes */ 4939b50d902SRodney W. Grimes (void) fseek(nf, 0L, 2); 4949b50d902SRodney W. Grimes collf = nf; 4959b50d902SRodney W. Grimes (void) Fclose(fp); 4969b50d902SRodney W. Grimes out: 4979b50d902SRodney W. Grimes (void) signal(SIGINT, sigint); 4989b50d902SRodney W. Grimes } 4999b50d902SRodney W. Grimes 5009b50d902SRodney W. Grimes /* 5019b50d902SRodney W. Grimes * Interpolate the named messages into the current 5029b50d902SRodney W. Grimes * message, preceding each line with a tab. 5039b50d902SRodney W. Grimes * Return a count of the number of characters now in 5049b50d902SRodney W. Grimes * the message, or -1 if an error is encountered writing 5059b50d902SRodney W. Grimes * the message temporary. The flag argument is 'm' if we 5069b50d902SRodney W. Grimes * should shift over and 'f' if not. 5079b50d902SRodney W. Grimes */ 5089b50d902SRodney W. Grimes int 5099b50d902SRodney W. Grimes forward(ms, fp, f) 5109b50d902SRodney W. Grimes char ms[]; 5119b50d902SRodney W. Grimes FILE *fp; 5129b50d902SRodney W. Grimes int f; 5139b50d902SRodney W. Grimes { 5149b50d902SRodney W. Grimes register int *msgvec; 5159b50d902SRodney W. Grimes extern char tempMail[]; 5169b50d902SRodney W. Grimes struct ignoretab *ig; 5179b50d902SRodney W. Grimes char *tabst; 5189b50d902SRodney W. Grimes 5199b50d902SRodney W. Grimes msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec); 5209b50d902SRodney W. Grimes if (msgvec == (int *) NOSTR) 5219b50d902SRodney W. Grimes return(0); 5229b50d902SRodney W. Grimes if (getmsglist(ms, msgvec, 0) < 0) 5239b50d902SRodney W. Grimes return(0); 5249b50d902SRodney W. Grimes if (*msgvec == 0) { 5259b50d902SRodney W. Grimes *msgvec = first(0, MMNORM); 526d030d2d2SPoul-Henning Kamp if (*msgvec == 0) { 5279b50d902SRodney W. Grimes printf("No appropriate messages\n"); 5289b50d902SRodney W. Grimes return(0); 5299b50d902SRodney W. Grimes } 530d030d2d2SPoul-Henning Kamp msgvec[1] = 0; 5319b50d902SRodney W. Grimes } 5329b50d902SRodney W. Grimes if (f == 'f' || f == 'F') 5339b50d902SRodney W. Grimes tabst = NOSTR; 5349b50d902SRodney W. Grimes else if ((tabst = value("indentprefix")) == NOSTR) 5359b50d902SRodney W. Grimes tabst = "\t"; 5369b50d902SRodney W. Grimes ig = isupper(f) ? NULL : ignore; 5379b50d902SRodney W. Grimes printf("Interpolating:"); 5389b50d902SRodney W. Grimes for (; *msgvec != 0; msgvec++) { 5399b50d902SRodney W. Grimes struct message *mp = message + *msgvec - 1; 5409b50d902SRodney W. Grimes 5419b50d902SRodney W. Grimes touch(mp); 5429b50d902SRodney W. Grimes printf(" %d", *msgvec); 5439b50d902SRodney W. Grimes if (send(mp, fp, ig, tabst) < 0) { 5449b50d902SRodney W. Grimes perror(tempMail); 5459b50d902SRodney W. Grimes return(-1); 5469b50d902SRodney W. Grimes } 5479b50d902SRodney W. Grimes } 5489b50d902SRodney W. Grimes printf("\n"); 5499b50d902SRodney W. Grimes return(0); 5509b50d902SRodney W. Grimes } 5519b50d902SRodney W. Grimes 5529b50d902SRodney W. Grimes /* 5539b50d902SRodney W. Grimes * Print (continue) when continued after ^Z. 5549b50d902SRodney W. Grimes */ 5559b50d902SRodney W. Grimes /*ARGSUSED*/ 5569b50d902SRodney W. Grimes void 5579b50d902SRodney W. Grimes collstop(s) 5589b50d902SRodney W. Grimes int s; 5599b50d902SRodney W. Grimes { 5609b50d902SRodney W. Grimes sig_t old_action = signal(s, SIG_DFL); 5619b50d902SRodney W. Grimes 5629b50d902SRodney W. Grimes sigsetmask(sigblock(0) & ~sigmask(s)); 5639b50d902SRodney W. Grimes kill(0, s); 5649b50d902SRodney W. Grimes sigblock(sigmask(s)); 5659b50d902SRodney W. Grimes signal(s, old_action); 5669b50d902SRodney W. Grimes if (colljmp_p) { 5679b50d902SRodney W. Grimes colljmp_p = 0; 5689b50d902SRodney W. Grimes hadintr = 0; 5699b50d902SRodney W. Grimes longjmp(colljmp, 1); 5709b50d902SRodney W. Grimes } 5719b50d902SRodney W. Grimes } 5729b50d902SRodney W. Grimes 5739b50d902SRodney W. Grimes /* 5749b50d902SRodney W. Grimes * On interrupt, come here to save the partial message in ~/dead.letter. 5759b50d902SRodney W. Grimes * Then jump out of the collection loop. 5769b50d902SRodney W. Grimes */ 5779b50d902SRodney W. Grimes /*ARGSUSED*/ 5789b50d902SRodney W. Grimes void 5799b50d902SRodney W. Grimes collint(s) 5809b50d902SRodney W. Grimes int s; 5819b50d902SRodney W. Grimes { 5829b50d902SRodney W. Grimes /* 5839b50d902SRodney W. Grimes * the control flow is subtle, because we can be called from ~q. 5849b50d902SRodney W. Grimes */ 5859b50d902SRodney W. Grimes if (!hadintr) { 5869b50d902SRodney W. Grimes if (value("ignore") != NOSTR) { 5879b50d902SRodney W. Grimes puts("@"); 5889b50d902SRodney W. Grimes fflush(stdout); 5899b50d902SRodney W. Grimes clearerr(stdin); 5909b50d902SRodney W. Grimes return; 5919b50d902SRodney W. Grimes } 5929b50d902SRodney W. Grimes hadintr = 1; 5939b50d902SRodney W. Grimes longjmp(colljmp, 1); 5949b50d902SRodney W. Grimes } 5959b50d902SRodney W. Grimes rewind(collf); 5969b50d902SRodney W. Grimes if (value("nosave") == NOSTR) 5979b50d902SRodney W. Grimes savedeadletter(collf); 5989b50d902SRodney W. Grimes longjmp(collabort, 1); 5999b50d902SRodney W. Grimes } 6009b50d902SRodney W. Grimes 6019b50d902SRodney W. Grimes /*ARGSUSED*/ 6029b50d902SRodney W. Grimes void 6039b50d902SRodney W. Grimes collhup(s) 6049b50d902SRodney W. Grimes int s; 6059b50d902SRodney W. Grimes { 6069b50d902SRodney W. Grimes rewind(collf); 6079b50d902SRodney W. Grimes savedeadletter(collf); 6089b50d902SRodney W. Grimes /* 6099b50d902SRodney W. Grimes * Let's pretend nobody else wants to clean up, 6109b50d902SRodney W. Grimes * a true statement at this time. 6119b50d902SRodney W. Grimes */ 6129b50d902SRodney W. Grimes exit(1); 6139b50d902SRodney W. Grimes } 6149b50d902SRodney W. Grimes 6159b50d902SRodney W. Grimes void 6169b50d902SRodney W. Grimes savedeadletter(fp) 6179b50d902SRodney W. Grimes register FILE *fp; 6189b50d902SRodney W. Grimes { 6199b50d902SRodney W. Grimes register FILE *dbuf; 6209b50d902SRodney W. Grimes register int c; 6219b50d902SRodney W. Grimes char *cp; 6229b50d902SRodney W. Grimes 6239b50d902SRodney W. Grimes if (fsize(fp) == 0) 6249b50d902SRodney W. Grimes return; 6259b50d902SRodney W. Grimes cp = getdeadletter(); 6269b50d902SRodney W. Grimes c = umask(077); 6279b50d902SRodney W. Grimes dbuf = Fopen(cp, "a"); 6289b50d902SRodney W. Grimes (void) umask(c); 6299b50d902SRodney W. Grimes if (dbuf == NULL) 6309b50d902SRodney W. Grimes return; 6319b50d902SRodney W. Grimes while ((c = getc(fp)) != EOF) 6329b50d902SRodney W. Grimes (void) putc(c, dbuf); 6339b50d902SRodney W. Grimes Fclose(dbuf); 6349b50d902SRodney W. Grimes rewind(fp); 6359b50d902SRodney W. Grimes } 636