rsalz@bbn.com (Rich Salz) (03/17/89)
Submitted-by: Dan Heller <island!argv@sun.com> Posting-number: Volume 18, Issue 29 Archive-name: mush6.4/part07 #! /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 7 (of 19)." # Contents: fkeys.c folders.c init.c # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:13 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'fkeys.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fkeys.c'\" else echo shar: Extracting \"'fkeys.c'\" \(13831 characters\) sed "s/^X//" >'fkeys.c' <<'END_OF_FILE' X/* @(#)fkeys.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X#define draw(x1,y1,x2,y2,OP) pw_vector(msg_win, x1,y1,x2,y2,OP,1) X#define box(x1,y1,x2,y2,OP) \ X draw(x1,y1, x1,y2,OP), draw(x1,y2, x2,y2,OP), \ X draw(x2,y2, x2,y1,OP), draw(x2,y1, x1,y1,OP) X Xstruct cmd fkey_cmds[] = { X { "top", fkey_cmd }, { "close", fkey_cmd }, { "bottom", fkey_cmd }, X { "move", fkey_cmd }, { "stretch", fkey_cmd }, { "repaint", fkey_cmd }, X { "settings", fkey_settings }, { NULL, quit } X}; X X#define L(n) KEY_LEFTFIRST+(n)-1 X#define R(n) KEY_RIGHTFIRST+(n)-1 X#define F(n) KEY_TOPFIRST+(n)-1 X#define BREAK_KEY KEY_TOPLAST X Xchar *leftkey_default_settings[] = { X "Left Function Key Settings", X "Unused", /* L1 */ "next", /* L2 */ X "undelete", /* L3 */ "delete", /* L4 */ X "replyall", /* L5 */ "replysender", /* L6 */ X "mail", /* L7 */ "Unset", /* L8 */ X "lpr", /* L9 */ "settings L", /* L10 */ X 0 X}; X Xchar *topkey_default_settings[] = { X "Top Function Key Settings", X "top", /* T1 */ "close", /* T2 */ X "move", /* T3 */ "stretch", /* T4 */ X "bottom", /* T5 */ "repaint", /* T6 */ X "Unset", /* T7 */ "Unset", /* T8 */ X "settings F", /* T9 */ X 0 X}; X Xchar *rightkey_default_settings[] = { X "Right Function Key Settings", X "Unset", /* R1 */ "Unset", /* R2 */ X "Unset", /* R3 */ "Unset", /* R4 */ X "Unset", /* R5 */ "Unset", /* R6 */ X "Unset", /* R7 */ "Unset", /* R8 */ X "Unset", /* R9 */ "Unset", /* R10 */ X "Unset", /* R11 */ "Unset", /* R12 */ X "Unset", /* R13 */ "Unset", /* R14 */ X "settings R", /* R15 */ X 0 X}; X X/* X * Execute commands defined by a function key. X * Left keys: X * L1 = (null) can't be set X * L2 ... L10 X * Top function keys X * F1 ... F9, BREAK/backspace (key not definable) X * Right function keys X * R1 ... R15 X * Usually, the last Function key displays the others' settings. X */ Xfkey(key) Xregister char *key; X{ X register char **argv, *p; X char buf[256]; X int n; X X /* user defined here... ... default settings here */ X if (!strncmp((p = key_set_to(key)), "Un", 2)) { X print("Funciton key: %s %s", key, p); X return 0; X } X /* make_command will screw up "p", so copy it first */ X (void) strcpy(buf, p); X Debug("(%s) \"%s\": ", key, p), turnon(glob_flags, CONT_PRNT); X if (argv = make_command(buf, TRPL_NULL, &n)) X (void) do_command(n, argv, msg_list); X return -1; X} X Xfkey_settings(i, argv) Xregister char i; Xregister char **argv; X{ X register char key, *p, **fkey_str; X char buf[256]; X char *help_args[17]; X X if (!*++argv) { X print("Must specify one of L, F or R to identify a function key set"); X return -1; X } X key = **argv; X switch(Upper(key)) { X when 'L': fkey_str = leftkey_default_settings; X when 'F': fkey_str = topkey_default_settings; X when 'R': fkey_str = rightkey_default_settings; X otherwise: print("Invalid key set: %c (choose L, F or R)", key); X return -1; X } X help_args[0] = fkey_str[0]; X for (i = 1; fkey_str[i]; i++) { X p = key_set_to(sprintf(buf, "%c%d", key, i)); X help_args[i] = savestr(sprintf(buf, "%c%-2.d %s", key, i, p)); X } X help_args[i] = 0; /* null terminate list */ X (void) help(print_sw->ts_windowfd, help_args, NULL); X X free_vec(help_args+1); X return 0; X} X Xchar * Xkey_set_to(p) Xregister char *p; X{ X register char *p2, **fkey_str; X X switch(*p) { X when 'L': fkey_str = leftkey_default_settings; X when 'F': fkey_str = topkey_default_settings; X when 'R': fkey_str = rightkey_default_settings; X } X p2 = do_set(fkeys, p); X return (p2)? p2: fkey_str[atoi(p+1)]; X} X Xfkey_cmd(x, p) Xregister char **p; X{ X if (!strcmp(*p, "close")) X toolquit(NO_ITEM, 0, NO_EVENT); X else if (!strcmp(*p, "top")) X wmgr_top(tool->tl_windowfd, rootfd); X else if (!strcmp(*p, "move")) X wmgr_move(tool->tl_windowfd, rootfd); X else if (!strcmp(*p, "stretch")) X wmgr_stretch(tool->tl_windowfd, rootfd); X else if (!strcmp(*p, "bottom")) X wmgr_bottom(tool->tl_windowfd, rootfd); X else if (!strcmp(*p, "repaint")) X wmgr_refreshwindow(tool->tl_windowfd, rootfd); X return -1; X} X X/* execute a command given a function key, if the key is user defined, X * call fkey() at top of file. Parameter is the key number in "ascii" X */ Xfunc_key(key) Xregister int key; X{ X register char *p; X char buf[4]; X int nkey; X X if (key >= KEY_LEFTFIRST && key <= KEY_LEFTLAST) X buf[0] = 'L', nkey = key - KEY_LEFTFIRST; X else if (key >= KEY_TOPFIRST && key <= KEY_TOPLAST) X buf[0] = 'F', nkey = key - KEY_TOPFIRST; X else if (key >= KEY_RIGHTFIRST && key <= KEY_RIGHTLAST) X buf[0] = 'R', nkey = key - KEY_RIGHTFIRST; X (void) sprintf(buf+1, "%d", nkey+1); X X return fkey(buf); X} X Xvoid Xset_fkeys() X{ X ready(display_keys() + 10); X print_valid_functions(txt.y+20); X getting_opts = 2; X win_setcursor(msg_sw->ts_windowfd, &checkmark); X} X Xchar *MSG = "Click the appropriate mouse button over a function key"; Xready(Y) X{ X static int y; X int x = (msg_rect.r_width - strlen(MSG)*l_width(LARGE))/2; X if (Y) X y = Y; X Clrtoeol(msg_win, (txt.x = 0), (txt.y = y), LARGE); X highlight(msg_win, x, y, LARGE, MSG); X} X X/* number of pixels in x and y directions describing the size of a graphical X * function key. they represent the little keys and big keys respectively. X */ X/* static struct pr_pos fkey_sizes[2] = { { 23, 23 }, { 50, 23 } }; */ Xstatic struct pr_pos fkey_sizes[2] = { { 24, 23 }, { 52, 23 } }; X X#define BORDER 4 /* border (distance) between keys */ X#define KEYTOP 15 /* distance from top to start drawing */ X#define LEFT_START 15 /* pixels from left to start drawing boxes */ X#define TOP_START (LEFT_START+2*fkey_sizes[0].x + fkey_sizes[1].x+BORDER) X#define RIGHT_START (TOP_START + 5*(fkey_sizes[0].x+BORDER) + \ X 5*(fkey_sizes[1].x+BORDER)) X X/* X * if !p, we're setting key at location x,y. X * else Set that key to this string (p). X */ Xvoid Xset_key(p, x,y) Xregister char *p; Xregister int x,y; X{ X char buf[256], **argv; X static char *key; X int argc; X X static int key_x, key_y; X if (!p) { X if (key = find_key(x,y)) { X print("Type new setting for key: %s", key); X (void) sprintf(buf, "Function key \"%s\": ", key); X highlight(msg_win, 20, txt.y, LARGE, buf); X txt.x = 20 + strlen(buf)*l_width(LARGE); X Clrtoeol(msg_win, txt.x, txt.y, LARGE); X type_cursor(PIX_SRC); X } else X ready(0); X key_x = x, key_y = y; X } else { X u_long save_bang = ison(glob_flags, IGN_BANG); X if (!*p) X (void) sprintf(buf, "unfkey %s", key); X else X (void) sprintf(buf, "fkey %s \"%s\"", key, p); X turnon(glob_flags, IGN_BANG); X if (argv = make_command(buf, TRPL_NULL, &argc)) { X (void) do_command(argc, argv, msg_list); X print("Function key %s: %s", key, key_set_to(key)); X } X if (!save_bang) X turnoff(glob_flags, IGN_BANG); X ready(0); X } X} X X/* passed the x and y coords of a mouse click, return the function key X * that exists in that position. NULL if no key there. string will be X * something like "L6" or "F9" or "R12" X */ Xchar * Xfind_key(x,y) Xint x, y; X{ X static char buf[6]; X int row, col; X static int old_left, old_top, old_right, old_bot; X X if (!(row = find_y(&y))) X return NULL; X if (x < LEFT_START || x > RIGHT_START + 3*(fkey_sizes[0].x+BORDER)) X return NULL; /* out of range */ X if (x > LEFT_START && x < TOP_START-fkey_sizes[0].x - BORDER) { X if ((col = (x > LEFT_START + fkey_sizes[0].x + BORDER)+1) == 1) X x = LEFT_START+1; X else x = LEFT_START + fkey_sizes[0].x + BORDER + 1; X if (col == 1 && row == 1) X return NULL; X /* unhighlight the old function key image */ X if (old_left) X box(old_left, old_top, old_right, old_bot, PIX_CLR); X old_left = x, old_top = y; X old_right = x+fkey_sizes[(col != 1)].x-2, old_bot = y+fkey_sizes[0].y-2; X /* highlight most recently selected function key image */ X box(x,y, old_right, old_bot, PIX_SRC); X X return sprintf(buf, "L%d", col + 2*(row-1)); X } X if (x > TOP_START && x < RIGHT_START - fkey_sizes[0].x - BORDER) { X int which; X if (row > 1) X return NULL; X which = (x - TOP_START) / (fkey_sizes[0].x + BORDER) + 1; X if (which == 15) X return NULL; /* Can't set break key (backspace on a sun3) */ X if (which == 14) X x = TOP_START + ((which = 9)-2) * (fkey_sizes[1].x+BORDER) - X fkey_sizes[0].x - BORDER + 1; X else if (which <= 2) X x = TOP_START + (which-1) * (fkey_sizes[0].x+BORDER) + 1; X else { X which = (which+3)/2; X x = TOP_START + (which-2) * (fkey_sizes[1].x+BORDER) + 1; X } X X /* unhighlight the old function key image */ X if (old_left) X box(old_left, old_top, old_right, old_bot, PIX_CLR); X old_left = x, old_top = y; X old_right = x+fkey_sizes[(which > 2 && which < 8)].x-2; X old_bot = y+fkey_sizes[0].y-2; X /* highlight most recently selected function key image */ X box(x,y, old_right, old_bot, PIX_SRC); X X return sprintf(buf, "F%d", which); X } X if (x > RIGHT_START) { X if (x < RIGHT_START + fkey_sizes[0].x) X x = RIGHT_START+1, col = 1; X else if (x < RIGHT_START + fkey_sizes[0].x + BORDER) X return NULL; /* cursor was clicked between keys */ X else if (x < RIGHT_START + 2*fkey_sizes[0].x + BORDER) X x = RIGHT_START+fkey_sizes[0].x+BORDER+1, col = 2; X else if (x < RIGHT_START + 2 * (fkey_sizes[0].x+BORDER)) X return NULL; /* click between keys again */ X else x = RIGHT_START + 2*(fkey_sizes[0].x+BORDER)+1, col = 3; X X /* unhighlight the old function key image */ X if (old_left) X box(old_left, old_top, old_right, old_bot, PIX_CLR); X old_left = x, old_top = y; X old_right = x+fkey_sizes[0].x-2, old_bot = y+fkey_sizes[0].y-2; X /* highlight most recently selected function key image */ X box(x,y, old_right, old_bot, PIX_SRC); X X return sprintf(buf, "R%d", col + 3*(row-1)); X } X return NULL; X} X X/* find_y will find which row in a function key pad a y coordinate X * represents. return 1,2,3,4, or 5 0 if inbetween rows X */ Xfind_y(y) Xregister int *y; X{ X int Y, y_incr = fkey_sizes[0].y, ret_value = 0; X for (Y = KEYTOP; Y <= KEYTOP + 6*y_incr + 4 * BORDER; Y += y_incr + BORDER) X if (*y < Y) { X *y = (Y - y_incr - BORDER) + 1; X return ret_value; X } else ret_value++; X return 0; X} X Xchar *l_msg = "Specifies which function key for setting value"; Xchar *m_msg = "Display current value for function key"; Xchar *r_msg = "Help setting and viewing function key values"; X Xdisplay_keys() X{ X register int i, x,y; X register char *p; X X do_clear(); X X x = LEFT_START, y = KEYTOP; X /* print left keys */ X for (i = 0; i < 10; i++) { X box(x, y, x + fkey_sizes[i%2].x, y + fkey_sizes[i%2].y, PIX_SRC); X box(x+2, y+2, x+fkey_sizes[i%2].x-2, y+fkey_sizes[i%2].y-2, PIX_SRC); X if (i && (p = find_key(x+4,y+4))) X pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p); X else pw_replrop(msg_win, x+3, y+3, fkey_sizes[0].x-5, fkey_sizes[0].y-5, X PIX_SRC | PIX_DST, &shade_50, 0,0); X if (i % 2) X y += fkey_sizes[0].y + BORDER, x = LEFT_START; X else X x += fkey_sizes[0].x + BORDER; X } X X x = TOP_START, y = KEYTOP; X /* print top keys */ X for (i = 1; i <= 10; i++) { X register int n = (i >= 3 && i <= 7); X box(x, y, x + fkey_sizes[n].x, y + fkey_sizes[n].y, PIX_SRC); X box(x+2, y+2, x + fkey_sizes[n].x-2, y + fkey_sizes[n].y-2, PIX_SRC); X if (i != 10 && (p = find_key(x+4,y+4))) X pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p); X /* shade the break key (backspace on sun3's) -- can't set */ X else if (i == 10) X pw_replrop(msg_win, x+3, y+3, fkey_sizes[n].x-5, fkey_sizes[n].y-5, X PIX_SRC | PIX_DST, &shade_50, 0,0); X x += fkey_sizes[n].x + BORDER; X } X X x = RIGHT_START; X /* print right keys */ X for (i = 0; i < 15; i++) { X box(x, y, x + fkey_sizes[0].x, y + fkey_sizes[0].y, PIX_SRC); X box(x+2, y+2, x + fkey_sizes[0].x-2, y + fkey_sizes[0].y-2, PIX_SRC); X if (p = find_key(x+4,y+4)) X pw_text(msg_win, x+3, y+3+l_height(SMALL),PIX_SRC, fonts[SMALL], p); X if (!((i+1) % 3)) X y += fkey_sizes[0].y + BORDER, x -= 2*(fkey_sizes[0].x + BORDER); X else X x += fkey_sizes[0].x + BORDER; X } X x = TOP_START; X y = KEYTOP + BORDER + fkey_sizes[0].y + l_height(DEFAULT); X pw_rop(msg_win, x, y-11, 16,16, PIX_SRC, &mouse_left, 0,0); X pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], l_msg); X X y += BORDER + fkey_sizes[0].y; X pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_middle, 0,0); X pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], m_msg); X X y += BORDER + fkey_sizes[0].y; X pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_right, 0,0); X pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], r_msg); X X x = (msg_rect.r_width - 26*l_width(DEFAULT))/2; X y += BORDER + fkey_sizes[0].y; X highlight(msg_win, x, y, DEFAULT, "You may not set shaded keys"); X X y += BORDER + fkey_sizes[0].y + 15; X for (i = 0; i < BORDER; i++) X draw(0, y+i, msg_rect.r_width, y+i, PIX_SRC); X y += 10; X for (i = 0; i < BORDER; i++) X draw(0, y+l_height(LARGE)+i, msg_rect.r_width, y+l_height(LARGE)+i, X PIX_SRC); X return y; X} X Xprint_valid_functions(y) Xregister int y; X{ X register int x, n, cmd_len = 12 * l_width(DEFAULT); X register char *p; X X y += 20, x = (msg_rect.r_width - 25*l_width(LARGE))/2; X highlight (msg_win, x, y, LARGE, "Available Command Names"); X y += 20, x = 30; X for (n = 0; p = cmds[n].command; n++) { X if (x + cmd_len > msg_rect.r_width - 5) X y += l_height(DEFAULT), x = 30; X pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p); X x += cmd_len; X } X for (n = 0; p = fkey_cmds[n].command; n++) { X if (x + cmd_len > msg_rect.r_width - 5) X y += l_height(DEFAULT), x = 30; X pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p); X x += cmd_len; X } X} END_OF_FILE if test 13831 -ne `wc -c <'fkeys.c'`; then echo shar: \"'fkeys.c'\" unpacked with wrong size! fi # end of 'fkeys.c' fi if test -f 'folders.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'folders.c'\" else echo shar: Extracting \"'folders.c'\" \(16743 characters\) sed "s/^X//" >'folders.c' <<'END_OF_FILE' X/* @(#)folders.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X Xstatic char oldfolder[MAXPATHLEN]; X X/* folder %[user] --new mailfile is the spool/mail/login file [user]. X * folder # --new mailfile is the folder previous to the current folder X * folder & --new mailfile is ~/mbox (or whatever "mbox" is set to) X * folder +file --new mailfile is in the directory "folder"; name is 'file' X * folder "path" --full path name or the one in current working directory. X * X * in all cases, changes are updated unless a '!' is specified after the X * folder command (e.g. "f!", "folder !" "fo!" .. all permutations) X * as usual, if new mail has arrived before the file is copied back, then X * user will be notified beforehand. X * X * RETURN -1 on error -- else return 0. All bits in msg_list are set to true. X */ Xfolder(argc, argv, list) Xregister char **argv, list[]; X{ X int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0; X char *tmp, *newfolder = NULL, buf[MAXPATHLEN]; X struct stat statbuf; X extern long last_spool_size; X X if (ison(glob_flags, IS_PIPE)) { X print("You can't pipe to the %s command.\n", *argv); X return -1; X } else if (ison(glob_flags, IS_SENDING)) { X print("You can't use the %s command while sending.\n", *argv); X return -1; X } X while (*++argv && (**argv == '-' || **argv == '!')) X if (!strcmp(*argv, "-?")) X return help(0, "folder", cmd_help); X else if (!strcmp(*argv, "-N")) X no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES)); X else if (!strcmp(*argv, "-r")) X do_read_only = 1; X else if (!strcmp(*argv, "!")) X turnoff(glob_flags, DO_UPDATE); X X if (updating) { X (void) strcpy(buf, mailfile); X if (ison(glob_flags, READ_ONLY)) X do_read_only = 1; X } else { X if (!*argv) { X mail_status(0); X return 0; X } X if (!strcmp(*argv, "#")) X if (!*oldfolder) { X print("No previous folder\n"); X return -1; X } else X newfolder = oldfolder; X else if (!strcmp(*argv, "&")) { X if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder) X newfolder = DEF_MBOX; X } else X newfolder = *argv; X n = 0; X tmp = getpath(newfolder, &n); X if (n == -1) { X print("%s: %s\n", newfolder, tmp); X return -1; X } else if (n == 1) { X print("%s: is a directory\n", tmp); X return -1; X } X /* strcpy so copyback() below (which calls getpath) doesn't change X * the data that tmp intended to point to. X */ X (void) strcpy(buf, tmp); X } X if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) { X error("Unable to read %s", buf); X return -1; X } X /* If the file can't be opened for writing, autoset READ_ONLY */ X if (!(statbuf.st_mode & 0200)) X do_read_only = 1; X#ifdef SUNTOOL X if (istool) lock_cursors(); X#endif /* SUNTOOL */ X X if (!copyback(updating ? "Update folder?" : "Change anyway?")) { X#ifdef SUNTOOL X if (istool) unlock_cursors(); X#endif /* SUNTOOL */ X /* an error occured updating the folder */ X return -1; X } X if (strcmp(mailfile, buf)) { X if (!updating) X (void) strcpy(oldfolder, mailfile); X strdup(mailfile, buf); X } X do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY); X last_size = spool_size = 0L; X while (msg_cnt--) { X xfree(msg[msg_cnt].m_date_recv); X xfree(msg[msg_cnt].m_date_sent); X msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING; X } X msg_cnt = 0, msg[0].m_offset = 0L; X turnoff(glob_flags, CONT_PRNT); X X turnon(glob_flags, IGN_SIGS); X /* clear the tempfile */ X if (tmpf) X (void) fclose(tmpf); X if (!do_read_only) { X if (!(tmpf = mask_fopen(tempfile, "w"))) { X error("error truncating %s", tempfile); X turnoff(glob_flags, IGN_SIGS); X return -1; X } X } X (void) load_folder(mailfile, TRUE, NULL); X if (do_read_only && !(tmpf = fopen(mailfile, "r"))) { X error(mailfile); X turnoff(glob_flags, IGN_SIGS); X return -1; X } X last_msg_cnt = msg_cnt; /* for check_new_mail */ X (void) mail_size(); X last_spool_size = spool_size; /* prevents bogus "new mail" messages */ X#ifdef SUNTOOL X if (istool) { X panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0); X pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0); X if (!msg_cnt) { X add_folder_to_menu(folder_item, 3); X add_folder_to_menu(save_item, 1); X } X } X#endif /* SUNTOOL */ X current_msg = 0; X turnoff(glob_flags, IGN_SIGS); X X /* now sort messages according a user-defined default */ X if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) && X (tmp = do_set(set_options, "sort"))) { X (void) sprintf(buf, "sort %s", tmp); X if (argv = make_command(buf, TRPL_NULL, &argc)) { X /* msg_list can't be null for do_command and since we're not X * interested in the result, call sort directly X */ X (void) sort(argc, argv, NULL); X free_vec(argv); X } X } X turnoff(glob_flags, DO_UPDATE); X X /* go to first NEW message */ X while (current_msg < msg_cnt && ison(msg[current_msg].m_flags, OLD)) X current_msg++; X if (current_msg == msg_cnt) X /* no new message found -- try first unread message */ X for (current_msg = 0; X current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD); X current_msg++) X ; X if (current_msg == msg_cnt) X current_msg = 0; X X if ((!istool || istool && !msg_cnt) && !iscurses) X mail_status(0); X /* be quiet if we're piping */ X if ((istool || !updating) && isoff(glob_flags, DO_PIPE) && X (istool || !no_hdrs) && msg_cnt) X (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list); X#ifdef SUNTOOL X if (istool) { X if (!msg_cnt) X print("No Mail in %s\n", mailfile); X if (!getting_opts) X if (msg_cnt && isoff(glob_flags, IS_GETTING)) X display_msg(current_msg, (long)0); X else X do_clear(); X unlock_cursors(); X } X#endif /* SUNTOOL */ X if (list) { X clear_msg_list(list); X bitput(list, list, msg_cnt, =~) /* macro */ X } X return 0; X} X Xfolders(argc, argv) Xregister char **argv; X{ X register char *p; X char buf[128], unused[MAXMSGS_BITS]; X X if (!(p = do_set(set_options, "folder")) || !*p) X p = DEF_FOLDER; X (void) sprintf(buf, "ls %s", p); X if (argv = make_command(buf, TRPL_NULL, &argc)) X return do_command(argc, argv, unused); X return -1; X} X X/* merge_folders filename -- concatenate the folder specified by filename X * to the current folder. X * X * RETURN -1 on error -- else return 0. A bit in msg_list is set to true X * for each of the "new" messages read in to the current folder. X */ Xmerge_folders(n, argv, list) Xregister char **argv, list[]; X{ X int no_hdrs = 0, newest_msg; X long orig_offset; X char *tmp, *newfolder = NULL, buf[MAXPATHLEN]; X X if (ison(glob_flags, IS_PIPE)) { X print("You can't pipe to the %s command.\n", *argv); X return -1; X } else if (ison(glob_flags, IS_SENDING)) { X print("You can't use the %s command while sending.\n", *argv); X return -1; X } X X while (*++argv && **argv == '-') X if (!strcmp(*argv, "-?")) X return help(0, "merge", cmd_help); X else if (!strcmp(*argv, "-N")) X no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES)); X X if (!*argv) X return 0; X X if (ison(glob_flags, READ_ONLY)) { X print("Folder is read-only.\n"); X return -1; X } X X if (!strcmp(*argv, "#")) X if (!*oldfolder) { X print("No previous folder\n"); X return -1; X } else X newfolder = oldfolder; X else if (!strcmp(*argv, "&")) { X if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder) X newfolder = DEF_MBOX; X } else X newfolder = *argv; X n = 0; X tmp = getpath(newfolder, &n); X if (n == -1) { X print("%s: %s\n", newfolder, tmp); X return -1; X } else if (n == 1) { X print("%s: is a directory\n", tmp); X return -1; X } X X turnon(glob_flags, IGN_SIGS); X orig_offset = msg[msg_cnt].m_offset; X (void) load_folder(tmp, 2, list); X msg[msg_cnt].m_offset = orig_offset; X newest_msg = last_msg_cnt; X Debug("newest_msg = %d\n", newest_msg); X last_msg_cnt = msg_cnt; /* for check_new_mail */ X Debug("msg_cnt = %d\n", msg_cnt); X (void) mail_size(); X turnoff(glob_flags, IGN_SIGS); X X if ((!istool || istool && !msg_cnt) X && !iscurses && !ison(glob_flags, PRE_CURSES)) X mail_status(0); X /* be quiet if we're piping or if told not to show headers */ X if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE) X && newest_msg < msg_cnt) X (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL); X return 0; X} X X/* X * Undigestify messages. If a message is in digest-format, there are many X * messages within this message which are to be extracted. Kinda like a X * folder within a folder. By default, this routine will create a new X * folder that contains the new messages. -m option will merge the new X * messages into the current folder. X */ Xdo_undigest(n, argv, list) Xchar *argv[], list[]; X{ X int r, articles = 0, merge = 0, appending = 0; X char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir, c; X FILE *fp; X X while (argv && *++argv && **argv == '-') { X n = 1; X while (c = argv[0][n++]) X switch(c) { X case 'm': X if (ison(glob_flags, READ_ONLY)) { X print("Folder is read only.\n"); X return -1; X } X merge++; X otherwise: return help(0, "undigest", cmd_help); X } X } X X if ((n = get_msg_list(argv, list)) == -1) X return -1; X X argv += n; X X if (*argv) { X int isdir = 1; /* Ignore file nonexistance errors */ X (void) strcpy(buf, getpath(*argv, &isdir)); X if (isdir < 0) { X print("%s: %s\n", *argv, buf); X return -1; X } else if (isdir == 1) { X print("%s: is a directory\n", buf); X return -1; X } X } else { X register char *p, *p2; X if (Access(dir = ".", W_OK) && X !(dir = do_set(set_options, "folder")) && X !(dir = do_set(set_options, "tmpdir"))) Xalted: X dir = ALTERNATE_HOME; X for (n = 0; n < msg_cnt; n++) X if (msg_bit(list, n)) X break; X X if (!(p = header_field(n, "subject"))) X (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir)); X else { X if (!lcase_strncmp(p, "re: ", 4)) X p += 4; X for (p2 = p; *p2; p2++) X if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') { X *p2 = 0; X break; X } X p2 = buf + Strcpy(buf, dir); X *p2++ = '/'; X (void) strcpy(p2, p); X } X } X X if (!Access(buf, W_OK)) { X fp = mask_fopen(buf, "a"); X appending = (fp > 0); X } else X fp = mask_fopen(buf, "w"); X if (!fp) { X if (!*argv && strcmp(dir, ALTERNATE_HOME)) X goto alted; X error("can't create %s", buf); X return -1; X } X X for (n = 0; n < msg_cnt; n++) { X if (!msg_bit(list, n)) X continue; X X print("undigesting message %d\n", n+1); X /* copy message into file making sure all headers exist. */ X r = undigest(n, fp); X if (r <= 0) X break; X articles += r; X } X fclose(fp); X if (r <= 0) { X if (!appending) X unlink(buf); X return -1; X } X if (merge) { X (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist); X (void) unlink(buf); X print("Merged in %d messages.\n", articles); X } else X print("Added %d messages to \"%s\".\n", articles, buf); X clear_msg_list(list); X for (n = 0; n < msg_cnt; n++) X if (msg_bit(newlist, n)) X set_msg_bit(list, n); X return 0; X} X X/* X * split digest-message 'n' to file "fp". X * return number of articles copied or -1 if system error on fputs. X * A digest is a folder-in-a-message in a special, semi-standard form. X */ Xundigest(n, fp) Xregister int n; Xregister FILE *fp; X{ X int art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */ X long get_hdr = 0L; X char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ]; X char from_hdr[256], afrom[256], adate[64]; X char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */ X SIGRET (*oldint)(), (*oldquit)(); X X if (!msg_get(n, from, sizeof from)) { X error("Unable to find msg %d", n+1); X return -1; X } X#ifndef MSG_SEPARATOR X else { X char *p = from + 5; X skipspaces(0); X p = index(p, ' '); X if (p) { X skipspaces(0); X fdate = p; X } X if (fputs(from, fp) == EOF) X return -1; X } X#endif /* !MSG_SEPARATOR */ X X on_intr(); X *afrom = *adate = *last_sep = '\0'; X while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size && X fgets(line, sizeof (line), tmpf)) { X if (ison(glob_flags, WAS_INTR)) X goto handle_error; X if (*line == '\n' && on_hdr > 0) /* blank line -- end of header */ X on_hdr = 0; X X /* Check for the beginning of a digest article */ X if (!strncmp(line, "--------", 8)) { X if (get_hdr) { X if (do_set(set_options, "warning")) X wprint("Article with no header? (added to article #%d)\n", X art_cnt); X /* Don't start a new message for whatever this is, X * just fseek back and keep appending to the last one. X */ X if (fseek(tmpf, get_hdr, L_SET) < 0 || X fputs(last_sep, fp) == EOF) { X art_cnt = -1; X goto handle_error; X } X get_hdr = 0L; X on_hdr = 0; X } else { X (void) strcpy(last_sep, line); X get_hdr = ftell(tmpf); X *afrom = *adate = '\0'; X on_hdr = -1; /* Haven't found the new header yet */ X } X continue; X } X X if (get_hdr) { X char *p = *line == '>' ? line + 1 : line; X if (*line == '\n') { X if (*afrom || *adate) { X (void) fseek(tmpf, get_hdr, L_SET); X /* Terminate the previous article */ X art_cnt++; X#ifdef MSG_SEPARATOR X#ifdef END_MSG_SEP X if (fputs(END_MSG_SEP, fp) == EOF) { X art_cnt = -1; X goto handle_error; X } X#endif /* END_MSG_SEP */ X#ifdef MMDF X /* MMDF has a newline in MSG_SEPARATOR */ X if (fputs(MSG_SEPARATOR, fp) == EOF) X#else /* !MMDF */ X /* Other MSG_SEPARATORs need a newline */ X if (fputs(MSG_SEPARATOR, fp) == EOF || X fputc('\n', fp) == EOF) X#endif /* MMDF */ X#else /* !MSG_SEPARATOR */ X /* Everybody else needs a From_ line */ X if (fprintf(fp, "From %s %s", *afrom ? afrom : "unknown", X *adate ? date_to_ctime(adate) : fdate) == EOF) X#endif /* MSG_SEPARATOR */ X { X art_cnt = -1; X goto handle_error; X } X /* Make sure there is a From: without a leading > */ X if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) { X art_cnt = -1; X goto handle_error; X } X get_hdr = 0L; X } else if (on_hdr < 0) X /* Skip blanks between "--------" and the hdr */ X get_hdr = ftell(tmpf); X } else if (on_hdr < 0) X on_hdr = 1; X if (on_hdr > 0 && !strncmp(p, "From: ", 6)) { X (void) get_name_n_addr(p + 6, NULL, afrom); X (void) no_newln(afrom); X /* Get the From: minus the leading > */ X if (p != line) X (void) strcpy(from_hdr, p); X else /* We don't need From: twice! */ X *from_hdr = '\0'; X } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) { X if (p = parse_date(line+6)) X (void) strcpy(adate, p); X } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) { X if (!*afrom && !*adate) X break; X } X } else if (fputs(line, fp) == EOF) { X /* Pipe broken, out of file space, etc */ X art_cnt = -1; X goto handle_error; X } X } X ++art_cnt; X#ifdef END_MSG_SEP X if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) { X art_cnt = -1; X goto handle_error; X } X#endif /* END_MSG_SEP */ X /* If we're still looking for a header, there is some stuff left X * at the end of the digest. Create an extra article for it. X */ X if (get_hdr) { X char *p; X (void) fseek(tmpf, get_hdr, L_SET); X if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size) X goto handle_error; X#ifdef MSG_SEPARATOR X#ifdef MMDF X if (fputs(MSG_SEPARATOR, fp) == EOF) X#else /* !MMDF */ X if (fputs(MSG_SEPARATOR, fp) == EOF || X fputc('\n', fp) == EOF) X#endif /* MMDF */ X#else /* !MSG_SEPARATOR */ X if (fputs(from, fp) == EOF) X#endif /* MSG_SEPARATOR */ X art_cnt = -1; X if (!(p = header_field(n, "from"))) X p = "Mush-Undigest (Real author unknown)"; X if (fprintf(fp, "From: %s\n", p) == EOF) X art_cnt = -1; X if (!(p = header_field(n, "date"))) X p = fdate, no_newln(p); X if (fprintf(fp, "Date: %s\n", p) == EOF) X art_cnt = -1; X if (!(p = header_field(n, "subject"))) X p = "Digest"; X if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF) X art_cnt = -1; X /* header_field() moves the pointer, so seek again */ X (void) fseek(tmpf, get_hdr, L_SET); X while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size X && fgets(line, sizeof (line), tmpf)) { X if (fputs(line, fp) == EOF) X art_cnt = -1; X#ifdef END_MSG_SEP X if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP))) X break; X#endif /* END_MSG_SEP */ X } X /* The END_MSG_SEP, if any, of the digest will have been output X * by the while loop above, so we don't need to add one here. X */ X ++art_cnt; X } Xhandle_error: X if (art_cnt == -1) X error("cannot completely undigest"); X else if (ison(glob_flags, WAS_INTR)) X art_cnt = -1; X off_intr(); X return art_cnt; X} END_OF_FILE if test 16743 -ne `wc -c <'folders.c'`; then echo shar: \"'folders.c'\" unpacked with wrong size! fi # end of 'folders.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'\" \(15373 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 */ Xshort dat_mouse_left[] = { X#include <images/confirm_left.pr> X}; X Xshort dat_mouse_middle[] = { X#include <images/confirm_middle.pr> X}; X Xshort dat_mouse_right[] = { X#include <images/confirm_right.pr> X}; X Xshort dat_mail_icon_1[] = { X#include "mail.icon.1" X}; X Xshort dat_mail_icon_2[] = { X#include "mail.icon.2" X}; X Xshort dat_coffee_cup[] = { X#include "coffee.cup.pr" X}; X Xshort dat_read_cursor[] = { X#include "glasses.pr" X}; X Xshort dat_write_cursor[] = { X#include "write.pr" X}; X Xshort dat_up_arrow[] = { X#include "up.arrow.pr" X}; X Xshort dat_dn_arrow[] = { X#include "dn.arrow.pr" X}; X Xshort dat_envelope[] = { X#include "envelope.pr" X}; X Xshort dat_cycle_cursor[] = { X#include "cycle.pr" X}; X Xshort dat_check_cursor[] = { X#include "check.pr" X}; X Xmpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1); Xmpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2); X Xmpr_static(mouse_left, 16, 16, 1, dat_mouse_left); Xmpr_static(mouse_middle, 16, 16, 1, dat_mouse_middle); Xmpr_static(mouse_right, 16, 16, 1, dat_mouse_right); Xmpr_static(coffee_cup, 16, 16, 1, dat_coffee_cup); Xmpr_static(glasses_cursor, 16, 16, 1, dat_read_cursor); Xmpr_static(pencil_cursor, 16, 16, 1, dat_write_cursor); Xmpr_static(up_arrow, 16, 16, 1, dat_up_arrow); Xmpr_static(dn_arrow, 16, 16, 1, dat_dn_arrow); Xmpr_static(envelope_cursor, 16, 16, 1, dat_envelope); Xmpr_static(cycle, 16, 16, 1, dat_cycle_cursor); Xmpr_static(check_cursor, 16, 16, 1, dat_check_cursor); X Xstruct cursor l_cursor = { 3, 3, PIX_SRC, &mouse_left }; Xstruct cursor m_cursor = { 3, 3, PIX_SRC, &mouse_middle }; Xstruct cursor r_cursor = { 3, 3, PIX_SRC, &mouse_right }; Xstruct cursor coffee = { 8, 8, PIX_SRC, &coffee_cup }; Xstruct cursor read_cursor = { 8, 8, PIX_SRC|PIX_DST, &glasses_cursor }; Xstruct cursor write_cursor = { 8, 8, PIX_SRC|PIX_DST, &pencil_cursor }; Xstruct cursor main_cursor = { 8, 8, PIX_SRC, &envelope_cursor }; Xstruct cursor checkmark = { 8, 8, PIX_SRC|PIX_DST, &check_cursor }; X X/* text and font will be set in mail_status() */ Xstruct 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 Xchar *font_files[] = { X "serif.r.14", "sail.r.6", "serif.r.16", X}; X Xchar *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 X#ifdef SYSV X#include <sys/utsname.h> X#endif /* SYSV */ X Xvoid Xinit() X{ X char *home, *realname, *argv[4]; X extern char *getlogin(), **calloc(); X char buf[MAXPATHLEN]; X#ifdef SYSV X extern struct passwd *getpwuid(); /* sys-v forgot this in pwd.h! */ X struct utsname ourhost; X#else X char ourhost[128]; X#endif /* SYSV */ X register char *p; X struct passwd *entry; X int cnt; X#ifdef BSD X struct hostent *hp; X#endif /* BSD */ X X home = getenv("HOME"); X realname = getenv("NAME"); X argv[1] = "="; X argv[3] = NULL; 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 if (!realname && (realname = entry->pw_gecos) && X (p = index(realname, ','))) X *p = 0; 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 argv[0] = "home"; X argv[2] = home; X (void) add_option(&set_options, argv); X } X if (realname) { X if (realname == entry->pw_gecos) { X for (p = buf; *realname; realname++) X if (*realname == '&') X *p++ = upper(*login), p += Strcpy(p, login+1); X else X *p++ = *realname; X *p = 0; X } else X (void) strcpy(buf, realname); X argv[0] = "realname"; X argv[2] = buf; X (void) add_option(&set_options, argv); X } X crt = 24; X screen = 18; X wrapcolumn = 0; /* Default is no wrap */ X escape = DEF_ESCAPE; X prompt = DEF_PROMPT; X X#ifdef BSD X (void) gethostname(ourhost, sizeof ourhost); X if (!(hp = gethostbyname(ourhost))) { X error("gethostbyname: %s", ourhost); X if (ourname = calloc((unsigned)2, sizeof (char *))) X strdup(ourname[0], ourhost); X } else { X int n = 0; X cnt = 2; /* 1 for ourhost and 1 for NULL terminator */ X for (p = hp->h_name; p && *p; p = hp->h_aliases[n++]) X if (strcmp(ourhost, p)) /* if host name is different */ X cnt++; X if (ourname = calloc((unsigned)cnt, sizeof (char *))) { X ourname[--cnt] = NULL; X for (p = hp->h_name; p && *p && n >= 0; p = hp->h_aliases[--n]) X if (strcmp(ourhost, p)) /* if host name is different */ X ourname[--cnt] = savestr(p); X strdup(ourname[0], ourhost); /* cnt better be 0! */ X } X } X endhostent(); X#endif /* BSD */ X#ifdef SYSV X ourname = calloc((unsigned)2, sizeof (char *)); X if ((uname (&ourhost) >= 0) && (*ourhost.nodename)) X ourname[0] = savestr(ourhost.nodename); X else { X /* Try to use uuname -l to get host's name if uname didn't work */ X char buff[50]; X char *p; X FILE *F; X X if (F = popen("exec uuname -l", "r")) { X if ((fgets(buff, sizeof buff, F) == buff) && X (p = strchr(buff, '\n'))) { X *p = '\0'; /* eliminate newline */ X ourname[0] = savestr (buff); X } X (void)pclose(F); X } X } X#endif /* SYSV */ X if (ourname && ourname[0]) { X for (p = buf, cnt = 0; ourname[cnt]; cnt++) { X if (cnt) X *p++ = ' '; X p += Strcpy(p, ourname[cnt]); X } X argv[0] = "hostname"; X argv[2] = buf; X (void) add_option(&set_options, argv); X } X init_bindings(); 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 */ Xsource(argc, argv) Xchar **argv; X{ X register char *p; X FILE *fp; X char file[128]; X u_long save_bang = ison(glob_flags, IGN_BANG); X int line_no = 0; X X if (argc && *++argv && !strcmp(*argv, "-?")) X return help(0, "source", 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 turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */ X (void) strcpy(file, p); X (void) src_parse(file, fp, 0, 0, &line_no); X /* if we entered the routine ignoring !, leave it that way. */ X if (!save_bang) X turnoff(glob_flags, IGN_BANG); X /* Sourcing might change things, so abort pipes/macros */ X return 0 - (in_pipe() || in_macro()); X} X X/* X * Do the actual file parsing for source(). The first argument should X * be the name of the file referenced by the second argument. The third X * argument is used for handling nested if_else_endif expressions. The X * fourth argument is used to keep track of the recursion depth, and the X * last argument keeps track of the line number in the current file. X * X * This function calls itself recursively. It also calls do_command(), X * which may in turn call source() recursively. X * X * If-then-else nesting algorithm: X * On any "if" (whether parsing or not), increment if_else X * On true "if" when parsing, evaluate by recursion X * On false "if" when parsing, set find_else equal to if_else X * On any "if" when not parsing, set find_endif equal to if_else X * On "else", invert parsing only when find_else equals if_else X * When "if" was false and there is nesting, recur for "else" X * Skip nested "if...endif" when find_else or find_endif true X * On "endif" or when recursion returns, decrement if_else X * On "endif", test both find_endif and find_else against if_else: X * when either matches, reset that one; X * when the lesser (less nested) matches, resume parsing X * On "endif", when if_else hits 0, continue (depth 0) or return X */ Xsrc_parse(file, fp, if_else, depth, line_no) Xchar *file; XFILE *fp; Xint if_else, depth, *line_no; X{ X register char *p, *p2, **newargv; X int parsing = 1, cont_line = 0; X int find_else = 0, find_endif = 0; X char line[BUFSIZ]; X int argc; X 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 || !parsing && !(newargv = mk_argv(line, &argc, 0)) X || parsing && !(newargv = make_command(line, TRPL_NULL, &argc))) { X if (!strncmp(line, "if", 2)) X find_else = ++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 looking for an else or endif, reset parsing */ X if (find_endif && find_endif == if_else) { X if (find_endif <= find_else || !find_else) X parsing = 1, find_else = 0; X find_endif = 0; X } X /* Note: find_else never < find_endif */ X if (find_else && find_else == if_else) X parsing = !parsing, find_else = 0; X /* Decrement if_else and check depth */ X if (--if_else == 0) X /* Resume parsing if at the top */ X if (depth == 0) X parsing = 1; X /* Return if not at the top */ X else X return 1; X } 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 /* If inside an else, ignore nested else; X * otherwise, recur when if_else > 1 */ X else if (!find_else && !find_endif && !parsing) { X parsing = src_parse(file, fp, 1, depth + 1, line_no); X --if_else; X } else if (find_else == if_else || if_else == 1) { X find_else = 0; X parsing = !parsing; X if (!parsing) X find_endif = if_else; X } X goto bad; X } else if (!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_else++; X /* If parsing, set parsing to 0 until X * evaluating the "if" proves otherwise. X * If not parsing, skip to the "endif". X */ X if (parsing) X parsing = 0; X else { X if (!find_endif) X find_endif = if_else; X goto bad; X } 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 (check for negation). X */ X if (*lhs == '!') { X if (!*++lhs && !(lhs = newargv[2])) { X print("%s: line %d: syntax error: \"if ! <what?>\"\n", X file, *line_no); X goto bad; X } X equals = FALSE; X } X if (*lhs == '-' && (lhs[1] == 'e' || lhs[1] == 'z') && !lhs[2]) { X char *path; X int n = 1; /* ignore ENOENT, I'll handle it here */ X struct stat statb; X X /* check for existence or zero-length folders/files */ X if (argc > 4) { X print("%s: line %d: if %s \"filename\"\n", X file, *line_no, lhs); X goto bad; X } X path = getpath(newargv[argc-1], &n); X parsing = !equals ^ (n == -1 || n == 1 && lhs[1] == 'e' || X !stat(path, &statb) && (lhs[1] == 'e' || !statb.st_size)); X } else { X if (equals && argc > 2) { X if (argc != 4) { X print("%s: %d: argument count error: %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", X 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) && X !iscurses && !equals))) X parsing = 1; X else if (rhs) { X if (strcmp(lhs, rhs) && !equals X || !strcmp(lhs, rhs) && equals) X parsing = 1; X } else if (isdigit(*lhs)) X parsing = !!(atoi(lhs) ? equals : !equals); X } X if (parsing) { X parsing = src_parse(file, fp, 1, depth + 1, line_no); X --if_else; X } X else X find_else = if_else; /* Look for a matching else */ Xbad: X free_vec(newargv); X continue; X } X if (parsing && argc > 0) X if (!strcmp(newargv[0], "exit")) { X if_else = find_else = find_endif = 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 if (depth == 0) X fclose(fp); X else X fseek(fp, 0L, 2); /* Skip ahead to the end */ X return 0; X} X X#ifdef SUNTOOL X/* open all fonts and place in fonts array. */ Xgetfonts() 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 15373 -ne `wc -c <'init.c'`; then echo shar: \"'init.c'\" unpacked with wrong size! fi # end of 'init.c' fi echo shar: End of archive 7 \(of 19\). cp /dev/null ark7isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 19 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.