home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / mail / cmd2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  9.8 KB  |  517 lines

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