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