argv@zipcode.com (Dan Heller) (04/21/91)
Submitted-by: Dan Heller <argv@zipcode.com> Posting-number: Volume 18, Issue 64 Archive-name: mush/part07 Supersedes: mush: Volume 12, Issue 28-47 #!/bin/sh # do not concatenate these parts, unpack them in order with /bin/sh # file dates.c continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 7; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping dates.c' else echo 'x - continuing file dates.c' sed 's/^X//' << 'SHAR_EOF' >> 'dates.c' && X X (void) strncpy(zone, tz, 7), zone[7] = 0; X return T; } 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 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': case 'W': (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 'Y': (void) sprintf(p, "%d", T->tm_year + 1900); 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 /* parse date and return a string that looks like X * %ld%3c%s gmt_in_secs weekday orig_timezone X * This function is a bunch of scanfs on known date formats. Don't X * trust the "weekday" name fields because they may not be spelled X * right, or have the correct punctuation. Figure it out once the X * year and month and date have been determined. X */ char * parse_date(p) register char *p; { X /* When scanf-ing if month isn't a month, it could be a _long_ string. X * this is also the static buffer whose address we return. X */ X static char month[64]; X char Wkday[4], Zone[12], dst[4]; X char a_or_p; X int Month = 0, Day = 0, Year = 0; X int Hours = -1, Mins = -1; X struct tm T; X X Zone[0] = dst[0] = 0; X skipspaces(0); 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 :-( Also reset X * Zone[0] after any sscanf() that could corrupt it on a partial match. X * X * Not yet handling all possible combinations of mailers using two-word X * time zones, e.g. MET DST instead of MEST. Only the specific case X * where this was reported has been handled here. X */ X X /* RFC822 formats and minor variations -- order important */ X X /* day_number month_name year_number time timezone */ X if (sscanf(p, "%d %s %d %d:%d:%*d %7s %3s", X &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day) X goto gotit; X Zone[0] = dst[0] = 0; X if (sscanf(p, "%d %s %d %d:%d %7s", X &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day) X goto gotit; X Zone[0] = dst[0] = 0; X /* day_name day_number month_name year_number time timezone */ X if (sscanf(p, "%*s %d %s %d %d:%d:%*d %7s %3s", X &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day) X goto gotit; X Zone[0] = dst[0] = 0; X if (sscanf(p, "%*s %d %s %d %d:%d %7s %3s", X &Day, month, &Year, &Hours, &Mins, Zone, dst) >= 5 && Day) X goto gotit; X Zone[0] = dst[0] = 0; X X /* Ctime format (From_ lines) -- timezone almost never found */ X X /* day_name month_name day_number time year_number */ X if (sscanf(p, "%*s %s %d %d:%d:%*d %d", X month, &Day, &Hours, &Mins, &Year) == 5) X goto gotit; X /* day_name month_name day_number time timezone year_number */ X if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %d", X month, &Day, &Hours, &Mins, Zone, &Year) == 6) X goto gotit; X Zone[0] = 0; X if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %3s %d", X month, &Day, &Hours, &Mins, Zone, dst, &Year) == 7) X goto gotit; X Zone[0] = dst[0] = 0; X X /* Other common variants */ X X /* day_number month_name year_number time-timezone (day) */ X /* ^no colon separator */ X if (sscanf(p, "%d %s %d %2d%2d-%6[0123456789]", X &Day, month, &Year, &Hours, &Mins, &Zone[1]) == 6) { X Zone[0] = '-'; X goto gotit; X } X if (sscanf(p, "%d %s %d %2d%2d-%7s", X &Day, month, &Year, &Hours, &Mins, Zone) == 6) X goto gotit; X Zone[0] = 0; X X /* day_number month_name year_number time timezone */ X /* ^no colon separator */ X /* (This is the odd one in the RFC822 examples section; */ X /* also catches the slop from partial hits above.) */ X if (sscanf(p, "%d %s %d %2d%2d %7s", X &Day, month, &Year, &Hours, &Mins, Zone) >= 5 && Day) X goto gotit; X Zone[0] = 0; X X Zone[1] = 0; /* Yes, Zone[1] -- tested below */ X X /* day_number month_name year_number, time "-" ?? */ X if (sscanf(p,"%d %s %d, %d:%d:%*d -%6[0123456789]", X &Day, month, &Year, &Hours, &Mins, &Zone[1]) >= 5 && Day) { X if (Zone[1]) X Zone[0] = '-'; X goto gotit; X } X X /* day_number month_name year_number 12_hour_time a_or_p */ X if (sscanf(p, "%d %s %d %d:%d:%*d %cm %7s", X &Day, month, &Year, &Hours, &Mins, &a_or_p, Zone) >= 6) { X if (a_or_p == 'p') X Hours += 12; X goto gotit; X } X X /* day_name month_name day_number year_number time */ X if (sscanf(p, "%*s %s %d %d %d:%d:%*d %7s", X month, &Day, &Year, &Hours, &Mins, Zone) >= 5) X goto gotit; X Zone[0] = 0; X if (sscanf(p, "%*s %s %d %d %d:%d %7s", X month, &Day, &Year, &Hours, &Mins, Zone) >= 5) X goto gotit; X Zone[0] = 0; X X /* day_name month_name day_number time timezone year_number */ X if (sscanf(p, "%*s %s %d %d:%d:%*d %7s %d", X month, &Day, &Hours, &Mins, Zone, &Year) == 6) X goto gotit; X Zone[0] = 0; X if (sscanf(p, "%*s %s %d %d:%d %7s %d", X month, &Day, &Hours, &Mins, Zone, &Year) == 6) X goto gotit; X Zone[0] = 0; X X /* day_number-month_name-year time */ X if (sscanf(p,"%d-%[^-]-%d %d:%d", &Day, month, &Year, &Hours, &Mins) == 5) X goto gotit; X X /* day_name, day_number-month_name-year time */ X if (sscanf(p,"%*s %d-%[^-]-%d %d:%d", X &Day, month, &Year, &Hours, &Mins) == 5) X goto gotit; X X /* year_number-month_number-day_number time */ X if (sscanf(p, "%d-%d-%d %d:%d", &Year, &Month, &Day, &Hours, &Mins) == 5) X goto gotit; X X /* month_name day_number time year Zone */ X /* (ctime, but without the day name) */ X if (sscanf(p, "%s %d %d:%d:%*d %d %7s", X month, &Day, &Hours, &Mins, &Year, Zone) >= 5) X goto gotit; X Zone[0] = 0; X X if (ison(glob_flags, WARNING)) X print("Unknown date format: %s\n", p); X return NULL; X gotit: X if (!lcase_strncmp(dst, "dst", -1)) { X (void) strcat(Zone, " "); X (void) strcat(Zone, dst); X } X if (Year > 1900) X Year -= 1900; X if (!Month && (Month = month_to_n(month)) == -1) { X print("bad month: %s\n", p); X return NULL; X } X if (Zone[0] == 0) { X /* Use local time zone if none found -- important for date_recv */ X (void) time_n_zone(Zone); X } X { X /* Lots of foolishness with casts for Xenix-286 16-bit ints */ X X long days_ctr; /* 16-bit ints overflowed Sept 12, 1989 */ X X days_ctr = ((long)Year * 365L) + ((Year + 3) / 4); X days_ctr += mtbl[Month-1] + Day + 6; X if (Month > 2 && (Year % 4 == 0)) X days_ctr++; X (void) (sprintf(Wkday, "%.3s", day_names[(int)(days_ctr % 7L)])); X } X T.tm_sec = 0; /* not recorded, so ignore it */ X T.tm_min = Mins; X T.tm_hour = Hours; X T.tm_mday = Day; X T.tm_mon = Month - 1; X T.tm_year = Year; X T.tm_wday = T.tm_yday = 0; /* not used in time2gmt() */ X T.tm_isdst = 0; /* determined from Zone */ X return sprintf(month, "%ld%s%s", time2gmt(&T, Zone, 1), Wkday, Zone); } X /* pass a string in the standard date format, put into string. X * return values in buffers provided they are not null. X */ char * date_to_string(Date, Yr, Mon, Day, Wkday, Tm, Zone, ret_buf) char *Date, *Yr, *Mon, *Day, *Wkday, *Tm, *Zone, *ret_buf; { X long gmt; X struct tm *T; X char a_or_p, *p = ret_buf; X X Zone[0] = 0; X (void) sscanf(Date, "%ld%3c%s", &gmt, Wkday, Zone); X Wkday[3] = 0; X gmt += getzoff(Zone); X T = gmtime(&gmt); X a_or_p = (T->tm_hour < 12)? 'a': 'p'; X X (void) sprintf(Yr, "%d", T->tm_year + 1900); X (void) sprintf(Day, "%d", T->tm_mday); X (void) strcpy(Mon, month_names[T->tm_mon]); X p += strlen(sprintf(p, "%s %2.d, ", Mon, T->tm_mday)); X 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, "%2.d:%02d%cm", X (T->tm_hour)? (T->tm_hour <= 12)? T->tm_hour: T->tm_hour-12: 12, X T->tm_min, a_or_p); X (void) strcpy(Tm, p); X X return ret_buf; } X /* pass a string in the internal mush date format. X * return pointer to static buffer holding ctime-format date. X */ char * date_to_ctime(Date) char *Date; { X static char ret_buf[32]; X long gmt; X X ret_buf[0] = 0; X (void) sscanf(Date, "%ld", &gmt); X (void) strcpy(ret_buf, ctime(&gmt)); X X return ret_buf; } X /* X * Build a date string according to the specification in the RFC for Date: X */ char * rfc_date(buf) char buf[]; { X struct tm *T; X char zone[8]; X X T = time_n_zone(zone); #ifndef USA X { X long zoff_hr, zoff_sec = getzoff(zone); X if (zoff_sec < 0) { X zone[0] = '-'; X zoff_sec = -zoff_sec; X } else X zone[0] = '+'; X zoff_hr = zoff_sec / 3600; X zoff_sec -= zoff_hr * 3600; X (void) sprintf(&zone[1], "%02d%02d", zoff_hr, zoff_sec / 60); X } #endif /* !USA */ X X return sprintf(buf, "%s, %d %s %d %02d:%02d:%02d %s", X day_names[T->tm_wday], /* day name */ X T->tm_mday, /* day of the month */ X month_names[T->tm_mon], /* month name */ X T->tm_year + 1900, /* year number */ X T->tm_hour, /* hours (24hr) */ X T->tm_min, T->tm_sec, /* mins/secs */ X zone); /* timezone */ } X #define JAN 1 #define FEB 2 #define MAR 3 #define APR 4 #define MAY 5 #define JUN 6 #define JUL 7 #define AUG 8 #define SEP 9 #define OCT 10 #define NOV 11 #define DEC 12 X /* stolen direct from ELM */ month_to_n(name) register char *name; { 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 } } SHAR_EOF echo 'File dates.c is complete' && chmod 0644 dates.c || echo 'restore of dates.c failed' Wc_c="`wc -c < 'dates.c'`" test 15621 -eq "$Wc_c" || echo 'dates.c: original size 15621, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= digestify ============== if test -f 'digestify' -a X"$1" != X"-c"; then echo 'x - skipping digestify (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting digestify (Text)' sed 's/^X//' << 'SHAR_EOF' > 'digestify' && #! ../bin/mush -F! # # Mush digestifier. Makes a folder or a list of messages into a digest. # # A "digest" is a collection of E-mail messages bundled together into a # single message for ease of redistribution. The individual messages # in the digest are called "articles". Each article has a small set of # essential headers (usually From:, Date:, and Subject:) and is divided # from the preceding and following articles by an "article separator" # string (usually eight hyphens, "--------"). The Mush built-in command # "undigest" unpacks most digests, including those made by this script. # # Usage: # From your shell: digestify -f mailbox # From within mush: # First: cmd digest "set digest = '\!*' ; source digestify" # Then: digest [msg-list] # Or: message-selection-command | digest # # Note that by default it makes a digest of the ENTIRE folder! # X # # Rudimentary sanity checks # if ! $?version X echo "You must have Mush version 7.0 or higher to run this script" X exit endif if ! $?thisfolder X echo "You can't use this script as an init file; try using -F" X exit endif X # # Set up defaults # if ! $?digest X set digest = * X if $?interact X unset interact # Assume non-interactive if no input list X endif else X set interact # Note that this is interactive X if "X$digest" == X X set digest = * # Default to all messages for empty input X else X $digest | set digest # Pre-expand message numbers X endif endif X # # Suppress any "that isn't set" messages from "unset" # if $?warning X set savewarn endif unset warning oldpre oldpost oldindent oldign oldshow X # # Save everything in case the user wants it back. # Could wrap all this with "if $?interact" but this script # might be read by "mush -F", in which case we need this. # if $?pre_indent_str X set oldpre = "$pre_indent_str" endif if $?post_indent_str X set oldpost = "$post_indent_str" endif if $?indent_str X set oldindent = "$indent_str" endif if $?alwaysignore X set oldign = "$alwaysignore" endif if $?show_hdrs X set oldshow = "$show_hdrs" endif if $?quiet X set oldquiet = "$quiet" endif if $?no_expand X set savenoex endif X # # Prepare to form the digest. # set indent_str no_expand alwaysignore=include quiet=await,newmail unset post_indent_str alias DIGEST $thisfolder # Any target in place of $thisfolder set pre_indent_str="--------" # Insert your digest separator here set show_hdrs=from,date,subject # Add any other headers you want X # # Now do it. All that work for a two-line operation .... # NOTE: If you change DIGEST above, remove the "await" command here! # Backslashes prevent any cmd expansion from confusing us. # \delete $digest \mail -UH /dev/null -I $digest -s "Digest of $thisfolder" DIGEST; \await -T 1 X # # Clean out the deleted stuff if not interactive # if ! $?interact X \update endif X # # Be neat and put everything back the way it was. # unset indent_str no_expand alwaysignore quiet pre_indent_str show_hdrs unalias DIGEST if $?savenoex X set no_expand endif if $?oldquiet X set quiet = "$oldquiet" endif if $?oldpre X set pre_indent_str = "$oldpre" endif if $?oldpost X set post_indent_str = "$oldpost" endif if $?oldindent X set indent_str = "$oldindent" endif if $?oldign X set alwaysignore = "$oldign" endif if $?oldshow X set show_hdrs = "$oldshow" endif unset oldpre oldpost oldindent oldign oldshow oldquiet nonoex digest if $?savewarn X unset savewarn X set warning endif SHAR_EOF chmod 0755 digestify || echo 'restore of digestify failed' Wc_c="`wc -c < 'digestify'`" test 3468 -eq "$Wc_c" || echo 'digestify: original size 3468, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= doproc.c ============== if test -f 'doproc.c' -a X"$1" != X"-c"; then echo 'x - skipping doproc.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting doproc.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'doproc.c' && /* @(#)doproc.c (c) copyright 10/18/86 (Dan Heller) */ X /* do main panel item procedures */ #include "mush.h" X extern void start_textsw_edit(); extern Panel get_compose_panel(); void set_comp_items(); X extern Panel_item X file_item, folder_text_item, folder_item, msg_num_item, read_item, X reply_item, save_item, sub_hdr_item[6]; X /* following macro is for the next two procedures */ #define hdr_item(item) \ X (item == sub_hdr_item[0] || item == sub_hdr_item[1] || \ X item == sub_hdr_item[2] || item == sub_hdr_item[3] || \ X item == sub_hdr_item[4] || item == sub_hdr_item[5]) X void delete_mail(item, value, event) register Panel_item item; int value; register Event *event; { X int val = value; /* save cuz we reset value immediately */ X u_long bang = ison(glob_flags, IGN_BANG); X char buf[128]; X X (void) panel_set(item, PANEL_VALUE, 0, 0); X if (hdr_item(item) && event_id(event) != MS_LEFT || val == 2) { X help(0, "delete", tool_help); X return; X } X /* delete current message */ X wprint(sprintf(buf, "\\%sdelete %s\n", X ((event_id(event) == MS_LEFT || val == 0)? "" : "un"), X panel_get_value(msg_num_item)) + 1); /* +1 skips the backslash */ X turnon(glob_flags, IGN_BANG); X (void) cmd_line(buf, msg_list); X if (!bang) X turnoff(glob_flags, IGN_BANG); } X void read_mail(item, value, event) Panel_item item; Event *event; { X int this_msg = current_msg; X X /* check "event" in case we were called from hdr_sw.c X * in which case event would be NULL X */ X if (event && event_id(event) == MS_RIGHT && item && X (item == read_item || X (item == sub_hdr_item[0] || item == sub_hdr_item[1]))) { X (void) help(0, "next", tool_help); X return; X } X if (item && (item == sub_hdr_item[4] || item == sub_hdr_item[5])) { X (void) help(0, "Menu Read", tool_help); X return; X } X if (!msg_cnt) { X wprint ("No Mail.\n"); X return; X } X if (item && item == read_item || ison(msg[current_msg].m_flags, DELETE)) X (void) next_msg(); X if (this_msg != current_msg || ison(msg[current_msg].m_flags, UNREAD) || X (current_msg < n_array[0] || current_msg > n_array[screen])) { X set_isread(current_msg); X (void) do_hdrs(0, DUBL_NULL, NULL); X } X if (isoff(msg[current_msg].m_flags, DELETE)) X display_msg(current_msg, (u_long)0); } X /* the panel button that says "filename" and "directory", etc... text item */ Panel_setting file_dir(item, event) Panel_item item; Event *event; { X register char *p; X u_long bang = ison(glob_flags, IGN_BANG); X char buf[MAXPATHLEN]; X X if (event_id(event) == ESC) { X /* file expansion request */ X int n; X char **files; X p = panel_get_value(item); X (void) sprintf(buf, "%s*", p); X timeout_cursors(1); X if ((n = filexp(buf, &files)) > 0) { X Debug("%d: ",n), print_argv(files); X if (n > 1) { X n = lcprefix(files, 0); X files[0][n] = 0; X } X panel_set_value(item, trim_filename(files[0])); X free_vec(files); X } else X errbell(n); /* see curs_io.c */ X timeout_cursors(0); X return PANEL_NONE; X } X X if (item == folder_text_item) { X (void) sprintf(buf, "folder %s %s", X (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) && X !ask("Folder has been modified. Update changes?"))? "!" : "", X panel_get_value(folder_text_item)); X } X else if (item == file_item) { X register char *b = buf; X char msgstr[BUFSIZ]; X X if (event_id(event) == '\n' || event_id(event) == '\r') X b += Strcpy(buf, "save "); X else X b += Strcpy(buf, "write "); X if ((p = panel_get_value(msg_num_item)) && *p) X b += Strcpy(b, p); X else { X if (ison(msg[current_msg].m_flags, DELETE) && X !do_set(set_options, "show_deleted")) { X (void) sprintf(msgstr, "Message %d deleted -- save anyway?", X current_msg+1); X if (ask(msgstr) != TRUE) { X wprint("Message not saved\n"); X return PANEL_NONE; X } X } X b += strlen(sprintf(b, "%d", current_msg+1)); X } X *b++ = ' ', *b = 0; X if (!(p = panel_get_value(item)) || !*p && X (!(p = do_set(set_options, "mbox")) || !*p)) X p = DEF_MBOX; X if (chk_option("verify", "save")) { X (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p)); X if (ask(msgstr) != TRUE) { X wprint("Message not saved\n"); X return PANEL_NONE; X } X } X (void) strcpy(b, p); /* now add to command */ X } X turnon(glob_flags, IGN_BANG); X (void) cmd_line(buf, msg_list); X if (!bang) X turnoff(glob_flags, IGN_BANG); X return PANEL_NONE; } X #ifndef NO_WALK_MENUS void xx_file_dir(item, value) Panel_item item; char * value; { X char buf[BUFSIZ]; X u_long bang = ison(glob_flags, IGN_BANG); X X if (item == folder_item) { X (void) sprintf(buf, "folder %s ", X (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) && X !ask("Folder has been modified. Update changes?"))? "!" : ""); X strcat(buf, value); X } else if (item == save_item) { X char msgstr[BUFSIZ], *p; X register char *p2 = (char *)panel_get_value(msg_num_item); X (void) strcpy(buf, "save "); X X if (p2 && *p2) { X (void) strcat(buf, p2); X (void) strcat(buf, " "); X } X (void) strcat(buf, value); X if (chk_option("verify", "save")) { X (void) sprintf(msgstr, "Save in %s? ", trim_filename(value)); X if (ask(msgstr) != TRUE) { X wprint("Message not saved\n"); X return; X } X } X } X turnon(glob_flags, IGN_BANG); X (void) cmd_line(buf, msg_list); X if (!bang) X turnoff(glob_flags, IGN_BANG); X (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ } X /* X * callback routine for the panel items that need filename input. X * (folder and save) X */ void do_file_dir(item, event) Panel_item item; Event *event; { X if (item == folder_item) { X char *p = panel_get_value(folder_text_item); X if (!*p) { X ok_box("Enter folder name."); X return; X } X xx_file_dir(item, p); X } else if (item == save_item) { X if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) { X event_id(event) = '\n'; /* let file_dir think it got a \n */ X file_dir(file_item, event); X return; X } X } X (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ } #else /* NO_WALK_MENUS */ X /* X * callback routine for the panel items that need filename input. X * (folder and save) X */ void do_file_dir(item, value, event) Panel_item item; int value; Event *event; { X char buf[BUFSIZ]; X u_long bang = ison(glob_flags, IGN_BANG); X X if (item == folder_item) { X (void) sprintf(buf, "folder %s ", X (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) && X !ask("Folder has been modified. Update changes?"))? "!" : ""); X if (event_id(event) == MS_LEFT) { X char *p = panel_get_value(folder_text_item); X if (!*p) { X ok_box("Enter folder name."); X return; X } X (void) strcat(buf, p); X } else if (!value) X (void) strcat(buf, "%"); X else if (value == 1) X (void) strcat(buf, "&"); X else if (value == 2) X (void) strcat(buf, "#"); X else X (void) strcat(buf, panel_get(item, PANEL_CHOICE_STRING, value)); X } else if (item == save_item) { X char msgstr[BUFSIZ], *p; X (void) strcpy(buf, "save "); X if (event_id(event) == MS_LEFT) { X if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) { X event_id(event) = '\n'; /* let file_dir think it got a \n */ X file_dir(file_item, event); X return; X } X } else if (value == 0) { X register char *p2 = (char *)panel_get_value(msg_num_item); X X if (!(p = do_set(set_options, "mbox")) || !*p) X p = DEF_MBOX; X if (p2 && *p2) { X (void) strcat(buf, p2); X (void) strcat(buf, " "); X } X (void) strcat(buf, p); X } else X (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value)); X if (chk_option("verify", "save")) { X (void) sprintf(msgstr, "Save in %s? ", trim_filename(p)); X if (ask(msgstr) != TRUE) { X wprint("Message not saved\n"); X return; X } X } X } X turnon(glob_flags, IGN_BANG); X (void) cmd_line(buf, msg_list); X if (!bang) X turnoff(glob_flags, IGN_BANG); X (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ } #endif /* NO_WALK_MENUS */ X /*ARGSUSED*/ void do_help(item, value, event) Panel_item item; register int value; Event *event; { X register char *p, *helpfile = tool_help; X if (!event || event_id(event) == MS_LEFT) X value = 0; X switch(value) { X case 0: p = "about", helpfile = cmd_help; X when 1: p = "help"; X when 2: p = "mouse"; X when 3: p = "windows"; X when 4: p = "hdr_format", helpfile = cmd_help; X when 5: p = "msg_list", helpfile = cmd_help; X when 6: p = "folder"; X otherwise: p = "general"; X } X (void) help(0, p, helpfile); } X /*ARGSUSED*/ void do_update(item, value, event) Panel_item item; int value; Event *event; { X char *argv[2]; X if (event && event_id(event) != MS_LEFT) { X if (value == 0) { X if (check_new_mail() == 0) X print("No new mail.\n"); X } else X (void) help(0, "update", tool_help); X return; X } X argv[0] = "update"; X argv[1] = NULL; X timeout_cursors(TRUE); X (void) folder(0, argv, NULL); X timeout_cursors(FALSE); } X /*ARGSUSED*/ void toolquit(item, value, event) Panel_item item; int value; Event *event; { X void wmgr_changestate(), wmgr_changelevel(); X register int which; X X if (!value || event_id(event) == MS_LEFT) { X if (ison(glob_flags, DO_UPDATE)) { X do_update(NO_ITEM, 0, NO_EVENT); X turnoff(glob_flags, NEW_MAIL); X } X check_icons(); X mail_status(0); /* lower flag (if up) print current num of msgs */ X /* wmgr_changestate (window_get(tool, WIN_FD), rootfd, TRUE); */ X /* wmgr_changelevel (window_get(tool, WIN_FD), parentfd, TRUE); */ X close_frame(); X window_set(tool, FRAME_CLOSED, TRUE, NULL); X is_iconic = ((int) window_get(tool, FRAME_CLOSED)); X return; X } else if (value == 2) { X (void) help(0, "quit", tool_help); X return; X } X /* modify this to check for "abort" choice when ternary return values X * are possible! X */ X if (isoff(glob_flags, DO_UPDATE) || X ask("Folder has been modified -- update?")) { X if (!copyback("Quit anyway?", TRUE)) X return; X } X cleanup(0); } X /*ARGSUSED*/ void do_mark(item, value, event) Panel_item item; int value; Event *event; { X if (event && (event_id(event) == MS_LEFT) || value == 0) { X int msg_num = event? current_msg : (int)item; X /* mark message */ X if (ison(msg[msg_num].m_flags, M_PRIORITY(0))) X turnoff(msg[msg_num].m_flags, M_PRIORITY(0)); X else X turnon(msg[msg_num].m_flags, M_PRIORITY(0)); X (void) do_hdrs(0, DUBL_NULL, NULL); X } else if (value < 7) { X /* set priority */ X char buf[90]; X (void) cmd_line(sprintf(buf, "mark -%c %s", X value < 6? value + 'A' - 1 : ' ', X panel_get_value(msg_num_item)), NULL); X } else X (void) help(0, "mark", tool_help); X if (value != 7 && item) X panel_set_value(item, 0); } X /*ARGSUSED*/ void do_lpr(item, value, event) Panel_item item; int value; Event *event; { X char buf[128]; X X if (event && (event_id(event) == MS_LEFT)) { X wprint("Sending message %d to printer...\n", current_msg+1); X (void) strcpy(buf, "lpr "); X if (value) X (void) sprintf(buf, "lpr \"%s\"", panel_get_value(msg_num_item)); X timeout_cursors(TRUE); X (void) cmd_line(buf, msg_list); X timeout_cursors(FALSE); X } else X (void) help(0, "printer", tool_help); } X /* panel selection button pressed to send a letter. X * we've attached the sign panel item to this item to 1) avoid X * using a global and 2) make it general enough so that multiple X * compose windows can have multiple send_items and we can X * identify which sign/fortune items are associated with this X * particular letter. The fortune item is attached to the sign X * item. X */ /*ARGSUSED*/ void do_send(item, value, event) Panel_item item; int value; register Event *event; { X Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL); X Panel_item sign_item = (Panel_item)panel_get(item, PANEL_CLIENT_DATA); X Panel_item fortune_item = X (Panel_item)panel_get(sign_item, PANEL_CLIENT_DATA); X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA); X char *argv[5], buf[64]; X char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA); X char *p, *oldsign = NULL, *oldfortune = NULL; X X if (textsw_store_file(textsw, file, 0, 0)) { X error("Can't save to %s", file); X return; X } X /* check if user changed variables before sending */ X if (p = do_set(set_options, "autosign")) X oldsign = savestr(p); X if (panel_get_value(sign_item) && !oldsign) X cmd_line(strcpy(buf, "\\set autosign"), NULL); X else if (!panel_get_value(sign_item) && oldsign) X cmd_line(strcpy(buf, "\\unset autosign"), NULL); X if (p = do_set(set_options, "fortune")) X oldfortune = savestr(p); X if (panel_get_value(fortune_item) && !oldfortune) X (void) cmd_line(strcpy(buf, "\\set fortune"), NULL); X else if (!panel_get_value(fortune_item) && oldfortune) X (void) cmd_line(strcpy(buf, "\\unset fortune"), NULL); X turnoff(glob_flags, IS_GETTING); X argv[0] = "mail"; X argv[1] = "-Uh"; X argv[2] = file; X argv[3] = NULL; X clear_msg_list(msg_list); X timeout_cursors(TRUE); X if (do_mail(3, argv, msg_list) == 0) { X (void) unlink(file); X set_comp_items(panel); X } X if (panel_get_value(sign_item) && !oldsign) X (void) cmd_line(strcpy(buf, "\\unset autosign"), NULL); X else if (!panel_get_value(sign_item) && oldsign) { X argv[0] = "set"; X argv[1] = "autosign"; X if (*oldsign) { X argv[2] = "="; X argv[3] = oldsign; X argv[4] = NULL; X (void) set(4, argv, NULL); X } else { X argv[2] = NULL; X (void) set(2, argv, NULL); X } X } X if (panel_get_value(fortune_item) && !oldfortune) X cmd_line(strcpy(buf, "\\unset fortune"), NULL); X else if (!panel_get_value(fortune_item) && oldfortune) { X argv[0] = "set"; X argv[1] = "fortune"; X if (*oldfortune) { X argv[2] = "="; X argv[3] = oldfortune; X argv[4] = NULL; X (void) set(4, argv, NULL); X } else { X argv[2] = NULL; X (void) set(2, argv, NULL); X } X } X xfree(oldsign), xfree(oldfortune); X timeout_cursors(FALSE); } X /*ARGSUSED*/ void do_include(item, value, event) Panel_item item; int value; Event *event; { X extern FILE *ed_fp; X char *p, buf[64], *file; X Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL), X PANEL_CLIENT_DATA); X X if (event && event_id(event) == MS_LEFT) X value = 0; X if (value == 2) { X (void) help(0, "include", tool_help); X return; X } X p = panel_get_value(msg_num_item); X (void) sprintf(buf, "%c%c%s", *escape, value == 0? 'i' : 'f', p? p : ""); X X file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA); X if (textsw_store_file(textsw, file, 0, 0)) { X (void) ask("Something's wrong... Click anything."); X return; X } X if (ed_fp) { X (void) ask("tmpfile already in use... Click anything."); X (void) fclose(ed_fp); X } X if (!(ed_fp = mask_fopen(file, "a"))) { X error("Cannot open %s to append msg.", file); X return; X } X (void) add_to_letter(buf); X (void) fclose(ed_fp), ed_fp = NULL_FILE; #ifdef SUN_4_0 /* SunOS 4.0+ */ X window_set(textsw, TEXTSW_FILE_CONTENTS, file, NULL); #else /* SUN_4_0 */ X textsw_load_file(textsw, file, 1, 0, 0); #endif /* SUN_4_0 */ X window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL); X (void) unlink(file); } X /*ARGSUSED*/ void do_compose(item, value, event) Panel_item item; int value; Event *event; { X char buf[5]; X X if (event && event_id(event) != MS_LEFT) { X (void) help(0, "compose", tool_help); X return; X } X open_compose(); X if (!compose_frame) X return; /* open failed */ X clear_msg_list(msg_list); X if (do_mail(0, DUBL_NULL, msg_list) == 0) { X Panel panel = get_compose_panel(); X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA); X start_textsw_edit(textsw, TRUE); X set_comp_items(panel); X } } X /* X * notify proc for reply button -- also called from select.c (do_menu()) , X * in which case "event" is null and "value" contains the message X * number of the message to reply to. X */ /*ARGSUSED*/ void respond_mail(item, value, event) Panel_item item; int value; Event *event; { X int tmp = current_msg; X char buf[256]; X X if (event && event_id(event) == MS_LEFT) X value = 0; X if (event && value == 4) { X (void) help(0, "respond", tool_help); X return; X } X if (!msg_cnt) { X wprint("No messages to respond to.\n"); X return; X } X if (ison(glob_flags, IS_GETTING)) { X wprint("Finish editing current message first.\n"); X return; X } X if (!event) X tmp = value, value = 0; X open_compose(); X if (!compose_frame) X return; /* open failed */ X (void) sprintf(buf, "%s %s %d", X (value == 2 || value == 3)? "\\replyall" : "\\replysender", X (value == 1 || value == 3)? "-i": NO_STRING, tmp+1); X if (cmd_line(buf, NULL) != -1) { X Panel panel = get_compose_panel(); X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA); X wprint("Responding to message %d\n", tmp+1); X start_textsw_edit(textsw, FALSE); X set_comp_items(panel); X } } X /*ARGSUSED*/ void load_from_file(item, value, event) Panel_item item; int value; Event *event; { X int x = 0; X Textsw textsw; X Panel_item filename_item = (Panel_item)panel_get(item, PANEL_CLIENT_DATA); X char *file, *p = panel_get_value(filename_item); #ifndef SUN_4_0 /* SunOS 4.0+ */ X char *sfile, buf[128]; X extern FILE *ed_fp; #endif /* SUN_4_0 */ X X if (!*p) { X wprint("Specify Filename.\n"); X return; X } X file = getpath(p, &x); X if (x == 1) X wprint("%s: is a directory.\n", p); X else if (x == -1) X wprint("%s: %s\n", p, file); X if (x) X return; X timeout_cursors(TRUE); X textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL), X PANEL_CLIENT_DATA); X if (event_id(event) != MS_LEFT && value == 1) X /* replace */ X textsw_load_file(textsw, file, 1, 0, 0); X else { X /* insert */ #ifdef SUN_4_0 /* SunOS 4.0+ */ X window_set(textsw, TEXTSW_INSERT_FROM_FILE, file, NULL); #else /* SUN_4_0 */ X /* best we can do with pre 4.0 is save the current file X * and append the new file onto the end. X */ X sfile = (char *)window_get(textsw, TEXTSW_CLIENT_DATA); X if (textsw_store_file(textsw, sfile, 0, 0)) { X (void) ask("Can't save file... Click anything."); X return; X } X if (ed_fp) { X (void) ask("tmpfile already in use... Click anything."); X fclose(ed_fp); X } X if (!(ed_fp = mask_fopen(sfile, "a"))) { X error("Cannot open %s.", sfile); X return; X } X (void) sprintf(buf, "%c%c%s", *escape, 'r', trim_filename(p)); X (void) add_to_letter(buf); X (void) fclose(ed_fp), ed_fp = NULL_FILE; X textsw_load_file(textsw, sfile, 1, 0, 0); X (void) unlink(sfile); #endif /* SUN_4_0 */ X } X window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL); X panel_set_value(item, 0); X timeout_cursors(FALSE); } X /*ARGSUSED*/ void save_to_file(item, value, event) Panel_item item; Event *event; { X Panel_item filename_item = panel_get(item, PANEL_CLIENT_DATA); X char *file = panel_get_value(filename_item); X FILE *fp; X Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL), X PANEL_CLIENT_DATA); X X if (!*file) { X wprint("Specify Filename\n"); X return; X } X timeout_cursors(TRUE); X /* append to file -- no confirmation necessary */ X if (fp = open_file(file, FALSE, TRUE)) { X char buf[BUFSIZ]; X Textsw_index next_pos = 0, tmp; X Textsw_index length = X (Textsw_index)window_get(textsw, TEXTSW_LENGTH); X do { X tmp = next_pos; X next_pos = (Textsw_index) window_get(textsw, TEXTSW_CONTENTS, X next_pos, buf, sizeof(buf)); X if (fwrite(buf, sizeof(char), (int)(next_pos - tmp), fp) == 0) X error("%s may be incomplete", file); X } while (next_pos < length); X (void) close_lock(file, fp); X wprint("Wrote %d bytes to %s\n", length, trim_filename(file)); X } X timeout_cursors(FALSE); } X void abort_mail(item, event) Panel_item item; Event *event; { X Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL); X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA); X wprint("Aborted letter.\n"); X textsw_reset(textsw, 0, 0); X rm_edfile(0); X set_comp_items(panel); } X /* set the compose panel items */ void set_comp_items(panel) Panel panel; { X Panel_item item, next; X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA); X int getting = ison(glob_flags, IS_GETTING) != 0; X int i = 0; X X window_set(textsw, TEXTSW_READ_ONLY, !getting, NULL); X /* remove next line when multiple composes become a reality */ X (void) panel_set(reply_item, PANEL_SHOW_ITEM, !getting, NULL); X /* skip "close" item */ X item = (Panel_item) panel_get(panel, PANEL_FIRST_ITEM); X for (item = (Panel_item) panel_get(item, PANEL_NEXT_ITEM); X item; item = next) { X next = (Panel_item) panel_get(item, PANEL_NEXT_ITEM); X (void) panel_set(item, X PANEL_SHOW_ITEM, (i++ < 1)? !getting : getting, NULL); X } } X /* X * Ask a yes/no question and return an answer: TRUE or FALSE. X */ ask(question) char *question; { #ifdef SUN_4_0 /* SunOS 4.0+ */ X return alert_prompt(tool, (Event *)NULL, X ALERT_MESSAGE_STRINGS, question, NULL, X ALERT_BUTTON_YES, "Yes", X ALERT_BUTTON_NO, "No", X NULL) == ALERT_YES; #else /* SUN_4_0 */ X Event event; X struct prompt prompt; X Rect *rect = (Rect *)window_get(tool, WIN_RECT); X char buf[MAXPATHLEN]; X X (void) sprintf(buf, X "%s \nPress LEFT Button to Confirm. Anything else to cancel.", X question); X prompt.prt_rect.r_left = rect->r_left + (rect->r_width / 3); X prompt.prt_rect.r_top = rect->r_top + (rect->r_height / 3); X prompt.prt_rect.r_width = prompt.prt_rect.r_height = PROMPT_FLEXIBLE; X prompt.prt_font = mush_font; X prompt.prt_text = buf; X X menu_prompt(&prompt, &event, window_get(tool, WIN_FD)); X return event_id(&event) == MS_LEFT; #endif /* SUN_4_0 */ } X void ok_box(buf) char *buf; { #ifdef SUN_4_0 X (void) alert_prompt(tool, (Event *)NULL, X ALERT_MESSAGE_STRINGS, buf, NULL, X ALERT_BUTTON_YES, "Ok", X NULL); #else /* SUN_4_0 */ X Event event; X struct prompt prompt; X Rect *rect = (Rect *)window_get(tool, WIN_RECT); X (void) strcat(buf, " \nPress LEFT Button to Continue."); X prompt.prt_rect.r_left = rect->r_left + (rect->r_width / 3); X prompt.prt_rect.r_top = rect->r_top + (rect->r_height / 3); X prompt.prt_rect.r_width = prompt.prt_rect.r_height = PROMPT_FLEXIBLE; X prompt.prt_font = mush_font; X prompt.prt_text = buf; X menu_prompt(&prompt, &event, window_get(tool, WIN_FD)); #endif /* SUN_4_0 */ } X Panel_setting msg_num_done(item, event) Panel_item item; Event *event; { X char buf[82]; X u_long bang = ison(glob_flags, IGN_BANG); X register char *p; X int n; X X if (event_id(event) != '\n' && event_id(event) != '\r') { X (void) help(0, "message range", tool_help); X return PANEL_NONE; X } X (void) sprintf(buf, "headers %s", (p = (char *)panel_get_value(item))); X (void) panel_set(item, PANEL_VALUE, NO_STRING, NULL); X if (!(n = chk_msg(p))) X return PANEL_NONE; X current_msg = --n; X turnon(glob_flags, IGN_BANG); X (void) cmd_line(buf, msg_list); X if (!bang) X turnoff(glob_flags, IGN_BANG); X (void) display_msg(n, (u_long)0); X return PANEL_NONE; } X void do_sort(item, value, event) Panel_item item; int value; Event *event; { X char *argv[3], list[MAXMSGS_BITS]; X char *p = (char *)panel_get_value(msg_num_item); X int n = 0; X X if (p && *p) { X argv[0] = p; X argv[1] = NULL; X n = get_msg_list(argv, list); X } X argv[0] = "sort"; X argv[2] = NULL; X X if (event_id(event) == MS_LEFT) X value = 0; X switch(value) { X case 0: argv[1] = "S"; X when 1: argv[1] = "a"; X when 2: argv[1] = "l"; X when 3: argv[1] = "R"; X when 4: argv[1] = "s"; X when 5: argv[1] = "d"; X when 6: argv[1] = "p"; X when 7: do_set(set_options, "sort"); X when 8: (void) help(0, "sort", tool_help); X } X if (value != 8) { X if (n > 0) { X turnon(glob_flags, IS_PIPE); X (void) sort(2, argv, list); X turnoff(glob_flags, IS_PIPE); X } else X (void) sort(2, argv, NULL); X (void) do_hdrs(0, DUBL_NULL, NULL); X } X (void) panel_set(item, PANEL_VALUE, 0, NULL); } X void do_options(item, value, event) Panel_item item; int value; Event *event; { X if (event_id(event) == MS_LEFT) { X view_options(); X return; X } X switch (value) { X case 0: X view_options(); X when 1: X do_ignore(); X when 2: X do_aliases(); X } } SHAR_EOF chmod 0644 doproc.c || echo 'restore of doproc.c failed' Wc_c="`wc -c < 'doproc.c'`" test 24153 -eq "$Wc_c" || echo 'doproc.c: original size 24153, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= execute.c ============== if test -f 'execute.c' -a X"$1" != X"-c"; then echo 'x - skipping execute.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting execute.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'execute.c' && /* execute.c (c) copyright 10/28/86 (Dan Heller) */ X #include "mush.h" #ifdef BSD #include <sys/wait.h> #else #ifndef SYSV #include <wait.h> #endif /* SYSV */ #endif /* BSD */ X #ifdef lint #include <sys/resource.h> #endif /* lint */ X static jmp_buf execjbuf; X #ifdef SUNTOOL X /*ARGSUSED*/ Notify_value my_wait3(tty, pid, status, rusage) Tty tty; int pid; union wait *status; struct rusage *rusage; { X extern Panel_item edit_item; X Textsw textsw = (Textsw)window_get(tty, WIN_CLIENT_DATA); X char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA); X int i = 0; X X if (WIFSTOPPED(*status)) { X kill(pid, SIGCONT); X return (NOTIFY_IGNORED); X } X if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */ X return NOTIFY_DONE; X /* editor died -- reset exec_pid so no one thinks we're running */ X exec_pid = 0; X (void) window_set(tty, TTY_ARGV, TTY_ARGV_DO_NOT_FORK, NULL); X wprint("Editor done.\n"); X (void) window_set(tty_sw, WIN_SHOW, FALSE, NULL); #ifdef SUN_4_0 /* SunOS 4.0+ */ X (void) window_set(textsw, X WIN_SHOW, TRUE, X TEXTSW_FILE_CONTENTS, file, X NULL); #else /* SUN_4_0 */ X textsw_load_file(textsw, file, 1, 0, 0); X textsw_set(textsw, WIN_SHOW, TRUE, NULL); #endif /* SUN_4_0 */ X textsw_normalize_view(textsw, (Textsw_index)0); X (void) unlink(file); X set_comp_items(panel_get(edit_item, PANEL_PARENT_PANEL)); X X return NOTIFY_DONE; } X tool_edit_letter(textsw, argv) Textsw textsw; char **argv; { X Rect *msg_rect = (Rect *)window_get(textsw, WIN_RECT); X X wprint("Starting \"%s\"...\n", *argv); #ifdef SUN_4_0 X window_set(textsw, WIN_SHOW, FALSE, NULL); #else /* SUN_4_0 */ X textsw_set(textsw, WIN_SHOW, FALSE, NULL); #endif /* SUN_4_0 */ X ttysw_output(tty_sw, "\f", 1); /* clear screen */ X (void) window_set(tty_sw, X WIN_RECT, msg_rect, X TTY_ARGV, argv, X WIN_SHOW, TRUE, X NULL); X if ((exec_pid = (int) window_get(tty_sw, TTY_PID)) == -1) { X error("Couldn't execute %s", *argv); X return -1; X } X notify_set_wait3_func(tty_sw, my_wait3, exec_pid); X Debug("tty pid = %d\n", exec_pid); X return 0; } #endif /* SUNTOOL */ X execute(argv) char **argv; { #ifdef SYSV X int status; #else X union wait status; #endif /* SYSV */ #ifdef SIGCONT X SIGRET (*oldstop)(), (*oldcont)(); #endif /* SIGCONT */ X int pid; X SIGRET (*oldint)(), (*oldquit)(); X X oldint = signal(SIGINT, SIG_IGN); X oldquit = signal(SIGQUIT, SIG_IGN); #ifdef SIGCONT X oldstop = signal(SIGTSTP, SIG_DFL); X oldcont = signal(SIGCONT, SIG_DFL); #endif /* SIGCONT */ X turnon(glob_flags, IGN_SIGS); X X echo_on(); X if (!setjmp(execjbuf)) { X if ((exec_pid = vfork()) == 0) { X (void) signal(SIGINT, SIG_DFL); X (void) signal(SIGQUIT, SIG_DFL); X (void) signal(SIGPIPE, SIG_DFL); X (void) closefileds(3); /* close all descriptors above 2 */ 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 may also be waiting. X * This loop will usually get broken by the longjmp() (except tool), X * but in certain circumstances sigchldcatcher isn't yet active. X */ X while ((pid = wait(&status)) != -1 && pid != exec_pid) X Debug("The exec loop caught a signal? (pid = %d)\n", pid); X } X /* reset our ttymodes */ X echo_off(); X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); #ifdef SIGCONT X (void) signal(SIGTSTP, oldstop); X (void) signal(SIGCONT, oldcont); #endif /* SIGCONT */ X turnoff(glob_flags, IGN_SIGS); } X SIGRET sigchldcatcher() { #ifdef SYSV X int status; #else X union wait status; #endif /* SYSV */ X int pid; X #ifdef BSD X while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) { X Debug("%d died...\n", pid); X if (pid == exec_pid) X break; X } #else #ifndef SYSV X while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid) X Debug("%d died...\n", pid); #else /* SYSV */ X while ((pid = wait((int *)0)) > 0 && pid != exec_pid) X Debug("%d died...\n", pid); #endif /* SYSV */ #endif /* BSD */ X if (pid == exec_pid && pid > 0) { X exec_pid = 0; X longjmp(execjbuf, 1); X } } SHAR_EOF chmod 0644 execute.c || echo 'restore of execute.c failed' Wc_c="`wc -c < 'execute.c'`" test 4196 -eq "$Wc_c" || echo 'execute.c: original size 4196, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= expr.c ============== if test -f 'expr.c' -a X"$1" != X"-c"; then echo 'x - skipping expr.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting expr.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'expr.c' && /* @(#)expr.c 2.3 (c) copyright 10/15/86 (Dan Heller) */ X #include "mush.h" X char *eval_expr(); X /* Parse a string (p) to interpret numbers and ranges of numbers (n-m) X * delimited by whitespace or comma's. Set msg_list bitfields using X * macros in mush.h. X * Return the address of the end of whatever we parsed (in case there's X * more that the calling routine cares to deal with). X * Finally, remember that user specifies one more than actual message number X */ char * do_range(p, list1) register char *p, *list1; { X register int num1 = -1, num2 = -1, except = 0; X register char *p2; X char list2[MAXMSGS_BITS]; X X if (!p) X return ""; X while (*p) { X if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') { X if (isdigit(*p)) { X char c; X p2 = p; X skipdigits(0); /* find the end of the digits */ X c = *p, *p = 0; /* temporarily plug a null */ X if (!(num2 = chk_msg(p2))) { X clear_msg_list(list1); X return NULL; X } X *p = c; X } else if (*p == '$') X p++, num2 = msg_cnt; X else if (*p == '.') X p++, num2 = current_msg+1; X else if (*p == '^') X p++, num2 = 1; X if (except) X unset_msg_bit(list1, num2-1); X else X set_msg_bit(list1, num2-1); X if (num1 >= 0) { X if (num1 > num2) { X print("syntax error: range sequence order reversed.\n"); X clear_msg_list(list1); X return NULL; X } X while (++num1 < num2) X if (except) X unset_msg_bit(list1, num1-1); X else X set_msg_bit(list1, num1-1); X num1 = num2 = -1; X } X } X /* expressions to evaluate start with a ` X * p2 points to first char passed the last char parsed. X */ X if (*p == '`') { X clear_msg_list(list2); X if (!(p = eval_expr(p, list2))) { X clear_msg_list(list1); X return NULL; X } else { X if (except) X bitput(list2, list1, msg_cnt, &=~); /* MACRO */ X else X bitput(list2, list1, msg_cnt, |=); /* MACRO */ X } X } X /* NOT operator: `* {5}' (everything except for 5) X * `4-16 {8-10}' (4 thru 16 except for 8,9,10) X */ X if (*p == '{' || *p == '}') { X if (*p == '{' && (except || num1 >= 0)) X break; X if (*p == '}' && !except) { X print("syntax error: missing {\n"); /* } */ X break; X } X except = !except; X } else if (*p == '-') X if (num1 >= 0 || num2 < 0 X || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1))) X break; X else X num1 = num2; X else if (*p == ',' || *p == '*') { X if (num1 >= 0) X break; X else if (*p == '*') { X if (except) X clear_msg_list(list1); X else X for (num1 = 0; num1 < msg_cnt; num1++) X set_msg_bit(list1, num1); X num1 = -1; X } X } else if (!index(" \t`", *p)) X break; X if (*p) X skipspaces(1); /* don't make user type stuff squished together */ X } X if (num1 >= 0 || except) { X if (except) X /* { */ print("syntax error: unmatched }\n"); X else X print("syntax error: unfinished range\n"); X clear_msg_list(list1); X return NULL; X } X return p; } X /* X * convert a message list to an ascii string. X */ void list_to_str(list, str) char list[], *str; { X int n, m = -1; X X for (n = 0; n < msg_cnt; n++) { X if (msg_bit(list, n)) { X if (m == -1) X str += strlen(sprintf(str, "%d", (m = n) + 1 )); X continue; X } X if (m == -1) X continue; X if (n - m > 2) X str += strlen(sprintf(str, "-%d", n)); X else if (n - m == 2) X str += strlen(sprintf(str, " %d", n)); X *str++ = ' '; X m = -1; X } X if (m > -1 && m != n - 1) { X if (n - m > 2) X *str++ = '-'; X else X *str++ = ' '; X str += Strcpy(str, itoa(msg_cnt)); X } X *str = 0; } X /* evaluate expressions: X * mail> delete `pick -f root` deletes all messages from root. X * mail> save * {`pick -s "Re:"`} save all message that don't have "Re:" X * in the subject header. X * mail> save `pick -x -s "Re:"` same X * args as follows: X * p should point to the first ` -- check for it. X * on tells whether to turn bits on or off if messages match. SHAR_EOF true || echo 'restore of expr.c failed' fi echo 'End of part 7' echo 'File expr.c is continued in part 8' echo 8 > _shar_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.