home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / ucbmail / cmd2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-06-03  |  11.2 KB  |  617 lines

  1. /*
  2.  *  C M D 2 . C 
  3.  *
  4.  *  EE/CIS Computer Lab
  5.  *  Department of Computer and Information Sciences
  6.  *  Department of Electrical Engineering
  7.  *  University of Delaware
  8.  *
  9.  *  REVISION HISTORY:
  10.  *
  11.  *  $Revision: 1.4 $
  12.  *
  13.  *  $Log:    cmd2.c,v $
  14.  * Revision 1.4  86/01/07  13:41:18  galvin
  15.  * Change swrite to include MMDF delimiters in messages and to
  16.  * output the entire message instead of skipping the first/last line.
  17.  * 
  18.  * Revision 1.3  85/12/18  13:21:13  galvin
  19.  * Add another argument to send to indicate whether or not this
  20.  * message should be delimited by MMDF message delimiters.
  21.  * 
  22.  * Change all but "temp" file opens/closes to use MMDF locking routines.
  23.  * 
  24.  * Revision 1.2  85/12/18  03:10:35  galvin
  25.  * Added comment header for revision history.
  26.  * 
  27.  *
  28.  */
  29.  
  30. /*
  31.  * Copyright (c) 1980 Regents of the University of California.
  32.  * All rights reserved.  The Berkeley software License Agreement
  33.  * specifies the terms and conditions for redistribution.
  34.  */
  35.  
  36. #ifndef lint
  37. static char *sccsid = "@(#)cmd2.c    5.2 (Berkeley) 6/21/85";
  38. #endif not lint
  39.  
  40. #include "./rcv.h"
  41. #include <sys/stat.h>
  42. #include "./mmdf.h"
  43.  
  44. /*
  45.  * Mail -- a mail program
  46.  *
  47.  * More user commands.
  48.  */
  49.  
  50. /*
  51.  * If any arguments were given, go to the next applicable argument
  52.  * following dot, otherwise, go to the next applicable message.
  53.  * If given as first command with no arguments, print first message.
  54.  */
  55.  
  56. next(msgvec)
  57.     int *msgvec;
  58. {
  59.     register struct message *mp;
  60.     register int *ip, *ip2;
  61.     int list[2], mdot;
  62.  
  63.     if (*msgvec != NULL) {
  64.  
  65.         /*
  66.          * If some messages were supplied, find the 
  67.          * first applicable one following dot using
  68.          * wrap around.
  69.          */
  70.  
  71.         mdot = dot - &message[0] + 1;
  72.  
  73.         /*
  74.          * Find the first message in the supplied
  75.          * message list which follows dot.
  76.          */
  77.  
  78.         for (ip = msgvec; *ip != NULL; ip++)
  79.             if (*ip > mdot)
  80.                 break;
  81.         if (*ip == NULL)
  82.             ip = msgvec;
  83.         ip2 = ip;
  84.         do {
  85.             mp = &message[*ip2 - 1];
  86.             if ((mp->m_flag & MDELETED) == 0) {
  87.                 dot = mp;
  88.                 goto hitit;
  89.             }
  90.             if (*ip2 != NULL)
  91.                 ip2++;
  92.             if (*ip2 == NULL)
  93.                 ip2 = msgvec;
  94.         } while (ip2 != ip);
  95.         printf("No messages applicable\n");
  96.         return(1);
  97.     }
  98.  
  99.     /*
  100.      * If this is the first command, select message 1.
  101.      * Note that this must exist for us to get here at all.
  102.      */
  103.  
  104.     if (!sawcom)
  105.         goto hitit;
  106.  
  107.     /*
  108.      * Just find the next good message after dot, no
  109.      * wraparound.
  110.      */
  111.  
  112.     for (mp = dot+1; mp < &message[msgCount]; mp++)
  113.         if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
  114.             break;
  115.     if (mp >= &message[msgCount]) {
  116.         printf("At EOF\n");
  117.         return(0);
  118.     }
  119.     dot = mp;
  120. hitit:
  121.     /*
  122.      * Print dot.
  123.      */
  124.  
  125.     list[0] = dot - &message[0] + 1;
  126.     list[1] = NULL;
  127.     return(type(list));
  128. }
  129.  
  130. /*
  131.  * Save a message in a file.  Mark the message as saved
  132.  * so we can discard when the user quits.
  133.  */
  134. save(str)
  135.     char str[];
  136. {
  137.  
  138.     return(save1(str, 1));
  139. }
  140.  
  141. /*
  142.  * Copy a message to a file without affected its saved-ness
  143.  */
  144. copycmd(str)
  145.     char str[];
  146. {
  147.  
  148.     return(save1(str, 0));
  149. }
  150.  
  151. /*
  152.  * Save/copy the indicated messages at the end of the passed file name.
  153.  * If mark is true, mark the message "saved."
  154.  */
  155. save1(str, mark)
  156.     char str[];
  157. {
  158.     register int *ip, mesg;
  159.     register struct message *mp;
  160.     char *file, *disp, *cmd;
  161.     int f, *msgvec, lc, t;
  162.     long cc;
  163.     FILE *obuf;
  164.     struct stat statb;
  165.  
  166.     cmd = mark ? "save" : "copy";
  167.     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  168.     if ((file = snarf(str, &f)) == NOSTR)
  169.         return(1);
  170.     if (!f) {
  171.         *msgvec = first(0, MMNORM);
  172.         if (*msgvec == NULL) {
  173.             printf("No messages to %s.\n", cmd);
  174.             return(1);
  175.         }
  176.         msgvec[1] = NULL;
  177.     }
  178.     if (f && getmsglist(str, msgvec, 0) < 0)
  179.         return(1);
  180.     if ((file = expand(file)) == NOSTR)
  181.         return(1);
  182.     printf("\"%s\" ", file);
  183.     fflush(stdout);
  184.     if (stat(file, &statb) >= 0)
  185.         disp = "[Appended]";
  186.     else
  187.         disp = "[New file]";
  188.     if ((obuf = lk_fopen(file, "a", (char *) 0, (char *) 0, 5)) == NULL) {
  189.         perror(NOSTR);
  190.         return(1);
  191.     }
  192.     cc = 0L;
  193.     lc = 0;
  194.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  195.         mesg = *ip;
  196.         touch(mesg);
  197.         mp = &message[mesg-1];
  198.         if ((t = send(mp, obuf, 0, 1)) < 0) {
  199.             perror(file);
  200.             lk_fclose(obuf, file, (char *) 0, (char *) 0);
  201.             return(1);
  202.         }
  203.         lc += t;
  204.         cc += mp->m_size;
  205.         if (mark)
  206.             mp->m_flag |= MSAVED;
  207.     }
  208.     fflush(obuf);
  209.     if (ferror(obuf))
  210.         perror(file);
  211.     lk_fclose(obuf, file, (char *) 0, (char *) 0);
  212.     printf("%s %d/%ld\n", disp, lc, cc);
  213.     return(0);
  214. }
  215.  
  216. /*
  217.  * Write the indicated messages at the end of the passed
  218.  * file name.
  219.  */
  220.  
  221. swrite(str)
  222.     char str[];
  223. {
  224.     register int *ip, mesg;
  225.     register struct message *mp;
  226.     register char *file, *disp;
  227.     char linebuf[BUFSIZ];
  228.     int f, *msgvec, lc, cc, t;
  229.     FILE *obuf, *mesf;
  230.     struct stat statb;
  231.  
  232.     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  233.     if ((file = snarf(str, &f)) == NOSTR)
  234.         return(1);
  235.     if ((file = expand(file)) == NOSTR)
  236.         return(1);
  237.     if (!f) {
  238.         *msgvec = first(0, MMNORM);
  239.         if (*msgvec == NULL) {
  240.             printf("No messages to write.\n");
  241.             return(1);
  242.         }
  243.         msgvec[1] = NULL;
  244.     }
  245.     if (f && getmsglist(str, msgvec, 0) < 0)
  246.         return(1);
  247.     printf("\"%s\" ", file);
  248.     fflush(stdout);
  249.     if (stat(file, &statb) >= 0)
  250.         disp = "[Appended]";
  251.     else
  252.         disp = "[New file]";
  253.     if ((obuf = fopen(file, "a")) == NULL) {
  254.         perror(NOSTR);
  255.         return(1);
  256.     }
  257.     cc = lc = 0;
  258.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  259.         mesg = *ip;
  260.         touch(mesg);
  261.         mp = &message[mesg-1];
  262.         mesf = setinput(mp);
  263.         t = mp->m_lines;
  264.             readline(mesf, linebuf);
  265.         fputs(delim1, obuf);
  266.         while (t-- > 0) {
  267.             fgets(linebuf, BUFSIZ, mesf);
  268.             fputs(linebuf, obuf);
  269.             cc += strlen(linebuf);
  270.         }
  271.         fputs(delim2, obuf);
  272.         lc += mp->m_lines;
  273.         mp->m_flag |= MSAVED;
  274.     }
  275.     fflush(obuf);
  276.     if (ferror(obuf))
  277.         perror(file);
  278.     fclose(obuf);
  279.     printf("%s %d/%d\n", disp, lc, cc);
  280.     return(0);
  281. }
  282.  
  283. /*
  284.  * Snarf the file from the end of the command line and
  285.  * return a pointer to it.  If there is no file attached,
  286.  * just return NOSTR.  Put a null in front of the file
  287.  * name so that the message list processing won't see it,
  288.  * unless the file name is the only thing on the line, in
  289.  * which case, return 0 in the reference flag variable.
  290.  */
  291.  
  292. char *
  293. snarf(linebuf, flag)
  294.     char linebuf[];
  295.     int *flag;
  296. {
  297.     register char *cp;
  298.  
  299.     *flag = 1;
  300.     cp = strlen(linebuf) + linebuf - 1;
  301.  
  302.     /*
  303.      * Strip away trailing blanks.
  304.      */
  305.  
  306.     while (*cp == ' ' && cp > linebuf)
  307.         cp--;
  308.     *++cp = 0;
  309.  
  310.     /*
  311.      * Now search for the beginning of the file name.
  312.      */
  313.  
  314.     while (cp > linebuf && !any(*cp, "\t "))
  315.         cp--;
  316.     if (*cp == '\0') {
  317.         printf("No file specified.\n");
  318.         return(NOSTR);
  319.     }
  320.     if (any(*cp, " \t"))
  321.         *cp++ = 0;
  322.     else
  323.         *flag = 0;
  324.     return(cp);
  325. }
  326.  
  327. /*
  328.  * Delete messages.
  329.  */
  330.  
  331. delnorm(msgvec)
  332.     int msgvec[];
  333. {
  334.     return(delm(msgvec));
  335. }
  336.  
  337. /*
  338.  * Delete messages, then type the new dot.
  339.  */
  340.  
  341. deltype(msgvec)
  342.     int msgvec[];
  343. {
  344.     int list[2];
  345.     int lastdot;
  346.  
  347.     lastdot = dot - &message[0] + 1;
  348.     if (delm(msgvec) >= 0) {
  349.         list[0] = dot - &message[0];
  350.         list[0]++;
  351.         if (list[0] > lastdot) {
  352.             touch(list[0]);
  353.             list[1] = NULL;
  354.             return(type(list));
  355.         }
  356.         printf("At EOF\n");
  357.         return(0);
  358.     }
  359.     else {
  360.         printf("No more messages\n");
  361.         return(0);
  362.     }
  363. }
  364.  
  365. /*
  366.  * Delete the indicated messages.
  367.  * Set dot to some nice place afterwards.
  368.  * Internal interface.
  369.  */
  370.  
  371. delm(msgvec)
  372.     int *msgvec;
  373. {
  374.     register struct message *mp;
  375.     register *ip, mesg;
  376.     int last;
  377.  
  378.     last = NULL;
  379.     for (ip = msgvec; *ip != NULL; ip++) {
  380.         mesg = *ip;
  381.         touch(mesg);
  382.         mp = &message[mesg-1];
  383.         mp->m_flag |= MDELETED|MTOUCH;
  384.         mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
  385.         last = mesg;
  386.     }
  387.     if (last != NULL) {
  388.         dot = &message[last-1];
  389.         last = first(0, MDELETED);
  390.         if (last != NULL) {
  391.             dot = &message[last-1];
  392.             return(0);
  393.         }
  394.         else {
  395.             dot = &message[0];
  396.             return(-1);
  397.         }
  398.     }
  399.  
  400.     /*
  401.      * Following can't happen -- it keeps lint happy
  402.      */
  403.  
  404.     return(-1);
  405. }
  406.  
  407. /*
  408.  * Undelete the indicated messages.
  409.  */
  410.  
  411. undelete(msgvec)
  412.     int *msgvec;
  413. {
  414.     register struct message *mp;
  415.     register *ip, mesg;
  416.  
  417.     for (ip = msgvec; ip-msgvec < msgCount; ip++) {
  418.         mesg = *ip;
  419.         if (mesg == 0)
  420.             return;
  421.         touch(mesg);
  422.         mp = &message[mesg-1];
  423.         dot = mp;
  424.         mp->m_flag &= ~MDELETED;
  425.     }
  426. }
  427.  
  428. /*
  429.  * Interactively dump core on "core"
  430.  */
  431.  
  432. core()
  433. {
  434.     register int pid;
  435.     int status;
  436.  
  437.     if ((pid = vfork()) == -1) {
  438.         perror("fork");
  439.         return(1);
  440.     }
  441.     if (pid == 0) {
  442.         sigchild();
  443.         abort();
  444.         _exit(1);
  445.     }
  446.     printf("Okie dokie");
  447.     fflush(stdout);
  448.     while (wait(&status) != pid)
  449.         ;
  450.     if (status & 0200)
  451.         printf(" -- Core dumped\n");
  452.     else
  453.         printf("\n");
  454.     return(0);
  455. }
  456.  
  457. /*
  458.  * Clobber as many bytes of stack as the user requests.
  459.  */
  460. clobber(argv)
  461.     char **argv;
  462. {
  463.     register int times;
  464.  
  465.     if (argv[0] == 0)
  466.         times = 1;
  467.     else
  468.         times = (atoi(argv[0]) + 511) / 512;
  469.     clob1(times);
  470. }
  471.  
  472. /*
  473.  * Clobber the stack.
  474.  */
  475. clob1(n)
  476. {
  477.     char buf[512];
  478.     register char *cp;
  479.  
  480.     if (n <= 0)
  481.         return;
  482.     for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
  483.         ;
  484.     clob1(n - 1);
  485. }
  486.  
  487. /*
  488.  * Add the given header fields to the retained list.
  489.  * If no arguments, print the current list of retained fields.
  490.  */
  491. retfield(list)
  492.     char *list[];
  493. {
  494.     char field[BUFSIZ];
  495.     register int h;
  496.     register struct ignore *igp;
  497.     char **ap;
  498.  
  499.     if (argcount(list) == 0)
  500.         return(retshow());
  501.     for (ap = list; *ap != 0; ap++) {
  502.         istrcpy(field, *ap);
  503.  
  504.         if (member(field, retain))
  505.             continue;
  506.  
  507.         h = hash(field);
  508.         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  509.         igp->i_field = calloc((unsigned) (strlen(field) + 1),
  510.                       sizeof (char));
  511.         strcpy(igp->i_field, field);
  512.         igp->i_link = retain[h];
  513.         retain[h] = igp;
  514.         nretained++;
  515.     }
  516.     return(0);
  517. }
  518.  
  519. /*
  520.  * Print out all currently retained fields.
  521.  */
  522. retshow()
  523. {
  524.     register int h, count;
  525.     struct ignore *igp;
  526.     char **ap, **ring;
  527.     int igcomp();
  528.  
  529.     count = 0;
  530.     for (h = 0; h < HSHSIZE; h++)
  531.         for (igp = retain[h]; igp != 0; igp = igp->i_link)
  532.             count++;
  533.     if (count == 0) {
  534.         printf("No fields currently being retained.\n");
  535.         return(0);
  536.     }
  537.     ring = (char **) salloc((count + 1) * sizeof (char *));
  538.     ap = ring;
  539.     for (h = 0; h < HSHSIZE; h++)
  540.         for (igp = retain[h]; igp != 0; igp = igp->i_link)
  541.             *ap++ = igp->i_field;
  542.     *ap = 0;
  543.     qsort((char *) ring, count, sizeof (char *), igcomp);
  544.     for (ap = ring; *ap != 0; ap++)
  545.         printf("%s\n", *ap);
  546.     return(0);
  547. }
  548.  
  549. /*
  550.  * Add the given header fields to the ignored list.
  551.  * If no arguments, print the current list of ignored fields.
  552.  */
  553. igfield(list)
  554.     char *list[];
  555. {
  556.     char field[BUFSIZ];
  557.     register int h;
  558.     register struct ignore *igp;
  559.     char **ap;
  560.  
  561.     if (argcount(list) == 0)
  562.         return(igshow());
  563.     for (ap = list; *ap != 0; ap++) {
  564.         if (isign(*ap))
  565.             continue;
  566.         istrcpy(field, *ap);
  567.         h = hash(field);
  568.         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  569.         igp->i_field = calloc((unsigned) (strlen(field) + 1),
  570.                       sizeof (char));
  571.         strcpy(igp->i_field, field);
  572.         igp->i_link = ignore[h];
  573.         ignore[h] = igp;
  574.     }
  575.     return(0);
  576. }
  577.  
  578. /*
  579.  * Print out all currently ignored fields.
  580.  */
  581. igshow()
  582. {
  583.     register int h, count;
  584.     struct ignore *igp;
  585.     char **ap, **ring;
  586.     int igcomp();
  587.  
  588.     count = 0;
  589.     for (h = 0; h < HSHSIZE; h++)
  590.         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  591.             count++;
  592.     if (count == 0) {
  593.         printf("No fields currently being ignored.\n");
  594.         return(0);
  595.     }
  596.     ring = (char **) salloc((count + 1) * sizeof (char *));
  597.     ap = ring;
  598.     for (h = 0; h < HSHSIZE; h++)
  599.         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  600.             *ap++ = igp->i_field;
  601.     *ap = 0;
  602.     qsort((char *) ring, count, sizeof (char *), igcomp);
  603.     for (ap = ring; *ap != 0; ap++)
  604.         printf("%s\n", *ap);
  605.     return(0);
  606. }
  607.  
  608. /*
  609.  * Compare two names for sorting ignored field list.
  610.  */
  611. igcomp(l, r)
  612.     char **l, **r;
  613. {
  614.  
  615.     return(strcmp(*l, *r));
  616. }
  617.