/* * Save/copy the indicated messages at the end of the passed file name. * If mark is true, mark the message "saved." */ int save1(char str[], int mark, const char *cmd, struct ignoretab *ignore) { struct message *mp; char *file; const char *disp; int f, *msgvec, *ip; FILE *obuf; msgvec = (int *)salloc((msgCount + 2) * sizeof(*msgvec)); if ((file = snarf(str, &f)) == NULL) return (1); if (!f) { *msgvec = first(0, MMNORM); if (*msgvec == 0) { printf("No messages to %s.\n", cmd); return (1); } msgvec[1] = 0; } if (f && getmsglist(str, msgvec, 0) < 0) return (1); if ((file = expand(file)) == NULL) return (1); printf("\"%s\" ", file); (void)fflush(stdout); if (access(file, 0) >= 0) disp = "[Appended]"; else disp = "[New file]"; if ((obuf = Fopen(file, "a")) == NULL) { warn((char *)NULL); return (1); } for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { mp = &message[*ip - 1]; touch(mp); if (sendmessage(mp, obuf, ignore, NULL) < 0) { warnx("%s", file); (void)Fclose(obuf); return (1); } if (mark) mp->m_flag |= MSAVED; } (void)fflush(obuf); if (ferror(obuf)) warn("%s", file); (void)Fclose(obuf); printf("%s\n", disp); return (0); }
/* * Pipe the messages requested. */ static int pipe1(char *str, int doign) { char *cmd; int f, *msgvec, ret; off_t stats[2]; /*LINTED*/ msgvec = (int *)salloc((msgCount + 2) * sizeof *msgvec); if ((cmd = laststring(str, &f, 1)) == NULL) { cmd = value("cmd"); if (cmd == NULL || *cmd == '\0') { fputs(catgets(catd, CATSET, 16, "variable cmd not set\n"), stderr); return 1; } } if (!f) { *msgvec = first(0, MMNORM); if (*msgvec == 0) { if (inhook) return 0; puts(catgets(catd, CATSET, 18, "No messages to pipe.")); return 1; } msgvec[1] = 0; } else if (getmsglist(str, msgvec, 0) < 0) return 1; if (*msgvec == 0) { if (inhook) return 0; printf("No applicable messages.\n"); return 1; } printf(catgets(catd, CATSET, 268, "Pipe to: \"%s\"\n"), cmd); stats[0] = stats[1] = 0; if ((ret = type1(msgvec, doign, 0, 1, 0, cmd, stats)) == 0) { printf("\"%s\" ", cmd); if (stats[0] >= 0) printf("%lu", (long)stats[0]); else printf(catgets(catd, CATSET, 27, "binary")); printf("/%lu\n", (long)stats[1]); } return ret; }
/* * Interpolate the named messages into the current * message, preceding each line with a tab. * Return a count of the number of characters now in * the message, or -1 if an error is encountered writing * the message temporary. The flag argument is 'm' if we * should shift over and 'f' if not. */ static int forward(char *ms, FILE *fp, int f) { int *msgvec; struct ignoretab *ig; char *tabst; enum sendaction action; /*LINTED*/ msgvec = (int *)salloc((msgCount+1) * sizeof *msgvec); if (msgvec == NULL) return(0); if (getmsglist(ms, msgvec, 0) < 0) return(0); if (*msgvec == 0) { *msgvec = first(0, MMNORM); if (*msgvec == 0) { printf(catgets(catd, CATSET, 68, "No appropriate messages\n")); return(0); } msgvec[1] = 0; } if (f == 'f' || f == 'F') tabst = NULL; else if ((tabst = value("indentprefix")) == NULL) tabst = "\t"; ig = upperchar(f) ? (struct ignoretab *)NULL : ignore; action = upperchar(f) ? SEND_QUOTE_ALL : SEND_QUOTE; printf(catgets(catd, CATSET, 69, "Interpolating:")); for (; *msgvec != 0; msgvec++) { struct message *mp = message + *msgvec - 1; touch(mp); printf(" %d", *msgvec); if (send(mp, fp, ig, tabst, action, NULL) < 0) { perror(catgets(catd, CATSET, 70, "temporary mail file")); return(-1); } } printf("\n"); return(0); }
/* * Interpolate the named messages into the current * message, preceding each line with a tab. * Return a count of the number of characters now in * the message, or -1 if an error is encountered writing * the message temporary. The flag argument is 'm' if we * should shift over and 'f' if not. */ int forward(char ms[], FILE *fp, char *fn, int f) { int *msgvec; struct ignoretab *ig; char *tabst; msgvec = (int *)salloc((msgCount+1) * sizeof(*msgvec)); if (msgvec == NULL) return (0); if (getmsglist(ms, msgvec, 0) < 0) return (0); if (*msgvec == 0) { *msgvec = first(0, MMNORM); if (*msgvec == 0) { printf("No appropriate messages\n"); return (0); } msgvec[1] = 0; } if (f == 'f' || f == 'F') tabst = NULL; else if ((tabst = value("indentprefix")) == NULL) tabst = "\t"; ig = isupper((unsigned char)f) ? NULL : ignore; printf("Interpolating:"); for (; *msgvec != 0; msgvec++) { struct message *mp = message + *msgvec - 1; touch(mp); printf(" %d", *msgvec); if (sendmessage(mp, fp, ig, tabst) < 0) { warnx("%s", fn); return (-1); } } printf("\n"); return (0); }
/* * Execute a single command. * Command functions return 0 for success, 1 for error, and -1 * for abort. A 1 or -1 aborts a load or source. A -1 aborts * the interactive command loop. * Contxt is non-zero if called while composing mail. */ int execute(char linebuf[], int contxt) { char word[LINESIZE]; char *arglist[MAXARGC]; const struct cmd *com; char *cp, *cp2; int c, muvec[2]; int e = 1; /* * Strip the white space away from the beginning * of the command, then scan out a word, which * consists of anything except digits and white space. * * Handle ! escapes differently to get the correct * lexical conventions. */ for (cp = linebuf; isspace((unsigned char)*cp); cp++) ; if (*cp == '!') { if (sourcing) { printf("Can't \"!\" while sourcing\n"); goto out; } shell(cp+1); return (0); } cp2 = word; while (*cp != '\0' && strchr(" \t0123456789$^.:/-+*'\"", *cp) == NULL) *cp2++ = *cp++; *cp2 = '\0'; /* * Look up the command; if not found, bitch. * Normally, a blank command would map to the * first command in the table; while sourcing, * however, we ignore blank lines to eliminate * confusion. */ if (sourcing && *word == '\0') return (0); com = lex(word); if (com == NULL) { printf("Unknown command: \"%s\"\n", word); goto out; } /* * See if we should execute the command -- if a conditional * we always execute it, otherwise, check the state of cond. */ if ((com->c_argtype & F) == 0) if ((cond == CRCV && !rcvmode) || (cond == CSEND && rcvmode)) return (0); /* * Process the arguments to the command, depending * on the type he expects. Default to an error. * If we are sourcing an interactive command, it's * an error. */ if (!rcvmode && (com->c_argtype & M) == 0) { printf("May not execute \"%s\" while sending\n", com->c_name); goto out; } if (sourcing && com->c_argtype & I) { printf("May not execute \"%s\" while sourcing\n", com->c_name); goto out; } if (readonly && com->c_argtype & W) { printf("May not execute \"%s\" -- message file is read only\n", com->c_name); goto out; } if (contxt && com->c_argtype & R) { printf("Cannot recursively invoke \"%s\"\n", com->c_name); goto out; } switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { case MSGLIST: /* * A message list defaulting to nearest forward * legal message. */ if (msgvec == 0) { printf("Illegal use of \"message list\"\n"); break; } if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) break; if (c == 0) { *msgvec = first(com->c_msgflag, com->c_msgmask); msgvec[1] = 0; } if (*msgvec == 0) { printf("No applicable messages\n"); break; } e = (*com->c_func)(msgvec); break; case NDMLIST: /* * A message list with no defaults, but no error * if none exist. */ if (msgvec == 0) { printf("Illegal use of \"message list\"\n"); break; } if (getmsglist(cp, msgvec, com->c_msgflag) < 0) break; e = (*com->c_func)(msgvec); break; case STRLIST: /* * Just the straight string, with * leading blanks removed. */ while (isspace((unsigned char)*cp)) cp++; e = (*com->c_func)(cp); break; case RAWLIST: /* * A vector of strings, in shell style. */ if ((c = getrawlist(cp, arglist, sizeof(arglist) / sizeof(*arglist))) < 0) break; if (c < com->c_minargs) { printf("%s requires at least %d arg(s)\n", com->c_name, com->c_minargs); break; } if (c > com->c_maxargs) { printf("%s takes no more than %d arg(s)\n", com->c_name, com->c_maxargs); break; } e = (*com->c_func)(arglist); break; case NOLIST: /* * Just the constant zero, for exiting, * eg. */ e = (*com->c_func)(0); break; default: errx(1, "Unknown argtype"); } out: /* * Exit the current source file on * error. */ if (e) { if (e < 0) return (1); if (loading) return (1); if (sourcing) unstack(); return (0); } if (com == NULL) return (0); if (value("autoprint") != NULL && com->c_argtype & P) if ((dot->m_flag & MDELETED) == 0) { muvec[0] = dot - &message[0] + 1; muvec[1] = 0; type(muvec); } if (!sourcing && (com->c_argtype & T) == 0) sawcom = 1; return (0); }