v18i029: Mail user's shell version 6.4, Part07/19
Rich Salz
rsalz at bbn.com
Fri Mar 17 02:00:06 AEST 1989
Submitted-by: Dan Heller <island!argv at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list