v14i035: Mail User's Shell, version 6.0, Part03/14
Rich Salz
rsalz at bbn.com
Thu Apr 14 10:22:17 AEST 1988
Submitted-by: island!argv at sun.com (Dan Heller)
Posting-number: Volume 14, Issue 35
Archive-name: mush6.0/part03
#! /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 3 (of 14)."
# Contents: curs_io.c dates.c execute.c file.c main_panel.c signals.c
# Wrapped by rsalz at fig.bbn.com on Wed Apr 13 20:04:43 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'curs_io.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'curs_io.c'\"
else
echo shar: Extracting \"'curs_io.c'\" \(7380 characters\)
sed "s/^X//" >'curs_io.c' <<'END_OF_FILE'
X/* @(#)curs_io.c (c) copyright 3/18/87 (Dan Heller) */
X
X/* curs_io.c -- curses based I/O */
X#include "mush.h"
X
X#ifdef CURSES
X#include "bindings.h"
X#endif /* CURSES */
X
char *_unctrl[] = {
X "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
X "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
X "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
X " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
X ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";",
X "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I",
X "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
X "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
X "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
X "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "^?"
X};
X
X#ifdef Addch
X#undef Addch
X#endif /* Addch */
X
X#ifndef CURSES
X
X#define Addch(c) if (isoff(glob_flags, ECHO_FLAG)) \
X fputc(c, stdout), fflush(stdout)
X
X#else
X
X/* see end of Getstr */
X#define Addch(c) \
X if (iscurses) \
X addch(c), refresh(); \
X else if (isoff(glob_flags, ECHO_FLAG)) \
X fputc(c, stdout), fflush(stdout)
X#endif /* CURSES */
X
X/*
X * get a string of at most 'length' chars.
X * allow backspace-space-backspace, kill word and kill line
X * (options set by user in stty).
X * length is the max length this string can get. offset is from beginning
X * of string.
X * input of ^D returns -1; otherwise, return the number of chars in string.
X */
Getstr(String, length, offset)
char String[];
register int length;
X{
X register int c, literal_next = FALSE;
X int count = offset;
X
X while ((c = getchar()) != '\n' && c != '\r' && c != EOF &&
X isoff(glob_flags, WAS_INTR)) {
X /* echo isn't set, so whatever the character, enter it */
X if (ison(glob_flags, ECHO_FLAG))
X if (count < length)
X String[count++] = c;
X else {
X print("Warning: string too long. Truncated at %d chars.\n",
X length);
X break;
X }
X /* ^D as the first char on a line or two ^D's in a row is EOF */
X else if (c == CTRL(D) && !count)
X break;
X else if (c == '\\') {
X literal_next = TRUE;
X Addch(String[count++] = '\\');
X } else if (literal_next) {
X literal_next = FALSE;
X if (iscntrl(c) || c == _tty.sg_kill || c == _tty.sg_erase
X#ifdef TIOCGLTC
X || c == ltchars.t_werasc
X#endif /* TIOCGLTC */
X )
X backspace(String, &count);
X String[count++] = c;
X if (iscntrl(c) || c == _tty.sg_erase) {
X if (iscntrl(c))
X Addch('^');
X Addch(_unctrl[c][1]);
X } else
X Addch(c);
X } else if (c == _tty.sg_erase || c == CTRL(H) || c == 127 /*CTRL(?)*/) {
X if (count)
X backspace(String, &count);
X /* if iscurses, then backspacing too far is cancelling a function */
X else if (!count && iscurses) {
X String[0] = '\0';
X return -1;
X }
X } else if (c == _tty.sg_kill) {
X if (count) {
X do backspace(String, &count);
X while (count);
X }
X } else
X#ifndef TIOCGLTC
X if (c == CTRL(R)) /* system doesn't have ltchars */
X#else
X if (c == ltchars.t_rprntc) /* reprint line */
X#endif /* TIOCGLTC */
X String[count] = 0, printf("\n%s", String);
X else
X#ifndef TIOCGLTC
X if (c == CTRL(W)) /* system doesn't have ltchars */
X#else
X if (c == ltchars.t_werasc) /* word erase */
X#endif /* TIOCGLTC */
X while (count) {
X backspace(String, &count);
X if (!count ||
X isspace(String[count-1]) && !isspace(String[count]) ||
X !isalnum(String[count-1]) && isalnum(String[count]))
X break;
X }
X else if (c == '\t')
X do {
X Addch(' ');
X String[count] = ' ';
X } while (++count % 8 && count < length);
X else if (count == length)
X bell();
X else {
X String[count++] = c;
X if (c != '\t' && iscntrl(c)) {
X Addch('^');
X Addch(_unctrl[c][1]);
X } else
X Addch(c);
X }
X }
X if (c == CTRL(D) || c == EOF || ison(glob_flags, WAS_INTR)) {
X if (feof(stdin))
X clearerr(stdin);
X return -1;
X }
X if (count && String[count-1] == '\\') {
X int count2;
X if (isoff(glob_flags, ECHO_FLAG))
X putchar('\n');
X if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1)
X return -1;
X return count + count2;
X }
X if (!iscurses && isoff(glob_flags, ECHO_FLAG))
X putchar('\n');
X while (count > 0 && isspace(String[count-1]))
X --count;
X String[count] = 0;
X return count;
X}
X
static
backspace(str, n)
register char *str;
int *n;
X{
X (*n)--;
X Addch('\b'); Addch(' '); Addch('\b');
X if (iscntrl(str[*n])) {
X Addch('\b'); Addch(' '); Addch('\b');
X }
X}
X
X#undef Addch
X
X#ifdef CURSES
X/*
X * prompt for a carriage return, but return whatever user types unless
X * it's a character which he might regret (like 'q' or 'x'). Ignore
X * interrupts (kind of) because we have nowhere to longjmp to. When we
X * return, we'll setjmp again (top of loop.c)
X */
hit_return()
X{
X int c;
X
X turnon(glob_flags, IGN_SIGS);
X iscurses = FALSE;
X (void) check_new_mail();
X iscurses = TRUE;
X mail_status(1), addstr("...continue... "), refresh();
X c = getcmd();
X turnoff(glob_flags, IGN_SIGS);
X
X /* don't let the user type something he might regret */
X if (c == C_QUIT || c == C_EXIT)
X return C_NULL;
X return c;
X}
X
curses_msg_list(str, list, m_list)
register char *str, *list;
char m_list[];
X{
X register char *p = NULL;
X int c;
X
X print(str);
X c = Getstr(list, COLS-13, 0);
X move(LINES-1, 0), refresh();
X if (c <= 0 || !(p = do_range(list, m_list)) ||
X (p == list && *p && *p != '$' && *p != '^')) {
X if (p)
X print("Invalid message list: %s", p);
X return 0;
X }
X return 1;
X}
X
curs_vars(which)
int which; /* really, a char */
X{
X char c, buf[128], buf2[128], *string;
X struct options **list;
X
X switch(which) {
X case C_OWN_HDR : string = "my_hdr", list = &own_hdrs;
X when C_ALIAS : string = "alias", list = &aliases;
X when C_IGNORE : string = "ignore", list = &ignore_hdr;
X when C_VAR_SET : string = "set", list = &set_options;
X otherwise : clr_bot_line(); return;
X }
X
X print("%s [? Set Unset All]: ", string);
X c = getchar();
X clr_bot_line();
X switch (Lower(c)) {
X /* if help, print help -- if "all", show all settings. */
X case '?' : case 'a' :
X if (c == '?') {
X if (!strcmp(string, "set")) {
X print("which variable? [all <var>]: ");
X if ((c = Getstr(buf+1, COLS-40, 0)) < 0)
X return;
X clr_bot_line();
X buf[0] = '?';
X if (c > 0) {
X char *argv[3];
X argv[0] = string;
X argv[1] = buf;
X argv[2] = NULL;
X Lower(buf[1]);
X if (!strcmp(buf+1, "a"))
X (void) strcpy(buf+1, "all");
X if (!strcmp(buf+1, "all"))
X turnon(glob_flags, CNTD_CMD);
X (void) set(2, argv);
X return;
X }
X }
X /* help returns next command (hit_return) */
X help(0, string, cmd_help);
X turnon(glob_flags, CNTD_CMD);
X return;
X }
X turnon(glob_flags, CNTD_CMD);
X (void) do_set(*list, NULL);
X
X /* if set, prompt for string and let user type */
X when 's' :
X print("set: ");
X c = Getstr(buf, COLS-18, 0);
X clr_bot_line();
X if (c > 0)
X (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
X
X /* if unset, just as easy as set! */
X when 'u' :
X print("unset: ", string);
X if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf))
X print("%s isn't set", buf);
X }
X if (ison(glob_flags, CNTD_CMD))
X putchar('\n');
X}
X
X#endif /* CURSES */
END_OF_FILE
if test 7380 -ne `wc -c <'curs_io.c'`; then
echo shar: \"'curs_io.c'\" unpacked with wrong size!
fi
# end of 'curs_io.c'
fi
if test -f 'dates.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dates.c'\"
else
echo shar: Extracting \"'dates.c'\" \(7499 characters\)
sed "s/^X//" >'dates.c' <<'END_OF_FILE'
X/* @(#)dates.c 1.1 (c) copyright 10/15/86 (Dan Heller) */
X
X#include "mush.h"
X
char *day_names[] = {
X "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"
X};
char *month_names[] = { /* imported in pick.c */
X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X};
X
X/* Time() returns a string according to criteria:
X * if "now" is 0, then the current time is gotten and used.
X * else, use the time described by now
X * opts points to a string of args which is parsed until an unknown
X * arg is found and opts will point to that upon return.
X * valid args are T (time of day), D (day of week), M (month), Y (year),
X * N (number of day in month -- couldn't think of a better letter).
X */
char *
Time(opts, now)
register char *opts;
long now;
X{
X static char time_buf[30];
X struct tm *T;
X register char *p = time_buf;
X long x;
X
X if (!opts)
X return NULL;
X if (now)
X x = now;
X else
X (void) time(&x);
X T = localtime(&x);
X for (;; opts++) {
X switch(*opts) {
X case 'T':
X if (ison(glob_flags, MIL_TIME))
X (void) sprintf(p, "%2d:%02d", T->tm_hour, T->tm_min);
X else
X (void) sprintf(p, "%d:%02d", (T->tm_hour) ?
X ((T->tm_hour <= 12) ? T->tm_hour : T->tm_hour - 12) :
X 12, T->tm_min);
X when 'D': (void) strcpy(p, day_names[T->tm_wday]);
X when 'M': (void) strcpy(p, month_names[T->tm_mon]);
X when 'Y': (void) sprintf(p, "%d", T->tm_year);
X when 'N': (void) sprintf(p, "%d", T->tm_mday);
X otherwise: *--p = 0; return time_buf;
X }
X p += strlen(p);
X *p++ = ' ';
X }
X}
X
X/* find the date of a message and return a string of the same form
X * described by parse_date() below.
X */
char *
msg_date(n)
register int n;
X{
X register char *p, *p2 = NULL;
X char line[BUFSIZ];
X
X /* not in use */
X /* try the easy way out first -- This is potentially a serious kludge
X * because not all message-id lines are right. -- most of the time,
X * this is correct. it's not correct from messages from strange
X * mailers (non-sendmail) they do a different format in message-id.
X if ((p = header_field(n, "message-id")) && (p2 = index(p, '<'))) {
X p = p2+1;
X if (p2 = index(p, '.')) {
X *p2 = 0;
X return p;
X }
X }
X */
X
X /* else, get the "date" line, if that fails, get the date in "From" line */
X if ((p = header_field(n, "date")) && (p2 = parse_date(p)))
X return p2;
X
X (void) fseek(tmpf, msg[n].m_offset, L_SET);
X (void) fgets(line, BUFSIZ, tmpf);
X if (!(p = index(line, ' ')) || !(p2 = index(p+1, ' ')))
X return NULL;
X p = p2;
X
X if (!(p2 = parse_date(p)))
X print("Message %d has bad date: %s\n", n+1, p);
X return p2;
X}
X
X/* parse date and return a string that looks like
X * "%2d%2d%2d%2d%2d", yr,mo,date,hrs,mins
X */
char *
parse_date(p)
register char *p;
X{
X /* If it's not a month, it can get _long_. this is also the static
X * buffer whose address we return.
X */
X static char month[64];
X int Month = 0, Day = 0, Year = 0, Hours = -1, Mins = -1;
X
X skipspaces(0);
X
X /* Possible combinations that we could have:
X * day_number month_name year_number time timezone ...
X * day_name month_name day_number time year_number
X * day_name month_name day_number year_number time
X * day_name day_number month_name year_number time
X * day_number month_name year_number time
X * day_number month_name year_number time-timezone (day)
X * ^no colon separator
X * day_name month_name day_number time timezone year_number
X * day_number-month_name-year time
X * day_name, day_number-month_name-year time
X * day_number month_name year_number, time "-"
X */
X /* programmer's note -- there are too many scanfs here for some compilers
X * to put them all into one if statement. Use goto's :-(
X */
X if (sscanf(p, "%*s %s %d %d %d:%d", month,&Day,&Year,&Hours,&Mins) == 5)
X goto gotit;
X if (sscanf(p, "%d %s %d %d:%d", &Day,month,&Year,&Hours,&Mins) == 5)
X goto gotit;
X if (sscanf(p, "%*s %s %d %d:%d:%*d %d", month,&Day,&Hours,&Mins,&Year) == 5)
X goto gotit;
X if (sscanf(p, "%*s %d %s %d %d:%d", &Day,month,&Year,&Hours,&Mins) == 5)
X goto gotit;
X if (sscanf(p, "%d %s %d %d:%d", &Day,month,&Year,&Hours,&Mins) == 5)
X goto gotit;
X if (sscanf(p, "%d %s %d %2d%2d", &Day,month,&Year,&Hours,&Mins) == 5)
X goto gotit;
X if (sscanf(p, "%*s %s %d %d:%d:%*d %*s %d",
X month, &Day, &Hours, &Mins, &Year) == 5)
X goto gotit;
X if (sscanf(p, "%*s %s %d %d:%d %*s %d",
X month, &Day, &Hours, &Mins, &Year) == 5)
X goto gotit;
X if (sscanf(p,"%d-%[^-]-%d %d:%d", &Day, month, &Year, &Hours, &Mins) == 5)
X goto gotit;
X if (sscanf(p,"%d %s %d, %d:%d:%*d -",&Day, month, &Year, &Hours, &Mins)== 5)
X goto gotit;
X if (sscanf(p,"%*s %d-%[^-]-%d %d:%d",&Day, month, &Year, &Hours, &Mins)== 5)
X goto gotit;
X goto didnt_getit;
gotit:
X if (Year > 1900)
X Year -= 1900;
X if ((Month = month_to_n(month)) == -1) {
X print("bad month: %s\n", p);
X return NULL;
X }
X return sprintf(month, "%02d%02d%02d%02d%02d", Year,Month,Day,Hours,Mins);
didnt_getit:
X if (ison(glob_flags, WARNING))
X print("Unknown date format: %s\n", p);
X return NULL;
X}
X
X/* pass a string in the form described above, put into string.
X * return values in buffers provided they are not null.
X */
char *
date_to_string(Date, Yr, Mon, Day, Wkday, Tm, ret_buf)
char *Date, *Yr, *Mon, *Day, *Wkday, *Tm, *ret_buf;
X{
X
X static int mtbl[]={0,31,59,90,120,151,181,212,243,273,304,334};
X unsigned int days_ctr;
X int yr, mon, day, hr, mins;
X char a_or_p, *p = ret_buf;
X
X (void) sscanf(Date, "%2d%2d%2d%2d%02d", &yr, &mon, &day, &hr, &mins);
X a_or_p = (hr < 12)? 'a': 'p';
X
X if (Wkday) {
X days_ctr = ((yr * 365) + ((yr + 3) / 4) + mtbl[mon-1] + day + 6);
X if (mon > 2 && (yr % 4 == 0))
X days_ctr++;
X (void) (sprintf(Wkday, "%.3s", day_names[days_ctr % 7]));
X }
X if (Yr)
X (void) sprintf(Yr, "19%d", yr);
X if (Day)
X (void) sprintf(Day, "%d", day);
X if (Mon)
X (void) strcpy(Mon, month_names[mon-1]);
X p += strlen(sprintf(p, "%s %2.d, ", month_names[mon-1], day));
X if (ison(glob_flags, MIL_TIME))
X (void) sprintf(p, "%2d:%02d",hr,mins);
X else
X (void) sprintf(p, "%2.d:%02d%cm",
X (hr)? (hr <= 12)? hr: hr - 12: 12, mins, a_or_p);
X if (Tm)
X (void) strcpy(Tm, p);
X return ret_buf;
X}
X
X#define JAN 1
X#define FEB 2
X#define MAR 3
X#define APR 4
X#define MAY 5
X#define JUN 6
X#define JUL 7
X#define AUG 8
X#define SEP 9
X#define OCT 10
X#define NOV 11
X#define DEC 12
X
X/* stolen direct from ELM */
month_to_n(name)
register char *name;
X{
X /** return the month number given the month name... **/
X
X register char ch;
X
X switch (lower(*name)) {
X case 'a' : if ((ch = lower(name[1])) == 'p')
X return(APR);
X else if (ch == 'u')
X return(AUG);
X else return(-1); /* error! */
X case 'd' : return(DEC);
X case 'f' : return(FEB);
X case 'j' : if ((ch = lower(name[1])) == 'a')
X return(JAN);
X else if (ch == 'u') {
X if ((ch = lower(name[2])) == 'n')
X return(JUN);
X else if (ch == 'l')
X return(JUL);
X else return(-1); /* error! */
X }
X else return(-1); /* error */
X case 'm' : if ((ch = lower(name[2])) == 'r')
X return(MAR);
X else if (ch == 'y')
X return(MAY);
X else return(-1); /* error! */
X case 'n' : return(NOV);
X case 'o' : return(OCT);
X case 's' : return(SEP);
X default : return(-1);
X }
X}
END_OF_FILE
if test 7499 -ne `wc -c <'dates.c'`; then
echo shar: \"'dates.c'\" unpacked with wrong size!
fi
# end of 'dates.c'
fi
if test -f 'execute.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'execute.c'\"
else
echo shar: Extracting \"'execute.c'\" \(5679 characters\)
sed "s/^X//" >'execute.c' <<'END_OF_FILE'
X/* execute.c (c) copyright 10/28/86 (Dan Heller) */
X
X#include "mush.h"
X#ifdef BSD
X#include <sys/wait.h>
X#else
X#ifndef SYSV
X#include <wait.h>
X#endif /* SYSV */
X#endif /* BSD */
X
X#ifdef lint
X#include <sys/resource.h>
X#endif /* lint */
X
execute(argv)
char **argv;
X{
X#ifdef SYSV
X int status;
X#else
X union wait status;
X#endif /* SYSV */
X#ifdef SIGCONT
X int (*oldstop)(), (*oldcont)();
X#endif /* SIGCONT */
X int pid, (*oldint)(), (*oldquit)();
X
X#ifdef SUNTOOL
X if (istool) {
X print("Editing letter...");
X
X panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
X win_setrect(tty_sw->ts_windowfd, &msg_rect);
X msg_rect.r_height = 0;
X win_setrect(msg_sw->ts_windowfd, &msg_rect);
X if ((exec_pid = ttysw_fork(tty_sw->ts_data, argv,
X &tty_sw->ts_io.tio_inputmask,
X &tty_sw->ts_io.tio_outputmask,
X &tty_sw->ts_io.tio_exceptmask)) == -1)
X error("%s failed", *argv), sigchldcatcher();
X Debug("tty pid = %d\n", exec_pid);
X return;
X }
X#endif /* SUNTOOL */
X oldint = signal(SIGINT, SIG_IGN);
X oldquit = signal(SIGQUIT, SIG_IGN);
X#ifdef SIGCONT
X oldstop = signal(SIGTSTP, SIG_DFL);
X oldcont = signal(SIGCONT, SIG_DFL);
X#endif /* SIGCONT */
X turnon(glob_flags, IGN_SIGS);
X
X echo_on();
X if ((exec_pid = vfork()) == 0) {
X (void) signal(SIGINT, SIG_DFL);
X (void) signal(SIGQUIT, SIG_DFL);
X execvp(*argv, argv);
X if (errno == ENOENT)
X print("%s: command not found.\n", *argv);
X else
X error(*argv);
X _exit(-1);
X }
X /* parent's got to do something; sigchldcatcher will do waiting
X * if other forks die (sendmail), then this wait will catch them,
X * This loop will really get -1, cuz sigchldcatcher will catch all else.
X */
X while ((pid = wait(&status) != -1) && pid != exec_pid)
X Debug("The exec loop caught a signal? (pid = %d)\n", pid);
X /* reset our ttymodes */
X echo_off();
X (void) signal(SIGINT, oldint);
X (void) signal(SIGQUIT, oldquit);
X#ifdef SIGCONT
X (void) signal(SIGTSTP, oldstop);
X (void) signal(SIGCONT, oldcont);
X#endif /* SIGCONT */
X turnoff(glob_flags, IGN_SIGS);
X}
X
sigchldcatcher()
X{
X#ifdef SUNTOOL
X struct rect rect;
X extern FILE *ed_fp;
X#endif /* SUNTOOL */
X#ifdef SYSV
X int status;
X#else
X union wait status;
X#endif /* SYSV */
X int pid;
X
X#ifdef BSD
X /* The follwoing SHOULDN'T be necessary, but it is!!! ttysw_fork()
X * returns the pid of the thing that it executes, but that's not the
X * pid that dies! There are many procs that might die from ttysw_fork
X * one of them is the process, another is the tty, etc... other
X * procs that might die are sendmail, fortune, etc... tool_sigchld()
X * handles these, but we can't let it have control unless we KNOW the
X * editor is done.
X * so if what we catch is not the exec_pid from ttysw_fork(), then
X * send ourselves a sigchld to go thru this routine again. mush -d
X */
X while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
X Debug("%d died...\n", pid);
X if (pid == exec_pid)
X break;
X }
X#else
X#ifndef SYSV
X while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid)
X Debug("%d died...\n", pid);
X#else /* SYSV */
X while ((pid = wait((int *)0)) > 0 && pid != exec_pid)
X Debug("%d died...\n", pid);
X#endif /* SYSV */
X#endif /* BSD */
X#ifndef SUNTOOL
X }
X#else /* SUNTOOL */
X if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */
X return;
X /* editor died -- reset exec_pid so no one thinks we're running */
X exec_pid = 0;
X /* only the tool needs to continue from here. Reset the win */
X if (istool < 1)
X return;
X tool_sigchld(tool);
X print("Editor done.");
X win_getrect(tty_sw->ts_windowfd, &msg_rect);
X if (msg_rect.r_height < 2 * l_height(curfont)) {
X print_more(" (well, something just happened)");
X return;
X }
X {
X extern char *edfile;
X if (!(ed_fp = fopen(edfile, "r+")))
X error("can't reopen %s", edfile);
X (void) fseek(ed_fp, 0L, 2);
X }
X /* I'd like to be able to just pw_rop the tty window onto the window
X * we're going to use now, but I can't access the data struture!
X *
X * pw_rop(msg_win, 0, 0, msg_rect.r_width, msg_rect.r_height, PIX_SRC,
X * ((struct ??? *)(tty_sw->ts_data))->pr_pixrect, 0, 0);
X * So, instead, just clear the window and write the last N lines from the
X * end of the file into the window.
X */
X rect.r_top = rect.r_left = rect.r_height = 0;
X rect.r_width = msg_rect.r_width;
X win_setrect(tty_sw->ts_windowfd, &rect);
X win_setrect(msg_sw->ts_windowfd, &msg_rect);
X do_clear();
X /* read the last 2K bytes in the file -- search backwards for enough
X * carriage returns that will fill the window with the end of the letter
X * written so far and display the text.
X */
X {
X register long where = ftell(ed_fp);
X register int cr = 0, lines = msg_rect.r_height * l_height(curfont) - 3;
X char buf[2*BUFSIZ], *p;
X where = max(0, where-2*BUFSIZ);
X (void) fseek(ed_fp, where, L_SET);
X p = buf + read(fileno(ed_fp), buf, 2*BUFSIZ);
X *p = 0;
X while (cr < lines && p > buf)
X if (*--p == '\n')
X cr++;
X if (p > buf)
X while (*p != '\n')
X p++;
X Addstr(p);
X }
X panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
X panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
X panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0);
X wprint("(continue editing letter.)\n");
X type_cursor(PIX_SRC);
X}
X
sigtermcatcher()
X{
X ttysw_done(tty_sw->ts_data);
X if (ison(glob_flags, IS_GETTING))
X rm_edfile(-1);
X cleanup(SIGTERM);
X}
X#endif /* SUNTOOL */
END_OF_FILE
if test 5679 -ne `wc -c <'execute.c'`; then
echo shar: \"'execute.c'\" unpacked with wrong size!
fi
# end of 'execute.c'
fi
if test -f 'file.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'file.c'\"
else
echo shar: Extracting \"'file.c'\" \(8484 characters\)
sed "s/^X//" >'file.c' <<'END_OF_FILE'
X/* file.c -- Copyright (1988) Dan Heller */
X
X#include "mush.h"
X#include <pwd.h>
X
X/* takes string 'p' and address of int (isdir). If p uses the ~ to reference
X * a home directory of somesort, then expand it. find out what sort of
X * file final path is. set isidr to 1 if a directory, 0 if not, -1 on error
X * return final path. If an error occurrs, return string indicating error.
X * if isdir has a value of 1 when passed, it ignores "No such file or directory"
X */
char *
getpath(p, isdir)
register char *p;
int *isdir;
X{
X static char buf[BUFSIZ];
X struct stat stat_buf;
X
X if (!p || !*p || !strcmp(p, "~")) {
X char *home = do_set(set_options, "home");
X if (!home || !*home)
X home = ALTERNATE_HOME;
X (void) strcpy(buf, home); /* no arg means home */
X } else if (*p == '~') {
X if (p[1] != '/') {
X /* not our home, but someone else's
X * look for ~user or ~user/subpath
X * if '/' exists, separate into tmp="user" p="subpath"
X */
X struct passwd *ent, *getpwnam();
X char *p2 = p+1;
X if (p = index(p2, '/'))
X *p++ = 0;
X if (!(ent = getpwnam(p2))) {
X *isdir = -1;
X return sprintf(buf, "no such user: %s", p2);
X }
X /* append subpath to pathname */
X if (p && *p)
X (void) sprintf(buf, "%s/%s", ent->pw_dir, p);
X /* if *p == NULL, pathname is done (buf), set isdir = 1 */
X else {
X *isdir = 1;
X return strcpy(buf, ent->pw_dir);
X }
X } else {
X char *home = do_set(set_options, "home");
X if (!home || !*home)
X home = ALTERNATE_HOME;
X (void) sprintf(buf, "%s/%s", home, p+2);
X }
X } else if (*p == '%') {
X /* if %user, append user name... else, it's just us */
X (void) sprintf(buf, "%s/", MAILDIR);
X if (!*++p || *p == ' ' || *p == '\t')
X (void) strcat(buf, login);
X else
X (void) strcat(buf, p);
X } else if (*p == '+') {
X register char *p2 = do_set(set_options, "folder");
X if (!p2 || !*p2)
X p2 = DEF_FOLDER;
X (void) sprintf(buf, "%s/%s", p2, ++p);
X if (*buf == '~') {
X int t_isdir = *isdir;
X char *t, tmp[256];
X (void) strcpy(tmp, buf);
X t = getpath(tmp, &t_isdir);
X if (t_isdir == -1) {
X *isdir = -1;
X return t;
X }
X /* strcpy(buf, t); --buf already has info because it's static */
X }
X } else { /* allow \ to escape the special chars, +, %, ~ */
X if (*p == '\\')
X p++;
X (void) strcpy(buf, p);
X }
X if (stat(buf, &stat_buf)) {
X (void) access(buf, F_OK); /* set errno to the "real" reason */
X if (errno == ENOENT && *isdir == 1) {
X *isdir = 0; /* say it's a regular file even tho it doesn't exist */
X return buf; /* it may be wanted for creating */
X }
X *isdir = -1;
X return sys_errlist[errno];
X }
X *isdir = ((stat_buf.st_mode & S_IFDIR) != 0);
X return buf;
X}
X
X/*
X * Given a filename[pointer] (p), a file pointer, and a mode, file_to_fp
X * opens the file with the mode.
X * If the mode is "r" then we read the file into the file pointer at the
X * end (fseek(fp, 2, 0)). If the file is opened for writing, then read
X * from the beginning of fp and write it into the file.
X * This is usually called to read .signatures into messages (thus,
X * opening .signture with "r" and writing to the end of fp which is probably
X * the sendmail process or the message file pointer) or to write fortunes into
X * the message buffer: reading fp (the popened fortune) and writing into file.
X */
void
file_to_fp(p, fp, mode)
register char *p;
register FILE *fp;
char *mode;
X{
X int x = 1;
X char *file, buf[BUFSIZ];
X FILE *tmp_fp;
X
X if (!p || !*p) {
X print("specify filename");
X return;
X }
X file = getpath(p, &x);
X if (x == -1) { /* on error, file contains error message */
X wprint(file);
X return;
X }
X wprint("%s: ", file);
X if (x) /* if x == 1, then path is a directory */
X wprint("directory.\n");
X else if (!(tmp_fp = fopen(file, mode))) {
X wprint("%s\n", sys_errlist[errno]);
X return;
X } else if (*mode != 'r') {
X rewind(fp);
X for(x = 0; fgets(buf, BUFSIZ, fp); x++)
X fputs(buf, tmp_fp);
X } else
X for(x = 0; fgets(buf, BUFSIZ, tmp_fp); x++)
X fputs(buf, fp);
X wprint("%s%d line%s\n", (*mode == 'a')? "added ": "",
X x, (x == 1)? "": "s");
X fflush(fp);
X fclose(tmp_fp);
X}
X
X/* clear all contents of the file. Careful that the file is opened for
X * _writing_ --tempfile is opened for reading, so don't try to empty it
X * if you're using ftruncate. Return -1 on error, 0 on success.
X */
emptyfile(fp, fname)
register FILE **fp;
register char *fname;
X{
X Debug("Emptying \"%s\"\n", fname);
X#ifndef SYSV
X return ftruncate(fileno(*fp), 0L);
X#else
X {
X int omask = umask(077), ret;
X fclose(*fp);
X if (!(*fp = fopen(fname, "w")))
X ret = -1;
X ret = 0;
X (void) umask(omask);
X return ret;
X }
X#endif /* SYSV */
X}
X
X/*
X * Finds out how many file descriptors are opened. Useful for making sure
X * no files got opened in subprocedures which were not subsequently closed.
X */
nopenfiles(argc)
X{
X register int nfiles = 0;
X#ifdef MAXFILES
X register int size = MAXFILES;
X#else
X register int size = getdtablesize();
X#endif /* MAXFILES */
X
X if (argc < 2)
X print("open file descriptors:");
X while (--size >= 0)
X if (fcntl(size, F_GETFL, 0) != -1) {
X if (argc < 2)
X print_more(" %d", size);
X ++nfiles;
X }
X if (argc < 2)
X print("\n");
X return nfiles;
X}
X
X/*
X * Open a path for writing or appending -- return a FILE pointer.
X * If program is TRUE, then use popen, not fopen and don't check
X * to see if the file is writable.
X */
FILE *
open_file(p, program)
register char *p;
X{
X register FILE *newfile = NULL_FILE;
X register char *tmp;
X int x = 1;
X
X if (program || *p == '/')
X tmp = p, x = 0;
X else
X tmp = getpath(p, &x);
X if (x == 1)
X print("%s is a directory.\n", tmp);
X else if (x == -1)
X print("%s: %s\n", p, tmp);
X else {
X register char *mode = NULL;
X /* if it doesn't exist open for "w" */
X if (program || Access(tmp, F_OK))
X mode = "w";
X /* if we can't write to it, forget it */
X else if (Access(tmp, W_OK))
X error(tmp);
X else
X mode = "a";
X if (mode)
X if (program) {
X if (!(newfile = popen(tmp, mode))) {
X error("Can't execute %s\n", tmp);
X return newfile;
X }
X } else
X if (!(newfile = fopen(tmp, mode)))
X error("Can't write to %s", tmp);
X else
X Debug("Successfully opened %s\n", tmp);
X }
X return newfile;
X}
X
X/*
X * find_files gets a set of addresses and an array of
X * file pointers and the maximum size that array can be.
X * The object is to find the files or programs listed in "s", attempt
X * to fopen/popen them and save their filepointers in the array. If the
X * size is 0, then just extract the file names and give error messages
X * for each one since they will not be opened. Return the number of
X * files opened and delete all files (opened or not) from the list in
X * "s". Tokens beginning with a "/, ~, or + are files; tokens beginning
X * with a | are programs.
X * The string "s" is modified to be a list of address -- all names AND
X * files are stripped out of the list.
X */
find_files(s, files, size)
register char *s;
FILE *files[];
X{
X register int total = 0, prog;
X char file[BUFSIZ], buf[BUFSIZ], *start = s, c;
X register char *p, *b = buf;
X
X do {
X if (!(p = get_name_n_addr(s, NULL, file)))
X break;
X c = *p, *p = 0;
X /* It's a file -- try to open it. This doesn't get written back
X * onto "buf" since it is supposed to be extracted anyway.
X */
X if (*file == '+' || *file == '~' || *file == '|' || *file == '/') {
X prog = (*file == '|');
X if (size && total < size) {
X /* either open "file" or &file[1] */
X if (files[total] = open_file(&file[prog], prog))
X total++;
X } else
X print("No open space for %s\n", file);
X } else {
X b += Strcpy(b, s);
X *b++ = ',', *b++ = ' ';
X }
X for (*p = c, s = p; *s == ',' || isspace(*s); s++)
X ;
X } while (*s);
X for (*b-- = 0; b > buf && (*b == ',' || isspace(*b)); b--)
X *b = 0;
X (void) strcpy(start, buf);
X return total;
X}
X
X/*
X * access(2) has an undocumented feature which ignores suid. If you are
X * su'ed and try to read your mail, you will be unable to because access()
X * will give the illusion that you cannot read/write to your mbox. Solve
X * the problem by using stat() instead.
X */
Access(file, mode)
register char *file;
X{
X struct stat buf;
X
X if (stat(file, &buf) == -1)
X return -1;
X if (mode == R_OK)
X return (buf.st_mode & 0400)? 0 : -1;
X if (mode == W_OK)
X return (buf.st_mode & 0200)? 0 : -1;
X return 0;
X}
END_OF_FILE
if test 8484 -ne `wc -c <'file.c'`; then
echo shar: \"'file.c'\" unpacked with wrong size!
fi
# end of 'file.c'
fi
if test -f 'main_panel.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'main_panel.c'\"
else
echo shar: Extracting \"'main_panel.c'\" \(9189 characters\)
sed "s/^X//" >'main_panel.c' <<'END_OF_FILE'
X/* "@(#)main_panel.c (c) copyright 10/18/86 (Dan Heller) */
X
X#include "mush.h"
X
make_main_panel(choice_args, button_args)
char **choice_args, **button_args;
X{
X /* main panel stuff: */
X panel_sw = panel_create(tool,
X PANEL_HEIGHT, 80,
X 0);
X main_panel = (Panel)panel_sw->ts_data;
X
X quit_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 4,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Done", 6, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Done",
X PANEL_CHOICE_STRINGS, "Close to Icon",
X "Quit Tool",
X "Help",
X 0,
X PANEL_NOTIFY_PROC, toolquit,
X 0);
X
X help_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 79,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Help", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Available Help",
X PANEL_CHOICE_STRINGS, "General",
X "Help with \"help\"",
X "The Mouse",
X "Windows",
X "Function Keys",
X "Message headers",
X "Message lists",
X 0,
X PANEL_NOTIFY_PROC, do_help,
X 0);
X
X read_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 136,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Next", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Next Message",
X PANEL_CHOICE_STRINGS, "Read Next", "Help", 0,
X PANEL_NOTIFY_PROC, read_mail,
X 0);
X
X respond_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 193,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Reply", 5, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Respond to Current Message",
X PANEL_CHOICE_STRINGS, "Sender Only",
X "Sender Only (include msg)",
X "All Recipients",
X "All Recipients (include msg)",
X "Help", 0,
X PANEL_NOTIFY_PROC, respond_mail,
X 0);
X
X delete_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 259,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Delete", 6, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Delete/Undelete Messages",
X PANEL_CHOICE_STRINGS, "Delete",
X "Undelete",
X "Help", 0,
X PANEL_NOTIFY_PROC, delete_mail,
X 0);
X
X sort_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 334,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Sort", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Sort Messages",
X PANEL_CHOICE_STRINGS, "By Date",
X "By Author",
X "By Subject",
X "By Subject (ignore Re:)",
X "By Status",
X "Help", 0,
X PANEL_NOTIFY_PROC, do_sort,
X 0);
X
X option_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 391,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Opts", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Mail Options",
X PANEL_CHOICE_STRINGS, "Set Options", "Function keys",
X "Help", 0,
X PANEL_NOTIFY_PROC, p_set_opts,
X 0);
X
X alias_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 448,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Aliases", 7, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Mail Aliases",
X PANEL_CHOICE_STRINGS, "Current Aliases",
X "Add/Change alias",
X "Unalias", "Help", 0,
X PANEL_NOTIFY_PROC, p_set_opts,
X 0);
X
X comp_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 532,
X PANEL_ITEM_Y, 4,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Compose", 8, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Compose a letter",
X PANEL_CHOICE_STRINGS, "Help", 0,
X PANEL_NOTIFY_PROC, do_compose,
X 0);
X
X file_item = panel_create_item(main_panel, PANEL_TEXT,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 4,
X PANEL_ITEM_Y, 30,
X PANEL_LABEL_FONT, fonts[DEFAULT],
X PANEL_SHOW_MENU, TRUE,
X PANEL_LABEL_STRING, "filename:",
X PANEL_MENU_CHOICE_STRINGS, "Save message without message header",0,
X PANEL_VALUE_DISPLAY_LENGTH, 35,
X PANEL_NOTIFY_STRING, "\n\r",
X PANEL_NOTIFY_PROC, file_dir,
X 0);
X
X input_item = panel_create_item(main_panel, PANEL_TEXT,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 373,
X PANEL_ITEM_Y, 30,
X PANEL_SHOW_ITEM, FALSE,
X PANEL_SHOW_MENU, TRUE,
X PANEL_LABEL_FONT, fonts[DEFAULT],
X PANEL_VALUE_DISPLAY_LENGTH, 20,
X PANEL_NOTIFY_STRING, "\n\r",
X PANEL_NOTIFY_PROC, text_done,
X 0);
X
X print_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 4,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Printer", 7, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Printing Messages",
X PANEL_CHOICE_STRINGS, "Help", 0,
X PANEL_NOTIFY_PROC, do_lpr,
X 0);
X
X folder_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 88,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "folder", 6, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Change folder",
X PANEL_CHOICE_STRINGS, "System Mailbox",
X "Main Mailbox",
X "Last Accessed Folder",
X 0,
X PANEL_NOTIFY_PROC, do_file_dir,
X 0);
X
X add_folder_to_menu(folder_item, 3);
X
X save_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 163,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Save", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Save messages",
X PANEL_CHOICE_STRINGS, "~/mbox", 0,
X PANEL_NOTIFY_PROC, do_file_dir,
X 0);
X
X add_folder_to_menu(save_item, 1);
X
X cd_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 220,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "chdir", 5, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Change Working Directory",
X PANEL_CHOICE_STRINGS, "Print Current directory",
X "HOME directory",
X "Private Mail directory.",
X "Help", 0,
X PANEL_NOTIFY_PROC, do_file_dir,
X 0);
X
X update_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 286,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Update", 6, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Updating folders",
X PANEL_CHOICE_STRINGS, "Help", 0,
X PANEL_NOTIFY_PROC, do_update,
X 0);
X
X send_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 361,
X PANEL_ITEM_Y, 50,
X PANEL_SHOW_ITEM, FALSE,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Send", 6, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Send Letter",
X PANEL_CHOICE_STRINGS, "Help", 0,
X PANEL_NOTIFY_PROC, do_send,
X 0);
X
X edit_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 436,
X PANEL_ITEM_Y, 50,
X PANEL_SHOW_ITEM, FALSE,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Editor", 4, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Editing",
X PANEL_CHOICE_STRINGS, "Help", 0,
X PANEL_NOTIFY_PROC, do_edit,
X 0);
X
X abort_item = panel_create_item(main_panel, PANEL_BUTTON,
X PANEL_ATTRIBUTE_LIST, button_args,
X PANEL_ITEM_X, 511,
X PANEL_ITEM_Y, 50,
X PANEL_SHOW_ITEM, FALSE,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Abort", 5, fonts[LARGE]),
X PANEL_NOTIFY_PROC, abort_mail,
X 0);
X
X font_item = panel_create_item(main_panel, PANEL_CHOICE,
X PANEL_ATTRIBUTE_LIST, choice_args,
X PANEL_ITEM_X, 577,
X PANEL_ITEM_Y, 50,
X PANEL_LABEL_IMAGE,
X panel_button_image(main_panel, "Fonts", 5, fonts[LARGE]),
X PANEL_MENU_TITLE_STRING, "Fonts",
X PANEL_SHOW_MENU_MARK, TRUE,
X PANEL_CHOICE_FONTS, fonts[0], fonts[1], fonts[2], 0,
X PANEL_CHOICE_STRINGS, "Default", "Small", "Large", 0,
X PANEL_NOTIFY_PROC, change_font,
X 0);
X}
X
X/*
X * Open the user's mail folder (either user set or default path) and find all
X * the files (assumed to be mail folders) and add them to the menu list of
X * folders to use.
X */
add_folder_to_menu(item, n)
struct panel_item *item;
register int n;
X{
X register FILE *pp = NULL_FILE;
X register char *p, *tmp = NULL;
X int x = 0;
X char buf[128], path[128];
X
X if (!(p = do_set(set_options, "folder")) || !*p)
X p = DEF_FOLDER;
X if (p) {
X tmp = getpath(p, &x);
X if (x == -1) {
X if (errno != ENOENT)
X print("%s: %s\n", p, tmp);
X tmp = NULL;
X }
X }
X if (p = tmp) {
X p = sprintf(buf, "%s %s", LS_COMMAND, p);
X if (!(pp = popen(buf, "r")))
X error(buf);
X else {
X *path = '+';
X while (fgets(path+1, 128, pp)) {
X struct stat s_buf;
X if (p = index(path+1, '\n'))
X *p = 0;
X (void) sprintf(buf, "%s/%s", tmp, path+1);
X if (stat(buf, &s_buf) || s_buf.st_mode & S_IFDIR)
X continue;
X panel_set(item, PANEL_CHOICE_STRING, n++, path, 0);
X }
X pclose(pp);
X }
X }
X panel_set(item, PANEL_CHOICE_STRING, n, "Help", 0);
X}
END_OF_FILE
if test 9189 -ne `wc -c <'main_panel.c'`; then
echo shar: \"'main_panel.c'\" unpacked with wrong size!
fi
# end of 'main_panel.c'
fi
if test -f 'signals.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'signals.c'\"
else
echo shar: Extracting \"'signals.c'\" \(9615 characters\)
sed "s/^X//" >'signals.c' <<'END_OF_FILE'
X/* @(#)signals.c (c) copyright 10/18/86 (Dan Heller) */
X
X#include "mush.h"
X
X#ifndef SYSV
extern char *sys_siglist[];
X#else
X/* sys-v doesn't have normal sys_siglist */
static char *sys_siglist[] = {
X/* no error */ "no error",
X/* SIGHUP */ "hangup",
X/* SIGINT */ "interrupt (rubout)",
X/* SIGQUIT */ "quit (ASCII FS)",
X/* SIGILL */ "illegal instruction (not reset when caught)",
X/* SIGTRAP */ "trace trap (not reset when caught)",
X/* SIGIOT */ "IOT instruction",
X/* SIGEMT */ "EMT instruction",
X/* SIGFPE */ "floating point exception",
X/* SIGKILL */ "kill (cannot be caught or ignored)",
X/* SIGBUS */ "bus error",
X/* SIGSEGV */ "segmentation violation",
X/* SIGSYS */ "bad argument to system call",
X/* SIGPIPE */ "write on a pipe with no one to read it",
X/* SIGALRM */ "alarm clock",
X/* SIGTERM */ "software termination signal from kill",
X/* SIGUSR1 */ "user defined signal 1",
X/* SIGUSR2 */ "user defined signal 2",
X/* SIGCLD */ "death of a child",
X/* SIGPWR */ "power-fail restart"
X};
X#endif /* SYSV */
X
X#ifdef SUNTOOL
msgwin_handlesigwinch()
X{
X register struct rect rect;
X if (exec_pid)
X return;
X rect = msg_rect;
X pw_damaged(msg_win);
X /* this prevents old screen from being lost when editor finishes */
X if (isoff(glob_flags, IS_GETTING))
X gfxsw_interpretesigwinch(msg_sw->ts_data);
X gfxsw_handlesigwinch(msg_sw->ts_data);
X pw_repairretained(msg_win);
X pw_donedamaged(msg_win);
X win_getrect(msg_sw->ts_windowfd, &msg_rect);
X crt = msg_rect.r_height / l_height(curfont);
X if (rect.r_height != msg_rect.r_height || rect.r_width != rect.r_width)
X if (getting_opts == 1)
X display_opts(0);
X else if (getting_opts == 2)
X set_fkeys();
X else if (msg_pix)
X scroll_win(0);
X}
X
hdrwin_handlesigwinch()
X{
X register struct rect rect;
X rect = hdr_rect;
X pw_damaged(hdr_win);
X gfxsw_interpretesigwinch(hdr_sw->ts_data);
X gfxsw_handlesigwinch(hdr_sw->ts_data);
X pw_repairretained(hdr_win);
X pw_donedamaged(hdr_win);
X win_getrect(hdr_sw->ts_windowfd, &hdr_rect);
X if (rect.r_width != hdr_rect.r_width || rect.r_height != hdr_rect.r_height){
X pw_writebackground(hdr_win, 0,0,
X hdr_rect.r_width, hdr_rect.r_height, PIX_CLR);
X screen = hdr_rect.r_height/l_height(DEFAULT);
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X}
X
print_sigwinch()
X{
X pw_damaged(print_win);
X gfxsw_handlesigwinch(print_sw->ts_data);
X pw_writebackground(print_win, 0,0,
X win_getwidth(print_sw->ts_windowfd),
X win_getheight(print_sw->ts_windowfd), PIX_CLR);
X pw_donedamaged(print_win);
X print(NULL); /* reprint whatever was there before damage */
X}
X
sigwinchcatcher()
X{
X tool_sigwinch(tool);
X}
X#endif /* SUNTOOL */
X
interrupt(sig)
X{
X Debug("interrupt() caught: %d\n", sig);
X turnon(glob_flags, WAS_INTR);
X}
X
X/*
X * catch signals to reset state of the machine. Always print signal caught.
X * If signals are ignored, return. If we're running the shell, longjmp back.
X */
X/*ARGSUSED*/
catch(sig)
X{
X Debug("Caught signal: %d\n", sig);
X (void) signal(sig, catch);
X if (ison(glob_flags, IGN_SIGS) && sig != SIGTERM && sig != SIGHUP)
X return;
X print("%s: %s\n", prog_name, sys_siglist[sig]);
X turnoff(glob_flags, IS_PIPE);
X if (istool || sig == SIGTERM || sig == SIGHUP) {
X if (istool) /* istool is 2 if tool is complete */
X istool = 1;
X (void) setjmp(jmpbuf);
X if (ison(glob_flags, IS_GETTING))
X rm_edfile(-1);
X cleanup(sig);
X }
X if (ison(glob_flags, DO_SHELL)) {
X turnoff(glob_flags, IS_GETTING);
X longjmp(jmpbuf, 1);
X } else
X puts("exiting"), cleanup(sig);
X}
X
X#ifdef SIGCONT
stop_start(sig)
X{
X extern FILE *ed_fp;
X
X Debug("Caught signal: %d", sig);
X if (sig == SIGCONT) {
X (void) signal(SIGTSTP, stop_start);
X (void) signal(SIGCONT, stop_start);
X echo_off();
X if (istool || ison(glob_flags, IGN_SIGS) && !iscurses)
X return;
X /* we're not in an editor but we're editing a letter */
X if (ison(glob_flags, IS_GETTING)) {
X if (ed_fp)
X print("(Continue editing letter)\n");
X }
X#ifdef CURSES
X else if (iscurses)
X if (ison(glob_flags, IGN_SIGS)) {
X clr_bot_line();
X if (msg_list)
X puts(compose_hdr(current_msg));
X mail_status(1), addstr("...continue... ");
X refresh();
X } else {
X int curlin = max(1, current_msg - n_array[0] + 1);
X redraw();
X print("Continue");
X move(curlin, 0);
X refresh();
X /* make sure we lose reverse video on continuation */
X if (ison(glob_flags, REV_VIDEO) && msg_cnt) {
X char buf[256];
X (void) strncpy(buf, compose_hdr(current_msg), COLS-1);
X buf[COLS-1] = 0; /* strncpy does not null terminate */
X mvaddstr(curlin, 0, buf);
X }
X }
X#endif /* CURSES */
X else
X mail_status(1), fflush(stdout);
X } else {
X#ifdef CURSES
X if (iscurses) {
X /* when user stops mush, the current header is not in reverse
X * video -- note that a refresh() has not been called in curses.c!
X * so, make sure that when a continue is called, the reverse video
X * for the current message returns.
X */
X turnon(glob_flags, WAS_INTR);
X if (isoff(glob_flags, IGN_SIGS) && ison(glob_flags, REV_VIDEO) &&
X msg_cnt) {
X int curlin = max(1, current_msg - n_array[0] + 1);
X char buf[256];
X (void) strncpy(buf, stdscr->_y[curlin], COLS-1);
X buf[COLS-1] = 0; /* strncpy does not null terminate */
X STANDOUT(curlin, 0, buf);
X }
X print("Stopping...");
X }
X#endif /* CURSES */
X echo_on();
X (void) signal(SIGTSTP, SIG_DFL);
X (void) signal(SIGCONT, stop_start);
X (void) kill(getpid(), sig);
X }
X}
X#endif /* SIGCONT */
X
X/*ARGSUSED*/
cleanup(sig)
X{
X char buf[128], c = ison(glob_flags, IGN_SIGS)? 'n' : 'y';
X
X#ifdef CURSES
X if (iscurses)
X iscurses = FALSE, endwin();
X#endif /* CURSES */
X
X echo_on();
X
X if (ison(glob_flags, IS_GETTING))
X turnoff(glob_flags, IS_GETTING), dead_letter();
X if ((sig == SIGSEGV || sig == SIGBUS) && isoff(glob_flags, IGN_SIGS)
X && *tempfile) {
X fprintf(stderr, "remove %s [y]? ", tempfile), fflush(stderr);
X if (fgets(buf, 128, stdin))
X c = lower(*buf);
X }
X if (c != 'n' && *tempfile && unlink(tempfile) && !sig && errno != ENOENT)
X error(tempfile);
X#ifdef SUNTOOL
X if (istool && tool)
X tool_destroy(tool);
X#endif /* SUNTOOL */
X if (sig == SIGSEGV || sig == SIGBUS) {
X if (isoff(glob_flags, IGN_SIGS)) {
X fprintf(stderr, "coredump [n]? "), fflush(stderr);
X if (fgets(buf, 128, stdin))
X c = lower(*buf);
X }
X if (c == 'y')
X puts("dumping core for debugging"), abort();
X }
X exit(sig);
X}
X
X/*
X * if new mail comes in, print who it's from. sprintf it all into one
X * buffer and print that instead of separate print statements to allow
X * the tool mode to make one print statment. The reason for this is that
X * when the tool is refreshed (caused by a resize, reopen, move, top, etc)
X * the last thing printed is displayed -- display the entire line.
X */
check_new_mail()
X{
X int ret_value;
X char buf[BUFSIZ];
X register char *p = buf;
X static long last_spool_size = -1;
X
X#ifdef SUNTOOL
X static int is_iconic, was_iconic;
X
X if (istool) {
X timerclear(&(mail_timer.it_interval));
X timerclear(&(mail_timer.it_value));
X mail_timer.it_value.tv_sec = time_out;
X setitimer(ITIMER_REAL, &mail_timer, NULL);
X }
X#endif /* SUNTOOL */
X /* if fullscreen access in progress (help), don't do anything */
X if (ret_value = mail_size()) {
X#ifdef CURSES
X int new_hdrs = last_msg_cnt;
X#endif /* CURSES */
X#ifdef SUNTOOL
X /* if our status has changed from icon to toolform, then
X * there will already be a message stating number of new
X * messages. reset `n' to msg_cnt so we don't restate
X * the same # of new messages upon receipt of yet another new message.
X */
X if (istool && !(is_iconic = (tool->tl_flags&TOOL_ICONIC)) && was_iconic)
X last_msg_cnt = msg_cnt;
X#endif /* SUNTOOL */
X turnon(glob_flags, NEW_MAIL);
X getmail(); /* msg_cnt gets incremented here */
X if (istool) {
X mail_status(0);
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X p += Strcpy(p, "New mail ");
X if (msg_cnt - last_msg_cnt <= 1)
X p += strlen(sprintf(p, "(#%d) ", msg_cnt));
X else
X p += strlen(sprintf(p, "(#%d thru #%d)\n", last_msg_cnt+1,msg_cnt));
X#ifdef SUNTOOL
X /*
X * If mush is in tool mode and in icon form, don't update
X * last_msg_cnt so that when the tool is opened, print() will
X * print the correct number of "new" messages.
X */
X if (!istool || !(was_iconic = tool->tl_flags & TOOL_ICONIC))
X#endif /* SUNTOOL */
X if (iscurses && isoff(glob_flags, CNTD_CMD))
X last_msg_cnt = msg_cnt;
X else while (last_msg_cnt < msg_cnt) {
X char *p2 = compose_hdr(last_msg_cnt++) + 9;
X if (strlen(p2) + (p - buf) >= BUFSIZ-5) {
X (void) strcat(p, "...\n");
X /* force a break by setting last_msg_cnt correctly */
X last_msg_cnt = msg_cnt;
X } else
X p += strlen(sprintf(p, " %s\n", p2));
X }
X#ifdef CURSES
X if (iscurses && isoff(glob_flags, CNTD_CMD)) {
X if (new_hdrs - n_array[screen-1] < screen)
X (void) do_hdrs(0, DUBL_NULL, NULL);
X print("%s ...", buf);
X } else
X#endif /* CURSES */
X print("%s", buf); /* buf might have %'s in them!!! */
X } else
X#ifdef SUNTOOL
X if (!istool || !is_iconic)
X#endif /* SUNTOOL */
X turnoff(glob_flags, NEW_MAIL);
X if (last_spool_size > -1 && /* handle first case */
X strcmp(mailfile, spoolfile) && last_spool_size < spool_size)
X print("You have new mail in your system mailbox.\n"), ret_value = 1;
X last_spool_size = spool_size;
X return ret_value;
X}
X
X/*ARGSUSED*/ /* we ignore the sigstack, cpu-usage, etc... */
bus_n_seg(sig)
X{
X fprintf(stderr, "%s: %s\n", prog_name,
X (sig == SIGSEGV)? "Segmentation violation": "Bus error");
X cleanup(sig);
X}
END_OF_FILE
if test 9615 -ne `wc -c <'signals.c'`; then
echo shar: \"'signals.c'\" unpacked with wrong size!
fi
# end of 'signals.c'
fi
echo shar: End of archive 3 \(of 14\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 14 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list