home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / mush5.7 / part11 / pick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-09-19  |  9.8 KB  |  391 lines

  1. /* @(#)pick.c    2.4    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. static int before, mdy[3], search_from, search_subj, search_to, xflg, icase;
  6.  
  7. do_pick(n, argv, list)
  8. register int n;
  9. register char **argv, list[];
  10. {
  11.     if (n > 1 && !strcmp(argv[1], "-?"))
  12.     return help(0, "pick", cmd_help);
  13.  
  14.     /* if is_pipe, then the messages to search for are already set.
  15.      * if not piped, then reverse the bits for all message numbers.
  16.      * That is, search EACH message. only those matching will be returned.
  17.      */
  18.     if (isoff(glob_flags, IS_PIPE))
  19.     bitput(list, list, msg_cnt, =~) /* macro, turn on all bits */
  20.     if (pick(n, argv, list, isoff(glob_flags, DO_PIPE)) == -1)
  21.     return -1;
  22.     if (isoff(glob_flags, DO_PIPE)) {
  23.     if (istool)
  24.         print("Messages: ");
  25.     for (n = 0; n < msg_cnt; n++)
  26.         if (msg_bit(list, n))
  27.         if (istool)
  28.             print_more("%d ", n+1);
  29.         else
  30.             print("%s\n", compose_hdr(n));
  31.     }
  32.     return 0;
  33. }
  34.  
  35. pick(ret, argv, list, verbose)
  36. register int ret;
  37. register char **argv, list[];
  38. {
  39.     register char c;
  40.     int o_before = before, o_mdy[3], o_search_from = search_from,
  41.     o_search_subj = search_subj, o_search_to = search_to, o_xflg = xflg, n;
  42.     for (c = 0; c < 3; c++)
  43.     o_mdy[c] = mdy[c];
  44.  
  45.     ret = -1;
  46.     if (!msg_cnt) {
  47.     print("No Messages.\n");
  48.     goto bad;
  49.     }
  50.  
  51.     icase = before = mdy[0] = search_from = search_subj = xflg = 0;
  52.     while (*argv && *++argv && **argv == '-')
  53.     switch(c = argv[0][1]) {
  54.         /* users specifies a range */
  55.         case 'r': {
  56.         int X = 2;
  57.         /* if not a pipe, then clear all bits cuz we only want
  58.          * to search the message specified here...
  59.          * If it is a pipe, then add to the messages searched for.
  60.          */
  61.         if (isoff(glob_flags, IS_PIPE))
  62.             clear_msg_list(list);
  63.         /*  "-r10-15"
  64.          *     ^argv[1][2]  if NULL, then
  65.          * list detached from "r" e.g. "-r" "5-20"
  66.          */
  67.         if (!argv[0][X])
  68.             argv++, X = 0;
  69.         (*argv) += X;
  70.         n = get_msg_list(argv, list);
  71.         (*argv) -= X;
  72.         if (n == -1)
  73.             goto bad;
  74.         argv += (n-1); /* we're going to increment another up top */
  75.         }
  76.         when 'd':
  77.         if (!*++argv) {
  78.             print("specify a date for -%c\n", c);
  79.             goto bad;
  80.         }
  81.         if (!date1(*argv))
  82.             goto bad;
  83.         when 's' : case 'f': case 't':
  84.         if (search_subj + search_from + search_to > 1) {
  85.             print("specify one of `s', `f' or `t' only\n");
  86.             goto bad;
  87.             }
  88.             if (c == 's')
  89.             search_subj = 1;
  90.         else if (c == 'f')
  91.             search_from = 1;
  92.         else
  93.             search_to = 1;
  94.         when 'x' : xflg = 1;
  95.         when 'i' : icase = 1;
  96.         otherwise:
  97.         print("pick: unknown flag: %c\n", argv[0][1]);
  98.         clear_msg_list(list);
  99.         return -1;
  100.     }
  101.     if (verbose) {
  102.     print_more("Searching for messages");
  103.     if (mdy[1] == 0)
  104.         print(" that %s \"%s\"", (xflg)? "doesn't contain": "contains",
  105.                 (*argv)? *argv: "<previous expression>");
  106.     if (search_subj)
  107.         print_more(" in subject line");
  108.     else if (search_from)
  109.         print_more(" from author names");
  110.     else if (search_to)
  111.         print_more(" from the To: field");
  112.     if (mdy[1] > 0) {
  113.         extern char *month_names[]; /* from dates.c */
  114.         print_more(" dated on or %s %s. %d, 19%d.",
  115.           (before)? "before": "after",
  116.           month_names[mdy[0]], mdy[1], mdy[2]);
  117.     }
  118.     print_more("\n");
  119.     }
  120.     if (mdy[1] > 0 && icase)
  121.     print("using date: -i flag ignored.\n");
  122.     ret = find_pattern(*argv, list);
  123. bad:
  124.     before = o_before, search_from = o_search_from,
  125.     search_subj = o_search_subj, search_to = o_search_to, xflg = o_xflg;
  126.     for (c = 0; c < 3; c++)
  127.     mdy[c] = o_mdy[c];
  128.     return ret;
  129. }
  130.  
  131. find_pattern(p, list)
  132. register char *p, list[];
  133. {
  134.     register int n, val, i; /* val is return value from regex or re_exec */
  135.     long bytes = 0;
  136.     char buf[BUFSIZ];
  137.     static char *err = (char *)-1;
  138. #ifndef SYSV
  139.     char *re_comp();
  140. #else
  141.     char *regcmp(), *regex();
  142. #endif SYSV
  143.  
  144.     if (p && *p == '\\')
  145.     p++;  /* take care of escaping special cases (`-', `\') */
  146.  
  147.     /* specify what we're looking for */
  148.     if (p && *p) {
  149.     if (icase)
  150.         p = lcase_strcpy(buf, p);
  151. #ifndef SYSV
  152.     if (err = re_comp(p)) {
  153.         print("re_comp error: %s\n", err);
  154.         clear_msg_list(list);
  155.         return -1;
  156.     }
  157. #else
  158.     if (err && p)
  159.         xfree(err);
  160.     if (p && !(err = regcmp(p, NULL))) {
  161.         print("regcmp error: %s\n", p);
  162.         clear_msg_list(list);
  163.         return -1;
  164.     }
  165. #endif SYSV
  166.     } else if (err == (char *)-1 && mdy[1] <= 0) {
  167.     print("No previous regular expression\n");
  168.     clear_msg_list(list);  /* doesn't matter really */
  169.     return -1;
  170.     }
  171.     /* start searching: set bytes, and message number: n */
  172.     for (n = 0; n < msg_cnt; n++)
  173.     if (msg_bit(list, n)) {
  174.         if (mdy[1] > 0) {
  175.         int msg_mdy[3];
  176.         if (!(p = msg_date(n))) {
  177.             unset_msg_bit(list, n);
  178.             continue; /* error: don't consider this message */
  179.         }       /* yr mo da */
  180.         (void) sscanf(p, "%2d%2d%2d",
  181.              &msg_mdy[2], &msg_mdy[0], &msg_mdy[1]);
  182.         msg_mdy[0]--;
  183.         Debug("checking %d's date: %d-%d-%d  ",
  184.                  n+1, msg_mdy[0]+1, msg_mdy[1], msg_mdy[2]);
  185.         /* start at year and wrap around.
  186.          * only when match the day (4), check for == (match)
  187.          */
  188.         for (i = 2; i < 5; i++)
  189.             if (before && msg_mdy[i%3] < mdy[i%3]
  190.             || !before && msg_mdy[i%3] > mdy[i%3]
  191.             || i == 4 && (msg_mdy[i%3] == mdy[i%3])) {
  192.                 Debug("matched (%s).\n",
  193.                 (i == 2)? "year" : (i == 3)? "month" : "day");
  194.                 break;
  195.             } else if (msg_mdy[i%3] != mdy[i%3]) {
  196.             Debug("failed.\n");
  197.             unset_msg_bit(list, n);
  198.             break;
  199.             }
  200.         continue;
  201.         }
  202.         /* we must have the right date -- if we're searching for a
  203.          * string, find it.
  204.          */
  205.         (void) fseek(tmpf, msg[n].m_offset, L_SET);
  206.         bytes = 0;
  207.         while (bytes < msg[n].m_size) {
  208.         if (!search_subj && !search_from && !search_to &&
  209.                 !(p = fgets(buf, BUFSIZ, tmpf)))
  210.             break;
  211.         else if (search_subj) {
  212.             if (!(p = header_field(n, "subject"))) {
  213.             unset_msg_bit(list, n);
  214.             break;
  215.             }
  216.         } else if (search_from) {
  217.             if (!(p = header_field(n, "from"))) {
  218.             register char *p2;
  219.             (void) fseek(tmpf, msg[n].m_offset, L_SET);
  220.             p2 = fgets(buf, BUFSIZ, tmpf);
  221.             p = index(p2, ' '), p++;
  222.             if (p2 = any(p, " \t"))
  223.                 *p2 = 0;
  224.             }
  225.         } else if (search_to) {
  226.             if (!(p = header_field(n, "to"))) {
  227.             unset_msg_bit(list, n);
  228.             break;
  229.             }
  230.         }
  231.         if (icase)
  232.             p = lcase_strcpy(buf, p);
  233. #ifndef SYSV
  234.         val = re_exec(p);
  235. #else
  236.         val = !!regex(err, p, NULL); /* convert value to a boolean */
  237. #endif SYSV
  238.         if (val == -1) {   /* doesn't apply in system V */
  239.             print("Internal error for pattern search.\n");
  240.             clear_msg_list(list); /* it doesn't matter, really */
  241.             return -1;
  242.         }
  243.         if (xflg)
  244.             val = !val;
  245.         if (!val) {
  246.             /* unset the bit if match failed. If it matches later
  247.              * in the search, we'll reset to true in the next iteration.
  248.              * this doesn't apply for author or subject picks.
  249.              */
  250.             unset_msg_bit(list, n);
  251.             bytes += strlen(p);
  252.         } else {
  253.             set_msg_bit(list, n);
  254.             break;
  255.         }
  256.         if (search_subj || search_from || search_to)
  257.             break;
  258.         }
  259.     }
  260.     return 0;
  261. }
  262.  
  263. #ifdef CURSES
  264. /*
  265.  * search for a pattern in composed message headers -- also see next function
  266.  * flags ==  0   forward search (prompt).
  267.  * flags == -1   continue search (no prompt).
  268.  * flags ==  1   backward search (prompt).
  269.  */
  270. search(flags)
  271. register int flags;
  272. {
  273.     register char   *p;
  274.     char           pattern[128];
  275.     register int    this_msg = current_msg, val = 0;
  276.     static char     *err = (char *)-1, direction;
  277.     int            (*oldint)(), (*oldquit)();
  278. #ifndef SYSV
  279.     char *re_comp();
  280. #else SYSV
  281.     char *regcmp();
  282. #endif SYSV
  283.  
  284.     if (msg_cnt <= 1) {
  285.     print("Not enough messages to invoke a search.\n");
  286.     return 0;
  287.     }
  288.     pattern[0] = '\0';
  289.     if (flags == -1)
  290.     print("continue %s search...", direction? "forward" : "backward");
  291.     else
  292.     print("%s search: ", flags? "backward" : "forward");
  293.     if (flags > -1)
  294.     if (Getstr(pattern, COLS-18, 0) < 0)
  295.         return 0;
  296.     else
  297.         direction = !flags;
  298. #ifndef SYSV
  299.     if (err = re_comp(pattern)) {
  300.     print(err);
  301.     return 0;
  302.     }
  303. #else
  304.     if (err && *pattern)
  305.     xfree(err);
  306.     else if (err == (char *)-1 && !*pattern) {
  307.     print("No previous regular expression.");
  308.     return 0;
  309.     }
  310.     if (*pattern && !(err = regcmp(pattern, NULL))) {
  311.     print("Error in regcmp in %s", pattern);
  312.     return 0;
  313.     }
  314. #endif SYSV
  315.     move(LINES-1, 0), refresh();
  316.     on_intr();
  317.  
  318.     do  {
  319.     if (direction)
  320.         current_msg = (current_msg+1) % msg_cnt;
  321.     else
  322.         if (--current_msg < 0)
  323.         current_msg = msg_cnt-1;
  324.         p = compose_hdr(current_msg);
  325. #ifndef SYSV
  326.     val = re_exec(p);
  327. #else
  328.     val = !!regex(err, p, NULL); /* convert value to a boolean */
  329. #endif SYSV
  330.     if (val == -1)     /* doesn't apply in system V */
  331.         print("Internal error for pattern search.\n");
  332.     } while (!val && current_msg != this_msg && isoff(glob_flags, WAS_INTR));
  333.  
  334.     if (ison(glob_flags, WAS_INTR)) {
  335.     print("Pattern search interruped.");
  336.     current_msg = this_msg;
  337.     } else if (val == 0)
  338.     print("Pattern not found.");
  339.  
  340.     off_intr();
  341.     return val;
  342. }
  343. #endif CURSES
  344.  
  345. /*
  346.  * parse a user given date string and set mdy[] array with correct
  347.  * values.  Return 0 on failure.
  348.  */
  349. date1(p)
  350. register char *p;
  351. {
  352.     register char *p2;
  353.     long      t;
  354.     int       i;
  355.     struct tm       *today;
  356.  
  357.     if (*p == '-') {
  358.     before = 1;
  359.     skipspaces(1);
  360.     }
  361.     if (!isdigit(*p) && *p != '/') {
  362.     print("syntax error on date: \"%s\"\n", p);
  363.     return 0;
  364.     }
  365.     (void) time (&t);
  366.     today = localtime(&t);
  367.     for (i = 0; i < 3; i++)
  368.     if (!p || !*p || *p == '/') {
  369.         switch(i) {   /* default to today's date */
  370.         case 0: mdy[0] = today->tm_mon;
  371.         when 1: mdy[1] = today->tm_mday;
  372.         when 2: mdy[2] = today->tm_year;
  373.         }
  374.         if (p && *p)
  375.         p++;
  376.     } else {
  377.         p2 = (*p)? index(p+1, '/') : NULL;
  378.         mdy[i] = atoi(p); /* atoi will stop at the '/' */
  379.         if (i == 0 && (--(mdy[0]) < 0 || mdy[0] > 11)) {
  380.         print("Invalid month: %s\n", p);
  381.         return 0;
  382.         } else if (i == 1 && (mdy[1] < 1 || mdy[1] > 31)) {
  383.         print("Invalid day: %s\n", p);
  384.         return 0;
  385.         }
  386.         if (p = p2) /* set p to p2 and check to see if it's valid */
  387.         p++;
  388.     }
  389.     return 1;
  390. }
  391.