home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
mush6.4
/
part08
/
setopts.c
< prev
Wrap
C/C++ Source or Header
|
1989-03-12
|
18KB
|
696 lines
/* setopts.c (c) copyright 1986 (Dan Heller) */
#include "mush.h"
#include "bindings.h"
/* add an option indicated by "set option[=value]" or by "alias name alias"
* function is recursive, so multilists get appended accordingly
*/
add_option(list, argv)
register struct options **list;
register char **argv;
{
register struct options *tmp;
struct options *calloc();
register char *option, *value = NULL;
if (!(option = *argv))
return 1;
/* check for one of three forms:
* option=value option = value option= value
* value can be in quotes to preserve whitespace
*/
if (*++argv && !strcmp(*argv, "=")) {
if (value = *++argv) /* example: "set foo = " */
++argv;
} else if (value = index(option, '=')) {
/* option=value strip into option="option" value="value"; (quotes?) */
register char c, *p2;
*value = 0; /* option is now a null terminated `option' */
if ((c = *++value) == '"' || c == '\'') {
*value++ = 0;
if (!(p2 = index(value, c))) {
print("No matching %c for %s.\n", c, option);
return 0;
} else
*p2 = 0;
} else if (!c) { /* example: "set crt=" */
if (!*argv) {
print("No value for %s.\n", option);
return 0;
}
value = *argv++;
}
}
/* check for internal vars that can't be set this way */
if (check_internal(option)) {
print("You can't change %s with \"set\".\n", option);
return 0;
}
/* check to see if option is already set by attempting to unset it */
(void) un_set(list, option);
/* now make a new option struct and set fields */
if (!(tmp = calloc((unsigned)1, sizeof(struct options)))) {
error("calloc");
return -1;
}
tmp->option = savestr(option);
tmp->value = savestr(value); /* strdup handles the NULL case */
tmp->next = *list;
*list = tmp;
/* check for options which must have values or are used frequently */
if (*list == set_options) {
#if defined(CURSES) || defined(SUNTOOL)
if (!strcmp(tmp->option, "no_reverse"))
turnoff(glob_flags, REV_VIDEO);
else
#endif /* CURSES || SUNTOOL */
if (!strcmp(tmp->option, "prompt"))
prompt = (tmp->value)? tmp->value : DEF_PROMPT;
else if (!strcmp(tmp->option, "warning"))
turnon(glob_flags, WARNING);
else if (!strcmp(tmp->option, "mil_time"))
turnon(glob_flags, MIL_TIME);
#ifndef MSG_SEPARATOR
else if (!strcmp(tmp->option, "date_received"))
turnon(glob_flags, DATE_RECV);
#endif /* MSG_SEPARATOR */
else if (!strcmp(tmp->option, "escape"))
escape = (tmp->value)? tmp->value : DEF_ESCAPE;
else if (!strcmp(tmp->option, "hdr_format"))
hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
else if (!strcmp(tmp->option, "crt")) {
if (!istool)
crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
} else if (!strcmp(tmp->option, "screen")) {
screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
#ifdef CURSES
if (iscurses && screen > LINES-2)
screen = LINES-2;
#endif /* CURSES */
} else if (!strcmp(tmp->option, "wrapcolumn")) {
char wval[16];
wrapcolumn =
(tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
#ifdef CURSES
/* Use COLS-2 because of silly terminals like vt100 */
if (iscurses && wrapcolumn > COLS - 2)
wrapcolumn = COLS - 2;
#endif /* CURSES */
xfree(tmp->value);
tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
} else if (!strcmp(tmp->option, "history"))
init_history((value && *value)? atoi(value) : 1);
else if (!strcmp(tmp->option, "known_hosts")) {
register char *p;
int n;
/* in case user separated with commas */
for (p = index(tmp->value, ','); p; p = index(p+1, ','))
*p = ' ';
free_vec(known_hosts);
known_hosts = mk_argv(tmp->value, &n, FALSE);
} else if (!strcmp(tmp->option, "hostname")) {
register char *p;
int n;
/* in case user separated with commas */
for (p = index(tmp->value, ','); p; p = index(p+1, ','))
*p = ' ';
free_vec(ourname);
ourname = mk_argv(tmp->value, &n, FALSE);
}
}
if (*argv)
return add_option(list, argv);
return 1;
}
/*
* If str is NULL, just print options and their values. Note that numerical
* values are not converted to int upon return. If str is not NULL
* return the string that matched, else return NULL;
*/
char *
do_set(list, str)
register struct options *list;
register char *str;
{
register struct options *opts;
#ifdef SUNTOOL
int x,y;
if (istool && !str)
y = 10 + 2 * l_height(LARGE);
#endif /* SUNTOOL */
if (!str && !istool)
(void) do_pager(NULL, TRUE); /* page using internal pager */
for (opts = list; opts; opts = opts->next)
if (!str) {
#ifdef SUNTOOL
if (istool)
pw_text(msg_win, 5, y, PIX_SRC, fonts[DEFAULT], opts->option);
else
#endif /* SUNTOOL */
(void) do_pager(opts->option, FALSE);
if (opts->value)
#ifdef SUNTOOL
if (istool) {
x = 30*l_width(DEFAULT);
pw_text(msg_win, x,y, PIX_SRC, fonts[DEFAULT], opts->value);
pw_text(msg_win, x+1, y, PIX_SRC|PIX_DST,
fonts[DEFAULT], opts->value);
x += strlen(opts->value)*l_width(DEFAULT);
} else
#endif /* SUNTOOL */
{
(void) do_pager(" \t", FALSE);
(void) do_pager(opts->value, FALSE);
}
#ifdef SUNTOOL
if (istool)
Clrtoeol(msg_win, x, y, DEFAULT), y += l_height(DEFAULT);
else
#endif /* SUNTOOL */
if (do_pager("\n", FALSE) == EOF)
break;
} else {
if (strcmp(str, opts->option))
continue;
if (opts->value)
return opts->value;
else
return "";
}
if (!str && !istool)
(void) do_pager(NULL, FALSE); /* terminate internal pager */
/* if we still haven't matched, check for environment vars */
if (str && list == set_options) {
register int N, n;
for (N = 0; environ[N]; N++) {
char *p = index(environ[N], '=');
if (p)
*p = 0;
n = lcase_strncmp(str, environ[N], -1);
if (p)
*p = '=';
if (!n)
return p+1;
}
}
return NULL;
}
/*
* unset the variable described by p in the list "list".
* if the variable isn't set, then return 0, else return 1.
*/
un_set(list, p)
register struct options **list;
register char *p;
{
register struct options *opts = *list, *tmp;
if (!list || !*list || !p || !*p)
return 0;
if (*list == set_options) {
#if defined(CURSES) || defined(SUNTOOL)
if (!strcmp(p, "no_reverse"))
turnon(glob_flags, REV_VIDEO);
else
#endif /* CURSES || SUNTOOL */
if (!strcmp(p, "prompt"))
prompt = DEF_PROMPT;
else if (!strcmp(p, "warning"))
turnoff(glob_flags, WARNING);
else if (!strcmp(p, "mil_time"))
turnoff(glob_flags, MIL_TIME);
#ifndef MSG_SEPARATOR
else if (!strcmp(p, "date_received"))
turnoff(glob_flags, DATE_RECV);
#endif /* MSG_SEPARATOR */
else if (!strcmp(p, "escape"))
escape = DEF_ESCAPE;
else if (!strcmp(p, "hdr_format"))
hdr_format = DEF_HDR_FMT;
else if (!strcmp(p, "crt"))
crt = 18;
else if (!strcmp(p, "screen")) {
screen = 18;
#ifdef CURSES
if (iscurses && screen > LINES-2)
screen = LINES-2;
#endif /* CURSES */
} else if (!strcmp(p, "wrapcolumn"))
wrapcolumn = 0;
else if (!strcmp(p, "history"))
init_history(1);
else if (!strcmp(p, "known_hosts")) {
free_vec(known_hosts);
known_hosts = DUBL_NULL;
} else if (!strcmp(p, "hostname")) {
free_vec(ourname);
ourname = DUBL_NULL;
}
}
if (!strcmp(p, opts->option)) {
*list = (*list)->next;
xfree (opts->option);
if (opts->value)
xfree(opts->value);
xfree((char *)opts);
return 1;
}
for ( ; opts->next; opts = opts->next)
if (!strcmp(p, opts->next->option)) {
tmp = opts->next;
opts->next = opts->next->next;
xfree (tmp->option);
if (tmp->value)
xfree(tmp->value);
xfree ((char *)tmp);
return 1;
}
return 0;
}
/* The functions below return 0 since they don't affect
* messages.
*/
set(n, argv, list)
register int n;
register char **argv;
char *list;
{
char firstchar = **argv;
register char *cmd = *argv;
register struct options **optlist;
char buf[BUFSIZ];
if (*cmd == 'u')
cmd += 2;
if (*++argv && !strcmp(*argv, "-?"))
return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
if (*argv && **argv == '?') {
int incurses;
if (!strcmp(*argv, "?all")) {
if (incurses = iscurses) /* assign and compare to TRUE */
clr_bot_line(), iscurses = FALSE;
(void) do_pager(NULL, TRUE); /* start internal pager */
for (n = 0; variable_stuff(n, NULL, buf); n++)
if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
break;
(void) do_pager(NULL, FALSE); /* terminate pager */
iscurses = incurses;
} else {
/* May return null if variable not set. */
(void) variable_stuff(0, (*argv)+1, buf);
print("%s\n", buf);
}
return 0;
}
if (firstchar == 'u') {
if (!*argv) {
print("%s what?\n", cmd);
return -1;
} else {
optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
do if (!strcmp(*argv, "*"))
while (*optlist)
(void) un_set(optlist, (*optlist)->option);
else if (!un_set(optlist, *argv))
print("un%s: %s not set\n",
(*cmd == 'i')? "ignore" : "set", *argv);
while (*++argv);
}
return 0;
}
if (!*argv) {
(void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
return 0;
}
/*
* Check for input redirection. If so, set the variable to the ascii
* value of the current msg_list.
*/
if (ison(glob_flags, IS_PIPE)) {
char *newargv[4];
if (*cmd == 'i') {
print("You can't pipe to the \"%s\" command.\n", cmd);
return -1;
}
list_to_str(list, buf);
if (!buf[0])
return -1;
newargv[0] = argv[0];
newargv[1] = "=";
newargv[2] = buf;
newargv[3] = NULL;
(void) add_option(&set_options, newargv);
return 0;
}
/*
* finally, just set the variable the user requested.
*/
(void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
return 0;
}
/*
* The alts list is a list of hostnames or pathnames where the user
* has an account. If he doesn't specify "metoo", then when replying
* to mail, if his address is listed, it will be removed. The syntax
* is compatible with ucb Mail in that just hostnames can be used.
* However, there is an added feature that mush provides which another
* login name or path to another login can be specified by preceding the
* path or login with a !
* "argv" may be a file pointer to write the data into by use of save_opts()
*/
alts(argc, argv)
register char **argv;
{
char buf[BUFSIZ], *p;
/* check here first because a 0 argc means to write it to a file */
if (argc <= 1) {
int n;
if (!alternates)
return;
if (argc == 0)
fprintf((FILE *)argv, "alts ");
for (n = 0; alternates[n]; n++) {
p = 0;
(void) reverse(strcpy(buf, alternates[n]));
if (isalpha(buf[0]) && (p = rindex(buf, '!')))
*p = 0;
if (argc == 0)
fprintf((FILE *)argv, "%s ", buf);
else
wprint("%s ", buf);
if (p)
*p = '!';
}
if (argc == 0)
fputc('\n', (FILE *)argv);
else
wprint("\n");
return 0;
}
if (argc-- && *++argv && !strcmp(*argv, "-?"))
return help(0, "alts", cmd_help);
free_vec(alternates);
if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
while (argc-- > 0) {
if (argv[argc][0] != '!' && argv[argc][0] != '*') {
p = buf + Strcpy(buf, argv[argc]);
*p++ = '!', p += Strcpy(p, login);
alternates[argc] = savestr(reverse(buf));
} else
alternates[argc] = savestr(reverse(argv[argc]));
}
return 0;
}
save_opts(cnt, argv)
char **argv;
{
char file[256], *tmp;
register FILE *fp;
if (cnt && *++argv && !strcmp(*argv, "-?"))
return help(0, "source_help", cmd_help);
if (cnt && *argv)
(void) strcpy(file, *argv);
else if (tmp = getenv("MAILRC"))
(void) strcpy(file, tmp);
else {
char *home = do_set(set_options, "home");
if (!home || !*home)
home = ALTERNATE_HOME;
/* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
(void) sprintf(file, "%s/%s", home, MAILRC);
}
cnt = 1;
tmp = getpath(file, &cnt);
if (cnt) {
if (cnt == -1)
print("%s: %s\n", file, tmp);
else
print("%s is a directory.\n", tmp);
return -1;
}
/* See if the file exists and confirm overwrite */
if (!Access(tmp, F_OK)) {
int overwrite = TRUE;
char buf[4];
print("\"%s\" exists. Overwrite? ", tmp);
if (!istool) {
if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
overwrite = FALSE;
}
#ifdef SUNTOOL
else {
int c = confirm(panel_sw->ts_windowfd);
if (lower(c) != 'y' && c != MS_LEFT)
overwrite = FALSE;
}
#endif /* SUNTOOL */
if (!overwrite) {
print("\"%s\" unchanged.\n", tmp);
return -1;
}
}
if (!(fp = fopen(tmp, "w"))) {
error("Can't open %s", file);
return -1;
}
save_list("basic variable settings", set_options, "set", '=', fp);
save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
save_list("aliases", aliases, "alias", 0, fp);
alts(0, (char **)fp);
save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
save_list("command abbreviations", functions, "cmd", ' ', fp);
save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
#ifdef CURSES
save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
#endif /* CURSES */
save_cmd("line mode mappings", line_map, "map", 0, fp);
save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
fclose(fp);
print("All variables and options saved in %s\n", tmp);
return -1;
}
save_list(title, list, command, equals, fp)
struct options *list;
register char *command, *title, equals;
register FILE *fp;
{
register struct options *opts;
register char *p;
if (!list)
return;
fprintf(fp, "#\n# %s\n#\n", title);
for (opts = list; opts; opts = opts->next) {
if (list == set_options && !strcmp(opts->option, "cwd"))
continue; /* don't print $cwd */
fprintf(fp, "%s %s", command, opts->option);
if (opts->value && *opts->value) {
register char *quote;
if (!equals)
quote = NO_STRING;
else if (p = any(opts->value, "\"'"))
if (*p == '\'') quote = "\"";
else quote = "'";
else
if (!any(opts->value, " \t;|"))
quote = NO_STRING;
else quote = "'";
fputc(equals? equals: ' ', fp);
fprintf(fp, "%s%s%s", quote, opts->value, quote);
}
fputc('\n', fp);
}
}
extern struct cmd_map map_func_names[];
save_cmd(title, list, command, equals, fp)
struct cmd_map *list;
register char *command, *title;
register int equals;
register FILE *fp;
{
register struct cmd_map *opts;
register char *p;
char buf[MAX_MACRO_LEN * 2];
if (!list)
return;
fprintf(fp, "#\n# %s\n#\n", title);
for (opts = list; opts; opts = opts->m_next) {
register char *quote;
if ((p = any(opts->m_str, "\"'")) && *p == '\'')
quote = "\"";
else
quote = "'";
fprintf(fp, "%s %s%s%s", command, quote,
ctrl_strcpy(buf, opts->m_str, TRUE), quote);
if (equals && map_func_names[opts->m_cmd].m_str)
fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
if (opts->x_str && *opts->x_str) {
if ((p = any(opts->x_str, "\"'")) && *p == '\'')
quote = "\"";
else
quote = "'";
fprintf(fp, " %s%s%s", quote,
ctrl_strcpy(buf, opts->x_str, TRUE), quote);
}
fputc('\n', fp);
}
}
/*
* do_alias handles aliases, header settings, functions, and fkeys.
* since they're all handled in the same manner, the same routine is
* used. argv[0] determines which to use.
* alias is given here as an example
*
* alias identify all aliases
* alias name identify alias
* alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
* unalias arg1 [arg2 arg3 ... ] unalias args
*
* same is true for dealing with your own headers.
* (also the expand command)
* always return -1 since it has no effect on messages
*/
do_alias(argc, argv)
register char **argv;
{
register char *cmd = *argv, *p;
struct options **list;
char firstchar = *cmd, buf[BUFSIZ];
if (argc == 0)
return 0 - in_pipe();
if (firstchar == 'u')
firstchar = cmd[2];
if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
register char *help_str;
if (firstchar == 'a' || firstchar == 'e')
help_str = "alias";
else if (firstchar == 'c')
help_str = "cmd";
else if (firstchar == 'f')
help_str = "fkey";
else
help_str = "own_hdrs";
return help(0, help_str, cmd_help);
}
if (firstchar == 'a')
list = &aliases;
else if (firstchar == 'c')
list = &functions;
else if (firstchar == 'f')
list = &fkeys;
else
list = &own_hdrs;
if (*cmd == 'u') {
if (!*argv) {
print("%s what?\n", cmd);
return -1;
/* unset a list separated by spaces or ',' */
} else while (*argv) {
if (!strcmp(*argv, "*")) /* unset everything */
while (*list)
(void) un_set(list, (*list)->option);
else if (!un_set(list, *argv))
print("\"%s\" isn't set\n", *argv);
argv++;
}
return 0;
}
if (!*argv && *cmd != 'e') {
/* just type out all the aliases or own_hdrs */
(void) do_set(*list, NULL);
return 0;
}
if (*cmd == 'e') { /* command was "expand" (aliases only) */
if (!*argv) {
print("expand which alias?\n");
return -1;
} else
do {
print("%s: ", *argv);
if (p = alias_to_address(*argv))
print("%s\n", p);
} while (*++argv);
return 0;
}
/* at this point, *argv now points to a variable name ...
* check for hdr -- if so, *argv better end with a ':' (check *p)
*/
if (list == &own_hdrs && !(p = index(*argv, ':'))) {
print("header labels must end with a ':' (%s)\n", *argv);
return -1;
}
if (!argv[1] && !index(*argv, '='))
if (p = do_set(*list, *argv))
print("%s\n", p);
else
print("%s is not set\n", *argv);
else {
char *tmpargv[2];
(void) argv_to_string(buf, argv);
if ((p = any(buf, " \t=")) && *p != '=')
*p = '=';
/* if we're setting an alias, enforce the insertion of commas
* between each well-formed address.
*/
if (list == &aliases)
fix_up_addr(p+1);
tmpargv[0] = buf;
tmpargv[1] = NULL;
(void) add_option(list, tmpargv);
}
return 0;
}