home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / mush6.4 / part08 / setopts.c < prev   
C/C++ Source or Header  |  1989-03-12  |  18KB  |  696 lines

  1. /* setopts.c    (c) copyright 1986 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4. #include "bindings.h"
  5.  
  6. /* add an option indicated by "set option[=value]" or by "alias name alias"
  7.  * function is recursive, so multilists get appended accordingly
  8.  */
  9. add_option(list, argv)
  10. register struct options **list;
  11. register char **argv;
  12. {
  13.     register struct options *tmp;
  14.     struct options *calloc();
  15.     register char *option, *value = NULL;
  16.  
  17.     if (!(option = *argv))
  18.     return 1;
  19.     /* check for one of three forms:
  20.      * option=value    option = value  option= value
  21.      * value can be in quotes to preserve whitespace
  22.      */
  23.     if (*++argv && !strcmp(*argv, "=")) {
  24.     if (value = *++argv) /* example: "set foo = " */
  25.         ++argv;
  26.     } else if (value = index(option, '=')) {
  27.     /* option=value  strip into option="option" value="value"; (quotes?) */
  28.     register char c, *p2;
  29.     *value = 0; /* option is now a null terminated `option' */
  30.     if ((c = *++value) == '"' || c == '\'') {
  31.         *value++ = 0;
  32.         if (!(p2 = index(value, c))) {
  33.         print("No matching %c for %s.\n", c, option);
  34.         return 0;
  35.         } else
  36.         *p2 = 0;
  37.     } else if (!c) {  /* example: "set crt=" */
  38.         if (!*argv) {
  39.         print("No value for %s.\n", option);
  40.         return 0;
  41.         }
  42.         value = *argv++;
  43.     }
  44.     }
  45.  
  46.     /* check for internal vars that can't be set this way */
  47.     if (check_internal(option)) {
  48.     print("You can't change %s with \"set\".\n", option);
  49.     return 0;
  50.     }
  51.  
  52.     /* check to see if option is already set by attempting to unset it */
  53.     (void) un_set(list, option);
  54.  
  55.     /* now make a new option struct and set fields */
  56.     if (!(tmp = calloc((unsigned)1, sizeof(struct options)))) {
  57.     error("calloc");
  58.     return -1;
  59.     }
  60.     tmp->option = savestr(option);
  61.     tmp->value = savestr(value); /* strdup handles the NULL case */
  62.  
  63.     tmp->next = *list;
  64.     *list = tmp;
  65.  
  66.     /* check for options which must have values or are used frequently */
  67.     if (*list == set_options) {
  68. #if defined(CURSES) || defined(SUNTOOL)
  69.     if (!strcmp(tmp->option, "no_reverse"))
  70.         turnoff(glob_flags, REV_VIDEO);
  71.     else
  72. #endif /* CURSES || SUNTOOL */
  73.     if (!strcmp(tmp->option, "prompt"))
  74.         prompt = (tmp->value)? tmp->value : DEF_PROMPT;
  75.     else if (!strcmp(tmp->option, "warning"))
  76.         turnon(glob_flags, WARNING);
  77.     else if (!strcmp(tmp->option, "mil_time"))
  78.         turnon(glob_flags, MIL_TIME);
  79. #ifndef MSG_SEPARATOR
  80.     else if (!strcmp(tmp->option, "date_received"))
  81.         turnon(glob_flags, DATE_RECV);
  82. #endif /* MSG_SEPARATOR */
  83.     else if (!strcmp(tmp->option, "escape"))
  84.         escape = (tmp->value)? tmp->value : DEF_ESCAPE;
  85.     else if (!strcmp(tmp->option, "hdr_format"))
  86.         hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
  87.     else if (!strcmp(tmp->option, "crt")) {
  88.         if (!istool)
  89.         crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
  90.     } else if (!strcmp(tmp->option, "screen")) {
  91.         screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
  92. #ifdef CURSES
  93.         if (iscurses && screen > LINES-2)
  94.         screen = LINES-2;
  95. #endif /* CURSES */
  96.     } else if (!strcmp(tmp->option, "wrapcolumn")) {
  97.         char wval[16];
  98.         wrapcolumn =
  99.         (tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
  100. #ifdef CURSES
  101.         /* Use COLS-2 because of silly terminals like vt100 */
  102.         if (iscurses && wrapcolumn > COLS - 2)
  103.         wrapcolumn = COLS - 2;
  104. #endif /* CURSES */
  105.         xfree(tmp->value);
  106.         tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
  107.     } else if (!strcmp(tmp->option, "history"))
  108.         init_history((value && *value)? atoi(value) : 1);
  109.     else if (!strcmp(tmp->option, "known_hosts")) {
  110.         register char *p;
  111.         int n;
  112.         /* in case user separated with commas */
  113.         for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  114.         *p = ' ';
  115.         free_vec(known_hosts);
  116.         known_hosts = mk_argv(tmp->value, &n, FALSE);
  117.     } else if (!strcmp(tmp->option, "hostname")) {
  118.         register char *p;
  119.         int n;
  120.         /* in case user separated with commas */
  121.         for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  122.         *p = ' ';
  123.         free_vec(ourname);
  124.         ourname = mk_argv(tmp->value, &n, FALSE);
  125.     }
  126.     }
  127.  
  128.     if (*argv)
  129.     return add_option(list, argv);
  130.     return 1;
  131. }
  132.  
  133. /*
  134.  * If str is NULL, just print options and their values. Note that numerical
  135.  * values are not converted to int upon return.  If str is not NULL
  136.  * return the string that matched, else return NULL;
  137.  */
  138. char *
  139. do_set(list, str)
  140. register struct options *list;
  141. register char *str;
  142. {
  143.     register struct options *opts;
  144. #ifdef SUNTOOL
  145.     int x,y;
  146.  
  147.     if (istool && !str)
  148.     y = 10 + 2 * l_height(LARGE);
  149. #endif /* SUNTOOL */
  150.  
  151.     if (!str && !istool)
  152.     (void) do_pager(NULL, TRUE); /* page using internal pager */
  153.  
  154.     for (opts = list; opts; opts = opts->next)
  155.     if (!str) {
  156. #ifdef SUNTOOL
  157.         if (istool)
  158.         pw_text(msg_win, 5, y, PIX_SRC, fonts[DEFAULT], opts->option);
  159.         else
  160. #endif /* SUNTOOL */
  161.         (void) do_pager(opts->option, FALSE);
  162.         if (opts->value)
  163. #ifdef SUNTOOL
  164.         if (istool) {
  165.             x = 30*l_width(DEFAULT);
  166.             pw_text(msg_win, x,y, PIX_SRC, fonts[DEFAULT], opts->value);
  167.             pw_text(msg_win, x+1, y, PIX_SRC|PIX_DST,
  168.                  fonts[DEFAULT], opts->value);
  169.             x += strlen(opts->value)*l_width(DEFAULT);
  170.         } else
  171. #endif /* SUNTOOL */
  172.         {
  173.             (void) do_pager("     \t", FALSE);
  174.             (void) do_pager(opts->value, FALSE);
  175.         }
  176. #ifdef SUNTOOL
  177.         if (istool)
  178.         Clrtoeol(msg_win, x, y, DEFAULT), y += l_height(DEFAULT);
  179.         else
  180. #endif /* SUNTOOL */
  181.         if (do_pager("\n", FALSE) == EOF)
  182.             break;
  183.     } else {
  184.         if (strcmp(str, opts->option))
  185.         continue;
  186.         if (opts->value)
  187.         return opts->value;
  188.         else
  189.         return "";
  190.     }
  191.  
  192.     if (!str && !istool)
  193.     (void) do_pager(NULL, FALSE); /* terminate internal pager */
  194.  
  195.     /* if we still haven't matched, check for environment vars */
  196.     if (str && list == set_options) {
  197.     register int N, n;
  198.     for (N = 0; environ[N]; N++) {
  199.         char *p = index(environ[N], '=');
  200.         if (p)
  201.         *p = 0;
  202.         n = lcase_strncmp(str, environ[N], -1);
  203.         if (p)
  204.         *p = '=';
  205.         if (!n)
  206.         return p+1;
  207.     }
  208.     }
  209.     return NULL;
  210. }
  211.  
  212. /*
  213.  * unset the variable described by p in the list "list".
  214.  * if the variable isn't set, then return 0, else return 1.
  215.  */
  216. un_set(list, p)
  217. register struct options **list;
  218. register char *p;
  219. {
  220.     register struct options *opts = *list, *tmp;
  221.  
  222.     if (!list || !*list || !p || !*p)
  223.     return 0;
  224.     if (*list == set_options) {
  225. #if defined(CURSES) || defined(SUNTOOL)
  226.     if (!strcmp(p, "no_reverse"))
  227.         turnon(glob_flags, REV_VIDEO);
  228.     else
  229. #endif /* CURSES || SUNTOOL */
  230.     if (!strcmp(p, "prompt"))
  231.         prompt = DEF_PROMPT;
  232.     else if (!strcmp(p, "warning"))
  233.         turnoff(glob_flags, WARNING);
  234.     else if (!strcmp(p, "mil_time"))
  235.         turnoff(glob_flags, MIL_TIME);
  236. #ifndef MSG_SEPARATOR
  237.     else if (!strcmp(p, "date_received"))
  238.         turnoff(glob_flags, DATE_RECV);
  239. #endif /* MSG_SEPARATOR */
  240.     else if (!strcmp(p, "escape"))
  241.         escape = DEF_ESCAPE;
  242.     else if (!strcmp(p, "hdr_format"))
  243.         hdr_format = DEF_HDR_FMT;
  244.     else if (!strcmp(p, "crt"))
  245.         crt = 18;
  246.     else if (!strcmp(p, "screen")) {
  247.         screen = 18;
  248. #ifdef CURSES
  249.         if (iscurses && screen > LINES-2)
  250.         screen = LINES-2;
  251. #endif /* CURSES */
  252.     } else if (!strcmp(p, "wrapcolumn"))
  253.         wrapcolumn = 0;
  254.     else if (!strcmp(p, "history"))
  255.         init_history(1);
  256.     else if (!strcmp(p, "known_hosts")) {
  257.         free_vec(known_hosts);
  258.         known_hosts = DUBL_NULL;
  259.     } else if (!strcmp(p, "hostname")) {
  260.         free_vec(ourname);
  261.         ourname = DUBL_NULL;
  262.     }
  263.     }
  264.  
  265.     if (!strcmp(p, opts->option)) {
  266.     *list = (*list)->next;
  267.     xfree (opts->option);
  268.     if (opts->value)
  269.         xfree(opts->value);
  270.     xfree((char *)opts);
  271.     return 1;
  272.     }
  273.     for ( ; opts->next; opts = opts->next)
  274.     if (!strcmp(p, opts->next->option)) {
  275.         tmp = opts->next;
  276.         opts->next = opts->next->next;
  277.         xfree (tmp->option);
  278.         if (tmp->value)
  279.         xfree(tmp->value);
  280.         xfree ((char *)tmp);
  281.         return 1;
  282.     }
  283.     return 0;
  284. }
  285.  
  286. /* The functions below return 0 since they don't affect
  287.  * messages.
  288.  */
  289. set(n, argv, list)
  290. register int n;
  291. register char **argv;
  292. char *list;
  293. {
  294.     char firstchar = **argv;
  295.     register char *cmd = *argv;
  296.     register struct options **optlist;
  297.     char buf[BUFSIZ];
  298.  
  299.     if (*cmd == 'u')
  300.     cmd += 2;
  301.     if (*++argv && !strcmp(*argv, "-?"))
  302.     return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
  303.  
  304.     if (*argv && **argv == '?') {
  305.     int incurses;
  306.     if (!strcmp(*argv, "?all")) {
  307.         if (incurses = iscurses) /* assign and compare to TRUE */
  308.         clr_bot_line(), iscurses = FALSE;
  309.         (void) do_pager(NULL, TRUE); /* start internal pager */
  310.         for (n = 0; variable_stuff(n, NULL, buf); n++)
  311.         if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
  312.             break;
  313.         (void) do_pager(NULL, FALSE); /* terminate pager */
  314.         iscurses = incurses;
  315.     } else {
  316.         /* May return null if variable not set. */
  317.         (void) variable_stuff(0, (*argv)+1, buf);
  318.         print("%s\n", buf);
  319.     }
  320.     return 0;
  321.     }
  322.  
  323.     if (firstchar == 'u') {
  324.     if (!*argv) {
  325.         print("%s what?\n", cmd);
  326.         return -1;
  327.     } else {
  328.         optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
  329.         do  if (!strcmp(*argv, "*"))
  330.             while (*optlist)
  331.             (void) un_set(optlist, (*optlist)->option);
  332.         else if (!un_set(optlist, *argv))
  333.             print("un%s: %s not set\n",
  334.             (*cmd == 'i')? "ignore" : "set", *argv);
  335.         while (*++argv);
  336.     }
  337.     return 0;
  338.     }
  339.  
  340.     if (!*argv) {
  341.     (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
  342.     return 0;
  343.     }
  344.  
  345.     /*
  346.      * Check for input redirection.  If so, set the variable to the ascii
  347.      * value of the current msg_list.
  348.      */
  349.     if (ison(glob_flags, IS_PIPE)) {
  350.     char *newargv[4];
  351.  
  352.     if (*cmd == 'i') {
  353.         print("You can't pipe to the \"%s\" command.\n", cmd);
  354.         return -1;
  355.     }
  356.     list_to_str(list, buf);
  357.     if (!buf[0])
  358.         return -1;
  359.     newargv[0] = argv[0];
  360.     newargv[1] = "=";
  361.     newargv[2] = buf;
  362.     newargv[3] = NULL;
  363.     (void) add_option(&set_options, newargv);
  364.     return 0;
  365.     }
  366.  
  367.     /*
  368.      * finally, just set the variable the user requested.
  369.      */
  370.     (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
  371.     return 0;
  372. }
  373.  
  374. /*
  375.  *   The alts list is a list of hostnames or pathnames where the user
  376.  * has an account.  If he doesn't specify "metoo", then when replying
  377.  * to mail, if his address is listed, it will be removed.  The syntax
  378.  * is compatible with ucb Mail in that just hostnames can be used.
  379.  * However, there is an added feature that mush provides which another
  380.  * login name or path to another login can be specified by preceding the
  381.  * path or login with a !
  382.  * "argv" may be a file pointer to write the data into by use of save_opts()
  383.  */
  384. alts(argc, argv)
  385. register char **argv;
  386. {
  387.     char buf[BUFSIZ], *p;
  388.  
  389.     /* check here first because a 0 argc means to write it to a file */
  390.     if (argc <= 1) {
  391.     int n;
  392.     if (!alternates)
  393.         return;
  394.     if (argc == 0)
  395.         fprintf((FILE *)argv, "alts ");
  396.     for (n = 0; alternates[n]; n++) {
  397.         p = 0;
  398.         (void) reverse(strcpy(buf, alternates[n]));
  399.         if (isalpha(buf[0]) && (p = rindex(buf, '!')))
  400.         *p = 0;
  401.         if (argc == 0)
  402.         fprintf((FILE *)argv, "%s ", buf);
  403.         else
  404.         wprint("%s ", buf);
  405.         if (p)
  406.         *p = '!';
  407.     }
  408.     if (argc == 0)
  409.         fputc('\n', (FILE *)argv);
  410.     else
  411.         wprint("\n");
  412.     return 0;
  413.     }
  414.  
  415.     if (argc-- && *++argv && !strcmp(*argv, "-?"))
  416.     return help(0, "alts", cmd_help);
  417.  
  418.     free_vec(alternates);
  419.     if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
  420.     while (argc-- > 0) {
  421.         if (argv[argc][0] != '!' && argv[argc][0] != '*') {
  422.         p = buf + Strcpy(buf, argv[argc]);
  423.         *p++ = '!', p += Strcpy(p, login);
  424.         alternates[argc] = savestr(reverse(buf));
  425.         } else
  426.         alternates[argc] = savestr(reverse(argv[argc]));
  427.     }
  428.     return 0;
  429. }
  430.  
  431. save_opts(cnt, argv)
  432. char **argv;
  433. {
  434.     char file[256], *tmp;
  435.     register FILE *fp;
  436.  
  437.     if (cnt && *++argv && !strcmp(*argv, "-?"))
  438.     return help(0, "source_help", cmd_help);
  439.     if (cnt && *argv)
  440.     (void) strcpy(file, *argv);
  441.     else if (tmp = getenv("MAILRC"))
  442.     (void) strcpy(file, tmp);
  443.     else {
  444.     char *home = do_set(set_options, "home");
  445.     if (!home || !*home)
  446.         home = ALTERNATE_HOME;
  447.     /* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
  448.     if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
  449.             Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
  450.         (void) sprintf(file, "%s/%s", home, MAILRC);
  451.     }
  452.  
  453.     cnt = 1;
  454.     tmp = getpath(file, &cnt);
  455.     if (cnt) {
  456.     if (cnt == -1)
  457.         print("%s: %s\n", file, tmp);
  458.     else
  459.         print("%s is a directory.\n", tmp);
  460.     return -1;
  461.     }
  462.     /* See if the file exists and confirm overwrite */
  463.     if (!Access(tmp, F_OK)) {
  464.     int overwrite = TRUE;
  465.     char buf[4];
  466.     print("\"%s\" exists. Overwrite? ", tmp);
  467.     if (!istool) {
  468.         if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
  469.         overwrite = FALSE;
  470.     }
  471. #ifdef SUNTOOL
  472.     else {
  473.         int c = confirm(panel_sw->ts_windowfd);
  474.         if (lower(c) != 'y' && c != MS_LEFT)
  475.         overwrite = FALSE;
  476.     }
  477. #endif /* SUNTOOL */
  478.     if (!overwrite) {
  479.         print("\"%s\" unchanged.\n", tmp);
  480.         return -1;
  481.     }
  482.     }
  483.     if (!(fp = fopen(tmp, "w"))) {
  484.     error("Can't open %s", file);
  485.     return -1;
  486.     }
  487.  
  488.     save_list("basic variable settings", set_options, "set", '=', fp);
  489.  
  490.     save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
  491.  
  492.     save_list("aliases", aliases, "alias", 0, fp);
  493.  
  494.     alts(0, (char **)fp);
  495.  
  496.     save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
  497.  
  498.     save_list("command abbreviations", functions, "cmd", ' ', fp);
  499.  
  500.     save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
  501.  
  502. #ifdef CURSES
  503.     save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
  504. #endif /* CURSES */
  505.  
  506.     save_cmd("line mode mappings", line_map, "map", 0, fp);
  507.  
  508.     save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
  509.  
  510.     fclose(fp);
  511.     print("All variables and options saved in %s\n", tmp);
  512.     return -1;
  513. }
  514.  
  515. save_list(title, list, command, equals, fp)
  516. struct options *list;
  517. register char *command, *title, equals;
  518. register FILE *fp;
  519. {
  520.     register struct options *opts;
  521.     register char *p;
  522.  
  523.     if (!list)
  524.     return;
  525.     fprintf(fp, "#\n# %s\n#\n", title);
  526.     for (opts = list; opts; opts = opts->next) {
  527.     if (list == set_options && !strcmp(opts->option, "cwd"))
  528.         continue; /* don't print $cwd */
  529.     fprintf(fp, "%s %s", command, opts->option);
  530.     if (opts->value && *opts->value) {
  531.         register char *quote;
  532.         if (!equals)
  533.         quote = NO_STRING;
  534.         else if (p = any(opts->value, "\"'"))
  535.         if (*p == '\'') quote = "\"";
  536.         else quote = "'";
  537.         else
  538.         if (!any(opts->value, " \t;|"))
  539.             quote = NO_STRING;
  540.         else quote = "'";
  541.         fputc(equals? equals: ' ', fp);
  542.         fprintf(fp, "%s%s%s", quote, opts->value, quote);
  543.     }
  544.     fputc('\n', fp);
  545.     }
  546. }
  547.  
  548. extern struct cmd_map map_func_names[];
  549.  
  550. save_cmd(title, list, command, equals, fp)
  551. struct cmd_map *list;
  552. register char *command, *title;
  553. register int equals;
  554. register FILE *fp;
  555. {
  556.     register struct cmd_map *opts;
  557.     register char *p;
  558.     char buf[MAX_MACRO_LEN * 2];
  559.  
  560.     if (!list)
  561.     return;
  562.     fprintf(fp, "#\n# %s\n#\n", title);
  563.     for (opts = list; opts; opts = opts->m_next) {
  564.     register char *quote;
  565.     if ((p = any(opts->m_str, "\"'")) && *p == '\'')
  566.         quote = "\"";
  567.     else
  568.         quote = "'";
  569.     fprintf(fp, "%s %s%s%s", command, quote,
  570.             ctrl_strcpy(buf, opts->m_str, TRUE), quote);
  571.     if (equals && map_func_names[opts->m_cmd].m_str)
  572.         fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
  573.     if (opts->x_str && *opts->x_str) {
  574.         if ((p = any(opts->x_str, "\"'")) && *p == '\'')
  575.         quote = "\"";
  576.         else
  577.         quote = "'";
  578.         fprintf(fp, " %s%s%s", quote,
  579.             ctrl_strcpy(buf, opts->x_str, TRUE), quote);
  580.     }
  581.     fputc('\n', fp);
  582.     }
  583. }
  584.  
  585. /*
  586.  * do_alias handles aliases, header settings, functions, and fkeys.
  587.  * since they're all handled in the same manner, the same routine is
  588.  * used. argv[0] determines which to use.
  589.  * alias is given here as an example
  590.  *
  591.  * alias           identify all aliases
  592.  * alias name      identify alias
  593.  * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
  594.  * unalias arg1 [arg2 arg3 ... ]        unalias args
  595.  *
  596.  * same is true for dealing with your own headers.
  597.  * (also the expand command)
  598.  * always return -1 since it has no effect on messages
  599.  */
  600. do_alias(argc, argv)
  601. register char **argv;
  602. {
  603.     register char *cmd = *argv, *p;
  604.     struct options **list;
  605.     char firstchar = *cmd, buf[BUFSIZ];
  606.  
  607.     if (argc == 0)
  608.     return 0 - in_pipe();
  609.     if (firstchar == 'u')
  610.     firstchar = cmd[2];
  611.     if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
  612.     register char *help_str;
  613.     if (firstchar == 'a' || firstchar == 'e')
  614.         help_str = "alias";
  615.     else if (firstchar == 'c')
  616.         help_str = "cmd";
  617.     else if (firstchar == 'f')
  618.         help_str = "fkey";
  619.     else
  620.         help_str = "own_hdrs";
  621.     return help(0, help_str, cmd_help);
  622.     }
  623.  
  624.     if (firstchar == 'a')
  625.     list = &aliases;
  626.     else if (firstchar == 'c')
  627.     list = &functions;
  628.     else if (firstchar == 'f')
  629.     list = &fkeys;
  630.     else
  631.     list = &own_hdrs;
  632.  
  633.     if (*cmd == 'u') {
  634.     if (!*argv) {
  635.         print("%s what?\n", cmd);
  636.         return -1;
  637.     /* unset a list separated by spaces or ',' */
  638.     } else while (*argv) {
  639.         if (!strcmp(*argv, "*")) /* unset everything */
  640.         while (*list)
  641.             (void) un_set(list, (*list)->option);
  642.         else if (!un_set(list, *argv))
  643.         print("\"%s\" isn't set\n", *argv);
  644.         argv++;
  645.     }
  646.     return 0;
  647.     }
  648.  
  649.     if (!*argv && *cmd != 'e') {
  650.     /* just type out all the aliases or own_hdrs */
  651.     (void) do_set(*list, NULL);
  652.     return 0;
  653.     }
  654.  
  655.     if (*cmd == 'e') {   /* command was "expand" (aliases only) */
  656.     if (!*argv) {
  657.         print("expand which alias?\n");
  658.         return -1;
  659.     } else
  660.         do  {
  661.         print("%s: ", *argv);
  662.         if (p = alias_to_address(*argv))
  663.             print("%s\n", p);
  664.         } while (*++argv);
  665.     return 0;
  666.     }
  667.  
  668.     /* at this point, *argv now points to a variable name ...
  669.      * check for hdr -- if so, *argv better end with a ':' (check *p)
  670.      */
  671.     if (list == &own_hdrs && !(p = index(*argv, ':'))) {
  672.     print("header labels must end with a ':' (%s)\n", *argv);
  673.     return -1;
  674.     }
  675.     if (!argv[1] && !index(*argv, '='))
  676.     if (p = do_set(*list, *argv))
  677.         print("%s\n", p);
  678.     else
  679.         print("%s is not set\n", *argv);
  680.     else {
  681.     char *tmpargv[2];
  682.     (void) argv_to_string(buf, argv);
  683.     if ((p = any(buf, " \t=")) && *p != '=')
  684.         *p = '=';
  685.     /* if we're setting an alias, enforce the insertion of commas
  686.      * between each well-formed address.
  687.      */
  688.     if (list == &aliases)
  689.         fix_up_addr(p+1);
  690.     tmpargv[0] = buf;
  691.     tmpargv[1] = NULL;
  692.     (void) add_option(list, tmpargv);
  693.     }
  694.     return 0;
  695. }
  696.