rsalz@uunet.UU.NET (Rich Salz) (09/19/87)
Submitted-by: island!argv@Sun.COM (Dan Heller) Posting-number: Volume 11, Issue 56 Archive-name: mush5.7/Part06 #! /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 6 (of 12)." # Contents: curses.c msgs.c mush.h PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'curses.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'curses.c'\" else echo shar: Extracting \"'curses.c'\" \(17549 characters\) sed "s/^X//" >'curses.c' <<'END_OF_FILE' X/* @(#)curses.c (c) copyright 3/18/87 (Dan Heller) */ X X/* curses.c -- routine to deal with the curses interface */ X#ifdef CURSES X X#include "mush.h" X#include "bindings.h" X Xcurses_init(argc, argv) Xregister char **argv; X{ X char buf[80]; X extern char *UP, ttytype[]; X X if (argv && *++argv && !strcmp(*argv, "-?")) X return help(0, "curses", cmd_help); X if (iscurses) { X print("You can't run curses from the curses mode (silly)."); X return -1; X } X if (ison(glob_flags, IS_GETTING)) { X print("Finish your letter first.\n"); X return -1; X } X#ifdef SUNTOOL X if (istool) { X print("My, aren't we the adventuresome type!"); X timerclear(&(mail_timer.it_interval)); X timerclear(&(mail_timer.it_value)); X tool_destroy(tool), istool = FALSE; X curses_init(0, 0); X do_loop(); /* doesn't return */ X } X#endif SUNTOOL X X /* you can not start curses in no echo mode.. must be in normal mode */ X echo(), nocrmode(); X (void) initscr(); X#ifdef SIGCONT X /* initscr will play with signals -- make sure they're set right. */ X (void) signal(SIGTSTP, stop_start); X (void) signal(SIGCONT, stop_start); X#endif SIGCONT X if (!UP || !*UP) { X print("Terminal type %s can not use the curses interface.\n", ttytype); X return -1; X } X iscurses = TRUE; X noecho(), crmode(); /* reset tty state -- do not use "echo_on/off()" */ X scrollok(stdscr, TRUE); X /* if the user hasn't set his screen explicitely, set it for him */ X if (!do_set(set_options, "screen")) X switch (_tty.sg_ospeed) { X case B300 : screen = min(LINES-2, 7); X when B1200 : screen = min(LINES-2, 14); X when B2400 : screen = min(LINES-2, 22); X otherwise : screen = LINES-2; X } X else X screen = min(screen, LINES-2); X crt = LINES; X if (argc) X (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list); X if (!do_set(set_options, "no_reverse")) X turnon(glob_flags, REV_VIDEO); X turnoff(glob_flags, CONT_PRNT); X return -1; /* doesn't affect messages */ X} X X/* X * get input in cbreak mode and execute the appropriate command. X * when the command is done (usually), the user is prompted to X * hit any key to continue. At this point, the user may enter a X * new command so no screen refreshing needds to be done. This X * new command is returned to caller and may be passed back. X * X * The variable "cntd_cmd" (continued command) is set to true if X * this routine is called with the passed parameter (c) > 0. If X * so, then the character passed is the character input by the X * user at the last "hit return" prompt indicating that he wants X * to execute a new command and not draw the screen. X * X * cntd_cmd is also set to true if the command that the user invokes X * causes any sort of output that requires a screen refresh. The X * variable redo is set to 1 if the header page not only requires X * redrawing, but updating ... (new call to do_hdrs) X * X * calls that say: print("%s", compose_hdr(current_msg)) are constructed X * that way cuz if the header has a `%' in it, then print will try to X * expand it. X */ Xcurses_command(c) Xregister int c; X{ X char buf[BUFSIZ], file[128], list[128]; X int n, cntd_cmd = (c > 0), curlin; X static int redo; /* set if headers should be redrawn */ X X clear_msg_list(msg_list); /* play it safe */ X if (!cntd_cmd) { X (void) check_new_mail(); X curlin = max(1, current_msg - n_array[0] + 1); X (void) strncpy(buf, stdscr->_y[curlin], COLS-1); X buf[COLS-1] = 0; /* strncpy does not null terminate */ X if (ison(glob_flags, REV_VIDEO) && msg_cnt) X STANDOUT(curlin, 0, buf); X mail_status(0); X move(curlin, 0), refresh(); X /* reprint to remove reverse video from current line (don't refresh) */ X if (ison(glob_flags, REV_VIDEO)) X mvaddstr(curlin, 0, buf); X c = getcmd(); /* get input AFTER line redrawn without reverse video */ X } X buf[0] = list[0] = file[0] = '\0'; X X /* goto a specific line number */ X if (c == C_GOTO_MSG) { X c = C_NULL; X if (msg_cnt <= 1) X print("Not enough messages."); X else if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) { X for (n = 0; !msg_bit(msg_list, n); n++) X ; X if ((current_msg = n) < n_array[0] || n > n_array[screen-1]) X redo = 1; X } X if (cntd_cmd && msg_cnt) X print("%s", compose_hdr(current_msg)); X if (cntd_cmd) X putchar('\n'); X } else if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST X || c == C_DELETE_LIST || c == C_UNDEL_LIST) { X X if (msg_cnt <= 1) X print("Not enough messages."), c = C_NULL; X else if (!curses_msg_list(sprintf(buf, "%s msg list: ", X (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)? "save" : X (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list)) X c = C_NULL; X if (cntd_cmd) X putchar('\n'); X } X X /* first do non-mail command stype stuff */ X switch (c) { X case C_NULL : ; X X /* screen optimization stuff */ X when C_REVERSE : X if (ison(glob_flags, REV_VIDEO)) X turnoff(glob_flags, REV_VIDEO); X else X turnon(glob_flags, REV_VIDEO); X X when C_REDRAW : if (!redo) redraw(); X X /* X * screen movement X */ X when C_NEXT_MSG : X /* case 'j' : case 'J' : case '+' : case '\n' : /* next */ X if (current_msg + 2 > msg_cnt || !cntd_cmd && curlin == screen) X bell(); /* reached the end */ X else { X if (++current_msg > n_array[screen-1]) X redo = 1; X if (cntd_cmd) X print("%s", compose_hdr(current_msg)), putchar('\n'); X } X when C_PREV_MSG : X /* when 'k' : case 'K' : case '-' : case CTRL(k) : /* previous */ X if (!cntd_cmd && curlin == 1 || current_msg == 0) X bell(); /* at the beginning */ X else { X if (--current_msg < n_array[0]) X redo = 1; X if (cntd_cmd) X print("%s", compose_hdr(current_msg)), putchar('\n'); X } X when C_FIRST_MSG : case C_LAST_MSG : X n = current_msg; X if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] || X c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1]) X if (!cntd_cmd) X (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), X msg_list); X else X redo = 1; X if (cntd_cmd && n != current_msg) X print("%s", compose_hdr(current_msg)), putchar('\n'); X /* top and bottom of headers screen */ X when C_TOP_PAGE : case C_BOTTOM_PAGE : X if (!cntd_cmd) X if (c == C_TOP_PAGE) X current_msg = n_array[0]; X else X current_msg = min(n_array[screen-1], msg_cnt-1); X else X bell(); X when C_NEXT_SCREEN : /* next page */ X if (msg_cnt > screen) { X (void) cmd_line(strcpy(buf, "headers +"), msg_list); X current_msg = n_array[0]; X return redo = 0; X } else X bell(); X when C_PREV_SCREEN : /* previous page */ X if (current_msg > 0 || cntd_cmd) X (void) cmd_line(strcpy(buf, "headers -"), msg_list), redo = 0; X current_msg = (msg_cnt <= 1)? 0 : n_array[0]; X return 0; X /* break; (not stated for lint) */ X X case C_SHOW_HDR : X if (cntd_cmd && msg_cnt) X puts(compose_hdr(current_msg)); X X /* read from/save to record file (.mushrc) */ X when C_SOURCE : case C_SAVEOPTS : X print("%s filename [default]: ", X (c == C_SOURCE)? "source" : "save options to"); X if (Getstr(file, LINES-40, 0) < 0) { X clr_bot_line(); X return 0; X } X iscurses = FALSE; X turnon(glob_flags, PRE_CURSES); X (void) cmd_line(sprintf(buf, "%s %s", X (c == C_SOURCE) ? "source" : "saveopts", file), msg_list); X iscurses = TRUE; X turnoff(glob_flags, PRE_CURSES); X cntd_cmd = 1; X X /* X * search commands X */ X when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH : X if (c != C_CONT_SEARCH) X c = search(0 + (c == C_PREV_SEARCH)); X else X c = search(-1); X if (cntd_cmd) X putchar('\n'); X if (c == 0) X break; X if (cntd_cmd) X print("%s", compose_hdr(current_msg)), putchar('\n'); X if (n_array[0] > current_msg || n_array[screen-1] < current_msg) { X redo = 1; X if (!cntd_cmd) X (void) cmd_line(sprintf(buf, "headers %d", X current_msg+1), msg_list); X } X X /* X * actions on messages X */ X /* delete/undelete */ X when C_DELETE_MSG : case C_DELETE_LIST : X case C_UNDEL_MSG : case C_UNDEL_LIST : X if (!msg_cnt) { X print("No messages."); X if (cntd_cmd) X putchar('\n'); X break; X } X if (!*list) X set_msg_bit(msg_list, current_msg); X turnon(glob_flags, DO_UPDATE); X for (n = 0; n < msg_cnt; n++) X if (msg_bit(msg_list, n)) { X if (c == C_DELETE_MSG || c == C_DELETE_LIST) X turnon(msg[n].m_flags, DELETE); X else X turnoff(msg[n].m_flags, DELETE); X if (!cntd_cmd && msg_cnt < screen || X !cntd_cmd && n >= n_array[0] && n <= n_array[screen-1]) X mvaddstr(max(1, n - n_array[0] + 1), 0, compose_hdr(n)); X else X redo = 1; X } X if (cntd_cmd || *list) { X if (cntd_cmd) { /* print(), THEN putchar() -- overwrite line */ X print("%sdeleted %s", X (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list); X putchar('\n'); X } X if (ison(msg[current_msg].m_flags, DELETE)) X (void) next_msg(FALSE, DELETE); X if (do_set(set_options, "autoprint")) X return C_DISPLAY_MSG; X if (cntd_cmd) X puts(compose_hdr(current_msg)); X } X X /* X * write/save messages. If a list is necessary, the user already X * entered it above since he must have used a capital letter. If so, X * list will contain good data (already been validated above). X * if a list is given, set iscurses to 0 so that print statements X * will scroll and the user sees the multiple output. else, one X * line can go on the bottom line just fine. X */ X when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG : X case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : { X register char *p = X (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" : X (c == C_SAVE_MSG || c == C_SAVE_LIST)? "save" : "copy"; X print(sprintf(buf, "filename to %s [mbox]: ", p)); X if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) { X char *argv[3]; X clr_bot_line(); X argv[0] = strcpy(buf, p); X argv[1] = file; X argv[2] = NULL; X if (!*list) X set_msg_bit(msg_list, current_msg); X move(LINES-1, 0), refresh(); X if (*list) X iscurses = FALSE; X turnon(glob_flags, IS_PIPE); X if (save_msg(2, argv, msg_list) < 0) X *list = 0; X turnoff(glob_flags, IS_PIPE); X if (cntd_cmd) X putchar('\n'), puts(compose_hdr(current_msg)); X if (*list) X iscurses = cntd_cmd = redo = TRUE; X else if (!cntd_cmd && msg_cnt) X mvaddstr(curlin, 0, compose_hdr(current_msg)); X } else { X print("No messages saved."); X if (cntd_cmd) X putchar('\n'); X } X } X X /* preserve message */ X when C_PRESERVE : X if (!msg_cnt) { X print("No messages."); X if (cntd_cmd) X putchar('\n'); X break; X } X if (ison(msg[current_msg].m_flags, PRESERVE)) X turnoff(msg[current_msg].m_flags, PRESERVE); X else X turnon(msg[current_msg].m_flags, PRESERVE); X if (cntd_cmd) { X print("%s", compose_hdr(current_msg)), putchar('\n'); X redo = 1; X } else X mvaddstr(curlin, 0, compose_hdr(current_msg)); X X /* order messages (sort) and rediesplay the headers */ X when C_SORT : case C_REV_SORT : X (void) strcpy(file, "sort"); X if (c == C_REV_SORT) { X print("Reverse "), turnon(glob_flags, CONT_PRNT); X (void) strcat(file, " -"); X } X print("Order messages by [Status, date, subject, author]: "); X if ((c = getchar()) == 's' || c == 'S' || c == 'd' || c == 'a') { X print("reordering messages..."); X (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list); X print_more("done."); X if (cntd_cmd) X putchar('\n'), puts(compose_hdr(current_msg)); X redo = 1; X } else X clr_bot_line(); X X when C_QUIT_HARD : X (void) quit(0, DUBL_NULL); X redo = 1; /* new mail must have come in */ X X /* quit or update -- vrfy_update (returns 1 if updated) */ X when C_QUIT : case C_UPDATE : X if (!vrfy_update(&cntd_cmd, &redo)) X if (c == C_UPDATE) X break; X else X turnoff(glob_flags, DO_UPDATE); X if (c == C_QUIT) { X putchar('\n'); X cleanup(0); X redo = 1; X } X X when C_EXIT : case C_EXIT_HARD : X clr_bot_line(); X iscurses = FALSE; X if (c != C_EXIT && c != C_EXIT_HARD) X putchar('\n'); X cleanup(0); X X /* change to a new folder */ X when C_FOLDER : X for (;;) { X print("New folder (?=list): "); X if (Getstr(file, COLS-22, 0) > 0) { X if (!strcmp(file, "?")) { X clr_bot_line(); X iscurses = 0; X puts("folders in your folder directory:"); X (void) cmd_line(strcpy(buf, "folders"), msg_list); X puts("Precede folder names with a +. `%' to specify system mailbox."); X cntd_cmd = iscurses = 1; X continue; X } X clearok(stdscr, FALSE); X if (strcmp(file, "-?")) X vrfy_update(&cntd_cmd, &redo); X move(LINES-1, 0), refresh(); X if (cmd_line(sprintf(buf, "folder ! -N %s", file), X msg_list) == -1) { X /* error message was printed; leave room to read it */ X putchar('\n'); X cntd_cmd = 1, redo = 0; X } else X redo = 1, cntd_cmd = 0; X break; X } else { X print("\"%s\" unchanged.", mailfile); X if (cntd_cmd) X putchar('\n'); X break; X } X } X X /* shell escape */ X when C_SHELL_ESC : X print("Shell command: "); X if (Getstr(file, COLS-24, 0) < 0) X clr_bot_line(); X else { X putchar('\n'); X iscurses = FALSE; X (void) cmd_line(sprintf(buf, "sh %s", file), msg_list); X iscurses = TRUE; X cntd_cmd = 1; X } X X /* do a line-mode like command */ X when C_CURSES_ESC : X print(":"); X if (Getstr(buf, COLS-2, 0) < 0) X break; X putchar('\n'); X iscurses = FALSE; X if (!*buf) { X /* return -1 because iscurses = 0 is not enough! */ X redo = 0; X endwin(); /* this turns echoing back on! */ X echo_off(); X return -1; X } X (void) cmd_line(buf, msg_list); X /* they may have affected message status or had text output */ X cntd_cmd = redo = 1; X iscurses = TRUE; X if (msg_cnt) X puts(compose_hdr(current_msg)); X X /* send message to printer */ X when C_PRINT_MSG : lpr(0, DUBL_NULL, msg_list); X X /* cd */ X when C_CHDIR : X print("chdir to [.]: "); X if (Getstr(file, COLS-12, 0) < 0) X break; X clr_bot_line(); X (void) cmd_line(sprintf(buf, "cd %s", file), msg_list); X if (cntd_cmd) X putchar('\n'); X X /* variable settings */ X when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR : X curs_vars(c, &cntd_cmd); /* cntd_cmd is reset if there's output! */ X X when C_VERSION : X do_version(); /* duh */ X if (cntd_cmd) X putchar('\n'); X X when C_MAIL_FLAGS : X print("flags [-?]: "); X if ((c = Getstr(file, COLS-50, 0)) < 0) X break; X putchar('\n'); X if (c == 0) X (void) strcpy(file, "-?"); X /* Fall thru */ X case C_MAIL : X clr_bot_line(); X iscurses = FALSE; X (void) cmd_line(sprintf(buf, "mail %s", file), msg_list); X iscurses = TRUE, cntd_cmd = 1; X if (msg_cnt) X print("%s", compose_hdr(current_msg)), putchar('\n'); X X /* reply to mail */ X when C_REPLY_SENDER : case C_REPLY_ALL : { X register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender"; X clr_bot_line(); X iscurses = FALSE; X (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1), X msg_list); X iscurses = TRUE, cntd_cmd = 1; X if (msg_cnt) X print("%s", compose_hdr(current_msg)), putchar('\n'); X } X X /* type out a message */ X when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT : X if (!msg_cnt || X c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) { X if (!msg_cnt) X print("No messages."); X else X print("Message %d deleted; type 'u' to undelete.", X current_msg+1); X if (cntd_cmd) X putchar('\n'); X break; X } X clr_bot_line(); X iscurses = FALSE; X if (cntd_cmd) X putchar('\n'); X if (c == C_DISPLAY_MSG) X c = cmd_line(strcpy(buf, "type"), msg_list); X else if (c == C_TOP_MSG) X c = cmd_line(strcpy(buf, "top"), msg_list); X else X c = cmd_line(strcpy(buf, "next"), msg_list); X if (c > -1) X cntd_cmd = redo = 1; X iscurses = TRUE; X puts(compose_hdr(current_msg)); X X /* bind a key or string to a command */ X when C_BIND : case C_UNBIND : { X char *argv[2]; X argv[0] = (c == C_BIND) ? "bind" : "unbind"; X argv[1] = NULL; X if (bind_it(0, argv) < -1) X cntd_cmd = 1; X else if (cntd_cmd) /* if it was already set anyway */ X putchar('\n'); X } X X /* help stuff */ X when C_HELP : X (void) c_bind(NULL); X cntd_cmd = 1; X if (msg_cnt) X puts(compose_hdr(current_msg)); X X /* now do interactive stuff as if run from the mush shell */ X otherwise : X bell(); X if (cntd_cmd) { X /* use print instead of puts to overwrite hit_return msg */ X print("unknown command"), putchar('\n'); X redo = 1; X } X } X X if (cntd_cmd) { X int old_cnt = msg_cnt; X if (!(c = hit_return()) && !redo && msg_cnt == old_cnt) X redraw(); X clr_bot_line(); X if (old_cnt != msg_cnt) X redo = 1; X if (c) X return c; X } X if (redo) { X n = current_msg; X clear(); X if (msg_cnt < screen || n_array[0] < n && n < n_array[screen-1]) X (void) do_hdrs(0, DUBL_NULL, NULL); X else X (void) cmd_line(sprintf(buf, "headers %d", n+1), msg_list); X redo = 0; X } X return 0; X} X Xvrfy_update(cntd_cmd, redo) Xint *cntd_cmd, *redo; X{ X char buf[16]; X int c; X X /* update current folder */ X if (ison(glob_flags, DO_UPDATE)) { X print("Update %s [y]? ", mailfile); X if ((c = getchar()) == 'n' || c == 'N' || c == 7 || c == 127 || c == 4){ X print("%s unmodified.", mailfile); X if (*cntd_cmd) X putchar('\n'); X return 0; X } X (void) cmd_line(strcpy(buf, "update"), msg_list); X if (*cntd_cmd) X *redo = 1, *cntd_cmd = 0; X } X turnoff(glob_flags, DO_UPDATE); X return 1; /* make sure bottom line is clear and no reverse video */ X} X#endif CURSES END_OF_FILE if test 17549 -ne `wc -c <'curses.c'`; then echo shar: \"'curses.c'\" unpacked with wrong size! fi # end of 'curses.c' fi if test -f 'msgs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'msgs.c'\" else echo shar: Extracting \"'msgs.c'\" \(16268 characters\) sed "s/^X//" >'msgs.c' <<'END_OF_FILE' X/* @(#)msgs.c (c) copyright 10/18/86 (Dan Heller) */ X X#include "mush.h" X#ifdef SYSV X#include <sys/locking.h> X#endif SYSV X Xvoid Xdisplay_msg(n, flg) Xregister int n; Xlong flg; X{ X register FILE *pp; X X if (ison(msg[n].m_flags, DELETE)) { X print("Message %d deleted; ", n+1); X if (istool) X print_more("Select UNDELETE to read."); X else if (iscurses) X print_more("Type 'u' to undelete."); X else X print("Type 'undelete %d' to undelete\n", n+1); X return; X } X set_isread(n); X if (ison(flg, TOP)) { X turnon(flg, NO_HEADER); X print("Top of "), turnon(glob_flags, CONT_PRNT); X } X X if (!istool && isoff(flg, NO_PAGE) && X crt < msg[n].m_lines && isoff(flg, TOP)) { X turnon(glob_flags, IGN_SIGS); X echo_on(); X if (!(pp = popen(pager, "w"))) X error(pager); X else { X fprintf(pp, "Message #%d (%d lines)\n", n+1, msg[n].m_lines); X (void) copy_msg(n, pp, flg); X (void) pclose(pp); X } X echo_off(); X turnoff(glob_flags, IGN_SIGS); X } else { X print("Message #%d (%d lines)\n", n+1, msg[n].m_lines); X (void) copy_msg(n, stdout, flg); X } X} X X/* X * copy message 'n' to file "fp" according to various flag arguments X * return number of lines copied or -1 if system error on fputs. X */ Xcopy_msg(n, fp, flags) Xregister int n; Xlong flags; Xregister FILE *fp; X{ X register int ignoring = 0, lines = 0; X register char *indent_str; X int on_hdr = 1, top, squeeze = FALSE; X char line[BUFSIZ]; X X still_more = 0; X if (ison(flags, TOP)) { X register char *p = do_set(set_options, "toplines"); X top = (p)? atoi(p) : crt; X } X if (do_set(set_options, "alwaysignore")) X turnoff(flags, NO_IGNORE); X if (isoff(flags, NO_IGNORE) && do_set(set_options, "squeeze")) X squeeze = TRUE; X X#ifdef SUNTOOL X if (istool && fp == stdout) { X register int x = (msg[n].m_lines + 2) * l_height(curfont); X if (x > 32765) { /* to overcome a bug in pixrects that sun won't fix */ X print("message too big to display using this font"); X return 0; X } X if (x < msg_rect.r_height) /* make it at least as big as the window */ X x = msg_rect.r_height; X do_clear(); X lock_cursors(); X if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) { X error("mem_create"); X return 0; X } X pr_rop(msg_pix, 0,0, msg_rect.r_width-1, x-1, PIX_CLR, 0,0,0); X on_hdr = 1; X } X#endif SUNTOOL X if (ison(flags, INDENT) && X (!(indent_str = do_set(set_options, "indent_str")) || X !strcmp(indent_str, "indent_str"))) X indent_str = DEF_INDENT_STR; X (void) fseek(tmpf, msg[n].m_offset, L_SET); X while (still_more < msg[n].m_size && fgets(line, BUFSIZ, tmpf)) { X still_more += strlen(line); X X /* X * If squeeze is one, all blanks lines squeeze down to one blank line. X * If squeeze is two, squeezing is in progress. Otherwise, wait for \n. X */ X if (*line == '\n') { X if (on_hdr) /* blank line -- end of header */ X turnoff(flags, NO_HEADER), on_hdr = 0; X if (squeeze > 1) X continue; X else if (squeeze) X squeeze = 2; X } else if (squeeze > 1) X squeeze = 1; X X if (ison(flags, UPDATE_STATUS)) X if (!strncmp(line, "Status:", 7)) X continue; /* ignore this and other "Status" lines */ X else if (!on_hdr) { X /* preserve NEW/UNREAD status on preserved messages */ X if (isoff(msg[n].m_flags, PRESERVE)) { X (void) strcpy(line, "Status: O"); X if (isoff(msg[n].m_flags, UNREAD)) X (void) strcat(line, "R"); X (void) strcat(line, "\n"); X fputs(line, fp); X (void) strcpy(line, "\n"); X } X turnoff(flags, UPDATE_STATUS); X } X if (on_hdr && isoff(flags, NO_IGNORE)) { X register char *p = any(line, " \t:"); X if (!p) X ignoring = 0, on_hdr = 0; X else if (ignoring) X if (*p != ':') { X Debug("Ignoring: %s", line); X continue; X } X else X ignoring = 0; X if (p && *p == ':') { X register struct options *opts; X *p = 0; X ignoring = 0; X for (opts = ignore_hdr; opts; opts = opts->next) X if (!lcase_strcmp(opts->option, line)) { X ignoring = 1; X break; X } X *p = ':'; X if (ignoring) { X Debug("Ignoring: %s", line); X continue; X } X } X } X if (!on_hdr && ison(flags, TOP) && !--top) X break; X if (isoff(flags, NO_HEADER)) { X /* note that function returns the number of lines */ X lines++; X#ifdef SUNTOOL X if (istool && fp == stdout) { X Addstr(line); X continue; X } X#endif SUNTOOL X if (ison(flags, INDENT)) X fputs(indent_str, fp); X (void) fputs(line, fp); X if (errno == ENOSPC) X return -1; X } X } X#ifdef SUNTOOL X if (istool && fp == stdout) { X unlock_cursors(); X txt.y = still_more = msg_rect.r_height; X scroll_win(0); /* causes a display */ X } X#endif SUNTOOL X return lines; X} X X/* get mail from whatever the mailfile points to. open a tempfile for X * appending, then close it and reopen it for read-only. some systems X * have flakey read/write access. X */ Xvoid Xgetmail() X{ X register FILE *mail_fp; X int lines = 0, get_status = 1; X long ftell(), bytes; X char line[BUFSIZ]; X X if (!(mail_fp = fopen(mailfile, "r"))) { X error("Cannot open %s", mailfile); X return; X } X /* X * since this file is usually open for read-only, close it and then X * reopen it for appending. This is done to compensate for errors X * in XENIX and to play it safe with non-essentially writable files. X * see more notes below (end of proc). X */ X (void) fclose(tmpf); X { X int omask = umask(077); X tmpf = fopen(tempfile, "a"); X (void) umask(omask); X if (!tmpf) { X error("can't open %s for appending", tempfile); X (void) fclose(mail_fp); X return; X } X } X#ifdef SYSV X (void) locking(fileno(mail_fp), LK_LOCK, 0); X#else X#ifdef BSD X if (flock(fileno(mail_fp), LOCK_SH)) /* if file is locked, flock waits */ X error("WARNING: could not lock %s", mailfile); X#endif BSD X#endif SYSV X X (void) fseek(mail_fp, ftell(tmpf), 0); X X while (fgets(line, BUFSIZ, mail_fp) != NULL) { X if (!strncmp(line, "From ", 5)) { X if (msg_cnt == MAXMSGS-1) { X print("WARNING: exceeded %d messages.\n", MAXMSGS); X print("You should split \"%s\" into smaller files.\n",mailfile); X /* make sure that tempfile isn't removed!! */ X turnon(glob_flags, IGN_SIGS); X cleanup(0); /* probably a more elegant way to exit, but... */ X } X bytes = ftell(tmpf); X /* finish up message structure from previous message. X * if this is incorporating new mail, check "lines" to X * see if previous message has already been set! X */ X if (msg_cnt && lines) { X msg[msg_cnt-1].m_size = bytes - msg[msg_cnt-1].m_offset; X msg[msg_cnt-1].m_lines = lines; X } X msg[msg_cnt].m_offset = bytes; X msg[msg_cnt].m_flags = lines = 0; X turnon(msg[msg_cnt].m_flags, UNREAD); /* initialize */ X X fputs(line, tmpf); X if (errno == ENOSPC) X fs_error(); X X /* we've read the "From " line, now read the rest of X * the message headers till we get to a blank line. X */ X while (fgets(line, BUFSIZ, mail_fp) && (*line != '\n')) { X register char *p = line; X if (get_status && !(get_status = strncmp(p, "Status:", 7))) { X turnon(msg[msg_cnt].m_flags, OLD); X for (p += 8 ; *p != '\n'; p++) X switch(*p) { X case 'R': turnoff(msg[msg_cnt].m_flags, UNREAD); X } X } X fputs(line, tmpf), lines++; X if (errno == ENOSPC) X fs_error(); X } X msg_cnt++, get_status = 1; X } X fputs(line, tmpf), lines++; X if (errno == ENOSPC) X fs_error(); X } X /* msg_cnt may be 0 if there is an error with the format of mailfile */ X if (msg_cnt) { X msg[msg_cnt-1].m_size = ftell(tmpf) - msg[msg_cnt-1].m_offset; X msg[msg_cnt-1].m_lines = lines; X } X#ifdef SYSV X locking(fileno(mail_fp), LK_UNLCK, 0); X#endif /* SYSV */ X fclose(mail_fp); /* implicit unlock */ X /* I've had problems with sys-v opening a file for read/write. I'd X * try fgets after a seek to an arbitrary place and get NULL. "w+" X * could be broken (XENIX), so play it safe anyway. X */ X fclose(tmpf); X if (!(tmpf = fopen(tempfile, "r"))) X error("can't open %s for reading", tempfile); X} X Xfs_error() X{ X error("WARNING: can't write to \"%s\"", tempfile); X print("Read the manual on what to do on full file systems.\n"); X cleanup(0); X} X X/* X * copy temp or whatever back to mailfile X * Return 0 if new mail came and user doesn't want to exit. X */ Xcopyback() X{ X register int new = 0, i, j=0, k=0; X register long flg = 0; X register FILE *mbox = NULL_FILE, *mail_fp; X char *mbox_file, action = 0; X int hold = 0, delete_it = 0, dont_unlink = FALSE; X X#ifdef SUNTOOL X if (istool) { X timerclear(&(mail_timer.it_interval)); X timerclear(&(mail_timer.it_value)); X } X#endif SUNTOOL X if (ison(glob_flags, READ_ONLY)) { X print("Can't update %s: read only\n", mailfile); X return 1; X } X if (check_new_mail()) { X new = 1; X if (!istool) { X char buf[256]; X if (iscurses) X putchar('\n'); X print("Really quit? "), fflush(stdout); X buf[0] = 0; X if (!Getstr(buf, 256, 0) || lower(*buf) != 'y') X return 0; X } X } else if (!msg_cnt) /* prevent unnecessary overwrite */ X return 0; X /* open mbox if: "autodelete" AND "hold" are NOT set. */ X if (is_spool(mailfile) X && !(delete_it = !!do_set(set_options, "autodelete")) X && !(hold = !!do_set(set_options, "hold"))) { X register char *p; X int x = 1; /* tell getpath to ignore "ENOENT" if file not found */ X X if (!(p = do_set(set_options, "mbox"))) X p = DEF_MBOX; X mbox_file = getpath(p, &x); X if (x) { X if (x > 0) X print("%s is a directory.\n", mbox_file); X else X print("can't open %s: %s\n", p, mbox_file); X mbox = NULL_FILE; X } else { X char *mode = "a"; X if (access(mbox_file, 0)) /* does it exist? */ X mode = "w"; /* no, create it. */ X else if (access(mbox_file, 2)) /* if yes, can we write in it? */ X error("can't open %s", mbox_file); /* if no, print why not */ X if (!(mbox = fopen(mbox_file, mode))) X error("can't open %s", mbox_file); X } X } X /* reopen the mailfile; make sure it's not readable */ X { X int omask = umask(077); X mail_fp = fopen(mailfile, "w"); X (void) umask(omask); X if (!mail_fp) { X error("can't rewrite %s", mailfile); X return 0; X } X } X turnon(glob_flags, IGN_SIGS); X print("Updating \"%s\"", mailfile), fflush(stdout); X#ifdef SYSV X (void) locking(fileno(mail_fp), LK_LOCK, 0); X#else X#ifdef BSD X if (flock(fileno(mail_fp), LOCK_EX)) X error("WARNING: could not lock %s", mailfile); X#endif BSD X#endif SYSV X turnon(flg, UPDATE_STATUS); X turnon(flg, NO_IGNORE); X X for (i = 0; i < msg_cnt; i++) X /* check to see if message is marked for deletion or, if read and not X * preserved, delete it if autodelete is set. Otherwise, save the X * message in the spool file if hold is set. If all fails, save in mbox. X */ X if (ison(msg[i].m_flags, DELETE) X || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE) X && delete_it) { X Debug("%s %d", X (action!='d')? "\ndeleting message:" : "", i+1), action = 'd'; X continue; X } else if (ison(msg[i].m_flags, UNREAD) || X ison(msg[i].m_flags, PRESERVE) || hold || !mbox) { X j++; X Debug("%s %d", X (action!='s')? "\nsaving in spool:" : "", i+1), action = 's'; X if (copy_msg(i, mail_fp, flg) == -1) { X error("WARNING: could not write back to spool"); X print("ALL mail left in %s\n", tempfile); X print("Spool mailbox may be corrupted.\n"); X if (new) X print("New mail may be lost. :-(\n"); X dont_unlink = TRUE; X break; X } X } else if (is_spool(mailfile)) { /* copy back to mbox if spooldir */ X k++; X if (copy_msg(i, mbox, flg) == -1) { X error("WARNING: could not write to mbox"); X print("Unresolved mail left in %s\n", tempfile); X dont_unlink = TRUE; X break; X } X Debug("%s %d", X (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm'; X } X Debug("\n%s", mailfile); X#ifdef SYSV X locking(fileno(mail_fp), LK_UNLCK, 0); X#endif SYSV X fclose(mail_fp); /* implicit unlock for BSD */ X if (mbox) X fclose(mbox); X if (j) { X long times[2]; X times[1] = time(×[0]) - (long)2; X if (is_spool(mailfile) && utime(mailfile, times)) X error("utime"); X print_more(": saved %d message%s\n", j, (j==1)? NO_STRING: "s"); X } else if (!is_spool(mailfile) && !dont_unlink && !new) X if (unlink(mailfile)) X turnon(glob_flags, CONT_PRNT), error(": cannot remove"); X else X print_more(": removed\n"); X else X print_more(": empty\n"); X if (k) X print("saved %d message%s in %s\n",k,(k==1)? NO_STRING: "s",mbox_file); X if (new && !istool) X print("New mail has arrived.\n"); X turnoff(glob_flags, IGN_SIGS); X#ifdef SUNTOOL X if (istool) { X mail_timer.it_value.tv_sec = time_out; X setitimer(ITIMER_REAL, &mail_timer, NULL); X } X#endif SUNTOOL X return 1; X} X Xmail_size() X{ X struct stat buf; X if (!is_spool(mailfile)) { X char tmp[128]; X if (!stat(sprintf(tmp, "%s/%s", MAILDIR, login), &buf)) X spool_size = buf.st_size; X } X if (!*mailfile) X return 0; X if (stat(mailfile, &buf)) { X if (errno != ENOENT) X error("Can't stat %s", mailfile); X return 0; X } X if (is_spool(mailfile)) X spool_size = buf.st_size; X if (buf.st_size > last_size) { X last_size = buf.st_size; X return 1; X } X return 0; X} X Xvoid Xmail_status(as_prompt) X{ X static char buf[256]; X register int cnt = 0, new = 0, unread = 0, deleted = 0; X X for ( ; cnt < msg_cnt; cnt++) { X if (ison(msg[cnt].m_flags, UNREAD)) X unread++; X if (ison(msg[cnt].m_flags, DELETE)) X deleted++; X if (isoff(msg[cnt].m_flags, OLD)) X new++; X } X if (as_prompt) { X register char *p, *b = buf; X for (p = prompt; *p; p++) X if (*p == '\\') X switch (*++p) { X case 'n': case 'r': *b++ = '\n'; X when 't': *b++ = '\t'; X otherwise: *b++ = *p; X } X else if (*p == '%') X switch (*++p) { X case 'm': X b += strlen(sprintf(b,"%d",(msg_cnt)? current_msg+1:0)); X when 't': X b += strlen(sprintf(b, "%d", msg_cnt)); X when 'd': X b += strlen(sprintf(b, "%d", deleted)); X when 'u': X b += strlen(sprintf(b, "%d", unread)); X when 'n': X b += strlen(sprintf(b, "%d", new)); X when 'f': X b += Strcpy(b, mailfile); X if (ison(glob_flags, READ_ONLY)) X b += Strcpy(b, " [read only]"); X when 'T': case 'D': case 'Y': case 'M': case 'N': X b += Strcpy(b, Time(p, (long)0)); X otherwise: *b++ = *p; X } X else if (*p == '!') X b += strlen(sprintf(b, "%d", hist_no+1)); X else X *b++ = *p; X *b = 0; X print("%s", buf); /* buf MIGHT have a % in it... don't pass as fmt */ X return; X } X (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread", X mailfile, ison(glob_flags, READ_ONLY)? " [read only]" : "", X msg_cnt, (msg_cnt != 1)? "s": NO_STRING, new, unread); X if (istool || iscurses) X (void) sprintf(buf+strlen(buf), ", %d deleted", deleted); X#ifdef SUNTOOL X if (istool) { X static char ic_text[4]; X extern struct pixrect mail_icon_image1, mail_icon_image2; X (void) sprintf(ic_text, "%3d", msg_cnt); X tool_set_attributes(tool, X WIN_LABEL, buf, X WIN_ICON_LABEL, ic_text, X WIN_ICON_IMAGE, ison(glob_flags, NEW_MAIL)? X &mail_icon_image2 : &mail_icon_image1, X 0); X } else X#endif SUNTOOL X#ifdef CURSES X if (iscurses) X mvprintw(0, 0, "%-3d %-*s", X ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol(); X else X#endif CURSES X puts(buf); X return; X} X X/* return -1 since function doesn't affect messages */ Xcheck_flags(flags) Xu_long flags; X{ X print_more(" "); X if (ison(flags, VERBOSE)) X print_more("VERBOSE "); X if (ison(flags, INCLUDE)) X print_more("INCLUDE "); X if (ison(flags, INCLUDE_H)) X print_more("INCLUDE_H "); X if (ison(flags, EDIT)) X print_more("EDIT "); X if (ison(flags, SIGN)) X print_more("SIGN "); X if (ison(flags, DO_FORTUNE)) X print_more("DO_FORTUNE "); X if (ison(flags, NO_HEADER)) X print_more("NO_HEADER "); X if (ison(flags, DELETE)) X print_more("DELETE "); X if (ison(flags, OLD)) X print_more("OLD "); X if (ison(flags, UNREAD)) X print_more("UNREAD "); X if (ison(flags, UPDATE_STATUS)) X print_more("UPDATE_STATUS "); X if (ison(flags, NO_PAGE)) X print_more("NO_PAGE "); X if (ison(flags, INDENT)) X print_more("INDENT "); X if (ison(flags, NO_IGNORE)) X print_more("NO_IGNORE "); X if (ison(flags, PRESERVE)) X print_more("PRESERVE "); X print_more("\n"); X return -1; X} END_OF_FILE if test 16268 -ne `wc -c <'msgs.c'`; then echo shar: \"'msgs.c'\" unpacked with wrong size! fi # end of 'msgs.c' fi if test -f 'mush.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mush.h'\" else echo shar: Extracting \"'mush.h'\" \(17878 characters\) sed "s/^X//" >'mush.h' <<'END_OF_FILE' X/* @(#)mush.h (c) copyright 1986 (Dan Heller) */ X X#define VERSION "Mail User's Shell (Vers 5.7) Sun Sep 6 19:10:48 PDT 1987" X X#include "config.h" X X#ifdef CURSES X#include <curses.h> X#else CURSES X#include <stdio.h> X#endif /* CURSES */ X X#include <ctype.h> X#include <errno.h> X#include <setjmp.h> X#include "strings.h" X X#ifdef SUNTOOL X# include <suntool/tool_hs.h> X#else SUNTOOL X# include <sys/types.h> X# include <signal.h> X# ifndef SYSV X# include <sys/time.h> X# include <sys/ioctl.h> /* for ltchars */ X# else X# include <time.h> X# include <fcntl.h> X# endif /* SYSV */ X#endif /* SUNTOOL */ X X#include <sys/stat.h> X#include <sys/file.h> X X#ifdef SUNTOOL X# include <suntool/gfxsw.h> X# include <suntool/panel.h> X# include <suntool/ttysw.h> X# include <suntool/ttytlsw.h> X# include <suntool/menu.h> X# include <suntool/icon_load.h> X#endif /* SUNTOOL */ X X/* if no maximum number of files can be found, we'll use getdtablesize() */ X#ifdef _NFILE X# define MAXFILES _NFILE X#else X#ifdef NOFILE X# define MAXFILES NOFILE X#endif X#endif X X#ifndef CTRL X#define CTRL(c) ('c' & 037) X#endif X X#define ESC '\033' X X#define NO_STRING "" X#ifdef NULL X#undef NULL X#endif /* NULL */ X#define NULL (char *)0 X#define NULL_FILE (FILE *)0 X#define DUBL_NULL (char **)0 X#define TRPL_NULL (char ***)0 X#ifdef putchar X#undef putchar X#endif /* putchar */ X#define putchar(c) fputc(c, stdout) X#define bell() fputc('\007', stderr) X X#define on_intr() \ X turnoff(glob_flags, WAS_INTR), oldint = signal(SIGINT, interrupt), \ X oldquit = signal(SIGQUIT, interrupt) X X#define off_intr() \ X turnoff(glob_flags, WAS_INTR), (void) signal(SIGINT, oldint), \ X (void) signal(SIGQUIT, oldquit) X X/* Don't flush input when setting echo or cbreak modes (allow typeahead) */ X#ifdef TIOCSETN X#define stty(fd, sgttybuf) (ioctl(fd, TIOCSETN, sgttybuf)) X#endif /* TIOCSETN */ X X#ifndef CURSES X/* if curses is not defined, simulate the same tty based macros */ Xstruct sgttyb _tty; X X#define crmode() (_tty.sg_flags |= CBREAK, stty(0, &_tty)) X#define nocrmode() (_tty.sg_flags &= ~CBREAK, stty(0, &_tty)) X#define echo() (_tty.sg_flags |= ECHO, stty(0, &_tty)) X#define noecho() (_tty.sg_flags &= ~ECHO, stty(0, &_tty)) X#define savetty() (void) gtty(0, &_tty) X#endif /* ~CURSES */ X X#define echo_on() \ X if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) echo(), nocrmode() X#define echo_off() \ X if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) noecho(), crmode() X X#define strdup(dst, src) (xfree (dst), dst = savestr(src)) X#define Debug if (debug) printf X X#ifdef SYSV X#define L_SET 0 X#define F_OK 000 X#define R_OK 004 X#define W_OK 002 X#define E_OK 001 X#define u_long ulong_t X#define vfork fork X#define SIGCHLD SIGCLD X#endif /* SYSV */ X X#if !defined(SUNTOOL) && !defined(CURSES) X X#define TRUE 1 X#define FALSE 0 X#define print printf X#define wprint printf X#define print_more printf X X#endif /* SUNTOOL && !CURSES */ X X#ifndef max X#define max(a,b) (((a) > (b)) ? (a) : (b)) X#define min(a,b) (((a) < (b)) ? (a) : (b)) X#endif /* max */ X X#if defined(CURSES) && !defined(SUNTOOL) X#define wprint printf X#endif /* !SUNTOOL && CURSES */ X X#if defined(CURSES) || defined(SUNTOOL) X#define print_more turnon(glob_flags, CONT_PRNT), print Xvoid print(); /* printf to window or curses or tty accordingly */ X#endif /* CURSES || SUNTOOL */ X X#ifdef SUNTOOL X X#define NO_ITEM (Panel_item)0 X#define NO_EVENT (struct inputevent *)0 X#define TIME_OUT 60 /* sleep 60 secs between mailchecks */ X#define PIX_OR PIX_SRC ^ PIX_DST X#define ID event.ie_code X#define l_width(font) fonts[font]->pf_defaultsize.x /* width of letter */ X#define l_height(font) fonts[font]->pf_defaultsize.y /* height of letter */ X#define Clrtoeol(w,x,y,f) pw_text(w, x, y, PIX_SRC, fonts[f], blank) X X#define highlight(win,x,y,font,s) \ X pw_text(win,x,y, PIX_SRC, fonts[font],s), \ X pw_text(win,x+1,y, \ X (ison(glob_flags, REV_VIDEO))? PIX_NOT(PIX_SRC): PIX_SRC|PIX_DST, \ X fonts[font],s) X X/* Fonts */ X#define FONTDIR "/usr/lib/fonts/fixedwidthfonts" X#define DEFAULT 0 X#define SMALL 1 X#define LARGE 2 X#define MAX_FONTS 3 X X#endif /* SUNTOOL */ X X/* bits and pieces */ X#define turnon(flg,val) ((flg) |= ((u_long)1 << ((u_long)(val)-1L))) X#define turnoff(flg,val) ((flg) &= ~((u_long)1 << ((u_long)(val)-1L))) X#define ison(flg,val) ((u_long)(flg) & ((u_long)1 << ((u_long)(val)-1L))) X#define isoff(flg,val) (!ison((flg), (val))) X#define set_isread(n) \ X if (ison(msg[n].m_flags, UNREAD)) \ X turnon(glob_flags, DO_UPDATE), turnoff(msg[n].m_flags, UNREAD) X X/* msg lists represented by bits */ X#define clear_msg_list(list) (void) bzero(list, (msg_cnt+7)/8) X#define msg_bit(list, n) ((list[(n) / 8] >> ((n) % 8)) & 1) X#define set_msg_bit(list, n) (list[(n) / 8] |= (1 << ((n) % 8))) X#define unset_msg_bit(list, n) (list[(n) / 8] &= ~(1 << ((n) % 8))) X#define bput(S1, S2, Len, op) \ X { \ X register char *s1 = S1, *s2 = S2; \ X register int len = Len; \ X while(len--) \ X *s2++ op *s1++; \ X } X#define bitput(m1,m2,len,op) bput(m1, m2, (((len)+7)/8), op) X X/* convenience and/or readability */ X#define when break;case X#define otherwise break;default X#define lower(c) (isupper(c)? tolower(c): c) X#define Lower(c) (c = lower(c)) X#define upper(c) (islower(c)? toupper(c): c) X#define Upper(c) (c = upper(c)) X#define skipspaces(n) for(p += (n); *p == ' ' || *p == '\t'; ++p) X#define skipdigits(n) for(p += (n); isdigit(*p); ++p) X X#define NO_FLG 0 X X/* various flags */ Xlong glob_flags; /* global boolean flags thruout the whole program */ X#define DO_UPDATE 1 /* check for changes to avoid unnecessary copyback */ X#define REV_VIDEO 2 /* reverse video for curses or toolmode */ X#define CONT_PRNT 3 /* continue to print (maybe a printf) without a '\n' */ X#define DO_SHELL 4 /* run a shell even if no mail? (true if tool) */ X#define DO_PIPE 5 /* true if commands are piping to another command */ X#define IS_PIPE 6 /* true if commands' "input" is piped from another */ X#define IGN_SIGS 7 /* true if catch() should not longjump */ X#define IGN_BANG 8 /* ignore ! as a history reference (see source()) */ X#define ECHO_FLAG 9 /* if true, echo|cbreak is ON, don't echo typing (-e) */ X#define IS_GETTING 10 /* true if we're getting input for a letter */ X#define PRE_CURSES 11 /* true if curses will be run, but hasn't started yet */ X#define READ_ONLY 12 /* -r passed to folder() (or main) setting read only */ X#define REDIRECT 13 /* true if stdin is being redirected */ X#define WAS_INTR 14 /* catch interrupts, set this flag (signals.c) */ X#define WARNING 15 /* if set, various warning messages may be printed */ X#define NEW_MAIL 17 /* new mail has arrived; user is busy or in icon mode */ X X#define VERBOSE 1 /* verbose flag for sendmail */ X#define INCLUDE 2 /* include msg in response */ X#define INCLUDE_H 3 /* include msg with header */ X#define EDIT 4 /* enter editor by defualt on mailing */ X#define SIGN 5 /* auto-include ~/.signature in mail */ X#define DO_FORTUNE 6 /* add a fortune at end of msgs */ X X/* msg flags */ X#define NO_HEADER 7 /* don't print header of message (top, write) */ X#define DELETE 8 X#define OLD 9 X#define UNREAD 10 X#define UPDATE_STATUS 11 /* change status of msg when copyback */ X#define NO_PAGE 12 /* don't page this message */ X#define INDENT 13 /* indent included msg with string */ X#define NO_IGNORE 14 /* don't ignore headers */ X#define PRESERVE 15 /* preserve in mailbox unless deleted */ X#define TOP 15 /* just print the top of the message */ X#define FORWARD 16 /* Forward messages into the message buffer */ X X#define MAXMSGS_BITS MAXMSGS/sizeof(char) /* number of bits for bitmap */ X Xstruct msg { X u_long m_flags; X long m_offset; /* offset in tempfile of msg */ X long m_size; /* number of bytes in msg */ X int m_lines; /* number of lines in msg */ X} msg[MAXMSGS]; X Xstruct options { X char *option; X char *value; X struct options *next; X} *set_options, *aliases, *ignore_hdr, *functions, *fkeys, *own_hdrs; X#ifdef CURSES Xstruct options *bindings; X#endif /* CURSES */ X Xstruct cmd { X char *command; X int (*func)(); X}; Xextern struct cmd ucb_cmds[]; Xextern struct cmd cmds[], hidden_cmds[]; X#ifdef SUNTOOL Xextern struct cmd fkey_cmds[]; X#endif /* SUNTOOL */ X XFILE X *tmpf, /* temporary holding place for all mail */ X *open_file(), /* open a file or program for write/append */ X *popen(); /* this should be in stdio.h */ X Xextern char X *sys_errlist[], /* system's list of global error messages */ X#ifdef SUNTOOL X *font_files[], /* the names of the files fonts are kept in */ X *alt_fonts[], /* fonts to use if first ones don't work */ X#endif /* SUNTOOL */ X **environ; /* user's environment variables */ X Xextern int errno; /* global system error number */ Xjmp_buf jmpbuf; /* longjmp to jmpbuf on sigs (not in tool) */ X Xchar X debug, /* debug causes various print statements in code */ X tempfile[40], /* path to filename of temporary file */ X msg_list[MAXMSGS_BITS], /* MAXMSGS bits of boolean storage */ X *cmd_help, /* filename of location for "command -?" commands. */ X *login, /* login name of user */ X *mailfile, /* path to filename of current mailfile */ X *ourname[MAX_HOST_NAMES], /* the name and aliases of the current host */ X *prompt, /* the prompt string -- may have %d */ X *escape, /* the escape character when without editor */ X *editor, /* string describing editor to use (default vi) */ X *hdrs_only, /* true if -H flag was given --set to args */ X *hdr_format, /* set to the header format string; referenced a lot */ X *visual, /* string describing visual editor to use */ X *pager, /* string describing pager to use (default more) */ X *argv_to_string(), /* convert a vector of strings into one string */ X **make_command(), /* build a command vector (argv) */ X **mk_argv(), /* given a string, make a vector */ X *itoa(), /* return a string representation of a number */ X *lcase_strcpy(), /* just like strcpy, but convert all chars to lower */ X *variable_stuff(), /* return information about variables */ X *no_newln(), /* remove newline and extra whitespace - return end */ X *savestr(), /* strcpy arg into malloc-ed memory; return address */ X *date_to_string(), /* returns a string described by parse_date() */ X *msg_date(), /* return a string of the date of a message */ X *parse_date(), /* parse an ascii date, and return message-id str */ X *Time(), /* returns string expression of time (takes args) */ X *do_range(), /* parse a string converting to a "range" of numbers */ X *getpath(), /* static char returning path (expanding ~, +, %, #) */ X *compose_hdr(), /* returns a formatted line describing passed msg # */ X *my_atoi(), /* do an atoi, but return the last char parsed */ X *do_set(), /* set/unset an option, alias, ignored-hdr */ X *reply_to(), /* who do we reply to when responding */ X *cc_to(), /* when responding, return str which is the cc-list */ X *subject_to(), /* when responding, return str which is the subject */ X *header_field(), /* the line in msg described by arg (message header) */ X *alias_to_address(),/* convert a name[list] to "real" names */ X *set_header(), /* [interactive] proc to set/display to/subject/cc */ X *getenv(), *prog_name; X Xint X last_msg_cnt, /* when checking for new mail, save the last msg_cnt */ X msg_cnt, /* total number of messages */ X crt, /* min number of lines msg contains to invoke pager */ X current_msg, /* the current message we're dealing with */ X exec_pid, /* pid of a command that has been "exec"ed */ X hist_no, /* command's history number */ X iscurses; /* if we're running curses */ X istool, /* argv[0] == "xxxxtool", ranges from 0 to 2 */ X n_array[128], /* array of message numbers in the header window */ X screen, /* number of headers window can handle */ X X quit(), cleanup(), catch(), do_alias(), respond(), cd(), sh(), stop(), X folder(), save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(), X rm_edfile(), pick(), save_opts(), preserve(), sort(), readmsg(), X do_pick(), print_help(), folders(), question_mark(), do_from(), my_stty(), X do_version(), disp_hist(), source(), do_echo(), sigchldcatcher(), ls(), X nopenfiles(), Setenv(), Unsetenv(), Printenv(), bus_n_seg(), msg_flags(), X toggle_debug(), stop_start(), interrupt(); X Xlong X still_more, /* there is still more message to display */ X spool_size, /* size of sppol mail regardless of current folder */ X last_size, /* the lastsize of the mailfile since last check */ X time(); /* satisfy lint */ X Xvoid X xfree(), free_vec(), error(), getmail(), mail_status(), X file_to_fp(), init(), display_msg(), c_more(); X /* printf(), fclose(), fflush(), fputs(), fputc() */ X#ifndef CURSES Xstruct sgttyb _tty; /* tty characteristics */ X#endif /* CURSES */ X#ifdef TIOCGLTC Xstruct ltchars ltchars; /* tty character settings */ X#endif /* TIOCGLTC */ X X#ifdef CURSES X X#define STANDOUT(y,x,s) standout(), mvaddstr(y,x,s), standend() X#define redraw() clearok(curscr, TRUE), wrefresh(curscr) X Xint X curses_init(), /* interpret commands via the curses interface */ X bind_it(); /* bind chars or strings to functions */ X#endif /* CURSES */ X X#ifdef SUNTOOL Xvoid X lock_cursors(), unlock_cursors(), scroll_win(), X set_fkeys(), set_key(), toggle_opt(), help_opt(); X Xchar X *rite(), /* rite a char to msg_win: return string if c == '\n' */ X *find_key(), /* pass x,y coords to find which function key assoc. */ X *key_set_to(), /* pass fkey string, return string describing func */ X *panel_get(), /* returns what has been typed in a panel item */ X *tool_help, /* help for tool-related things (sometimes, overlap) */ X blank[128]; /* use to clear to end of line */ X Xint X time_out, /* time out interval to wait for new mail */ X rootfd, /* the root window's fd */ X parentfd, /* the parent's window fd */ X getting_opts, /* true if getting/setting opts from msg_win */ X curfont, /* the current font to use for mail message window */ X total_fonts, /* total number of fonts available */ X get_hdr_field, /* bitmask of header fields to be gotten */ X X msg_io(), msgwin_handlesigwinch(), hdr_io(), hdrwin_handlesigwinch(), X sigchldcatcher(), sigtermcatcher(), sigwinchcatcher(), do_sort(), X do_compose(), do_edit(), read_mail(), delete_mail(), respond_mail(), X do_hdr(), display_hdrs(), print_sigwinch(), p_set_opts(), X tool_mgmt(), do_help(), text_done(), msg_num_done(), do_lpr(), X toolquit(), change_font(), do_clear(), do_update(), X file_dir(), do_file_dir(), do_send(), abort_mail(), check_new_mail(), X fkey_cmd(), fkey_settings(); X Xstruct tchars tchars; /* more tty character settings */ X Xstruct tool *tool; /* main tool structure */ Xstruct toolsw X *panel_sw, /* main panel subwindow */ X *hdr_sw, /* subwindow for message headers */ X *hdr_panel_sw, /* panel for headers */ X *tty_sw, /* subwindow which forks a shell (usually editor) */ X *print_sw, /* subwindow for print statements */ X *msg_sw; /* main subwindow to display messages and more */ X Xstruct pixwin X *msg_win, /* main pixwin for message display and more */ X *hdr_win, /* pixwin for message headers */ X *print_win; /* pixwin for printing messages ( print() ) */ X Xstruct pr_pos txt; /* current position of text written */ Xstruct rect msg_rect, hdr_rect; /* sizes of the main and hdr rects */ Xstruct pixfont *fonts[MAX_FONTS]; /* array of fonts */ X XPanel X main_panel, /* the main panel dealing with generic items */ X hdr_panel; /* panel which contains message header specific items */ X XPanel_item X abort_item, /* abort mail in progress */ X alias_item, /* set/view/change current mail aliases */ X cd_item, /* changes file_item to cd (for cd-ing) */ X comp_item, /* compose a letter */ X delete_item, /* delete/undelete messages */ X edit_item, /* edit a message */ X font_item, /* choose which font to use */ X folder_item, /* change folders */ X file_item, /* text item for files or directories (forlder/cd) */ X hdr_display, /* format message headers are displayed */ X help_item, /* choose this to get various help */ X ignore_item, /* set/view/change message headers to be ignored */ X input_item, /* text item to get values for set/unsetting values */ X msg_num_item, /* text item to explicity state which message to read */ X next_scr, /* display the next screenful of message headers */ X option_item, /* set/view/unset mail options */ X prev_scr, /* display the previous screen of messages */ X print_item, /* send current message to the printer */ X quit_item, /* quit tool/close to icon */ X read_item, /* read the current message */ X respond_item, /* respond to messages */ X save_item, /* saves messages; uses text item input_item */ X send_item, /* when composing letter, this will send it off */ X sort_item, /* sort routine... */ X sub_hdr_item[6], /* display items that just sit there and give help */ X update_item; /* commit changes to folder */ X Xstruct itimerval mail_timer; /* frequency to check for new mail */ X X /* mouse symbols and data */ X/* left, middle and right mouse pixrects */ Xstruct cursor X l_cursor, m_cursor, r_cursor, coffee, read_cursor, write_cursor, X main_cursor, checkmark; X Xstruct pixrect *msg_pix; /* pixrect holding text of a message */ Xextern struct pixrect mouse_left, mouse_middle, mouse_right; Xextern struct pixrect dn_arrow, up_arrow, cycle, shade_50; X Xextern struct icon mail_icon; X#endif /* SUNTOOL */ END_OF_FILE if test 17878 -ne `wc -c <'mush.h'`; then echo shar: \"'mush.h'\" unpacked with wrong size! fi # end of 'mush.h' fi echo shar: End of archive 6 \(of 12\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 12 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 0t