home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / mush5.7 / part07 / misc.c < prev   
Encoding:
C/C++ Source or Header  |  1987-09-17  |  21.0 KB  |  867 lines

  1. /* @(#)misc.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. /* check to see if a string describes a message that is within the range of
  6.  * all messages; if invalid, return 0 and print error. else return msg number
  7.  */
  8. chk_msg(s)
  9. register char *s;
  10. {
  11.     register int n;
  12.  
  13.     if ((n = atoi(s)) > 0 && n <= msg_cnt)
  14.     return n;
  15.     else if (*s == '^' && msg_cnt)
  16.     return 1;
  17.     else if (*s == '$' && msg_cnt)
  18.     return msg_cnt;
  19.     else if (*s == '.' && msg_cnt)
  20.     return current_msg+1;
  21.     print("Invalid message number: %s\n", s);
  22.     return 0;
  23. }
  24.  
  25. /*
  26.  * loop thru all msgs starting with current_msg and find next message whose
  27.  * m_flags has the "flags" bit being on
  28.  */
  29. next_msg(on, flags)
  30. {
  31.     register int n = current_msg;
  32.     if (!msg_cnt)
  33.     return current_msg = 0;
  34.     for (n++; n != current_msg; n++)
  35.     if (n == msg_cnt)     /* hit the end, start back at the beginning */
  36.         n = -1; /* increments to 0 in  loop  */
  37.     else if (isoff(msg[n].m_flags, DELETE) &&
  38.         ((on && ison(msg[n].m_flags, flags)) ||
  39.         (!on && isoff(msg[n].m_flags, flags))))
  40.         return current_msg = n;
  41.     return current_msg = 0;
  42. }
  43.  
  44. /* takes string 'p' and address of int (isdir).  If p uses the ~ to reference
  45.  * a home directory of somesort, then expand it.  find out what sort of
  46.  * file final path is. set isidr to 1 if a directory, 0 if not, -1 on error
  47.  * return final path. If an error occurrs, return string indicating error.
  48.  * if isdir has a value of 1 when passed, it ignores "No such file or directory"
  49.  */
  50. #include <pwd.h>
  51. char *
  52. getpath(p, isdir)
  53. register char *p;
  54. int *isdir;
  55. {
  56.     static char buf[256];
  57.     struct stat stat_buf;
  58.  
  59.     if (!p || !*p || !strcmp(p, "~")) {
  60.     char *home = do_set(set_options, "home");
  61.     if (!home || !*home)
  62.         home = ALTERNATE_HOME;
  63.     (void) strcpy(buf, home);  /* no arg means home */
  64.     } else if (*p == '~') {
  65.     if (p[1] != '/') {
  66.         /* not our home, but someone else's
  67.          * look for ~user or ~user/subpath
  68.          * if '/' exists, separate into tmp="user" p="subpath"
  69.          */
  70.         struct passwd *ent, *getpwnam();
  71.         char *p2 = p+1;
  72.         if (p = index(p2, '/'))
  73.         *p++ = 0;
  74.         if (!(ent = getpwnam(p2))) {
  75.         *isdir = -1;
  76.         return sprintf(buf, "no such user: %s", p2);
  77.         }
  78.         /* append subpath to pathname */
  79.         if (p && *p)
  80.         (void) sprintf(buf, "%s/%s", ent->pw_dir, p);
  81.         /* if *p == NULL, pathname is done (buf), set isdir = 1 */
  82.         else {
  83.         *isdir = 1;
  84.         return strcpy(buf, ent->pw_dir);
  85.         }
  86.     } else {
  87.         char *home = do_set(set_options, "home");
  88.         if (!home || !*home)
  89.         home = ALTERNATE_HOME;
  90.         (void) sprintf(buf, "%s/%s", home, p+2);
  91.     }
  92.     } else if (*p == '%') {
  93.     /* if %user, append user name... else, it's just us */
  94.     (void) sprintf(buf, "%s/", MAILDIR);
  95.     if (!*++p || *p == ' ' || *p == '\t')
  96.         (void) strcat(buf, login);
  97.     else
  98.         (void) strcat(buf, p);
  99.     } else if (*p == '+') {
  100.     register char *p2 = do_set(set_options, "folder");
  101.     if (p2 && *p2)
  102.         (void) sprintf(buf, "%s/%s", p2, ++p);
  103.     else
  104.         (void) sprintf(buf, "~/%s", p);
  105.     if (*buf == '~') {
  106.         int t_isdir = *isdir;
  107.         char *t, tmp[256];
  108.         (void) strcpy(tmp, buf);
  109.         t = getpath(tmp, &t_isdir);
  110.         if (t_isdir == -1) {
  111.         *isdir = -1;
  112.         return t;
  113.         }
  114.         /* strcpy(buf, t); --buf already has info because it's static */
  115.     }
  116.     } else {  /* allow \ to escape the special chars, +, %, ~ */
  117.     if (*p == '\\')
  118.         p++;
  119.     (void) strcpy(buf, p);
  120.     }
  121.     if (stat(buf, &stat_buf)) {
  122.     (void) access(buf, 0); /* set errno to the "real" reason */
  123.     if (errno == ENOENT && *isdir == 1) {
  124.         *isdir = 0; /* say it's a regular file even tho it doesn't exist */
  125.         return buf; /* it may be wanted for creating */
  126.     }
  127.     *isdir = -1;
  128.     return sys_errlist[errno];
  129.     }
  130.     *isdir = ((stat_buf.st_mode & S_IFDIR) != 0);
  131.     return buf;
  132. }
  133.  
  134. /*
  135.  * Given a filename[pointer] (p), a file pointer, and a mode, file_to_fp
  136.  * opens the file with the mode.
  137.  * If the mode is "r" then we read the file into the file pointer at the
  138.  * end (fseek(fp, 2, 0)).  If the file is opened for writing, then read
  139.  * from the beginning of fp and write it into the file.
  140.  * This is usually called to read .signatures into messages (thus,
  141.  * opening .signture with "r" and writing to the end of fp which is probably
  142.  * the sendmail process or the message file pointer) or to write fortunes into
  143.  * the message buffer: reading fp (the popened fortune) and writing into file.
  144.  */
  145. void
  146. file_to_fp(p, fp, mode)
  147. register char *p;
  148. register FILE *fp;
  149. char *mode;
  150. {
  151.     int     x = 1;
  152.     char     *file, buf[BUFSIZ];
  153.     FILE     *tmp_fp;
  154.  
  155.     if (!p || !*p) {
  156.     print("specify filename");
  157.     return;
  158.     }
  159.     file = getpath(p, &x);
  160.     if (x == -1) { /* on error, file contains error message */
  161.     wprint(file);
  162.     return;
  163.     }
  164.     wprint("%s: ", file), fflush(stdout);
  165.     if (x)   /* if x == 1, then path is a directory */
  166.     wprint("directory.\n");
  167.     else if (!(tmp_fp = fopen(file, mode))) {
  168.     wprint("%s\n", sys_errlist[errno]);
  169.     return;
  170.     } else if (*mode != 'r') {
  171.     rewind(fp);
  172.     for(x = 0; fgets(buf, BUFSIZ, fp); x++)
  173.         fputs(buf, tmp_fp);
  174.     } else
  175.     for(x = 0; fgets(buf, BUFSIZ, tmp_fp); x++)
  176.         fputs(buf, fp);
  177.     wprint("%s%d line%s\n", (*mode == 'a')? "added ": "",
  178.                   x, (x == 1)? "": "s");
  179.     fflush(fp);
  180.     fclose(tmp_fp);
  181. }
  182.  
  183. /*
  184.  * lose the newline character, trailing whitespace, and return the end of p
  185.  * test for '\n' separately since some _ctype_[] arrays may not have the
  186.  * _S bit set for the newline character.  see <ctype.h> for more info.
  187.  */
  188. char *
  189. no_newln(p)
  190. register char *p;
  191. {
  192.     register char *p2 = p + strlen(p);    /* point it to the null terminator */
  193.  
  194.     while (p2 > p && *--p2 == '\n' || isspace(*p2))
  195.     *p2 = 0;  /* get rid of newline and trailing spaces */
  196.     return p2;
  197. }
  198.  
  199. /* find any character in string2 that's in string1 */
  200. char *
  201. any(s1, s2)
  202. register char *s1, *s2;
  203. {
  204.     register char *p;
  205.     if (!s1 || !*s1 || !s2 || !*s2)
  206.     return NULL;
  207.     for( ; *s1; s1++) {
  208.     for(p = s2; *p; p++)
  209.         if (*p == *s1)
  210.         return s1;
  211.     }
  212.     return NULL;
  213. }
  214.  
  215. /* since print_help just prints help, always return help() */
  216. print_help(argc, argv)
  217. register char **argv;
  218. {
  219. #ifdef SUNTOOL
  220.     if (istool)
  221.     return help(tool->tl_windowfd, "general", tool_help);
  222. #endif SUNTOOL
  223.     if (!argc || !*++argv)
  224.     return help(0, "general", cmd_help);
  225.     return help(0, *argv, cmd_help);
  226. }
  227.  
  228. /* since this function does not affect messages, return -1 */
  229. help(fd, str, file)
  230. #ifdef SUNTOOL
  231. caddr_t *str;
  232. #else
  233. char *str;
  234. #endif /* SUNTOOL */
  235. char *file;
  236. {
  237. #ifdef SUNTOOL
  238.     if (istool > 1) {
  239.     int oldmask;
  240.     if (!fd)
  241.         fd = print_sw->ts_windowfd;
  242.     oldmask = sigblock(1 << ((SIGALRM) - 1));
  243.     lock_cursors();
  244.     if (display_help(fd, str, file, fonts[LARGE]) && file)
  245.         error("can't read %s", file);
  246.     unlock_cursors();
  247.     (void) sigsetmask(oldmask);
  248.     } else
  249. #endif SUNTOOL
  250.     if (find_help(str, file) && file)
  251.     error("can't read %s", file);
  252.     return -1; /* doesn't affect any messages */
  253. }
  254.  
  255. #ifdef SUNTOOL
  256. void
  257. unlock_cursors()
  258. {
  259.     if (istool < 2)
  260.     return;
  261.     win_setcursor(print_sw->ts_windowfd, &main_cursor);
  262.     win_setcursor(panel_sw->ts_windowfd, &main_cursor);
  263.     if (getting_opts)
  264.     win_setcursor(msg_sw->ts_windowfd, &checkmark);
  265.     else if (ison(glob_flags, IS_GETTING))
  266.     win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  267.     else
  268.     win_setcursor(msg_sw->ts_windowfd, &read_cursor);
  269.     win_setcursor(hdr_panel_sw->ts_windowfd, &main_cursor);
  270.     win_setcursor(hdr_sw->ts_windowfd, &l_cursor);
  271. }
  272.  
  273. void
  274. lock_cursors()
  275. {
  276.     if (istool < 2)
  277.     return;
  278.     win_setcursor(hdr_sw->ts_windowfd, &coffee);
  279.     win_setcursor(print_sw->ts_windowfd, &coffee);
  280.     win_setcursor(panel_sw->ts_windowfd, &coffee);
  281.     win_setcursor(msg_sw->ts_windowfd, &coffee);
  282.     win_setcursor(hdr_panel_sw->ts_windowfd, &coffee);
  283. }
  284.  
  285. #include <suntool/fullscreen.h>
  286. /* return the event-id that confirmed */
  287. confirm(fd)
  288. {
  289.     struct fullscreen *fs;
  290.  
  291.     struct inputmask im;
  292.     struct inputevent event;
  293.  
  294.     fs = fullscreen_init(fd);
  295.     input_imnull(&im);
  296.     im.im_flags |= IM_ASCII;
  297.     win_setinputcodebit(&im, MS_LEFT);
  298.     win_setinputcodebit(&im, MS_MIDDLE);
  299.     win_setinputcodebit(&im, MS_RIGHT);
  300.     win_setinputmask(fd, &im, &im, WIN_NULLLINK);
  301.     win_setcursor(fd, &l_cursor);
  302.     if (input_readevent(fd, &event) == -1)
  303.     error("confim failed");
  304.     fullscreen_destroy(fs);
  305.     return ID;
  306. }
  307. #endif SUNTOOL
  308.  
  309. /* check two lists of strings each of which contain substrings.
  310.  * Each substring is delimited by any char in "delimeters"
  311.  * return true if any elements in list1 are on list2.
  312.  * thus:
  313.  * string1 = "foo, bar, baz"
  314.  * string2 = "foobar, baz, etc"
  315.  * delimeters = ", \t"
  316.  * example returns 1 because "baz" exists in both lists
  317.  * NOTE: case is ignored.
  318.  */
  319. chk_two_lists(list1, list2, delimeters)
  320. register char *list1, *list2, *delimeters;
  321. {
  322.     register char *p, c;
  323.     register int found = 0;
  324.  
  325.     if (p = any(list1, delimeters)) {
  326.     for (p++; *p && index(delimeters, *p); p++)
  327.         ;
  328.     if (chk_two_lists(p, list2, delimeters))
  329.         return 1;
  330.     }
  331.     if (p = any(list2, delimeters)) {
  332.     for (p++; *p && index(delimeters, *p); p++)
  333.         ;
  334.     if (chk_two_lists(list1, p, delimeters))
  335.         return 1;
  336.     }
  337.     if (p) {
  338.     while (index(delimeters, *(p-1)))
  339.         --p;
  340.     c = *p, *p = 0;
  341.     }
  342.     found = !lcase_strcmp(list1, list2);
  343.     if (p)
  344.     *p = c;
  345.     return found;
  346. }
  347.  
  348. bzero(addr, size)
  349. register char *addr;
  350. register int size;
  351. {
  352.     while (size-- > 0)
  353.     addr[size] = 0;
  354. }
  355.  
  356. /* see if there are at least Max lines in this file. return lines less than Max
  357.  * that actually *are* in the file
  358.  */
  359. lines_in(fp, Max)
  360. register FILE *fp;
  361. register int Max;
  362. {
  363.     char tmp[BUFSIZ];
  364.     long place_in_fp = ftell(fp);
  365.     rewind(fp);
  366.     while (Max > 0 && fgets(tmp, BUFSIZ, fp))
  367.     Max--;
  368.     (void) fseek(fp, place_in_fp, 0);
  369.     return Max;
  370. }
  371.  
  372. /* clear all contents of the file.  Careful that the file is opened for
  373.  * _writing_ --tempfile is opened for reading, so don't try to empty it
  374.  * if you're using ftruncate.   Return -1 on error, 0 on success.
  375.  */
  376. emptyfile(fp, fname)
  377. register FILE **fp;
  378. register char *fname;
  379. {
  380.     Debug("Emptying \"%s\"\n", fname);
  381. #ifndef SYSV
  382.     return ftruncate(fileno(*fp), 0);
  383. #else
  384.     {
  385.     int omask = umask(077), ret;
  386.     fclose(*fp);
  387.     if (!(*fp = fopen(fname, "w")))
  388.         ret = -1;
  389.     ret = 0;
  390.     (void) umask(omask);
  391.     return ret;
  392.     }
  393. #endif SYSV
  394. }
  395.  
  396. /* do an atoi() on the string passed and return in "val" the decimal value.
  397.  * the function returns a pointer to the location in the string that is not
  398.  * a digit.
  399.  */
  400. char *
  401. my_atoi(p, val)
  402. register char *p;
  403. register int *val;
  404. {
  405.     if (!p)
  406.     return NULL;
  407.     *val = 0;
  408.     while (isdigit(*p))
  409.     *val = (*val) * 10 + *p++ - '0';
  410.     return p;
  411. }
  412.  
  413. /* strcmp ignoring case */
  414. lcase_strcmp(str1, str2)
  415. register char *str1, *str2;
  416. {
  417.     while (*str1 && *str2)
  418.     if (lower(*str1) != lower(*str2))
  419.         break;
  420.     else
  421.         str1++, str2++;
  422.     return *str1 - *str2;
  423. }
  424.  
  425. /* strcpy coverting everything to lower case (arbitrary) to ignore cases */
  426. char *
  427. lcase_strcpy(dst, src)
  428. register char *dst, *src;
  429. {
  430.     register char *s = dst;
  431.  
  432.     /* "lower" is a macro, don't incrment its argument! */
  433.     while (*dst++ = lower(*src))
  434.     src++;
  435.     return s;
  436. }
  437.  
  438. /* this strcpy returns number of bytes copied */
  439. Strcpy(dst, src)
  440. register char *dst, *src;
  441. {
  442.     register int n = 0;
  443.     if (!dst || !src)
  444.     return 0;
  445.     while (*dst++ = *src++)
  446.     n++;
  447.     return n;
  448. }
  449.  
  450. void
  451. xfree(cp)
  452. char *cp;
  453. {
  454.     extern char end[];
  455.  
  456.     if (cp >= end && cp < (char *) &cp && debug < 2)
  457.     free(cp);
  458. }
  459.  
  460. char *
  461. savestr(s)
  462. register char *s;
  463. {
  464.     register char *p;
  465.     char *malloc();
  466.     if (!s)
  467.     s = "";
  468.     if (!(p = malloc((unsigned) (strlen(s) + 1)))) {
  469.     error("out of memory saving %s", s);
  470.     return NULL;
  471.     }
  472.     return strcpy(p, s);
  473. }
  474.  
  475. void
  476. free_vec(argv)
  477. char **argv;
  478. {
  479.     register int n;
  480.     if (!argv)
  481.     return;
  482.     for (n = 0; argv[n]; n++)
  483.     xfree(argv[n]);
  484.     xfree((char *)argv);
  485. }
  486.  
  487. /* copy a vector of stirngs into one string -- return the end of the string */
  488. char *
  489. argv_to_string(p, argv)
  490. register char *p, **argv;
  491. {
  492.     register int i;
  493.     register char *ptr = p;
  494.  
  495.     *p = 0;
  496.     if (!argv[0])
  497.     return "";
  498.     for (i = 0; argv[i]; i++)
  499.     ptr += strlen(sprintf(ptr, "%s ", argv[i]));
  500.     *--ptr = 0;   /* get rid of the last space */
  501.     return ptr;
  502. }
  503.  
  504. /* echo the command line. return -1 cuz no messages are affected */
  505. do_echo(argc, argv)
  506. register char **argv;
  507. {
  508.     char buf[BUFSIZ];
  509.     int no_return;
  510.  
  511.     if (argc > 1 && !strcmp(argv[1], "-?")) {
  512.     print("usage: %s [-n] ...\n", *argv);
  513.     return -1;
  514.     }
  515.     no_return = *++argv && !strcmp(*argv, "-n");
  516.     (void) argv_to_string(buf, argv+no_return);
  517.     print("%s%s", buf, (no_return)? "" : "\n");
  518.     return -1;
  519. }
  520.  
  521. /* return -1 on error or number of arguments in argv that were parsed */
  522. get_msg_list(argv, list)
  523. register char **argv;
  524. char list[];
  525. {
  526.     register char *p2, *p;
  527.     char buf[256];
  528.     register int n;
  529.  
  530.     if (!msg_cnt) {
  531.     print("No messages.\n");
  532.     return -1;
  533.     }
  534.     if (!argv || !*argv) {
  535.     if (isoff(glob_flags, IS_PIPE))
  536.         set_msg_bit(list, current_msg);
  537.     return 0;
  538.     }
  539.     /* first, stuff argv's args into a single char array buffer */
  540.     (void) argv_to_string(buf, argv);
  541.     p = buf;
  542.     Debug("get_msg_list: parsing: (%s): ", p);
  543.     /*
  544.      * if do_range returns NULL, an invalid message was specified
  545.      */
  546.     if (!(p2 = do_range(p, list)))
  547.     return -1;
  548.     /*
  549.      * if p2 == p (and p isn't $ or ^ or .), then no message list was
  550.      * specified.  set the current message in such cases if we're not piping
  551.      */
  552.     if (p2 == p) {
  553.     if (*p == '$')
  554.         set_msg_bit(list, msg_cnt-1);
  555.     else if (*p == '^')
  556.         set_msg_bit(list, 0);
  557.     else if (*p == '.' || isoff(glob_flags, IS_PIPE))
  558.         set_msg_bit(list, current_msg);
  559.     } else if (ison(glob_flags, IS_PIPE)) {
  560.     print("You can't pipe to a command *and* specifiy a msg_list\n");
  561.     return -1;
  562.     }
  563.     for (n = 0; p2 > p && *argv; n++)
  564.     p2 -= (strlen(*argv++)+1);
  565.     Debug("parsed %d args\n", n);
  566.     return n;
  567. }
  568.  
  569. char *
  570. itoa(n)
  571. {
  572.     static char buf[10];
  573.     return sprintf(buf, "%d", n);
  574. }
  575.  
  576. #ifdef NOT_NEEDED_NOW
  577. /* return whether or not this process is in the foreground or background */
  578. foreground()
  579. {
  580. #ifdef TIOCGPGRP
  581.     int tpgrp;    /* short in 4.1, int in 4.2 */
  582.  
  583.     if (ioctl(0, TIOCGPGRP, (char *)&tpgrp))
  584.     return 0;
  585.     return tpgrp == getpgrp(0);
  586. #else
  587.     return 1;
  588. #endif TIOCGPGRP
  589. }
  590. #endif NOT_NEEDED_NOW
  591.  
  592. #ifdef SYSV
  593. char *
  594. Sprintf(buf, fmt, args)
  595. register char *buf, *fmt;
  596. {
  597.     vsprintf(buf, fmt, &args);
  598.     return buf;
  599. }
  600. #endif /* SYSV */
  601.  
  602. /*
  603.  * Finds out how many file descriptors are opened.  Useful for making sure
  604.  * no files got opened in subprocedures which were not subsequently closed.
  605.  */
  606. nopenfiles(argc)
  607. {
  608.     register int nfiles = 0;
  609. #ifdef MAXFILES
  610.     register int size = MAXFILES;
  611. #else
  612.     register int size = getdtablesize();
  613. #endif MAXFILES
  614.  
  615.     if (argc < 2)
  616.     print("open file descriptors:");
  617.     while (--size >= 0)
  618.         if (fcntl(size, F_GETFL, 0) != -1) {
  619.         if (argc < 2)
  620.         print_more(" %d", size);
  621.             ++nfiles;
  622.         }
  623.     if (argc < 2)
  624.     print("\n");
  625.     return nfiles;
  626. }
  627.  
  628. /*
  629.  * Open a path for writing or appending -- return a FILE pointer.
  630.  * If program is TRUE, then use popen, not fopen and don't check 
  631.  * to see if the file is writable.
  632.  */
  633. FILE *
  634. open_file(p, program)
  635. register char *p;
  636. {
  637.     register FILE *newfile = NULL_FILE;
  638.     register char *tmp;
  639.     int x = 1;
  640.  
  641.     tmp = getpath(p, &x);
  642.     if (x == 1)
  643.     print("%s is a directory.\n", tmp);
  644.     else if (x == -1)
  645.     print("%s: %s\n", p, tmp);
  646.     else {
  647.     register char *mode = NULL;
  648.     /* if it doesn't exist open for "w" */
  649.     if (program || access(tmp, 0))
  650.         mode = "w";
  651.     /* if we can't write to it, forget it */
  652.     else if (access(tmp, 2))
  653.         error(tmp);
  654.     else
  655.         mode = "a";
  656.     if (mode)
  657.         if (program) {
  658.         if (!(newfile = popen(tmp, mode))) {
  659.             error("Can't execute %s\n", tmp);
  660.             return newfile;
  661.         }
  662.         } else
  663.         if (!(newfile = fopen(tmp, mode)))
  664.             error("Can't write to %s", tmp);
  665.         else
  666.         Debug("Successfully opened %s\n", tmp);
  667.     }
  668.     return newfile;
  669. }
  670.  
  671. /*
  672.  * find_files gets a string of space/comma delimeted words and an array of
  673.  * file pointers and the maximum size that array can be.
  674.  * The object is to find the files or programs listed in "p", attempt
  675.  * to fopen/popen them and save their filepointers in the array. If the
  676.  * size is 0, then just extract the file names and give error messages
  677.  * for each one since they will not be opened. Return the number of
  678.  * files opened and delete all files (opened or not) from the list in
  679.  * "p".  Tokens beginning with a "/, ~, or + are files; tokens beginning
  680.  * with a | are programs.
  681.  */
  682. find_files(p, files, size)
  683. register char *p;
  684. FILE *files[];
  685. {
  686.     register int     total = 0;
  687.     char          file[BUFSIZ], *start = p;
  688.     register char    *p2, *s;
  689.  
  690.     for (s = p; p = any(s, "~+/|"); s = p) {
  691.     int prog = 0;
  692.  
  693.     /* If there is no space or comma before this address, then
  694.      * it's not the beginning of an address, but part of another.
  695.      * Ignore this addres and continue to the next in the list.
  696.      */
  697.     if (p > start && *(p-1) != ',' && !isspace(*(p-1))) {
  698.         p++; /* prevent inifinite loop -- resume starting at next char */
  699.         continue;
  700.     }
  701.  
  702.     /* get the whole filename, stick it in "file" */
  703.     if (p2 = any(p, ", \t"))
  704.         *p2++ = '\0';
  705.     else
  706.         p2 = p + strlen(p);
  707.     (void) strcpy(file, p);
  708.     /* overwrite the filename in the string with whatever proceeds it */
  709.     while (isspace(*p2)) /* move to the next address (or end of string) */
  710.         p2++;
  711.     if (*p2)
  712.         (void) strcpy(p, p2);
  713.     else
  714.         do
  715.         *p = '\0';
  716.         while (--p >= start && (isspace(*p) || *p == ','));
  717.  
  718.     if (*file == '|')
  719.         prog = 1; /* it's a program name */
  720.     if (size && total < size) {
  721.         /* either open "file" or &file[1] */
  722.         if (files[total] = open_file(&file[prog], prog))
  723.         total++;
  724.     } else
  725.         print("No open space for %s\n", file);
  726.     skipspaces(0);
  727.     }
  728.     return total;
  729. }
  730.  
  731. /*
  732.  * execute a command from a string.  f'rinstance: "pick -f foobar"
  733.  * The string is made into an argv and then run.  Errors are printed
  734.  * if the command failed to make.
  735.  *   NOTES:
  736.  *     NEVER pass stright text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...")
  737.  *     no history is expanded (ignore_bang).
  738.  */
  739. cmd_line(buf, list)
  740. char buf[], list[];
  741. {
  742.     register char **argv;
  743.     int argc, ret_val = -1;
  744.     long save_bang = ison(glob_flags, IGN_BANG);
  745.     long save_do_pipe = ison(glob_flags, DO_PIPE);
  746.     long save_is_pipe = ison(glob_flags, IS_PIPE);
  747.  
  748.     turnon(glob_flags, IGN_BANG);
  749.     turnoff(glob_flags, DO_PIPE);
  750.     turnoff(glob_flags, IS_PIPE);
  751.     if (argv = make_command(buf, TRPL_NULL, &argc))
  752.     ret_val = do_command(argc, argv, list);
  753.     if (!save_bang)
  754.     turnoff(glob_flags, IGN_BANG);
  755.     if (save_do_pipe)
  756.     turnon(glob_flags, DO_PIPE);
  757.     if (save_is_pipe)
  758.     turnon(glob_flags, IS_PIPE);
  759.     return ret_val;
  760. }
  761.  
  762. glob_test(s)
  763. char *s;
  764. {
  765.     print("%s: glob_flags =", s);
  766.     if (ison(glob_flags, DO_UPDATE))
  767.     print_more(" DO_UPDATE");
  768.     if (ison(glob_flags, REV_VIDEO))
  769.     print_more(" REV_VIDEO");
  770.     if (ison(glob_flags, CONT_PRNT  ))
  771.     print_more(" CONT_PRNT");
  772.     if (ison(glob_flags, DO_SHELL    ))
  773.     print_more(" DO_SHELL");
  774.     if (ison(glob_flags, DO_PIPE))
  775.     print_more(" DO_PIPE");
  776.     if (ison(glob_flags, IS_PIPE))
  777.     print_more(" IS_PIPE");
  778.     if (ison(glob_flags, IGN_SIGS))
  779.     print_more(" IGN_SIGS");
  780.     if (ison(glob_flags, IGN_BANG))
  781.     print_more(" IGN_BANG");
  782.     if (ison(glob_flags, ECHO_FLAG))
  783.     print_more(" ECHO_FLAG");
  784.     if (ison(glob_flags, IS_GETTING))
  785.     print_more(" IS_GETTING");
  786.     if (ison(glob_flags, PRE_CURSES))
  787.     print_more(" PRE_CURSES");
  788.     if (ison(glob_flags, READ_ONLY  ))
  789.     print_more(" READ_ONLY");
  790.     if (ison(glob_flags, REDIRECT))
  791.     print_more(" REDIRECT");
  792.     if (ison(glob_flags, WAS_INTR ))
  793.     print_more(" WAS_INTR");
  794.     if (ison(glob_flags, WARNING   ))
  795.     print_more(" WARNING");
  796.     print_more("\n");
  797. }
  798.  
  799. is_spool(f)
  800. register char *f;
  801. {
  802.     return !strncmp(f, MAILDIR, strlen(MAILDIR));
  803. }
  804.  
  805. print_argv(argv)
  806. char **argv;
  807. {
  808.     while (*argv)
  809.     if (debug)
  810.         printf("(%s) ", *argv++);
  811.     else
  812.         wprint("%s ", *argv++);
  813.     if (debug) {
  814.     putchar('\n');
  815.     fflush(stdout);
  816.     } else
  817.     wprint("\n");
  818. }
  819.  
  820. msg_flags(c, v, list)
  821. register char **v, *list;
  822. {
  823.     register int    i;
  824.     register long    newflag = 0;
  825.  
  826.     if (c && *++v && !strcmp(*v, "-?"))
  827.     return help(0, "msg_flags", cmd_help);
  828.     if (c && (c = get_msg_list(v, list)) == -1)
  829.     return -1;
  830.     if (v && *(v += (c-1))) {
  831.     turnon(glob_flags, DO_UPDATE);
  832.     while (*++v)
  833.         for (c = 0; v[0][c]; c++)
  834.         switch (lower(v[0][c])) {
  835.             case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD);
  836.             when 'o' : turnon(newflag, OLD);
  837.             when 'r' : turnoff(newflag, UNREAD);
  838.             when 'd' : turnon(newflag, DELETE);
  839.             when 'p' : turnon(newflag, PRESERVE);
  840.             when 'u' : turnon(newflag, UNREAD);
  841.             otherwise: return help(0, "msg_flags", cmd_help);
  842.         }
  843.     }
  844.  
  845.     for (i = 0; i < msg_cnt; i++) {
  846.     if (!msg_bit(list, i))
  847.         continue;
  848.     else if (!newflag) {
  849.         wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1,
  850.         msg[i].m_offset, msg[i].m_lines, msg[i].m_size);
  851.         if (ison(msg[i].m_flags, UNREAD))
  852.         wprint(" UNREAD");
  853.         if (ison(msg[i].m_flags, OLD))
  854.         wprint(" OLD");
  855.         if (ison(msg[i].m_flags, DELETE))
  856.         wprint(" DELETE");
  857.         if (ison(msg[i].m_flags, PRESERVE))
  858.         wprint(" PRESERVE");
  859.         if (ison(msg[i].m_flags, UPDATE_STATUS))
  860.         wprint(" UPDATE_STATUS");
  861.         wprint("\n");
  862.     } else
  863.         msg[i].m_flags = newflag;
  864.     }
  865.     return 0;
  866. }
  867.