rsalz@bbn.com (Rich Salz) (04/14/88)
Submitted-by: island!argv@sun.com (Dan Heller) Posting-number: Volume 14, Issue 36 Archive-name: mush6.0/part04 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 14)." # Contents: help.c init.c misc.c pick.c setopts.c # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:44 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'help.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'help.c'\" else echo shar: Extracting \"'help.c'\" \(9753 characters\) sed "s/^X//" >'help.c' <<'END_OF_FILE' X/* @(#)help.c (c) copyright 10/15/86 (Dan Heller) */ X X/* X * This file conatins two main routines: X * display_help() and find_help() X * Both are virtually equivalent in functionality; they are passed X * a char * or a char **. If a char * is passed, then open "file" X * argument (containing help strings) and search for %str% and read X * the following text until %% or EOF into a local buffer. X * If str is a char **, then that array of strings is used directly. X * X * If display_help is used, then the final array of strings used is X * displayed in the center of the bitmapped console in a box with X * shading and the user must hit the left mouse button to remove the X * message. the fd passed is the fd of the window locking the screen. X * X * In text mode, the routine find_help is used (or, if the graphics X * mode doesn't want to lock the screen to display a message). The X * same actions occur, but instead of "ifdef"ing up one function, I X * just made two for readability. X */ X#include <stdio.h> X#include "strings.h" X X#define NULL_FILE (FILE *)0 X X#ifdef SUNTOOL X#include <suntool/tool_hs.h> X#include <signal.h> X#include <suntool/fullscreen.h> X X#define l_width() font->pf_defaultsize.x /* width of letter */ X#define l_height() font->pf_defaultsize.y /* height of letter */ X X#define draw(win,x1,y1,x2,y2,OP) pw_vector(win, x1,y1,x2,y2,OP,1) X#define box(win, x1,y1,x2,y2,OP) \ X draw(win,x1,y1, x1,y2, OP), \ X draw(win,x1,y2, x2,y2, OP), \ X draw(win,x2,y2, x2,y1, OP), \ X draw(win,x2,y1, x1,y1, OP) X X#define DEF_CONT_MSG "Click LEFT mouse Button to continue." DEFINE_CURSOR(oldcursor, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); X X/* shading */ static short dat_shade_25[] = { X#include <images/square_25.pr> X}; X static short dat_shade_50[] = { X#include <images/square_50.pr> X}; X static short dat_shade_75[] = { X#include <images/square_75.pr> X}; X static short dat_mouse_left[] = { X#include <images/confirm_left.pr> X}; X mpr_static(shade_25, 16, 16, 1, dat_shade_25); mpr_static(shade_50, 16, 16, 1, dat_shade_50); mpr_static(shade_75, 16, 16, 1, dat_shade_75); mpr_static(confirm_pr, 16, 16, 1, dat_mouse_left); X static struct cursor confirm_cursor = { 3, 3, PIX_SRC, &confirm_pr }; static struct pixrect *shading; X X#else X X#include <sys/types.h> X#define wprint printf X#define print printf X X#endif /* SUNTOOL */ X X/* what to print if nothing was found */ static char *def_msg[] = { X "There is no help found for this item.", X "Perhaps getting help from another item", X "would be of some use.", 0 X}; X X#define MAXLINES 40 X#define MAXLENGTH 128 static FILE *help_file; static char file_name[128]; X X#ifdef SUNTOOL display_help(fd, str, file, font) register caddr_t *str; /* could be a single or double pointer */ register char *file; register struct pixfont *font; X{ X struct fullscreen *fs; X struct inputmask im, old_im; X struct inputevent event; X struct rect rect; X register char *p; X register int x, y, z, height; X struct pixrect *saved, *save_bits(); X int width = 0, old_link; X char *cont_msg = DEF_CONT_MSG, *getenv(); X char args[MAXLINES][MAXLENGTH], help_str[40]; X X if (!shading) X if (p = getenv("SHADE")) { X register int x = atoi(p); X if (x <= 25) X shading = &shade_25; X else if (x <= 50) X shading = &shade_50; X else X shading = &shade_75; X } else X shading = &shade_25; X X /* If no file given, take "str" arg as message to print */ X if (!file || !*file) { X file = NULL; X for(height = 0; *str && height < MAXLINES-1; height++) { X if (!compose_str(*str, &width)) X break; X (void) strcpy(args[height], *str++); X } X } else { X if (!*file_name || strcmp(file_name, file)) { X (void) strcpy(file_name, file); X if (help_file) X fclose(help_file), help_file = NULL_FILE; X } X /* file remains open */ X if (!help_file && !(help_file = fopen(file_name, "r"))) X return -1; X /* look for %str% in helpfile */ X (void) sprintf(help_str, "%%%s%%\n", str); X X rewind(help_file); X X while(p = fgets(args[0], MAXLENGTH, help_file)) X if (*p == '%' && !strcmp(p, help_str)) X break; X X if (!p || !fgets(args[0], MAXLENGTH, help_file)) X for(height = 0; def_msg[height] && height < MAXLINES-1; height++) { X compose_str(def_msg[height], &width); X (void) strcpy(args[height], def_msg[height]); X } X else for (height = 0; p && *p && strcmp(p, "%%\n"); height++) { X compose_str(p, &width); X p = fgets(args[height+1], MAXLENGTH, help_file); X } X } X if (height == MAXLINES - 1) X print("Help message is too long!\n"); X X fs = fullscreen_init(fd); X /* Figure out the height and width in pixels (rect.r_height, rect.r_width) X * Remember to provide for the "confirm" line (cont_msg). X * extend the new box by 15 pixels on the sides (30 total), top, and bottom. X * finally, add 16 pixels for "shadow" -- remove before clearing area X * to preserve background and give a shadow-like appearance. X */ X if ((x = strlen(cont_msg)) > width) X width = x; /* this x value must be saved! */ X rect.r_width = (width*l_width()) + 30 + 16; X rect.r_height = ((height+1) * l_height()) + 30 + 16; X rect.r_left = fs->fs_screenrect.r_left + X (fs->fs_screenrect.r_width / 2) - (rect.r_width / 2); X rect.r_top = fs->fs_screenrect.r_top + X (fs->fs_screenrect.r_height / 2) - (rect.r_height / 2); X X /* save old area */ X saved = save_bits(fs->fs_pixwin, &rect); X X /* prepare surface, clear the background, and reset rect for shadow */ X pw_preparesurface(fs->fs_pixwin, &rect); X pw_lock(fs->fs_pixwin, &rect); X rect.r_width -= 16; X rect.r_height -= 16; X X pw_writebackground(fs->fs_pixwin, X rect.r_left, rect.r_top, rect.r_width, rect.r_height, PIX_CLR); X X /* make a box that's 5 pixels thick. Then add a thin box inside it */ X for (z = 0; z < 5; z++) X box(fs->fs_pixwin, X rect.r_left+z, rect.r_top+z, X rect.r_left+rect.r_width-z-1, rect.r_top+rect.r_height-z-1, X PIX_SRC); X box(fs->fs_pixwin, X rect.r_left+z+2, rect.r_top+z+2, X rect.r_left+rect.r_width-z-3, rect.r_top+rect.r_height-z-3, X PIX_SRC); X X /* shading -- pw_replrop() doesn't work (bug) X * NOTE: fs->fs_screenrect.r_top and r_left are negative values X */ X pr_replrop(fs->fs_pixwin->pw_pixrect, X rect.r_left + rect.r_width - fs->fs_screenrect.r_left, X rect.r_top + 16 - fs->fs_screenrect.r_top, X 16, rect.r_height-16, PIX_SRC|PIX_DST, shading, 0, 0); X pr_replrop(fs->fs_pixwin->pw_pixrect, X rect.r_left + 16 - fs->fs_screenrect.r_left, X rect.r_top+rect.r_height - fs->fs_screenrect.r_top, X rect.r_width, 16, PIX_SRC|PIX_DST, shading, 0, 0); X X if (x > width) X x = 15; X else X x = rect.r_width/2 - (x*l_width())/2; X y = rect.r_height - 15; X X /* Print everything in reverse order now; start with the "confirm" string X * (which is centered and highlighted) X */ X pw_text(fs->fs_pixwin, rect.r_left+x, rect.r_top+y, PIX_SRC,font, cont_msg); X pw_text(fs->fs_pixwin, rect.r_left+x+1, rect.r_top+y, PIX_SRC|PIX_DST, font, X cont_msg); X X y -= (5 + l_height()); X x = 15; X X /* now print each string in reverse order (start at bottom of box) */ X for (height--; height >= 0; height--) { X pw_text(fs->fs_pixwin, rect.r_left+x, rect.r_top+y, X PIX_SRC, font, args[height]); X y -= l_height(); X } X X pw_unlock(fs->fs_pixwin); X X /* wait for user to read and confirm */ X win_getinputmask(fd, &old_im, &old_link); X input_imnull(&im); X im.im_flags |= IM_ASCII; X win_setinputcodebit(&im, MS_LEFT); X win_setinputcodebit(&im, MS_MIDDLE); X win_setinputcodebit(&im, MS_RIGHT); X win_setinputmask(fd, &im, &im, WIN_NULLLINK); X win_getcursor(fd, &oldcursor); X win_setcursor(fd, &confirm_cursor); X while (input_readevent(fd, &event) != -1 && event.ie_code != MS_LEFT); X X /* restore old cursor */ X win_setcursor(fd, &oldcursor); X X /* restore old pixrect (size already restored) */ X rect.r_height += 16; /* to take care of the shadow */ X rect.r_width += 16; X restore_bits(fs->fs_pixwin, &rect, saved); X /* release screen */ X fullscreen_destroy(fs); X win_setinputmask(fd, &old_im, &old_im, old_link); X return 0; X} X static compose_str(p, width) register char *p; int *width; X{ X register int x; X if (!p || !*p) X return 0; X x = strlen(p); X if (p[x-1] == '\n') X p[--x] = 0; /* get rid of newline */ X if (x > *width) X *width = x; X return 1; X} X#endif /* SUNTOOL */ X find_help(str, file) register caddr_t *str; register char *file; X{ X register char *p; X char args[MAXLINES][MAXLENGTH], help_str[40]; X register int n, height; X extern char *no_newln(); X X /* If no file given, take "str" arg as message to print */ X if (!file || !*file) { X file = NULL; X for(height = 0; *str && height < MAXLINES-1; height++) X (void) strcpy(args[height], *str++); X } else { X if (!*file_name || strcmp(file_name, file)) { X (void) strcpy(file_name, file); X if (help_file) X fclose(help_file), help_file = NULL_FILE; X } X /* file remains open */ X if (!help_file && !(help_file = fopen(file_name, "r"))) X return -1; X /* look for %str% in helpfile */ X (void) sprintf(help_str, "%%%s%%\n", str); X rewind(help_file); X while(p = fgets(args[0], MAXLENGTH, help_file)) X if (*p == '%' && !strcmp(p, help_str)) X break; X if (!p || !fgets(args[0], MAXLENGTH, help_file)) X for(height = 0; def_msg[height] && height < MAXLINES-1; height++) X (void) strcpy(args[height], def_msg[height]); X else for (height = 0; p && *p && strcmp(p, "%%\n"); height++) X p = fgets(args[height+1], MAXLENGTH, help_file); X } X if (height == MAXLINES - 1) X print("Help message is too long!\n"); X X for (n = 0; n < height; n++) { X (void) no_newln(args[n]); X wprint("%s\n", args[n]); X } X X return 0; X} END_OF_FILE if test 9753 -ne `wc -c <'help.c'`; then echo shar: \"'help.c'\" unpacked with wrong size! fi # end of 'help.c' fi if test -f 'init.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'init.c'\" else echo shar: Extracting \"'init.c'\" \(10032 characters\) sed "s/^X//" >'init.c' <<'END_OF_FILE' X/* init.c (c) copyright 1986 (Dan Heller) */ X X/* init.c -- functions and whatnot that initialize everything */ X#include "mush.h" X#include <pwd.h> X X#ifdef SUNTOOL X/* mouse symbols */ short dat_mouse_left[] = { X#include <images/confirm_left.pr> X}; X short dat_mouse_middle[] = { X#include <images/confirm_middle.pr> X}; X short dat_mouse_right[] = { X#include <images/confirm_right.pr> X}; X short dat_mail_icon_1[] = { X#include "mail.icon.1" X}; X short dat_mail_icon_2[] = { X#include "mail.icon.2" X}; X short dat_coffee_cup[] = { X#include "coffee.cup.pr" X}; X short dat_read_cursor[] = { X#include "glasses.pr" X}; X short dat_write_cursor[] = { X#include "write.pr" X}; X short dat_up_arrow[] = { X#include "up.arrow.pr" X}; X short dat_dn_arrow[] = { X#include "dn.arrow.pr" X}; X short dat_envelope[] = { X#include "envelope.pr" X}; X short dat_cycle_cursor[] = { X#include "cycle.pr" X}; X short dat_check_cursor[] = { X#include "check.pr" X}; X mpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1); mpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2); X mpr_static(mouse_left, 16, 16, 1, dat_mouse_left); mpr_static(mouse_middle, 16, 16, 1, dat_mouse_middle); mpr_static(mouse_right, 16, 16, 1, dat_mouse_right); mpr_static(coffee_cup, 16, 16, 1, dat_coffee_cup); mpr_static(glasses_cursor, 16, 16, 1, dat_read_cursor); mpr_static(pencil_cursor, 16, 16, 1, dat_write_cursor); mpr_static(up_arrow, 16, 16, 1, dat_up_arrow); mpr_static(dn_arrow, 16, 16, 1, dat_dn_arrow); mpr_static(envelope_cursor, 16, 16, 1, dat_envelope); mpr_static(cycle, 16, 16, 1, dat_cycle_cursor); mpr_static(check_cursor, 16, 16, 1, dat_check_cursor); X struct cursor l_cursor = { 3, 3, PIX_SRC, &mouse_left }; struct cursor m_cursor = { 3, 3, PIX_SRC, &mouse_middle }; struct cursor r_cursor = { 3, 3, PIX_SRC, &mouse_right }; struct cursor coffee = { 8, 8, PIX_SRC, &coffee_cup }; struct cursor read_cursor = { 8, 8, PIX_SRC|PIX_DST, &glasses_cursor }; struct cursor write_cursor = { 8, 8, PIX_SRC|PIX_DST, &pencil_cursor }; struct cursor main_cursor = { 8, 8, PIX_SRC, &envelope_cursor }; struct cursor checkmark = { 8, 8, PIX_SRC|PIX_DST, &check_cursor }; X X/* text and font will be set in mail_status() */ struct icon mail_icon = { 64, 64, (struct pixrect *)NULL, X { 0, 0, 64, 64 }, &mail_icon_image1, X { 5, 5, 26, 12 }, NULL, (struct pixfont *)NULL, 0 }; X char *font_files[] = { X "serif.r.14", "sail.r.6", "serif.r.16", X}; X char *alt_fonts[] = { X "gacha.r.8", "sail.r.6", "screen.r.14", X}; X X#endif /* SUNTOOL */ X X#ifdef BSD X#include <netdb.h> X#endif /* BSD */ X void init() X{ X char *home; X extern char *getlogin(); X#ifdef SYSV X extern struct passwd *getpwuid(); /* sys-v forgot this in pwd.h! */ X#else X char ourhost[128]; X#endif /* SYSV */ X register char *p; X struct passwd *entry; X int cnt = 0; X#ifdef BSD X struct hostent *hp; X#endif /* BSD */ X X home = getenv ("HOME"); X X if (!(entry = getpwuid(getuid()))) X if (p = getlogin()) X strdup(login, p); X else { X login = "unknown"; X print("I don't know you, but that's ok.\n"); X } X else { X strdup(login, entry->pw_name); X if (!home || !*home) X home = entry->pw_dir; X endpwent(); X } X if (!home || !*home || Access(home, W_OK)) { X if (home && *home) X error(home); X else X print("No home!? "); X print_more("Using \"%s\" as home.\n", ALTERNATE_HOME); X } else { X char buf[MAXPATHLEN]; X cmd_line(sprintf(buf, "set home=\"%s\"", home), msg_list); X } X crt = 25; X screen = 18; X escape = DEF_ESCAPE; X prompt = DEF_PROMPT; X X#ifndef SYSV X (void) gethostname(ourhost, sizeof ourhost); X if (!(hp = gethostbyname(ourhost))) X error("gethostbyname: %s", ourhost); X else for (p = hp->h_name; p && *p && cnt < MAX_HOST_NAMES; X p = hp->h_aliases[cnt++]) X ourname[cnt] = savestr(p); X endhostent(); X#endif /* SYSV */ X X#ifdef CURSES X init_bindings(); X#endif /* CURSES */ X} X X/* X * Source a file, or just the default file. Since sourcing files X * means reading possible aliases, don't expand the ! as history X * by setting the IGN_BANG flag. Since a command in the sourced file X * may call source on another file, this routine may be called from X * within itself. Continue to ignore ! chars by setting save_bang (local). X * X * Try opening the file passed to us. If not given, check for the correct X * .rc file which is found in the user's home dir. X */ source(argc, argv) char **argv; X{ X register char *p, *p2, **newargv; X int line_no = 0, if_else = 0, parsing = 1, cont_line = 0; X FILE *fp; X char file[128], line[BUFSIZ]; X u_long save_bang = ison(glob_flags, IGN_BANG); X X if (argc && *++argv && !strcmp(*argv, "-?")) X return help(0, "source_help", cmd_help); X if (argc && *argv) X (void) strcpy(file, *argv); X else if (p = getenv("MAILRC")) X (void) strcpy(file, p); X else { X char *home = do_set(set_options, "home"); X if (!home || !*home) X home = ALTERNATE_HOME; X if (Access(sprintf(file, "%s/%s", home, MAILRC), R_OK) X && Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), R_OK)) X (void) strcpy(file, DEFAULT_RC); X } X X argc = 0; /* don't ignore ENOENT */ X p = getpath(file, &argc); X if (argc) { X if (strcmp(file, DEFAULT_RC)) X if (argc == -1) X print("%s: %s\n", file, p); X else X print("%s is a directory.\n", file); X return -1; X } X if (!(fp = fopen(p, "r"))) { X if (errno != ENOENT) X error("Can't open %s", p); X return -1; X } X (void) strcpy(file, p); X turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */ X while (p = fgets(&line[cont_line], BUFSIZ - cont_line, fp)) { X line_no++; X if (*(p2 = no_newln(p)) == '\\') { X cont_line = p2 - line; X continue; X } else X cont_line = 0; X /* don't consider comments (#) in lines. check if # is within quotes */ X if (p = any(line, "\"'#")) { X register int balanced = 1; X while (p && (*p == '\'' || *p == '"') && balanced) { X /* first find matching quote */ X register char *quote = index(p+1, *p); X if (!quote) { X print("%s: line %d: unbalanced %c.\n", file, line_no, *p); X balanced = 0; X } else X p = any(quote+1, "'\"#"); X } X if (!balanced) X continue; X if (p && *p == '#') X *p = 0; /* found a Comment: null terminate line at comment */ X } X if (!*line || !(newargv = make_command(line, TRPL_NULL, &argc))) { X if (!strncmp(line, "if", 2)) X if_else++, parsing = FALSE; X continue; X } X if (!strcmp(newargv[0], "endif")) { X if (!if_else) X print("%s: line %d: endif with no \"if\".\n", file, line_no); X else X if_else = 0, parsing = 1; X goto bad; X } else if (!strcmp(newargv[0], "else")) { X if (!if_else) X print("%s: line %d: if-less \"else\".\n", file, line_no); X else X parsing = !parsing; X goto bad; X } else if (parsing && !strcmp(newargv[0], "if")) { X /* if statements are of the form: X * if expr X * if !expr or if ! expr X * if expr == expr or if expr != expr X */ X int equals = TRUE; X register char *lhs = newargv[1], *rhs = NULL; X X if (if_else) X print("%s: line %d: no nested if statements!\n", file, line_no); X else X if_else = 1; X parsing = 0; X if (!lhs || !*lhs) { X print("%s: line %d: if what?\n", file, line_no); X goto bad; X } X /* "lhs" is the left hand side of the equation X * In this instance, we're doing case 2 above. X */ X if (*lhs == '!') { X int tmp = argc; X equals = FALSE; X if (!*++lhs) X if (!(lhs = newargv[2])) { X print("%s: %d: syntax error: \"if ! <what?>\"\n", X file, line_no); X goto bad; X } else X tmp--; X if (tmp > 2) { X print("%s: %d: syntax error: \"if !<expr> <more junk>\"\n", X file, line_no); X goto bad; X } X } else if (argc > 2) { X if (argc != 4) { X print("%s: %d: argument count error: line has %d args.\n", X file, line_no, argc); X goto bad; X } X /* now check newargv[1] for == or != */ X if (!strcmp(newargv[2], "!=")) X equals = FALSE; X else if (strcmp(newargv[2], "==")) { X print("%s: %d: use `==' or `!=' only.\n", file, line_no); X goto bad; X } X rhs = newargv[3]; X } X if (!strcmp(lhs, "redirect") && X (ison(glob_flags, REDIRECT) && equals || X isoff(glob_flags, REDIRECT) && !equals) X || !strcmp(lhs, "is_sending") && X (ison(glob_flags, IS_SENDING) && equals || X isoff(glob_flags, IS_SENDING) && !equals) X || !strcmp(lhs, "hdrs_only") && X (hdrs_only && equals || !hdrs_only && !equals) X || !strcmp(lhs, "istool") && X (istool && equals || !istool && !equals) X || !strcmp(lhs, "iscurses") && X ((iscurses || ison(glob_flags, PRE_CURSES)) && equals || X (isoff(glob_flags, PRE_CURSES) && !iscurses && !equals))) X parsing = 1; X else if (rhs) X if (strcmp(lhs, rhs) && !equals || !strcmp(lhs, rhs) && equals) X parsing = 1; bad: X free_vec(newargv); X continue; X } X if (parsing && argc > 0) X if (!strcmp(newargv[0], "exit")) { X if_else = 0; X break; X } else X (void) do_command(argc, newargv, msg_list); X else X free_vec(newargv); X } X if (if_else) X print("%s: missing endif\n", file); X fclose(fp); X /* if we entered the routine ignoring !, leave it that way. */ X if (!save_bang) X turnoff(glob_flags, IGN_BANG); X return -1; X} X X#ifdef SUNTOOL X/* open all fonts and place in fonts array. */ getfonts() X{ X char tmp[80]; X register int offset = strlen(FONTDIR) + 1; X struct pixfont *pf_open(); X X (void) sprintf(tmp, "%s/", FONTDIR); X for (total_fonts = 0; total_fonts < MAX_FONTS; total_fonts++) { X (void) strcpy(&tmp[offset], font_files[total_fonts]); X if (!(fonts[total_fonts] = pf_open(tmp))) { X (void) strcpy(&tmp[offset], alt_fonts[total_fonts]); X if (!(fonts[total_fonts] = pf_open(tmp))) { X print("couldn't open font \"%s\"\n", tmp); X fonts[total_fonts] = pf_default(); X } X } X } X} X#endif /* SUNTOOL */ END_OF_FILE if test 10032 -ne `wc -c <'init.c'`; then echo shar: \"'init.c'\" unpacked with wrong size! fi # end of 'init.c' fi if test -f 'misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'misc.c'\" else echo shar: Extracting \"'misc.c'\" \(10953 characters\) sed "s/^X//" >'misc.c' <<'END_OF_FILE' X/* @(#)misc.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X X/* check to see if a string describes a message that is within the range of X * all messages; if invalid, return 0 and print error. else return msg number X */ chk_msg(s) register char *s; X{ X register int n; X X if ((n = atoi(s)) > 0 && n <= msg_cnt) X return n; X else if (*s == '^' && msg_cnt) X return 1; X else if (*s == '$' && msg_cnt) X return msg_cnt; X else if (*s == '.' && msg_cnt) X return current_msg+1; X print("Invalid message number: %s\n", s); X return 0; X} X X/* X * loop thru all msgs starting with current_msg and find next undeleted X * message. If the variable "wrap" is set, wrap to the beginning of the X * message list if we hit the end. otherwise, stop at the end of the list. X */ next_msg() X{ X register int n = current_msg; X register int wrap = !!do_set(set_options, "wrap"); X X if (!msg_cnt) X return current_msg = 0; X for (n++; n != current_msg; n++) X if (n == msg_cnt) /* hit the end, start back at the beginning */ X if (!wrap) X return current_msg = msg_cnt - 1; X else X n = -1; /* increments to 0 in loop */ X else if (isoff(msg[n].m_flags, DELETE)) X return current_msg = n; X return current_msg = 0; X} X X/* since print_help just prints help, always return help() */ print_help(argc, argv) register char **argv; X{ X#ifdef SUNTOOL X if (istool) X return help(tool->tl_windowfd, "general", tool_help); X#endif /* SUNTOOL */ X if (!argc || !*++argv) X return help(0, "general", cmd_help); X return help(0, *argv, cmd_help); X} X X/* since this function does not affect messages, return -1 */ help(fd, str, file) X#ifdef SUNTOOL caddr_t *str; X#else char *str; X#endif /* SUNTOOL */ char *file; X{ X#ifdef SUNTOOL X if (istool > 1) { X int oldmask; X if (!fd) X fd = print_sw->ts_windowfd; X oldmask = sigblock(1 << ((SIGALRM) - 1)); X lock_cursors(); X if (display_help(fd, str, file, fonts[LARGE]) && file) X error("can't read %s", file); X unlock_cursors(); X (void) sigsetmask(oldmask); X } else X#endif /* SUNTOOL */ X if (find_help(str, file) && file) X error("can't read %s", file); X return -1; /* doesn't affect any messages */ X} X X#ifdef SUNTOOL void unlock_cursors() X{ X if (istool < 2) X return; X win_setcursor(print_sw->ts_windowfd, &main_cursor); X win_setcursor(panel_sw->ts_windowfd, &main_cursor); X if (getting_opts) X win_setcursor(msg_sw->ts_windowfd, &checkmark); X else if (ison(glob_flags, IS_GETTING)) X win_setcursor(msg_sw->ts_windowfd, &write_cursor); X else X win_setcursor(msg_sw->ts_windowfd, &read_cursor); X win_setcursor(hdr_panel_sw->ts_windowfd, &main_cursor); X win_setcursor(hdr_sw->ts_windowfd, &l_cursor); X} X void lock_cursors() X{ X if (istool < 2) X return; X win_setcursor(hdr_sw->ts_windowfd, &coffee); X win_setcursor(print_sw->ts_windowfd, &coffee); X win_setcursor(panel_sw->ts_windowfd, &coffee); X win_setcursor(msg_sw->ts_windowfd, &coffee); X win_setcursor(hdr_panel_sw->ts_windowfd, &coffee); X} X X#include <suntool/fullscreen.h> X/* return the event-id that confirmed */ confirm(fd) X{ X struct fullscreen *fs; X X struct inputmask im; X struct inputevent event; X X fs = fullscreen_init(fd); X input_imnull(&im); X im.im_flags |= IM_ASCII; X win_setinputcodebit(&im, MS_LEFT); X win_setinputcodebit(&im, MS_MIDDLE); X win_setinputcodebit(&im, MS_RIGHT); X win_setinputmask(fd, &im, &im, WIN_NULLLINK); X win_setcursor(fd, &l_cursor); X if (input_readevent(fd, &event) == -1) X error("confim failed"); X fullscreen_destroy(fs); X return ID; X} X#endif /* SUNTOOL */ X X/* return -1 on error or number of arguments in argv that were parsed */ get_msg_list(argv, list) register char **argv; char list[]; X{ X register char *p2, *p; X char buf[256]; X register int n; X X if (!msg_cnt) { X print("No messages.\n"); X return -1; X } X if (!argv || !*argv) { X if (isoff(glob_flags, IS_PIPE)) X set_msg_bit(list, current_msg); X return 0; X } X /* first, stuff argv's args into a single char array buffer */ X (void) argv_to_string(buf, argv); X p = buf; X Debug("get_msg_list: parsing: (%s): ", p); X /* X * if do_range returns NULL, an invalid message was specified X */ X if (!(p2 = do_range(p, list))) X return -1; X /* X * if p2 == p (and p isn't $ or ^ or .), then no message list was X * specified. set the current message in such cases if we're not piping X */ X if (p2 == p) { X if (*p == '$') X set_msg_bit(list, msg_cnt-1); X else if (*p == '^') X set_msg_bit(list, 0); X else if (*p == '.' || isoff(glob_flags, IS_PIPE)) X set_msg_bit(list, current_msg); X } X for (n = 0; p2 > p && *argv; n++) X p2 -= (strlen(*argv++)+1); X Debug("parsed %d args\n", n); X return n; X} X X#ifdef NOT_NEEDED_NOW X/* return whether or not this process is in the foreground or background */ foreground() X{ X#ifdef TIOCGPGRP X int tpgrp; /* short in 4.1, int in 4.2 */ X X if (ioctl(0, TIOCGPGRP, (char *)&tpgrp)) X return 0; X return tpgrp == getpgrp(0); X#else X return 1; X#endif /* TIOCGPGRP */ X} X#endif /* NOT_NEEDED_NOW */ X X/* X * execute a command from a string. f'rinstance: "pick -f foobar" X * The string is made into an argv and then run. Errors are printed X * if the command failed to make. X * NOTES: X * NEVER pass stright text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...") X * no history is expanded (ignore_bang). X */ cmd_line(buf, list) char buf[], list[]; X{ X register char **argv; X int argc, ret_val = -1; X u_long save_do_pipe = ison(glob_flags, DO_PIPE); X u_long save_is_pipe = ison(glob_flags, IS_PIPE); X X turnoff(glob_flags, DO_PIPE); X turnoff(glob_flags, IS_PIPE); X if (argv = make_command(buf, TRPL_NULL, &argc)) X ret_val = do_command(argc, argv, list); X if (save_do_pipe) X turnon(glob_flags, DO_PIPE); X else X turnoff(glob_flags, DO_PIPE); X if (save_is_pipe) X turnon(glob_flags, IS_PIPE); X else X turnoff(glob_flags, IS_PIPE); X return ret_val; X} X glob_test(s) char *s; X{ X print("%s: glob_flags =", s); X if (ison(glob_flags, DO_UPDATE)) X print_more(" DO_UPDATE"); X if (ison(glob_flags, REV_VIDEO)) X print_more(" REV_VIDEO"); X if (ison(glob_flags, CONT_PRNT )) X print_more(" CONT_PRNT"); X if (ison(glob_flags, DO_SHELL )) X print_more(" DO_SHELL"); X if (ison(glob_flags, DO_PIPE)) X print_more(" DO_PIPE"); X if (ison(glob_flags, IS_PIPE)) X print_more(" IS_PIPE"); X if (ison(glob_flags, IGN_SIGS)) X print_more(" IGN_SIGS"); X if (ison(glob_flags, IGN_BANG)) X print_more(" IGN_BANG"); X if (ison(glob_flags, ECHO_FLAG)) X print_more(" ECHO_FLAG"); X if (ison(glob_flags, IS_GETTING)) X print_more(" IS_GETTING"); X if (ison(glob_flags, PRE_CURSES)) X print_more(" PRE_CURSES"); X if (ison(glob_flags, READ_ONLY )) X print_more(" READ_ONLY"); X if (ison(glob_flags, REDIRECT)) X print_more(" REDIRECT"); X if (ison(glob_flags, WAS_INTR )) X print_more(" WAS_INTR"); X if (ison(glob_flags, WARNING )) X print_more(" WARNING"); X print_more("\n"); X} X msg_flags(c, v, list) register char **v, *list; X{ X register int i; X register u_long newflag = 0; X X if (c && *++v && !strcmp(*v, "-?")) X return help(0, "msg_flags", cmd_help); X if (c && (c = get_msg_list(v, list)) == -1) X return -1; X if (v && *(v += (c-1))) { X turnon(glob_flags, DO_UPDATE); X while (*++v) X for (c = 0; v[0][c]; c++) X switch (lower(v[0][c])) { X case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD); X when 'd' : turnon(newflag, DELETE); X when 'p' : turnon(newflag, PRESERVE); X when 'u' : turnon(newflag, UNREAD); /* fall thru! */ X case 'o' : turnon(newflag, OLD); X when 'r' : X if (v[0][c] == 'R') X turnoff(newflag, UNREAD), turnon(newflag, OLD); X else X turnon(newflag, REPLIED); X otherwise: return help(0, "msg_flags", cmd_help); X } X } X X for (i = 0; i < msg_cnt; i++) { X if (!msg_bit(list, i)) X continue; X else if (!newflag) { X wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1, X msg[i].m_offset, msg[i].m_lines, msg[i].m_size); X if (ison(msg[i].m_flags, UNREAD)) X wprint(" UNREAD"); X if (ison(msg[i].m_flags, OLD)) X wprint(" OLD"); X if (ison(msg[i].m_flags, DELETE)) X wprint(" DELETE"); X if (ison(msg[i].m_flags, PRESERVE)) X wprint(" PRESERVE"); X if (ison(msg[i].m_flags, REPLIED)) X wprint(" REPLIED"); X if (ison(msg[i].m_flags, UPDATE_STATUS)) X wprint(" UPDATE_STATUS"); X wprint("\n"); X } else X msg[i].m_flags = newflag; X } X return 0; X} X X/* X * Internal pager. Start the internal pager by passing the name of X * the pager in buf and passing TRUE as start_pager. If the internal X * pager is desired, pass NULL as buf. Continue paging by passing X * FALSE as start_page and the buf is the stuff to pass thru to the X * pager. End paging by passing NULL as buf and FALSE as start_flag. X * If the pager can't be used, or is null, we're paging ourselves. X * The -e command line flag (tty echoing done by terminal driver) makes X * this internal paging ugly, but hey -- such users get what they pay for. X * Windows does nothing but echo buf to the msg window. X * The "buff" passed to the pager should be a line at a time so as to X * count \n's. It could be modified to count \n's, but that'd be slow. X * Return EOF if pager died, user exited pager, or if user types 'q' X * at the --more-- prompt for the internal pager. X */ do_pager(buf, start_pager) register char *buf; X{ X static FILE *pp; X static int cnt; X X#ifdef SUNTOOL X if (istool) { X if (buf && !start_pager) X Addstr(buf); X return 0; X } X#endif /* SUNTOOL */ X if (start_pager) { X turnon(glob_flags, IGN_SIGS); X if (!buf) X pp = stdout; X else if (!(pp = popen(buf, "w"))) X error(buf); X else X echo_on(); X cnt = 0; X } else if (!buf) { X if (pp && pp != stdout) X pclose(pp); X pp = NULL_FILE; X echo_off(); X turnoff(glob_flags, IGN_SIGS); X } else if (pp != stdout) X return fputs(buf, pp); /* returns EOF if user exited pager */ X else { X register char c = 0, *cr = index(buf, '\n'); X if (cr && (c = *++cr) != '\0') X *cr = 0; /* send one line to stdout and prompt for more */ X (void) fputs(buf, pp); X if (cr && !(++cnt % (crt-1))) { X int n = c_more(NULL); X if (n == '\n' || n == '\r') X cnt--; /* go line by line */ X else if (n == CTRL(D) || n < 0) { X clearerr(stdin); X cnt += (cnt/2); X } else if (lower(n) == 'q') X return EOF; X } X if (c) { X *cr = c; X return do_pager(cr, FALSE); X } X } X return 0; X} X X/* curses based "more" like option */ c_more(p) register char *p; X{ X register int c; X X if (!p) X p = "--more--"; X print_more(p); X X while ((c = getchar()) >= 0 && c != CTRL(D) && !isspace(c) && X c != '\n' && c != '\r' && lower(c) != 'q') X bell(); X if (ison(glob_flags, ECHO_FLAG) && c != '\n' && c != '\r') X while (getchar() != '\n'); X printf("\r%*c\r", strlen(p), ' '), fflush(stdout); /* remove the prompt */ X return c; X} END_OF_FILE if test 10953 -ne `wc -c <'misc.c'`; then echo shar: \"'misc.c'\" unpacked with wrong size! fi # end of 'misc.c' fi if test -f 'pick.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pick.c'\" else echo shar: Extracting \"'pick.c'\" \(10751 characters\) sed "s/^X//" >'pick.c' <<'END_OF_FILE' X/* @(#)pick.c 2.4 (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X static int before, mdy[3], search_from, search_subj, search_to, xflg, icase; static search_hdr[64]; X do_pick(n, argv, list) register int n; register char **argv, list[]; X{ X if (n > 1 && !strcmp(argv[1], "-?")) X return help(0, "pick", cmd_help); X X /* if is_pipe, then the messages to search for are already set. X * if not piped, then reverse the bits for all message numbers. X * That is, search EACH message. only those matching will be returned. X */ X if (isoff(glob_flags, IS_PIPE)) X bitput(list, list, msg_cnt, =~) /* macro, turn on all bits */ X if (pick(n, argv, list, isoff(glob_flags, DO_PIPE)) == -1) X return -1; X if (isoff(glob_flags, DO_PIPE)) { X if (istool) X print("Messages: "); X for (n = 0; n < msg_cnt; n++) X if (msg_bit(list, n)) X if (istool) X print_more("%d ", n+1); X else X print("%s\n", compose_hdr(n)); X } X return 0; X} X pick(ret, argv, list, verbose) register int ret; register char **argv, list[]; X{ X register char c; X int o_before = before, o_mdy[3], o_search_from = search_from, X o_search_subj = search_subj, o_search_to = search_to, o_xflg = xflg, n; X X for (c = 0; c < 3; c++) X o_mdy[c] = mdy[c]; X X ret = -1; X if (!msg_cnt) { X print("No Messages.\n"); X goto bad; X } X X icase = before = search_from = search_subj = xflg = 0; X mdy[0] = search_hdr[0] = 0; X while (*argv && *++argv && **argv == '-') X switch(c = argv[0][1]) { X /* users specifies a range */ X case 'r': { X int X = 2; X /* if not a pipe, then clear all bits cuz we only want X * to search the message specified here... X * If it is a pipe, then add to the messages searched for. X */ X if (isoff(glob_flags, IS_PIPE)) X clear_msg_list(list); X /* "-r10-15" X * ^argv[1][2] if NULL, then X * list detached from "r" e.g. "-r" "5-20" X */ X if (!argv[0][X]) X argv++, X = 0; X (*argv) += X; X n = get_msg_list(argv, list); X (*argv) -= X; X if (n == -1) X goto bad; X argv += (n-1); /* we're going to increment another up top */ X } X when 'd': X if (!*++argv) { X print("specify a date for -%c\n", c); X goto bad; X } X if (!date1(*argv)) X goto bad; X when 's' : case 'f': case 't': case 'h': X if (search_subj + search_from + search_to + *search_hdr > 1) { X print("specify one of `s', `f', `t' or `h' only\n"); X goto bad; X } X if (c == 's') X search_subj = 1; X else if (c == 'f') X search_from = 1; X else if (c == 'h') X if (!*++argv) X print("Specify header to search for.\n"); X else X (void) strcpy(search_hdr, *argv); X else X search_to = 1; X when 'x' : xflg = 1; X when 'i' : icase = 1; X otherwise: X print("pick: unknown flag: %c\n", argv[0][1]); X clear_msg_list(list); X return -1; X } X if (verbose) { X print_more("Searching for messages"); X if (mdy[1] == 0) X print(" that %s \"%s\"", (xflg)? "doesn't contain": "contains", X (*argv)? *argv: "<previous expression>"); X if (search_subj) X print_more(" in subject line"); X else if (search_from) X print_more(" from author names"); X else if (search_to) X print_more(" from the To: field"); X else if (search_hdr[0]) X print_more(" from the message header: \"%s:\"", search_hdr); X if (mdy[1] > 0) { X extern char *month_names[]; /* from dates.c */ X print_more(" dated on or %s %s. %d, 19%d.", X (before)? "before": "after", X month_names[mdy[0]], mdy[1], mdy[2]); X } X print_more("\n"); X } X if (mdy[1] > 0 && icase) X print("using date: -i flag ignored.\n"); X ret = find_pattern(*argv, list); bad: X before = o_before, search_from = o_search_from; X search_subj = o_search_subj, search_to = o_search_to, xflg = o_xflg; X for (c = 0; c < 3; c++) X mdy[c] = o_mdy[c]; X return ret; X} X find_pattern(p, list) register char *p, list[]; X{ X register int n, val, i; /* val is return value from regex or re_exec */ X long bytes = 0; X char buf[BUFSIZ]; X static char *err = (char *)-1; X#ifdef REGCMP X char *regcmp(), *regex(); X#else /* REGCMP */ X char *re_comp(); X#endif /* REGCMP */ X X if (p && *p == '\\') X p++; /* take care of escaping special cases (`-', `\') */ X X /* specify what we're looking for */ X if (p && *p) { X if (icase) X p = lcase_strcpy(buf, p); X#ifdef REGCMP X if (err && p) X xfree(err); X if (p && !(err = regcmp(p, NULL))) { X print("regcmp error: %s\n", p); X clear_msg_list(list); X return -1; X } X#else /* REGCMP */ X if (err = re_comp(p)) { X print("re_comp error: %s\n", err); X clear_msg_list(list); X return -1; X } X#endif /* REGCMP */ X } else if (err == (char *)-1 && mdy[1] <= 0) { X print("No previous regular expression\n"); X clear_msg_list(list); /* doesn't matter really */ X return -1; X } X /* start searching: set bytes, and message number: n */ X for (n = 0; n < msg_cnt; n++) X if (msg_bit(list, n)) { X if (mdy[1] > 0) { X int msg_mdy[3]; X if (!(p = msg_date(n))) { X unset_msg_bit(list, n); X continue; /* error: don't consider this message */ X } /* yr mo da */ X (void) sscanf(p, "%2d%2d%2d", X &msg_mdy[2], &msg_mdy[0], &msg_mdy[1]); X msg_mdy[0]--; X Debug("checking %d's date: %d-%d-%d ", X n+1, msg_mdy[0]+1, msg_mdy[1], msg_mdy[2]); X /* start at year and wrap around. X * only when match the day (4), check for == (match) X */ X for (i = 2; i < 5; i++) X if (before && msg_mdy[i%3] < mdy[i%3] X || !before && msg_mdy[i%3] > mdy[i%3] X || i == 4 && (msg_mdy[i%3] == mdy[i%3])) { X Debug("matched (%s).\n", X (i == 2)? "year" : (i == 3)? "month" : "day"); X break; X } else if (msg_mdy[i%3] != mdy[i%3]) { X Debug("failed.\n"); X unset_msg_bit(list, n); X break; X } X continue; X } X /* we must have the right date -- if we're searching for a X * string, find it. X */ X (void) fseek(tmpf, msg[n].m_offset, L_SET); X bytes = 0; X while (bytes < msg[n].m_size) { X if (!search_subj && !search_from && !search_to && X !*search_hdr && !(p = fgets(buf, BUFSIZ, tmpf))) X break; X else if (search_subj) { X if (!(p = header_field(n, "subject"))) { X unset_msg_bit(list, n); X break; X } X } else if (search_from) { X if (!(p = header_field(n, "from"))) { X register char *p2; X (void) fseek(tmpf, msg[n].m_offset, L_SET); X if (!(p2 = fgets(buf, BUFSIZ, tmpf)) || X !(p = index(p2, ' '))) X continue; X p++; X if (p2 = any(p, " \t")) X *p2 = 0; X } X } else if (search_to) { X if (!(p = header_field(n, "to")) && X !(p = header_field(n, "apparently-to"))) { X unset_msg_bit(list, n); X break; X } X } X else if (*search_hdr) { X if (!(p = header_field(n, search_hdr))) { X unset_msg_bit(list, n); X break; X } X } X if (icase) X p = lcase_strcpy(buf, p); X#ifdef REGCMP X val = !!regex(err, p, NULL); /* convert value to a boolean */ X#else /* REGCMP */ X val = re_exec(p); X#endif /* REGCMP */ X if (val == -1) { /* doesn't apply in system V */ X print("Internal error for pattern search.\n"); X clear_msg_list(list); /* it doesn't matter, really */ X return -1; X } X if (xflg) X val = !val; X if (!val) { X /* unset the bit if match failed. If it matches later X * in the search, we'll reset to true in the next iteration. X * this doesn't apply for author or subject picks. X */ X unset_msg_bit(list, n); X bytes += strlen(p); X } else { X set_msg_bit(list, n); X break; X } X if (search_subj || search_from || search_to || *search_hdr) X break; X } X } X return 0; X} X X#ifdef CURSES X/* X * search for a pattern in composed message headers -- also see next function X * flags == 0 forward search (prompt). X * flags == -1 continue search (no prompt). X * flags == 1 backward search (prompt). X */ search(flags) register int flags; X{ X register char *p; X char pattern[128]; X register int this_msg = current_msg, val = 0; X static char *err = (char *)-1, direction; X int (*oldint)(), (*oldquit)(); X#ifdef REGCMP X char *regcmp(); X#else /* REGCMP */ X char *re_comp(); X#endif /* REGCMP */ X X if (msg_cnt <= 1) { X print("Not enough messages to invoke a search.\n"); X return 0; X } X pattern[0] = '\0'; X if (flags == -1) X print("continue %s search...", direction? "forward" : "backward"); X else X print("%s search: ", flags? "backward" : "forward"); X if (flags > -1) X if (Getstr(pattern, COLS-18, 0) < 0) X return 0; X else X direction = !flags; X#ifdef REGCMP X if (err && *pattern) X xfree(err); X else if (err == (char *)-1 && !*pattern) { X print("No previous regular expression."); X return 0; X } X if (*pattern && !(err = regcmp(pattern, NULL))) { X print("Error in regcmp in %s", pattern); X return 0; X } X#else /* REGCMP */ X if (err = re_comp(pattern)) { X print(err); X return 0; X } X#endif /* REGCMP */ X move(LINES-1, 0), refresh(); X on_intr(); X X do { X if (direction) X current_msg = (current_msg+1) % msg_cnt; X else X if (--current_msg < 0) X current_msg = msg_cnt-1; X p = compose_hdr(current_msg); X#ifdef REGCMP X val = !!regex(err, p, NULL); /* convert value to a boolean */ X#else /* REGCMP */ X val = re_exec(p); X#endif /* REGCMP */ X if (val == -1) /* doesn't apply in system V */ X print("Internal error for pattern search.\n"); X } while (!val && current_msg != this_msg && isoff(glob_flags, WAS_INTR)); X X if (ison(glob_flags, WAS_INTR)) { X print("Pattern search interruped."); X current_msg = this_msg; X } else if (val == 0) X print("Pattern not found."); X X off_intr(); X return val; X} X#endif /* CURSES */ X X/* X * parse a user given date string and set mdy[] array with correct X * values. Return 0 on failure. X */ date1(p) register char *p; X{ X register char *p2; X long t; X int i; X struct tm *today; X X if (*p == '-') { X before = 1; X skipspaces(1); X } X if (!isdigit(*p) && *p != '/') { X print("syntax error on date: \"%s\"\n", p); X return 0; X } X (void) time (&t); X today = localtime(&t); X for (i = 0; i < 3; i++) X if (!p || !*p || *p == '/') { X switch(i) { /* default to today's date */ X case 0: mdy[0] = today->tm_mon; X when 1: mdy[1] = today->tm_mday; X when 2: mdy[2] = today->tm_year; X } X if (p && *p) X p++; X } else { X p2 = (*p)? index(p+1, '/') : NULL; X mdy[i] = atoi(p); /* atoi will stop at the '/' */ X if (i == 0 && (--(mdy[0]) < 0 || mdy[0] > 11)) { X print("Invalid month: %s\n", p); X return 0; X } else if (i == 1 && (mdy[1] < 1 || mdy[1] > 31)) { X print("Invalid day: %s\n", p); X return 0; X } X if (p = p2) /* set p to p2 and check to see if it's valid */ X p++; X } X return 1; X} END_OF_FILE if test 10751 -ne `wc -c <'pick.c'`; then echo shar: \"'pick.c'\" unpacked with wrong size! fi # end of 'pick.c' fi if test -f 'setopts.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'setopts.c'\" else echo shar: Extracting \"'setopts.c'\" \(10923 characters\) sed "s/^X//" >'setopts.c' <<'END_OF_FILE' X/* setopts.c (c) copyright 1986 (Dan Heller) */ X X#include "mush.h" X X/* add an option indicated by "set option[=value]" or by "alias name alias" X * function is recursive, so multilists get appended accordingly X */ add_option(list, argv) register struct options **list; register char **argv; X{ X register struct options *tmp; X struct options *calloc(); X register char *option, *value = NULL; X X if (!(option = *argv)) X return 1; X /* check for one of three forms: X * option=value option = value option= value X * value can be in quotes to preserve whitespace X */ X if (*++argv && !strcmp(*argv, "=")) { X if (value = *++argv) /* example: "set foo = " */ X ++argv; X } else if (value = index(option, '=')) { X /* option=value strip into option="option" value="value"; (quotes?) */ X register char c, *p2; X *value = 0; /* option is now a null termined `option' */ X if ((c = *++value) == '"' || c == '\'') { X *value++ = 0; X if (!(p2 = index(value, c))) { X print("No matching %c for %s.\n", c, option); X return 0; X } else X *p2 = 0; X } else if (!c) { /* example: "set crt=" */ X if (!*argv) { X print("No value for %s.\n", option); X return 0; X } X value = *argv++; X } X } X /* check to see if option is already set by attempting to unset it */ X (void) un_set(list, option); X X /* now make a new option struct and set fields */ X if (!(tmp = calloc((unsigned)1, sizeof(struct options)))) { X error("calloc"); X return -1; X } X tmp->option = savestr(option); X tmp->value = savestr(value); /* strdup handles the NULL case */ X X tmp->next = *list; X *list = tmp; X X /* check for options which must have values or are used frequently */ X if (*list == set_options) { X#if defined(CURSES) || defined(SUNTOOL) X if (!strcmp(tmp->option, "no_reverse")) X turnoff(glob_flags, REV_VIDEO); X else X#endif /* CURSES || SUNTOOL */ X if (!strcmp(tmp->option, "prompt")) X prompt = (tmp->value)? tmp->value : DEF_PROMPT; X else if (!strcmp(tmp->option, "mil_time")) X turnon(glob_flags, MIL_TIME); X else if (!strcmp(tmp->option, "escape")) X escape = (tmp->value)? tmp->value : DEF_ESCAPE; X else if (!strcmp(tmp->option, "hdr_format")) X hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT; X else if (!strcmp(tmp->option, "crt")) { X if (!istool) X crt = (tmp->value)? max(atoi(tmp->value), 2): 18; X } else if (!strcmp(tmp->option, "screen")) { X screen = (tmp->value)? max(atoi(tmp->value), 1): 18; X#ifdef CURSES X if (iscurses && screen > LINES-2) X screen = LINES-2; X#endif /* CURSES */ X } else if (!strcmp(tmp->option, "history")) X init_history((value && *value)? atoi(value) : 1); X } X X if (*argv) X return add_option(list, argv); X return 1; X} X X/* X * If str is NULL, just print options and their values. Note that numerical X * values are not converted to int upon return. If str is not NULL X * return the string that matched, else return NULL; X */ char * do_set(list, str) register struct options *list; register char *str; X{ X register struct options *opts; X#ifdef SUNTOOL X int x,y; X X if (istool && !str) X y = 10 + 2 * l_height(LARGE); X#endif /* SUNTOOL */ X X if (!str && !istool) X (void) do_pager(NULL, TRUE); /* page using internal pager */ X X for (opts = list; opts; opts = opts->next) X if (!str) { X#ifdef SUNTOOL X if (istool) X pw_text(msg_win, 5, y, PIX_SRC, fonts[DEFAULT], opts->option); X else X#endif /* SUNTOOL */ X (void) do_pager(opts->option, FALSE); X if (opts->value) X#ifdef SUNTOOL X if (istool) { X x = 30*l_width(DEFAULT); X pw_text(msg_win, x,y, PIX_SRC, fonts[DEFAULT], opts->value); X pw_text(msg_win, x+1, y, PIX_SRC|PIX_DST, X fonts[DEFAULT], opts->value); X x += strlen(opts->value)*l_width(DEFAULT); X } else X#endif /* SUNTOOL */ X { X (void) do_pager(" \t", FALSE); X (void) do_pager(opts->value, FALSE); X } X#ifdef SUNTOOL X if (istool) X Clrtoeol(msg_win, x, y, DEFAULT), y += l_height(DEFAULT); X else X#endif /* SUNTOOL */ X if (do_pager("\n", FALSE) == EOF) X break; X } else { X if (strcmp(str, opts->option)) X continue; X if (opts->value) X return opts->value; X else X return ""; X } X X if (!str && !istool) X (void) do_pager(NULL, FALSE); /* terminate internal pager */ X X /* if we still haven't matched, check for environment vars */ X if (str && list == set_options) { X register int N, n; X for (N = 0; environ[N]; N++) { X char *p = index(environ[N], '='); X if (p) X *p = 0; X n = lcase_strcmp(str, environ[N]); X if (p) X *p = '='; X if (!n) X return p+1; X } X } X return NULL; X} X X/* X * unset the variable described by p in the list "list". X * if the variable isn't set, then return 0, else return 1. X */ un_set(list, p) register struct options **list; register char *p; X{ X register struct options *opts = *list, *tmp; X X if (!list || !*list || !p || !*p) X return 0; X if (*list == set_options) { X#if defined(CURSES) || defined(SUNTOOL) X if (!strcmp(p, "no_reverse")) X turnon(glob_flags, REV_VIDEO); X else X#endif /* CURSES || SUNTOOL */ X if (!strcmp(p, "prompt")) X prompt = DEF_PROMPT; X else if (!strcmp(p, "mil_time")) X turnoff(glob_flags, MIL_TIME); X else if (!strcmp(p, "escape")) X escape = DEF_ESCAPE; X else if (!strcmp(p, "hdr_format")) X hdr_format = DEF_HDR_FMT; X else if (!strcmp(p, "crt")) X crt = 18; X else if (!strcmp(p, "screen")) { X screen = 18; X#ifdef CURSES X if (iscurses && screen > LINES-2) X screen = LINES-2; X#endif /* CURSES */ X } else if (!strcmp(p, "history")) X init_history(1); X } X X if (!strcmp(p, opts->option)) { X *list = (*list)->next; X xfree (opts->option); X if (opts->value) X xfree(opts->value); X xfree((char *)opts); X return 1; X } X for ( ; opts->next; opts = opts->next) X if (!strcmp(p, opts->next->option)) { X tmp = opts->next; X opts->next = opts->next->next; X xfree (tmp->option); X if (tmp->value) X xfree(tmp->value); X xfree ((char *)tmp); X return 1; X } X return 0; X} X X/* The functions below return -1 since they don't affect X * messages. This prevents piping from do_loop(). X */ set(n, argv) register int n; register char **argv; X{ X char firstchar = **argv; X register char *cmd = *argv; X register struct options **list; X X if (*cmd == 'u') X cmd += 2; X if (*++argv && !strcmp(*argv, "-?")) X return help(0, (*cmd == 'i')? "ignore": "set", cmd_help); X if (*argv && **argv == '?') { X char buf[BUFSIZ]; X int incurses; X if (!strcmp(*argv, "?all")) { X if (incurses = iscurses) /* assign and compare to TRUE */ X clr_bot_line(), iscurses = FALSE; X (void) do_pager(NULL, TRUE); /* start internal pager */ X for (n = 0; variable_stuff(n, NULL, buf); n++) X if (do_pager(strcat(buf, "\n"), FALSE) == EOF) X break; X (void) do_pager(NULL, FALSE); /* terminate pager */ X iscurses = incurses; X } else { X /* May return null if variable not set. */ X (void) variable_stuff(0, (*argv)+1, buf); X print("%s\n", buf); X } X return -1; X } X X if (firstchar == 'u') { X if (!*argv) X print("%s what?\n", cmd); X else { X list = (*cmd == 'i')? &ignore_hdr : &set_options; X do if (!strcmp(*argv, "*")) X while (*list) X (void) un_set(list, (*list)->option); X else if (!un_set(list, *argv)) X print("un%s: %s not set\n", X (*cmd == 'i')? "ignore" : "set", *argv); X while (*++argv); X } X return -1; X } X if (!*argv) X (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL); X else X (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv); X return -1; X} X alts(argc, argv) register char **argv; X{ X char buf[256], buf2[256], *p; X u_long save_bang = ison(glob_flags, IGN_BANG); X X if (argc && *++argv && !strcmp(*argv, "-?")) X return help(0, "alts_help", cmd_help); X if (argc > 1) { X (void) argv_to_string(buf2, argv); X (void) sprintf(buf, "set alternates=\"%s\"", buf2); X turnon(glob_flags, IGN_BANG); X if (argv = make_command(buf, TRPL_NULL, &argc)) X (void) do_command(argc, argv, msg_list); X if (!save_bang) X turnoff(glob_flags, IGN_BANG); X } else X if (!(p = do_set(set_options, "alternates"))) X print("No alternate hostnames set.\n"); X else X print("Alternate hostnames: %s\n", p); X return -1; X} X save_opts(cnt, argv) char **argv; X{ X char file[256], *tmp; X register FILE *fp; X X if (cnt && *++argv && !strcmp(*argv, "-?")) X return help(0, "source_help", cmd_help); X if (cnt && *argv) X (void) strcpy(file, *argv); X else if (tmp = getenv("MAILRC")) X (void) strcpy(file, tmp); X else { X char *home = do_set(set_options, "home"); X if (!home || !*home) X home = ALTERNATE_HOME; X /* if .musrc doesn't exist, check .mailrc. If neither, force .mushrc */ X if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) && X Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK)) X (void) sprintf(file, "%s/%s", home, MAILRC); X } X X cnt = 1; X tmp = getpath(file, &cnt); X if (cnt) { X if (cnt == -1) X print("%s: %s\n", file, tmp); X else X print("%s is a directory.\n", tmp); X return -1; X } X /* See if the file exists and confirm overwrite */ X if (!Access(tmp, F_OK)) { X int overwrite = TRUE; X char buf[4]; X print("\"%s\" exists. Overwrite? ", tmp); X if (!istool) { X if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y') X overwrite = FALSE; X } X#ifdef SUNTOOL X else { X int c = confirm(panel_sw->ts_windowfd); X if (lower(c) != 'y' && c != MS_LEFT) X overwrite = FALSE; X } X#endif /* SUNTOOL */ X if (!overwrite) { X print("\"%s\" unchanged.\n", tmp); X return -1; X } X } X if (!(fp = fopen(tmp, "w"))) { X error("Can't open %s", file); X return -1; X } X X save_list("basic variable settings", set_options, "set", '=', fp); X X save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp); X X save_list("aliases", aliases, "alias", 0, fp); X X save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp); X X save_list("command abbreviations", functions, "cmd", ' ', fp); X X save_list("command macros for function keys", fkeys, "fkey", ' ', fp); X X fclose(fp); X print("All variables and options saved in %s\n", tmp); X return -1; X} X save_list(title, list, command, equals, fp) struct options *list; register char *command, *title, equals; register FILE *fp; X{ X register struct options *opts; X register char *p; X X if (!list) X return; X fprintf(fp, "#\n# %s\n#\n", title); X for (opts = list; opts; opts = opts->next) { X fprintf(fp, "%s %s", command, opts->option); X if (opts->value && *opts->value) { X register char *quote; X if (!equals) X quote = NO_STRING; X else if (p = any(opts->value, "\"'")) X if (*p == '\'') quote = "\""; X else quote = "'"; X else X if (!any(opts->value, " \t;|")) X quote = NO_STRING; X else quote = "'"; X fputc(equals? equals: ' ', fp); X fprintf(fp, "%s%s%s", quote, opts->value, quote); X } X fputc('\n', fp); X } X} END_OF_FILE if test 10923 -ne `wc -c <'setopts.c'`; then echo shar: \"'setopts.c'\" unpacked with wrong size! fi # end of 'setopts.c' fi echo shar: End of archive 4 \(of 14\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 14 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.