[comp.sources.unix] v18i029: Mail user's shell version 6.4, Part07/19

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.