home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / mush / part20 < prev    next >
Internet Message Format  |  1991-04-22  |  51KB

  1. From: argv@zipcode.com (Dan Heller)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i077:  mush - Mail User's Shell, Part20/22
  4. Message-ID: <1991Apr22.153808.111@sparky.IMD.Sterling.COM>
  5. Date: 22 Apr 91 15:38:08 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: b5859633 d851a387 5114387f a5d58b5a
  8.  
  9. Submitted-by: Dan Heller <argv@zipcode.com>
  10. Posting-number: Volume 18, Issue 77
  11. Archive-name: mush/part20
  12. Supersedes: mush: Volume 12, Issue 28-47
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file pick.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 20; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping pick.c'
  32. else
  33. echo 'x - continuing file pick.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'pick.c' &&
  35. X *    1d 1Y
  36. X *
  37. X * Return number of args parsed; -1 on error.
  38. X */
  39. ago_date(argv)
  40. char **argv;
  41. {
  42. #define SECS_PER_DAY   (60 * 60 * 24)
  43. #define SECS_PER_WEEK  (SECS_PER_DAY * 7)
  44. #define SECS_PER_MONTH ((int)(SECS_PER_DAY * 30.5))
  45. #define SECS_PER_YEAR  (SECS_PER_DAY * 365)
  46. X    register char *p;
  47. X    char       buf[256];
  48. X    int           n = 0, value;
  49. X    long       t;
  50. X    struct tm       *today;
  51. X
  52. X    (void) argv_to_string(buf, argv);
  53. X    p = buf;
  54. X    (void) time (&t); /* get current time in seconds and subtract new values */
  55. X    if (*p == '-')
  56. X    before = TRUE;
  57. X    else if (*p == '+')
  58. X    after = TRUE;
  59. X    skipspaces(before || after);
  60. X    while (*p) {
  61. X    if (!isdigit(*p)) {
  62. X        p -= 2;
  63. X        break; /* really a syntax error, but it could be other pick args */
  64. X    }
  65. X    p = my_atoi(p, &value); /* get 1 or more digits */
  66. X    skipspaces(0); /* 0 or more spaces */
  67. X    switch (lower(*p)) {   /* d, m, or y */
  68. X        case 'd' : t -= value * SECS_PER_DAY;
  69. X        when 'w' : t -= value * SECS_PER_WEEK;
  70. X        when 'm' : t -= value * SECS_PER_MONTH;
  71. X        when 'y' : t -= value * SECS_PER_YEAR;
  72. X        otherwise: return -1;
  73. X    }
  74. X    for (p++; Lower(*p) >= 'a' && *p <= 'z'; p++)
  75. X        ; /* skip the rest of this token */
  76. X    while (*p == ',' || isspace(*p))
  77. X        ++p; /* 0 or more whitespaces or commas */
  78. X    }
  79. X    today = localtime(&t);
  80. X    mdy[0] = today->tm_mon;
  81. X    mdy[1] = today->tm_mday;
  82. X    mdy[2] = today->tm_year;
  83. X
  84. X    /* Count the number of args parsed */
  85. X    for (n = 0; p > buf && *argv; n++)
  86. X    p -= (strlen(*argv++)+1);
  87. X    Debug("parsed %d args\n", n);
  88. X    return n;
  89. }
  90. SHAR_EOF
  91. echo 'File pick.c is complete' &&
  92. chmod 0644 pick.c ||
  93. echo 'restore of pick.c failed'
  94. Wc_c="`wc -c < 'pick.c'`"
  95. test 17697 -eq "$Wc_c" ||
  96.     echo 'pick.c: original size 17697, current size' "$Wc_c"
  97. rm -f _shar_wnt_.tmp
  98. fi
  99. # ============= print.c ==============
  100. if test -f 'print.c' -a X"$1" != X"-c"; then
  101.     echo 'x - skipping print.c (File already exists)'
  102.     rm -f _shar_wnt_.tmp
  103. else
  104. > _shar_wnt_.tmp
  105. echo 'x - extracting print.c (Text)'
  106. sed 's/^X//' << 'SHAR_EOF' > 'print.c' &&
  107. /* @(#)print.c    2.4    (c) copyright 10/15/86 (Dan Heller) */
  108. X
  109. #include "mush.h"
  110. #include <varargs.h>
  111. X
  112. /*ARGSUSED*/
  113. /*VARARGS1*/
  114. void
  115. error(fmt, arg1, arg2, arg3, arg4)
  116. register char *fmt;
  117. char *arg1, *arg2, *arg3, *arg4;
  118. {
  119. X    char buf[BUFSIZ];
  120. X
  121. X    (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4);
  122. X    sprintf(buf+strlen(buf), ": %s\n", sys_errlist[errno]);
  123. #ifdef SUNTOOL
  124. X    if (istool > 1)
  125. X    ok_box(buf);
  126. X    else
  127. #endif /* SUNTOOL */
  128. X    print(buf);
  129. }
  130. X
  131. #if defined(SUNTOOL) || defined(CURSES)
  132. /*
  133. X * print just like printf -- to a window, to curses, or to stdout.  Use vprintf
  134. X * if available.  msgbuf is the buffer used to print into if necessary.
  135. X * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
  136. X * (where indicated) otherwise, msgbuf is not typecast at all.
  137. X */
  138. /*VARARGS*/
  139. void
  140. print(va_alist)
  141. va_dcl
  142. {
  143. X    static char msgbuf[BUFSIZ];
  144. X    char *fmt;
  145. X    va_list args;
  146. #ifndef VPRINTF
  147. X    FILE foo;
  148. #endif /* VPRINTF */
  149. X    static int x; /* position on line saved for continued prints */
  150. X    char *p; /* same type as struct file _ptr,_buf in stdio.h */
  151. X
  152. #ifdef CURSES
  153. X    if (iscurses) {
  154. X    if (isoff(glob_flags, CONT_PRNT))
  155. X        move(LINES-1, x = 0), refresh();
  156. X    } else
  157. #endif /* CURSES */
  158. X    if (istool < 2) {
  159. X        va_start(args);
  160. X        fmt = va_arg(args, char *);
  161. #ifdef VPRINTF
  162. X        (void) vprintf(fmt, args);
  163. #else /* VPRINTF */
  164. X        _doprnt(fmt, args, stdout);
  165. #endif /* VPRINTF */
  166. X        va_end(args);
  167. X        (void) fflush(stdout);
  168. X        return;
  169. X    }
  170. X    va_start(args);
  171. X    fmt = va_arg(args, char *);
  172. X    if (fmt) {
  173. #ifdef VPRINTF
  174. X    (void) vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
  175. #else /* VPRINTF */
  176. X    foo._cnt = BUFSIZ;
  177. X    foo._base = foo._ptr = msgbuf; /* may have to cast(unsigned char *) */
  178. X    foo._flag = _IOWRT+_IOSTRG;
  179. X    (void) _doprnt(fmt, args, &foo);
  180. X    *foo._ptr = '\0'; /* plant terminating null character */
  181. #endif /* VPRINTF */
  182. X    }
  183. X    va_end(args);
  184. X    if (istool) {
  185. X    wprint("%s", msgbuf);
  186. X    return;
  187. X    }
  188. X    p = msgbuf;
  189. X    if (iscurses)
  190. X    while (p = index(p, '\n'))
  191. X        *p = ' ';
  192. #ifdef CURSES
  193. X    if (iscurses) {
  194. X    p = msgbuf;
  195. X    for (;;) {
  196. X        int len = COLS-1-x; /* space remaining at till the eol */
  197. X        /* don't wrap the line! Just print it and refresh() */
  198. X        printw("%-.*s", len, p), clrtoeol(), refresh();
  199. X        /* if length(p) (remainder of msgbuf) doesn't wrap, break loop */
  200. X        if ((x += strlen(p)) < COLS-1)
  201. X        break;
  202. X        /* the next print will overwrite bottom line, so \n first */
  203. X        putchar('\n'), move(LINES-1, x = 0); /* reset x */
  204. X        /* move p forward the number of chars we were able to display */
  205. X        p += len;
  206. X        turnon(glob_flags, CNTD_CMD); /* display ...continue... prompt */
  207. X    }
  208. X    turnoff(glob_flags, CONT_PRNT);
  209. X    (void) fflush(stdout); /* some sys-v's aren't fflushing \n's */
  210. X    return;
  211. X    }
  212. #endif /* CURSES */
  213. }
  214. X
  215. #endif /* SUNTOOL || CURSES */
  216. X
  217. /* for curses mode */
  218. clr_bot_line()
  219. {
  220. X    print("");
  221. }
  222. X
  223. #ifdef SUNTOOL
  224. X
  225. /*
  226. X * wprint prints stuff to a scrollable textsw.  This is intended for
  227. X * print statements that need to be recalled since print() overwrites
  228. X * its last message.
  229. X * For non-suntool mode, wprint() is just like printf().  For curses mode,
  230. X * wprint() does -not- act like print() -- lines length is not counted
  231. X * and newlines are not stripped.
  232. X */
  233. /*VARARGS*/
  234. void
  235. wprint(va_alist)
  236. va_dcl
  237. {
  238. #ifndef VPRINTF
  239. X    FILE foo;
  240. #endif /* VPRINTF */
  241. X    char msgbuf[BUFSIZ]; /* we're not getting huge strings */
  242. X    char *fmt;
  243. X    va_list args;
  244. X
  245. X    if (istool < 2) {
  246. X    va_start(args);
  247. X    fmt = va_arg(args, char *);
  248. #ifdef VPRINTF
  249. X    (void) vprintf(fmt, args);
  250. #else /* VPRINTF */
  251. X    _doprnt(fmt, args, stdout);
  252. #endif /* VPRINTF */
  253. X    va_end(args);
  254. X    (void) fflush(stdout);
  255. X    return;
  256. X    }
  257. X
  258. X    if (!mfprint_sw)
  259. X        return;
  260. X    va_start(args);
  261. X    fmt = va_arg(args, char *);
  262. X    if (fmt) {
  263. #ifdef VPRINTF
  264. X    (void) vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
  265. #else /* VPRINTF */
  266. X    foo._cnt = BUFSIZ;
  267. X    foo._base = foo._ptr = msgbuf; /* may have to cast (unsigned char *) */
  268. X    foo._flag = _IOWRT+_IOSTRG;
  269. X    _doprnt(fmt, args, &foo); /* format like printf into msgbuf via foo */
  270. X    *foo._ptr = '\0'; /* plant terminating null character */
  271. #endif /* VPRINTF */
  272. X    textsw_insert(mfprint_sw, msgbuf, strlen(msgbuf));
  273. X    }
  274. X    va_end(args);
  275. }
  276. X
  277. #include <sundev/kbio.h>
  278. #include <sundev/kbd.h>
  279. X
  280. bell()
  281. {
  282. #ifdef KIOCCMD
  283. X    if (istool) {
  284. X    int kbd = open("/dev/kbd", O_WRONLY, 0);
  285. X    struct timeval timer;
  286. X    timer.tv_sec = 0;
  287. X    timer.tv_usec = 100000;
  288. X    if (kbd != -1) {
  289. X        int cmd = KBD_CMD_BELL;
  290. X        (void) ioctl(kbd, KIOCCMD, &cmd);
  291. X        (void) select(32, (fd_set *) 0,(fd_set *) 0,(fd_set *) 0, &timer);
  292. X        cmd = KBD_CMD_NOBELL;
  293. X        (void) ioctl(kbd, KIOCCMD, &cmd);
  294. X        (void) close(kbd);
  295. X    }
  296. X    } else
  297. #endif /* KIOCCMD */
  298. X    (void) fputc('\007', stderr), (void) fflush(stderr);
  299. X    return 0;
  300. }
  301. X
  302. #endif /* SUNTOOL */
  303. X
  304. #ifdef BSD
  305. #undef fputs
  306. X
  307. /*
  308. X * The standard 4.x BSD fputs() does not return any useful value.
  309. X * For compatibility with Sun and SysV fputs(), we use this wrapper.
  310. X */
  311. X
  312. Fputs(line, fp)
  313. char *line;
  314. FILE *fp;
  315. {
  316. X    clearerr(fp);
  317. X    (void) fputs(line, fp);
  318. X    if (ferror(fp))
  319. X    return EOF;
  320. X    return 0;
  321. }
  322. X
  323. #endif /* BSD */
  324. SHAR_EOF
  325. chmod 0644 print.c ||
  326. echo 'restore of print.c failed'
  327. Wc_c="`wc -c < 'print.c'`"
  328. test 5154 -eq "$Wc_c" ||
  329.     echo 'print.c: original size 5154, current size' "$Wc_c"
  330. rm -f _shar_wnt_.tmp
  331. fi
  332. # ============= sample.mushrc ==============
  333. if test -f 'sample.mushrc' -a X"$1" != X"-c"; then
  334.     echo 'x - skipping sample.mushrc (File already exists)'
  335.     rm -f _shar_wnt_.tmp
  336. else
  337. > _shar_wnt_.tmp
  338. echo 'x - extracting sample.mushrc (Text)'
  339. sed 's/^X//' << 'SHAR_EOF' > 'sample.mushrc' &&
  340. # sample.mushrc
  341. # By Bart Schaefer and Dan Heller
  342. #
  343. # Change mush's temp file directory, to avoid quota collisions.
  344. # /usr/tmp so tmpfiles won't be rm'd before they can be recovered.
  345. set tmpdir=/usr/tmp
  346. X
  347. # Set the folder and mbox locations; the + expands to value of "folder".
  348. set folder=$HOME/Mail mbox=+mbox
  349. X
  350. # Set up the display early to allow quick exit in headers-only mode.
  351. # The hdrs_only flag is true if the command line was: "mush -H".
  352. # The variable hdr_format is set to change the format of the header
  353. # summaries that are displayed.
  354. if hdrs_only
  355. X    set hdr_format='%28a %M %-2N  %.33s'
  356. X    exit    # Quits reading this file
  357. else
  358. X    set hdr_format='%28a %M %-2N (%3.5l li) %.25s'
  359. endif
  360. X
  361. # Set the prompt to show current time, name of the current folder,
  362. # current message number, and count of total messages.
  363. set prompt="(%T) %f: #%m of %t> "
  364. X
  365. # Hitting <CR> should do nothing (helps make mush more shell-like).  If
  366. # newline is not set, hitting <CR> prints the next message (like Mail).
  367. # This variable could be set to any mush command.
  368. set newline
  369. X
  370. # These variables are helpful for new users:
  371. #    ask        -- always prompt for Subject: of mail
  372. #    ignoreeof    -- ignore end-of-file from keyboard
  373. #    verify        -- query that all is well before sending mail
  374. #    warning        -- report miscellaneous possible problems
  375. set ask verify warning
  376. set ignoreeof="echo 'Use "'"'quit'"'" to quit.'"
  377. X
  378. # When reading messages, don't bother looking at lengthy, boring headers.
  379. ignore message-id received via status
  380. X
  381. # Since mush has csh-like history, you might find it annoying to type
  382. # things like "mail host\!host1\!host2\!user" from within the mush shell.
  383. # Setting nonobang will prevent the "unknown event" and allow the !'s to
  384. # be typed without having to be preceded by backslashes.
  385. set nonobang
  386. X
  387. # By default, mush's history is set to the last command only.  Set it to
  388. # remember the last 100 commands.
  389. set history = 100
  390. X
  391. # If the variable "unix" is set, then any command that isn't a mush command
  392. # will execute the command as if you typed it from the shell.  Note, such
  393. # commands will not go through another shell -- this is it.
  394. set unix
  395. X
  396. # Mush tries to read ~/.mushrc first, then it tries ~/.mailrc.  Assuming
  397. # you use *this* file as your .mushrc, source the contents of .mailrc as
  398. # well in case there are Mail aliases that are set there.
  399. source $HOME/.mailrc
  400. X
  401. # Use a real pager.
  402. set pager=less
  403. X
  404. # When typing in a letter, it is sometimes convenient to have lines wrap
  405. # automatically similar to editors like vi and emacs.  In this example, if
  406. # the user types past column 74, a newline will automatically be inserted.
  407. set wrapcolumn=74
  408. X
  409. # If "autosign" is set, then a file can be read in automatically whenever
  410. # mail is sent.  This file is normally your "signature," that is, your
  411. # name and other information you want included in every message.
  412. set autosign = ~/.signature
  413. X
  414. # When you use the -i option to reply, or use the ~i tilde escape in a letter
  415. # when in compose mode, the current message will be included in your text.
  416. # Put a nice wrapper around those included messages.  Here, show the author's
  417. # name and the subject of his letter, label the end, and add a trailing blank
  418. # to separate each inclusion and make finding the end easier.
  419. set pre_indent_str='On %M %N, %T, %.50n wrote:\n} Subject: %.65s'
  420. set indent_str='} '    # actual message text is preceded by a "}"
  421. set post_indent_str='}-- End of excerpt from %.50n\n'
  422. X
  423. # Label replies with a header showing the who, what, and when of the
  424. # message being replied-to.
  425. set in_reply_to='%f\n\t"%s" (%d)'
  426. X
  427. # Mail routing and address-fixing conveniences.  If auto_route is set, then
  428. # replies to messages take a closer look at the addresses of the recipients.
  429. # If any redundant paths are present, they are pruned.  Also, the path that
  430. # precedes any hosts listed in the "known_hosts" list is truncated.  This is
  431. # useful for uucp sites only, and is therefore commented out in this sample.
  432. # set auto_route known_hosts="sun ucbcad well unicom"
  433. X
  434. # The "alts" command specifies alternate addresses that I have.  Here,
  435. # "*" expands to any "path" whose recipient ends with the user's current
  436. # login name.  If another login name is desired, the login and/or path
  437. # to that login must be preceded by a !.  Otherwise, standard paths are used.
  438. alts "*"
  439. X
  440. # The "map" command can rebind certain key sequences in tty-mode only.
  441. # Here, if the user types two R's in a row at the prompt, then the string
  442. # "reply -ei " will be echoed as if the user typed it.
  443. map RR "reply -ei "
  444. # "rr" will do a reply and do the newline for you so you don't have to.
  445. map rr "reply\n"
  446. X
  447. # The "map!" command is similar to "map" in that you can do keyboard
  448. # acceleration, but map! occurs during letter composition mode only.
  449. map! '\CT' '    '    # ^T generates 4 spaces in composition mode.
  450. # Here, hitting * twice will append a pre-signature.
  451. map! ** "\n            Later,\n"
  452. X
  453. # Be careful with map and map! -- you can cause an infinite loop.
  454. # Your interrupt key (usually ^C) will stop such loops.
  455. X
  456. # The curses mode allows the screen to be set up like a full screen editor.
  457. # There are basic "curses commands" which are bound to keyboard key-sequences
  458. # (usually one character).  The user can rebind these keys to suit his tastes.
  459. # Note that the binding for R below removes the binding of reply-all.
  460. #
  461. set curses_help        # Unset this to remove help message in curses.
  462. bind \n display        # Hit return to display the next message.
  463. bind t top        # Make it easier to see the top few lines.
  464. bind e macro "[line-mode]edit\n"    # Quick edit from curses.
  465. bind P macro "[line-mode]Print\n"    # Show me all the headers.
  466. bind R macro "[line-mode]reply -ei "    # Reply with inclusion and edit.
  467. bind A macro "R[getline]~t\n\CUargv\n"    # R to Dan w/auto address fix.
  468. X
  469. # "cmd" is used to set command line aliases similar to the way "csh"
  470. # does it.  The only difference is that "alias" is a reserved word in
  471. # Mush and Mail, so cmd is used.
  472. #
  473. cmd dq 'd \!*; q'        # Delete a message list, then quit.
  474. cmd unread 'flags \!* U O'    # Mark messages unread.
  475. cmd : curses            # Colon now "toggles" curses mode.
  476. X
  477. # Find messages from mailer-daemon (ignore upper/lower case).
  478. cmd md 'pick -i -f mailer-daemon'
  479. # Because mush can pipe commands to one another, including "cmd"'s, this
  480. # example will delete all messages from mailer-daemon
  481. cmd dmd 'md | delete'
  482. X
  483. # aliases -- just like Mail's, but you can specify "names"
  484. alias argv Dan Heller <argv@sun.com>
  485. alias bart Bart Schaefer <schaefer@cse.ogi.edu>
  486. alias mush-users Mush Users <mush-users-request@apple.com>
  487. SHAR_EOF
  488. chmod 0644 sample.mushrc ||
  489. echo 'restore of sample.mushrc failed'
  490. Wc_c="`wc -c < 'sample.mushrc'`"
  491. test 6535 -eq "$Wc_c" ||
  492.     echo 'sample.mushrc: original size 6535, current size' "$Wc_c"
  493. rm -f _shar_wnt_.tmp
  494. fi
  495. # ============= setopts.c ==============
  496. if test -f 'setopts.c' -a X"$1" != X"-c"; then
  497.     echo 'x - skipping setopts.c (File already exists)'
  498.     rm -f _shar_wnt_.tmp
  499. else
  500. > _shar_wnt_.tmp
  501. echo 'x - extracting setopts.c (Text)'
  502. sed 's/^X//' << 'SHAR_EOF' > 'setopts.c' &&
  503. /* setopts.c    (c) copyright 1986 (Dan Heller) */
  504. X
  505. #include "mush.h"
  506. #include "bindings.h"
  507. X
  508. static void
  509. insert_option(list, opt, order)
  510. struct options **list, *opt;
  511. int order;    /* Insert in sorted order? */
  512. {
  513. X    while (*list && (!order || (strcmp((*list)->option, opt->option) < 1)))
  514. X    list = &((*list)->next);
  515. X    opt->next = *list;
  516. X    *list = opt;
  517. }
  518. X
  519. /* add an option indicated by "set option[=value]" or by "alias name alias"
  520. X * function is recursive, so multilists get appended accordingly
  521. X */
  522. add_option(list, argv)
  523. register struct options **list;
  524. register char **argv;
  525. {
  526. X    register struct options *tmp;
  527. X    register char *option, *value = NULL;
  528. X
  529. X    if (!(option = *argv))
  530. X    return 1;
  531. X    /* check for one of three forms:
  532. X     * option=value  option= value  option = value
  533. X     */
  534. X    if (value = index(option, '=')) {
  535. X    if (value == option) {
  536. X        print("No variable specified\n");
  537. X        return 0;
  538. X    }
  539. X    /* "option=value" strip into option="option" value="value" */
  540. X    *value++ = 0; /* option is now a null terminated `option' */
  541. X    if (*value || (value = *++argv)) { /* "option= value" */
  542. X        ++argv;
  543. X    }
  544. X    } else if (*++argv && !strcmp(*argv, "=")) {
  545. X    if (value = *++argv) /* "option = value" */
  546. X        ++argv;
  547. X    }
  548. X
  549. X    /* check for internal vars that can't be set this way */
  550. X    if (*list == set_options && check_internal(option)) {
  551. X    print("You can't change %s with \"set\".\n", option);
  552. X    return 0;
  553. X    }
  554. X
  555. X    /* check to see if option is already set by attempting to unset it */
  556. X    if (un_set(list, option) == -1)
  557. X    return 0;
  558. X
  559. X    /* now make a new option struct and set fields */
  560. X    if (!(tmp = (struct options *)calloc((unsigned)1,sizeof(struct options)))) {
  561. X    error("calloc");
  562. X    return -1;
  563. X    }
  564. X    tmp->option = savestr(option);
  565. X    tmp->value = savestr(value); /* strdup handles the NULL case */
  566. X
  567. X    insert_option(list, tmp, (list != &own_hdrs));
  568. X
  569. X    /* check for options which must have values or are used frequently */
  570. X    if (*list == set_options) {
  571. #if defined(CURSES) || defined(SUNTOOL)
  572. X    if (!strcmp(tmp->option, "no_reverse"))
  573. X        turnoff(glob_flags, REV_VIDEO);
  574. X    else
  575. #endif /* CURSES || SUNTOOL */
  576. #ifdef SUNTOOL
  577. X    if (!strcmp(tmp->option, "tool_help"))
  578. X        if (tmp->value && *(tmp->value))
  579. X        strdup(tool_help, tmp->value);
  580. X        else {
  581. X        int n = 0;
  582. X        char *p = getpath(TOOL_HELP, &n);
  583. X        if (n)
  584. X            strdup(tool_help, "tool_help");
  585. X        else
  586. X            strdup(tool_help, p);
  587. X        strdup(tmp->value, tool_help);
  588. X        }
  589. X    else
  590. #endif /* SUNTOOL */
  591. X    if (!strcmp(tmp->option, "cmd_help"))
  592. X        if (tmp->value && *(tmp->value))
  593. X        strdup(cmd_help, tmp->value);
  594. X        else {
  595. X        int n = 0; /* don't ignore no such file or directory */
  596. X        char *p = getpath(COMMAND_HELP, &n);
  597. X        if (n)
  598. X            strdup(cmd_help, "cmd_help");
  599. X        else
  600. X            strdup(cmd_help, p);
  601. X        strdup(tmp->value, cmd_help);
  602. X        }
  603. X    else if (!strcmp(tmp->option, "prompt"))
  604. X        prompt = (tmp->value)? tmp->value : DEF_PROMPT;
  605. X    else if (!strcmp(tmp->option, "warning"))
  606. X        turnon(glob_flags, WARNING);
  607. X    else if (!strcmp(tmp->option, "mil_time"))
  608. X        turnon(glob_flags, MIL_TIME);
  609. #ifndef MSG_SEPARATOR
  610. X    else if (!strcmp(tmp->option, "date_received"))
  611. X        turnon(glob_flags, DATE_RECV);
  612. #endif /* MSG_SEPARATOR */
  613. X    else if (!strcmp(tmp->option, "escape")) {
  614. X        escape = (tmp->value)? tmp->value : DEF_ESCAPE;
  615. X        escape[1] = 0; /* only one character, please */
  616. X    } else if (!strcmp(tmp->option, "hdr_format"))
  617. X        hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
  618. X    else if (!strcmp(tmp->option, "crt")) {
  619. X        if (!istool)
  620. X        crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
  621. X    }
  622. X    else if (!strcmp(tmp->option, "screen")) {
  623. X        screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
  624. #ifdef CURSES
  625. X        if (iscurses && screen > LINES-2)
  626. X        screen = LINES-2;
  627. #endif /* CURSES */
  628. X    } else if (!strcmp(tmp->option, "wrapcolumn")) {
  629. X        char wval[16];
  630. X        wrapcolumn =
  631. X        (tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
  632. #ifdef CURSES
  633. X        /* Use COLS-2 because of silly terminals like vt100 */
  634. X        if (iscurses && wrapcolumn > COLS - 2)
  635. X        wrapcolumn = COLS - 2;
  636. #endif /* CURSES */
  637. X        xfree(tmp->value);
  638. X        tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
  639. X    } else if (!strcmp(tmp->option, "history"))
  640. X        init_history((value && *value)? atoi(value) : 1);
  641. X    else if (!strcmp(tmp->option, "realname")) {
  642. X        char *new[4];
  643. X        new[1] = "NAME";
  644. X        new[2] = tmp->value;
  645. X        new[3] = NULL;
  646. X        (void) Setenv(3, new); /* new[0] is ignored */
  647. X    } else if (!strcmp(tmp->option, "known_hosts")) {
  648. X        register char *p;
  649. X        int n;
  650. X        /* in case user separated with commas */
  651. X        for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  652. X        *p = ' ';
  653. X        free_vec(known_hosts);
  654. X        known_hosts = mk_argv(tmp->value, &n, FALSE);
  655. X    } else if (!strcmp(tmp->option, "hostname")) {
  656. X        register char *p;
  657. X        int n;
  658. X        /* in case user separated with commas */
  659. X        for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  660. X        *p = ' ';
  661. X        free_vec(ourname);
  662. X        ourname = mk_argv(tmp->value, &n, FALSE);
  663. X    } else if (!strcmp(tmp->option, "complete")) {
  664. X        if (value && *value) {
  665. X        m_xlate(value); /* use the original, don't change tmp->value */
  666. X        complete = value[0];
  667. X        complist = value[1];
  668. X        } else {
  669. X        tmp->value = savestr("\\E\\CD");
  670. X        complete = '\033';
  671. X        complist = '\004';
  672. X        }
  673. X    }
  674. X    }
  675. X
  676. X    if (*argv)
  677. X    return add_option(list, argv);
  678. X    return 1;
  679. }
  680. X
  681. /*
  682. X * If str is NULL, just print options and their values. Note that numerical
  683. X * values are not converted to int upon return.  If str is not NULL
  684. X * return the string that matched, else return NULL;
  685. X */
  686. char *
  687. do_set(list, str)
  688. register struct options *list;
  689. register char *str;
  690. {
  691. X    register struct options *opts;
  692. X
  693. X    if (!str)
  694. X    (void) do_pager(NULL, TRUE); /* page using internal pager */
  695. X
  696. X    for (opts = list; opts; opts = opts->next)
  697. X    if (!str) {
  698. X        (void) do_pager(opts->option, FALSE);
  699. X        if (opts->value && *opts->value) {
  700. X        (void) do_pager("     \t", FALSE);
  701. X        (void) do_pager(opts->value, FALSE);
  702. X        }
  703. X        if (do_pager("\n", FALSE) == EOF)
  704. X        break;
  705. X    } else {
  706. X        if (strcmp(str, opts->option))
  707. X        continue;
  708. X        if (opts->value)
  709. X        return opts->value;
  710. X        else
  711. X        return "";
  712. X    }
  713. X
  714. X    if (!str)
  715. X    (void) do_pager(NULL, FALSE); /* terminate internal pager */
  716. X
  717. X    /* if we still haven't matched, check for environment vars */
  718. X    if (str && list == set_options) {
  719. X    register int N, n;
  720. X    for (N = 0; environ[N]; N++) {
  721. X        char *p = index(environ[N], '=');
  722. X        if (p)
  723. X        *p = 0;
  724. X        n = lcase_strncmp(str, environ[N], -1);
  725. X        if (p)
  726. X        *p = '=';
  727. X        if (!n)
  728. X        return p+1;
  729. X    }
  730. X    }
  731. X    return NULL;
  732. }
  733. X
  734. /*
  735. X * unset the variable described by p in the list "list".
  736. X * if the variable isn't set, then return 0, else return 1.
  737. X */
  738. un_set(list, p)
  739. register struct options **list;
  740. register char *p;
  741. {
  742. X    register struct options *opts = *list, *tmp;
  743. X
  744. X    if (!list || !*list || !p || !*p)
  745. X    return 0;
  746. X    if (*list == set_options) {
  747. #if defined(CURSES) || defined(SUNTOOL)
  748. X    if (!strcmp(p, "no_reverse"))
  749. X        turnon(glob_flags, REV_VIDEO);
  750. X    else
  751. #endif /* CURSES || SUNTOOL */
  752. X    if (!strcmp(p, "prompt"))
  753. X        prompt = DEF_PROMPT;
  754. X    else if (!strcmp(p, "warning"))
  755. X        turnoff(glob_flags, WARNING);
  756. X    else if (!strcmp(p, "mil_time"))
  757. X        turnoff(glob_flags, MIL_TIME);
  758. #ifndef MSG_SEPARATOR
  759. X    else if (!strcmp(p, "date_received"))
  760. X        turnoff(glob_flags, DATE_RECV);
  761. #endif /* MSG_SEPARATOR */
  762. X    else if (!strcmp(p, "escape"))
  763. X        escape = DEF_ESCAPE;
  764. X    else if (!strcmp(p, "hdr_format"))
  765. X        hdr_format = DEF_HDR_FMT;
  766. X    else if (!strcmp(p, "crt"))
  767. X        crt = 18;
  768. X    else if (!strcmp(p, "screen")) {
  769. X        screen = 18;
  770. #ifdef CURSES
  771. X        if (iscurses && screen > LINES-2)
  772. X        screen = LINES-2;
  773. #endif /* CURSES */
  774. X    } else
  775. #ifdef SUNTOOL
  776. X    if (!strcmp(p, "tool_help")) {
  777. X        int n = 0;
  778. X        char *p2 = getpath(TOOL_HELP, &n);
  779. X        if (n)
  780. X        strdup(tool_help, "tool_help");
  781. X        else
  782. X        strdup(tool_help, p2);
  783. X    } else
  784. #endif /* SUNTOOL */
  785. X    if (!strcmp(p, "cmd_help")) {
  786. X        int n = 0; /* don't ignore no such file or directory */
  787. X        char *p2 = getpath(COMMAND_HELP, &n);
  788. X        if (n)
  789. X        strdup(cmd_help, "cmd_help");
  790. X        else
  791. X        strdup(cmd_help, p2);
  792. X    } else if (!strcmp(p, "wrapcolumn"))
  793. X        wrapcolumn = 0;
  794. X    else if (!strcmp(p, "history"))
  795. X        init_history(1);
  796. X    else if (!strcmp(p, "known_hosts")) {
  797. X        free_vec(known_hosts);
  798. X        known_hosts = DUBL_NULL;
  799. X    } else if (!strcmp(p, "hostname")) {
  800. X        free_vec(ourname);
  801. X        ourname = DUBL_NULL;
  802. X    } else if (ison(glob_flags, IS_GETTING) && !strcmp(p, "edit_hdrs")) {
  803. X        wprint("You must finish this letter first.\n");
  804. X        return -1;
  805. X    } else if (!strcmp(p, "complete"))
  806. X        complete = complist = 0;
  807. #ifdef SUNTOOL
  808. X    else if (!strcmp(p, "compose_icon")) {
  809. X        if (ison(glob_flags, IS_GETTING)) {
  810. X        wprint("You must finish this letter first.\n");
  811. X        return -1;
  812. X        } else
  813. X        /* destroy compose frame so that it is recreated
  814. X         * later as the proper type (base frame or subframe).
  815. X         */
  816. X        if (compose_frame)
  817. X            destroy_compose();
  818. X    }
  819. #endif
  820. X    }
  821. X
  822. X    if (!strcmp(p, opts->option)) {
  823. X    *list = (*list)->next;
  824. X    xfree (opts->option);
  825. X    if (opts->value)
  826. X        xfree(opts->value);
  827. X    xfree((char *)opts);
  828. X    return 1;
  829. X    }
  830. X    for ( ; opts->next; opts = opts->next)
  831. X    if (!strcmp(p, opts->next->option)) {
  832. X        tmp = opts->next;
  833. X        opts->next = opts->next->next;
  834. X        xfree (tmp->option);
  835. X        if (tmp->value)
  836. X        xfree(tmp->value);
  837. X        xfree ((char *)tmp);
  838. X        return 1;
  839. X    }
  840. X    return 0;
  841. }
  842. X
  843. /* The functions below return 0 since they don't affect
  844. X * messages.
  845. X */
  846. set(n, argv, list)
  847. register int n;
  848. register char **argv;
  849. char *list;
  850. {
  851. X    void list_to_str();
  852. X    char firstchar = **argv;
  853. X    register char *cmd = *argv;
  854. X    register struct options **optlist;
  855. X    char buf[BUFSIZ];
  856. X
  857. X    if (*cmd == 'u')
  858. X    cmd += 2;
  859. X    if (*++argv && !strcmp(*argv, "-?"))
  860. X    return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
  861. X
  862. X    if (*argv && **argv == '?') {
  863. X    int incurses;
  864. X    if (!strcmp(*argv, "?all")) {
  865. X        if (incurses = iscurses) /* assign and compare to TRUE */
  866. X        clr_bot_line(), iscurses = FALSE;
  867. X        (void) do_pager(NULL, TRUE); /* start internal pager */
  868. X        for (n = 0; variable_stuff(n, NULL, buf); n++)
  869. X        if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
  870. X            break;
  871. X        (void) do_pager(NULL, FALSE); /* terminate pager */
  872. X        iscurses = incurses;
  873. X    } else {
  874. X        /* May return null if variable not set. */
  875. X        (void) variable_stuff(0, (*argv)+1, buf);
  876. X        print("%s\n", buf);
  877. X    }
  878. X    return 0;
  879. X    }
  880. X
  881. X    if (firstchar == 'u') {
  882. X    if (!*argv) {
  883. X        print("%s what?\n", cmd);
  884. X        return -1;
  885. X    } else {
  886. X        optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
  887. X        do  if (!strcmp(*argv, "*")) {
  888. X            while (*optlist)
  889. X            (void) un_set(optlist, (*optlist)->option);
  890. #ifdef SUNTOOL
  891. X            if (*cmd != 'i')
  892. X            opts_panel_item(NULL);
  893. #endif /* SUNTOOL */
  894. X        } else if (!un_set(optlist, *argv) &&
  895. X            do_set(set_options, "warning"))
  896. X            print("un%s: %s not set\n",
  897. X            (*cmd == 'i')? "ignore" : "set", *argv);
  898. #ifdef SUNTOOL
  899. X        else if (*cmd != 'i')
  900. X            opts_panel_item(*argv);
  901. #endif /* SUNTOOL */
  902. X        while (*++argv);
  903. #ifdef SUNTOOL
  904. X        if (*cmd == 'i' && istool > 1)
  905. X        update_list_textsw(&ignore_hdr);
  906. #endif /* SUNTOOL */
  907. X    }
  908. X    return 0;
  909. X    }
  910. X
  911. X    if (!*argv) {
  912. X    (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
  913. X    return 0;
  914. X    }
  915. X
  916. X    /*
  917. X     * Check for input redirection.  If so, set the variable to the ascii
  918. X     * value of the current msg_list.
  919. X     */
  920. X    if (ison(glob_flags, IS_PIPE)) {
  921. X    char *newargv[4];
  922. X
  923. X    if (*cmd == 'i') {
  924. X        print("You can't pipe to the \"%s\" command.\n", cmd);
  925. X        return -1;
  926. X    }
  927. X    if (newargv[0] = index(argv[0], '='))
  928. X        *newargv[0] = 0;
  929. X    list_to_str(list, buf);
  930. X    if (!buf[0] && !do_set(set_options, argv[0])) {
  931. X        return 0;
  932. X    }
  933. X    newargv[0] = argv[0];
  934. X    newargv[1] = "=";
  935. X    newargv[2] = buf;
  936. X    newargv[3] = NULL;
  937. X    (void) add_option(&set_options, newargv);
  938. X    return 0;
  939. X    }
  940. X
  941. X    /*
  942. X     * finally, just set the variable the user requested.
  943. X     */
  944. X    (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
  945. #ifdef SUNTOOL
  946. X    if (istool > 1)
  947. X    if (*cmd == 'i')
  948. X        update_list_textsw(&ignore_hdr);
  949. X    else
  950. X        opts_panel_item(argv[0]);
  951. #endif /* SUNTOOL */
  952. X    return 0;
  953. }
  954. X
  955. /*
  956. X *   The alts list is a list of hostnames or pathnames where the user
  957. X * has an account.  If he doesn't specify "metoo", then when replying
  958. X * to mail, if his address is listed, it will be removed.  The syntax
  959. X * is compatible with ucb Mail in that just hostnames can be used.
  960. X * However, there is an added feature that mush provides which another
  961. X * login name or path to another login can be specified by preceding the
  962. X * path or login with a !
  963. X * "argv" may be a file pointer to write the data into by use of save_opts()
  964. X */
  965. alts(argc, argv)
  966. register char **argv;
  967. {
  968. X    char buf[BUFSIZ], *p;
  969. X
  970. X    /* check here first because a 0 argc means to write it to a file */
  971. X    if (argc <= 1) {
  972. X    int n;
  973. X    if (!alternates)
  974. X        return 0;
  975. X    if (argc == 0)
  976. X        (void) fprintf((FILE *)argv, "alts ");
  977. X    for (n = 0; alternates[n]; n++) {
  978. X        p = 0;
  979. X        buf[0] = 0;
  980. X        (void) strcpy(&buf[1], alternates[n]);
  981. X        if (buf[1] != '*')
  982. X        (void) reverse(&buf[1]);
  983. X        if ((p = rindex(&buf[1], '!')) && !lcase_strncmp(p+1, login, -1))
  984. X        *p = 0;
  985. X        else if (buf[1] != '*')
  986. X        buf[0] = '!';
  987. X        if (argc == 0)
  988. X        (void) fprintf((FILE *)argv, "%s ", *buf? buf : &buf[1]);
  989. X        else
  990. X        wprint("%s ", *buf? buf : &buf[1]);
  991. X        if (p)
  992. X        *p = '!';
  993. X    }
  994. X    if (argc == 0)
  995. X        (void) fputc('\n', (FILE *)argv);
  996. X    else
  997. X        wprint("\n");
  998. X    return 0;
  999. X    }
  1000. X
  1001. X    if (argc-- && *++argv && !strcmp(*argv, "-?"))
  1002. X    return help(0, "alts", cmd_help);
  1003. X
  1004. X    free_vec(alternates);
  1005. X    if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
  1006. X    while (argc-- > 0) {
  1007. X        if (argv[argc][0] == '!')
  1008. X        alternates[argc] = savestr(reverse(&argv[argc][1]));
  1009. X        else if (argv[argc][0] == '*') {
  1010. X        alternates[argc] = savestr(argv[argc]);
  1011. X        } else {
  1012. X        if (index(argv[argc], '@'))
  1013. X            bang_form(buf, argv[argc]);
  1014. X        else {
  1015. X            p = buf + Strcpy(buf, argv[argc]);
  1016. X            *p++ = '!', p += Strcpy(p, login);
  1017. X        }
  1018. X        alternates[argc] = savestr(reverse(buf));
  1019. X        }
  1020. X    }
  1021. X    return 0;
  1022. }
  1023. X
  1024. save_opts(cnt, argv)
  1025. char **argv;
  1026. {
  1027. X    char file[MAXPATHLEN], *tmp;
  1028. X    register FILE *fp;
  1029. X
  1030. X    if (cnt && *++argv && !strcmp(*argv, "-?"))
  1031. X    return help(0, "source", cmd_help);
  1032. X    if (cnt && *argv)
  1033. X    (void) strcpy(file, *argv);
  1034. X    else if ((tmp = getenv("MUSHRC")) || (tmp = getenv("MAILRC")))
  1035. X    (void) strcpy(file, tmp);
  1036. X    else {
  1037. X    char *home = do_set(set_options, "home");
  1038. X    if (!home || !*home)
  1039. X        home = ALTERNATE_HOME;
  1040. X    /* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
  1041. X    if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
  1042. X        Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
  1043. X        (void) sprintf(file, "%s/%s", home, MAILRC);
  1044. X    }
  1045. X
  1046. X    cnt = 1;
  1047. X    tmp = getpath(file, &cnt);
  1048. X    if (cnt) {
  1049. X    if (cnt == -1) {
  1050. X        print("%s: %s\n", file, tmp);
  1051. X        return -1;
  1052. X    } else {
  1053. X        print("%s is a directory.\n", tmp);
  1054. X        return -2;
  1055. X    }
  1056. X    }
  1057. X    /* See if the file exists and confirm overwrite */
  1058. X    if (!Access(tmp, F_OK)) {
  1059. X    int overwrite = TRUE;
  1060. X    char buf[BUFSIZ];
  1061. X    if (!istool) {
  1062. X        print("\"%s\" exists. Overwrite? ", trim_filename(tmp));
  1063. X        if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
  1064. X        overwrite = FALSE;
  1065. X    }
  1066. #ifdef SUNTOOL
  1067. X    else {
  1068. X        sprintf(buf, "\"%s\" exists. Overwrite? ", trim_filename(tmp));
  1069. X        overwrite = ask(buf);
  1070. X    }
  1071. #endif /* SUNTOOL */
  1072. X    if (!overwrite) {
  1073. X        print("\"%s\" unchanged.\n", tmp);
  1074. X        return -3;
  1075. X    }
  1076. X    }
  1077. X    if (!(fp = fopen(tmp, "w"))) {
  1078. X    error("Can't open %s", file);
  1079. X    return -1;
  1080. X    }
  1081. X
  1082. X    save_list("basic variable settings", set_options, "set", '=', fp);
  1083. X
  1084. X    save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
  1085. X
  1086. X    save_list("aliases", aliases, "alias", 0, fp);
  1087. X
  1088. X    (void) alts(0, (char **)fp);
  1089. X
  1090. X    save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
  1091. X
  1092. X    save_list("command abbreviations", functions, "cmd", ' ', fp);
  1093. X
  1094. X    save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
  1095. X
  1096. #ifdef CURSES
  1097. X    save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
  1098. #endif /* CURSES */
  1099. X
  1100. X    save_cmd("line mode mappings", line_map, "map", 0, fp);
  1101. X
  1102. X    save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
  1103. X
  1104. X    (void) fclose(fp);
  1105. X    print("All variables and options saved in %s\n", trim_filename(tmp));
  1106. X    return 0;
  1107. }
  1108. X
  1109. save_list(title, list, command, equals, fp)
  1110. struct options *list;
  1111. register char *command, *title, equals;
  1112. register FILE *fp;
  1113. {
  1114. X    register struct options *opts;
  1115. X    register char *p;
  1116. X
  1117. X    if (!list)
  1118. X    return;
  1119. X    (void) fprintf(fp, "#\n# %s\n#\n", title);
  1120. X    for (opts = list; opts; opts = opts->next) {
  1121. X    if (list == set_options && !strcmp(opts->option, "cwd"))
  1122. X        continue; /* don't print $cwd */
  1123. X    (void) fprintf(fp, "%s %s", command, opts->option);
  1124. X    if (opts->value && *opts->value) {
  1125. X        register char *quote;
  1126. X        if (!equals)
  1127. X        quote = NO_STRING;
  1128. X        else if (p = any(opts->value, "\"'"))
  1129. X        if (*p == '\'')
  1130. X            quote = "\"";
  1131. X        else
  1132. X            quote = "'";
  1133. X        else
  1134. X        if (!any(opts->value, " \t;|"))
  1135. X            quote = NO_STRING;
  1136. X        else
  1137. X            quote = "'";
  1138. X        (void) fputc(equals? equals: ' ', fp);
  1139. X        (void) fprintf(fp, "%s%s%s", quote, opts->value, quote);
  1140. X    }
  1141. X    (void) fputc('\n', fp);
  1142. X    }
  1143. }
  1144. X
  1145. extern struct cmd_map map_func_names[];
  1146. X
  1147. save_cmd(title, list, command, equals, fp)
  1148. struct cmd_map *list;
  1149. register char *command, *title;
  1150. register int equals;
  1151. register FILE *fp;
  1152. {
  1153. X    register struct cmd_map *opts;
  1154. X    register char *p;
  1155. X    char buf[MAX_MACRO_LEN * 2];
  1156. X
  1157. X    if (!list)
  1158. X    return;
  1159. X    (void) fprintf(fp, "#\n# %s\n#\n", title);
  1160. X    for (opts = list; opts; opts = opts->m_next) {
  1161. X    register char *quote;
  1162. X    if ((p = any(opts->m_str, "\"'")) && *p == '\'')
  1163. X        quote = "\"";
  1164. X    else
  1165. X        quote = "'";
  1166. X    (void) fprintf(fp, "%s %s%s%s", command, quote,
  1167. X            ctrl_strcpy(buf, opts->m_str, TRUE), quote);
  1168. X    if (equals && map_func_names[opts->m_cmd].m_str)
  1169. X        (void) fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
  1170. X    if (opts->x_str && *opts->x_str) {
  1171. X        if ((p = any(opts->x_str, "\"'")) && *p == '\'')
  1172. X        quote = "\"";
  1173. X        else
  1174. X        quote = "'";
  1175. X        (void) fprintf(fp, " %s%s%s", quote,
  1176. X            ctrl_strcpy(buf, opts->x_str, TRUE), quote);
  1177. X    }
  1178. X    (void) fputc('\n', fp);
  1179. X    }
  1180. }
  1181. X
  1182. /*
  1183. X * do_alias handles aliases, header settings, functions, and fkeys.
  1184. X * since they're all handled in the same manner, the same routine is
  1185. X * used. argv[0] determines which to use.
  1186. X * alias is given here as an example
  1187. X *
  1188. X * alias           identify all aliases
  1189. X * alias name      identify alias
  1190. X * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
  1191. X * unalias arg1 [arg2 arg3 ... ]        unalias args
  1192. X *
  1193. X * same is true for dealing with your own headers.
  1194. X * (also the expand command)
  1195. X */
  1196. do_alias(argc, argv)
  1197. register char **argv;
  1198. {
  1199. X    register char *cmd = *argv, *p;
  1200. X    struct options **list;
  1201. X    char firstchar = *cmd, buf[BUFSIZ];
  1202. X
  1203. X    if (argc == 0)
  1204. X    return 0 - in_pipe();
  1205. X    if (firstchar == 'u')
  1206. X    firstchar = cmd[2];
  1207. X    if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
  1208. X    register char *help_str;
  1209. X    if (firstchar == 'a' || firstchar == 'e')
  1210. X        help_str = "alias";
  1211. X    else if (firstchar == 'c')
  1212. X        help_str = "cmd";
  1213. X    else if (firstchar == 'f')
  1214. X        help_str = "fkey";
  1215. X    else
  1216. X        help_str = "my_hdr";
  1217. X    return help(0, help_str, cmd_help);
  1218. X    }
  1219. X
  1220. X    if (firstchar == 'a')
  1221. X    list = &aliases;
  1222. X    else if (firstchar == 'c')
  1223. X    list = &functions;
  1224. X    else if (firstchar == 'f')
  1225. X    list = &fkeys;
  1226. X    else
  1227. X    list = &own_hdrs;
  1228. X
  1229. X    if (*cmd == 'u') {
  1230. X    if (!*argv) {
  1231. X        print("%s what?\n", cmd);
  1232. X        return -1;
  1233. X    /* unset a list separated by spaces or ',' */
  1234. X    } else while (*argv) {
  1235. X        if (!strcmp(*argv, "*")) /* unset everything */
  1236. X        while (*list)
  1237. X            (void) un_set(list, (*list)->option);
  1238. X        else if (!un_set(list, *argv))
  1239. X        print("\"%s\" isn't set\n", *argv);
  1240. X        argv++;
  1241. X    }
  1242. #ifdef SUNTOOL
  1243. X    if (istool > 1)
  1244. X        update_list_textsw(list);
  1245. #endif /* SUNTOOL */
  1246. X    return 0;
  1247. X    }
  1248. X
  1249. X    if (!*argv && *cmd != 'e') {
  1250. X    /* just type out all the aliases or own_hdrs */
  1251. X    (void) do_set(*list, NULL);
  1252. X    return 0;
  1253. X    }
  1254. X
  1255. X    if (*cmd == 'e') {   /* command was "expand" (aliases only) */
  1256. X    if (!*argv) {
  1257. X        print("expand which alias?\n");
  1258. X        return -1;
  1259. X    } else
  1260. X        do  {
  1261. X        print("%s: ", *argv);
  1262. X        if (p = alias_to_address(*argv))
  1263. X            print("%s\n", p);
  1264. X        } while (*++argv);
  1265. X    return 0;
  1266. X    }
  1267. X
  1268. X    /* at this point, *argv now points to a variable name ...
  1269. X     * check for hdr -- if so, *argv better end with a ':' (check *p)
  1270. X     */
  1271. X    if (list == &own_hdrs && !(p = index(*argv, ':'))) {
  1272. X    print("header labels must end with a ':' (%s)\n", *argv);
  1273. X    return -1;
  1274. X    }
  1275. X    if (!argv[1] && !index(*argv, '='))
  1276. X    if (p = do_set(*list, *argv))
  1277. X        print("%s\n", p);
  1278. X    else
  1279. X        print("%s is not set\n", *argv);
  1280. X    else {
  1281. X    char *tmpargv[2];
  1282. X    (void) argv_to_string(buf, argv);
  1283. X    if ((p = any(buf, " \t=")) && *p != '=')
  1284. X        *p = '=';
  1285. X    /* if we're setting an alias, enforce the insertion of commas
  1286. X     * between each well-formed address.
  1287. X     */
  1288. X    if (list == &aliases)
  1289. X        fix_up_addr(p+1);
  1290. X    tmpargv[0] = buf;
  1291. X    tmpargv[1] = NULL;
  1292. X    (void) add_option(list, tmpargv);
  1293. #ifdef SUNTOOL
  1294. X    if (istool > 1)
  1295. X        update_list_textsw(list);
  1296. #endif /* SUNTOOL */
  1297. X    }
  1298. X    return 0;
  1299. }
  1300. SHAR_EOF
  1301. chmod 0644 setopts.c ||
  1302. echo 'restore of setopts.c failed'
  1303. Wc_c="`wc -c < 'setopts.c'`"
  1304. test 21221 -eq "$Wc_c" ||
  1305.     echo 'setopts.c: original size 21221, current size' "$Wc_c"
  1306. rm -f _shar_wnt_.tmp
  1307. fi
  1308. # ============= signals.c ==============
  1309. if test -f 'signals.c' -a X"$1" != X"-c"; then
  1310.     echo 'x - skipping signals.c (File already exists)'
  1311.     rm -f _shar_wnt_.tmp
  1312. else
  1313. > _shar_wnt_.tmp
  1314. echo 'x - extracting signals.c (Text)'
  1315. sed 's/^X//' << 'SHAR_EOF' > 'signals.c' &&
  1316. /* @(#)signals.c    (c) copyright 10/18/86 (Dan Heller) */
  1317. X
  1318. #include "mush.h"
  1319. X
  1320. #ifdef SUNTOOL
  1321. extern int compose_destroy;
  1322. #endif
  1323. X
  1324. static int was_stopped;
  1325. X
  1326. #ifndef SYSV
  1327. extern char *sys_siglist[];
  1328. #else
  1329. /* sys-v doesn't have normal sys_siglist */
  1330. static char    *sys_siglist[] = {
  1331. /* no error */  "no error",
  1332. /* SIGHUP */    "hangup",
  1333. /* SIGINT */    "interrupt (rubout)",
  1334. /* SIGQUIT */    "quit (ASCII FS)",
  1335. /* SIGILL */    "illegal instruction (not reset when caught)",
  1336. /* SIGTRAP */    "trace trap (not reset when caught)",
  1337. /* SIGIOT */    "IOT instruction",
  1338. /* SIGEMT */    "EMT instruction",
  1339. /* SIGFPE */    "floating point exception",
  1340. /* SIGKILL */    "kill (cannot be caught or ignored)",
  1341. /* SIGBUS */    "bus error",
  1342. /* SIGSEGV */    "segmentation violation",
  1343. /* SIGSYS */    "bad argument to system call",
  1344. /* SIGPIPE */    "write on a pipe with no one to read it",
  1345. /* SIGALRM */    "alarm clock",
  1346. /* SIGTERM */    "software termination signal from kill",
  1347. /* SIGUSR1 */    "user defined signal 1",
  1348. /* SIGUSR2 */    "user defined signal 2",
  1349. /* SIGCLD */    "death of a child",
  1350. /* SIGPWR */    "power-fail restart"
  1351. };
  1352. #endif /* SYSV */
  1353. X
  1354. SIGRET
  1355. intrpt(sig)
  1356. {
  1357. X    if (!was_stopped)
  1358. X    Debug("interrupt() caught: %d\n", sig);
  1359. X    mac_flush();
  1360. X    turnon(glob_flags, WAS_INTR);
  1361. }
  1362. X
  1363. /*
  1364. X * catch signals to reset state of the machine.  Always print signal caught.
  1365. X * If signals are ignored, return.  If we're running the shell, longjmp back.
  1366. X */
  1367. /*ARGSUSED*/
  1368. SIGRET
  1369. catch(sig)
  1370. {
  1371. X    if (!was_stopped)
  1372. X    Debug("Caught signal: %d\n", sig);
  1373. X    (void) signal(sig, catch);
  1374. X    if (ison(glob_flags, IGN_SIGS) && sig != SIGTERM && sig != SIGHUP)
  1375. X    return;
  1376. X    mac_flush();
  1377. X    turnoff(glob_flags, IS_PIPE);
  1378. X    if (istool || sig == SIGTERM || sig == SIGHUP) {
  1379. #ifdef SUNTOOL
  1380. X    if (istool > 1) { /* istool is 2 if tool is complete */
  1381. X        if (compose_destroy) {
  1382. X        if (sig == SIGTERM) /* tty_sw is dying */
  1383. X            return;
  1384. X        if (sig == SIGHUP) { /* compose frame went away */
  1385. X            compose_destroy = 0;
  1386. X            compose_frame = 0;
  1387. X            return;
  1388. X        }
  1389. X        }
  1390. #ifndef SUN_4_0
  1391. X        /* spurious SIGHUPs in 3.5 */
  1392. X        if (sig == SIGHUP && window_get(tool, WIN_SHOW))
  1393. X        return;
  1394. #endif /* SUN_4_0 */
  1395. X        istool = 1;
  1396. X    }
  1397. #endif /* SUNTOOL */
  1398. X    if (!was_stopped)
  1399. X        print("%s: %s\n", prog_name, sys_siglist[sig]);
  1400. X    (void) setjmp(jmpbuf);
  1401. X    if (ison(glob_flags, IS_GETTING))
  1402. X        rm_edfile(-1);
  1403. X    cleanup(sig);
  1404. X    }
  1405. X    if (!was_stopped)
  1406. X    print("%s: %s\n", prog_name, sys_siglist[sig]);
  1407. X    if (ison(glob_flags, DO_SHELL)) {
  1408. X    /* wrapcolumn may have been trashed -- restore it */
  1409. X    if (ison(glob_flags, IS_GETTING)) {
  1410. X        char *fix = do_set(set_options, "wrapcolumn");
  1411. X        if (fix && *fix)
  1412. X        wrapcolumn = atoi(fix);
  1413. X    }
  1414. X    turnoff(glob_flags, IS_GETTING);
  1415. #ifdef SYSV
  1416. X    /* Interrupting "await" leaves an alarm timer running, which
  1417. X     * some SysV systems mishandle.  Clean up.
  1418. X     */
  1419. X    if (!istool)
  1420. X        (void) signal(SIGALRM, SIG_IGN);
  1421. #endif /* SYSV */
  1422. X    longjmp(jmpbuf, 1);
  1423. X    } else {
  1424. X    if (!was_stopped)
  1425. X        puts("exiting");
  1426. X    cleanup(sig);
  1427. X    }
  1428. }
  1429. X
  1430. #ifdef SIGCONT
  1431. #ifdef SIGTTOU
  1432. jmp_buf ttoubuf;
  1433. X
  1434. SIGRET
  1435. tostop(sig)
  1436. {
  1437. X    (void) signal(SIGTTOU, SIG_DFL);
  1438. X    if (was_stopped)
  1439. X    longjmp(ttoubuf, 1);
  1440. }
  1441. #endif /* SIGTTOU */
  1442. X
  1443. SIGRET
  1444. stop_start(sig)
  1445. {
  1446. X    extern FILE *ed_fp;
  1447. X
  1448. X    Debug("Caught signal: %d", sig);
  1449. X    if (sig == SIGCONT) {
  1450. X    (void) signal(SIGTSTP, stop_start);
  1451. X    (void) signal(SIGCONT, stop_start);
  1452. #ifdef SIGTTOU
  1453. X    /* Restoring echo mode may cause a SIGTTOU if mush was killed
  1454. X     * while in the background.  Jump around the echo_off() call if
  1455. X     * we get a TTOU when attempting it.  Leave was_stopped on in
  1456. X     * this case, and don't do all the associated prompting.
  1457. X     */
  1458. X    (void) signal(SIGTTOU, tostop);
  1459. X    if (setjmp(ttoubuf) == 0) {
  1460. X        echo_off();
  1461. X        was_stopped = 0;
  1462. X    }
  1463. #ifdef CURSES
  1464. X    else
  1465. X        iscurses = 0;
  1466. #endif /* CURSES */
  1467. #endif /* SIGTTOU */
  1468. X    if (istool || was_stopped || ison(glob_flags, IGN_SIGS) && !iscurses)
  1469. X        return;
  1470. X    /* we're not in an editor but we're editing a letter */
  1471. X    if (ison(glob_flags, IS_GETTING)) {
  1472. X        if (ed_fp)
  1473. X        print("(Continue editing letter)\n");
  1474. X    }
  1475. #ifdef CURSES
  1476. X    else if (iscurses)
  1477. X        if (ison(glob_flags, IGN_SIGS)) {
  1478. X        clr_bot_line();
  1479. X        if (msg_cnt)
  1480. X            puts(compose_hdr(current_msg));
  1481. X        mail_status(1), addstr("...continue... ");
  1482. X        refresh();
  1483. X        } else {
  1484. X        int curlin = max(1, current_msg - n_array[0] + 1);
  1485. X        redraw();
  1486. X        print("Continue");
  1487. X        move(curlin, 0);
  1488. X        refresh();
  1489. X        /* make sure we lose reverse video on continuation */
  1490. X        if (ison(glob_flags, REV_VIDEO) && msg_cnt) {
  1491. X            char buf[256];
  1492. X            (void) strncpy(buf, compose_hdr(current_msg), COLS-1);
  1493. X            buf[COLS-1] = 0; /* strncpy does not null terminate */
  1494. X            mvaddstr(curlin, 0, buf);
  1495. X        }
  1496. X        }
  1497. #endif /* CURSES */
  1498. X    else
  1499. X        mail_status(1), (void) fflush(stdout);
  1500. X    } else {
  1501. #ifdef CURSES
  1502. X    if (iscurses) {
  1503. X        /* when user stops mush, the current header is not in reverse
  1504. X         * video -- note that a refresh() has not been called in curses.c!
  1505. X         * so, make sure that when a continue is called, the reverse video
  1506. X         * for the current message returns.
  1507. X         */
  1508. X        turnon(glob_flags, WAS_INTR);
  1509. X        if (isoff(glob_flags, IGN_SIGS) && ison(glob_flags, REV_VIDEO) &&
  1510. X            msg_cnt) {
  1511. X        int curlin = max(1, current_msg - n_array[0] + 1);
  1512. X        char buf[256];
  1513. X        scrn_line(curlin, buf);
  1514. X        STANDOUT(curlin, 0, buf);
  1515. X        }
  1516. X        print("Stopping...");
  1517. X    }
  1518. #endif /* CURSES */
  1519. X    echo_on();
  1520. X    (void) signal(SIGTSTP, SIG_DFL);
  1521. X    (void) signal(SIGCONT, stop_start);
  1522. X    was_stopped = 1;
  1523. X    (void) kill(getpid(), sig);
  1524. X    }
  1525. }
  1526. #endif /* SIGCONT */
  1527. X
  1528. /*ARGSUSED*/
  1529. void
  1530. cleanup(sig)
  1531. {
  1532. X    char buf[128], c;
  1533. X
  1534. X    if (sig != SIGTERM && sig != SIGHUP && ison(glob_flags, IGN_SIGS))
  1535. X    c = 'n';
  1536. X    else
  1537. X    c = 'y';
  1538. X
  1539. #ifdef CURSES
  1540. X    if (iscurses && sig != SIGHUP)
  1541. X    iscurses = FALSE, endwin();
  1542. #endif /* CURSES */
  1543. X
  1544. X    if (!was_stopped)
  1545. X    echo_on();
  1546. X
  1547. X    if (ison(glob_flags, IS_GETTING))
  1548. X    turnoff(glob_flags, IS_GETTING), dead_letter(sig);
  1549. X    if ((sig == SIGSEGV || sig == SIGBUS) && isoff(glob_flags, IGN_SIGS)
  1550. X        && *tempfile && !istool) {
  1551. X    (void) fprintf(stderr, "remove %s [y]? ", tempfile), (void) fflush(stderr);
  1552. X    if (fgets(buf, sizeof(buf), stdin))
  1553. X        c = lower(*buf);
  1554. X    }
  1555. X    if (c != 'n' && *tempfile) {
  1556. X    if (sig == SIGHUP && do_set(set_options, "hangup") &&
  1557. X        copyback(NULL, TRUE) && isoff(glob_flags, CORRUPTED))
  1558. X        (void) unlink(tempfile);
  1559. X    else if (unlink(tempfile) && !sig && errno != ENOENT)
  1560. X        error(tempfile);
  1561. X    }
  1562. X    if (sig == SIGSEGV || sig == SIGBUS) {
  1563. X    if (isoff(glob_flags, IGN_SIGS) && !istool) {
  1564. X        (void) fprintf(stderr, "coredump [n]? "), (void) fflush(stderr);
  1565. X        if (fgets(buf, sizeof(buf), stdin))
  1566. X        c = lower(*buf);
  1567. X    }
  1568. X    if (c == 'y') {
  1569. X        if (!istool)
  1570. X        puts("dumping core for debugging");
  1571. X        abort();
  1572. X    }
  1573. X    }
  1574. X    exit(sig);
  1575. }
  1576. X
  1577. long    last_spool_size = -1;    /* declared here cuz it's initialized here */
  1578. X
  1579. #ifdef SUNTOOL
  1580. Notify_value
  1581. do_check()
  1582. {
  1583. X    if (isoff(glob_flags, IGN_SIGS))
  1584. X    (void) check_new_mail();
  1585. X    return (NOTIFY_DONE) ;
  1586. }
  1587. #endif /* SUNTOOL */
  1588. X
  1589. /*
  1590. X * Get any new mail that has arrived.  This function assumes that a
  1591. X * call to mail_size() has already been done, so that last_spool_size
  1592. X * can be compared to spool_size to decide what should be done.
  1593. X *
  1594. X * The value for last_spool_size is updated to the new spool_size only
  1595. X * if update_size is TRUE.  check_new_mail() depends on the -1 initial
  1596. X * value of last_spool_size for correct "New mail" messages, so it
  1597. X * uses FALSE and updates last_spool_size itself.
  1598. X */
  1599. get_new_mail(update_size)
  1600. int update_size;
  1601. {
  1602. X    if (last_spool_size > spool_size && !strcmp(mailfile, spoolfile)) {
  1603. X    print("Someone changed \"%s\"!  ", mailfile);
  1604. X    if (update_size)
  1605. X        return 1;    /* Don't reinit if called from copyback() */
  1606. X    print_more("Reinitializing...\n");
  1607. X    if (isoff(glob_flags, READ_ONLY))
  1608. X        (void) emptyfile(&tmpf, tempfile);
  1609. X    current_msg = msg_cnt = 0;
  1610. X    turnoff(glob_flags, CORRUPTED);
  1611. X    }
  1612. X    if (ison(glob_flags, CORRUPTED))
  1613. X    return 0;
  1614. X    if (load_folder(mailfile, 1, NULL) < 1) {
  1615. X    print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile);
  1616. X    turnon(glob_flags, CORRUPTED);
  1617. X    return update_size;
  1618. X    /* NOTE: The above is used to stop check_new_mail() from calling
  1619. X     * show_new_mail(), while still allowing copyback() to detect the
  1620. X     * possible error and to query about updating the folder.  There
  1621. X     * should be a better-defined way to handle this.
  1622. X     */
  1623. X    }
  1624. X    /* Prevent both bogus "new mail" messages and missed new mail */
  1625. X    last_size = msg[msg_cnt].m_offset;
  1626. X    if (!strcmp(mailfile, spoolfile)) {
  1627. X    spool_size = last_size;
  1628. X    if (last_spool_size != spool_size)
  1629. X        turnon(glob_flags, NEW_MAIL);
  1630. X    } else if (last_spool_size < spool_size)
  1631. X    turnon(glob_flags, NEW_MAIL);
  1632. X    if (msg_cnt && current_msg < 0)
  1633. X    current_msg = 0;
  1634. X    if (last_spool_size != spool_size) {
  1635. X    if (update_size)
  1636. X        last_spool_size = spool_size;
  1637. X    return 1;
  1638. X    }
  1639. X    return 0;
  1640. }
  1641. X
  1642. #ifdef SUNTOOL
  1643. int is_iconic, was_iconic;
  1644. #endif /* SUNTOOL */
  1645. X
  1646. /*
  1647. X * Display a summary when new mail has come in.  sprintf it all into one
  1648. X * buffer and print that instead of separate print statements to allow
  1649. X * the tool mode to make one print statement. The reason for this is that
  1650. X * when the tool is refreshed (caused by a resize, reopen, move, top, etc)
  1651. X * the last thing printed is displayed -- display the entire line.
  1652. X */
  1653. show_new_mail()
  1654. {
  1655. X    char        buf[BUFSIZ];
  1656. X    register char  *p = buf;
  1657. X    int           noisy = !chk_option("quiet", "newmail");
  1658. #ifdef CURSES
  1659. X    int new_hdrs = last_msg_cnt;
  1660. #endif /* CURSES */
  1661. X
  1662. X    if (msg_cnt == last_msg_cnt)
  1663. X    return 1;    /* Nothing to print */
  1664. #ifdef SUNTOOL
  1665. X    if (istool) {
  1666. X    mail_status(0);
  1667. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  1668. X    if (noisy && !chk_option("quiet", "tool"))
  1669. X        bell();
  1670. X    }
  1671. #endif /* SUNTOOL */
  1672. X    if (msg_cnt < last_msg_cnt) {
  1673. X    last_msg_cnt = msg_cnt;
  1674. X    if (!istool)
  1675. X        mail_status(0);
  1676. X    if (iscurses && isoff(glob_flags, CNTD_CMD))
  1677. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1678. X    return 0;
  1679. X    }
  1680. X    if (noisy) {
  1681. X    p += Strcpy(p, "New mail ");
  1682. X    if (msg_cnt - last_msg_cnt <= 1)
  1683. X        p += strlen(sprintf(p, "(#%d) ", msg_cnt));
  1684. X    else
  1685. X        p += strlen(sprintf(p, "(#%d thru #%d)\n", last_msg_cnt+1,msg_cnt));
  1686. X    }
  1687. #ifdef SUNTOOL
  1688. X    /*
  1689. X     * If mush is in tool mode and in icon form, don't update
  1690. X     * last_msg_cnt so that when the tool is opened, print() will
  1691. X     * print the correct number of "new" messages.
  1692. X     */
  1693. X    if (istool && (was_iconic = (int) window_get(tool, FRAME_CLOSED)))
  1694. X    (void) strcpy(p, "\n");
  1695. X    else
  1696. #endif /* SUNTOOL */
  1697. X    {
  1698. X    if (!noisy || iscurses && isoff(glob_flags, CNTD_CMD))
  1699. X        last_msg_cnt = msg_cnt;
  1700. X    else while (last_msg_cnt < msg_cnt) {
  1701. X        char *p2 = compose_hdr(last_msg_cnt++) + 9;
  1702. X        if (strlen(p2) + (p - buf) >= BUFSIZ-5) {
  1703. X        (void) strcpy(p, "...\n");
  1704. X        /* force a break by setting last_msg_cnt correctly */
  1705. X        last_msg_cnt = msg_cnt;
  1706. X        } else
  1707. X        p += strlen(sprintf(p, " %s\n", p2));
  1708. X    }
  1709. X    }
  1710. #ifdef CURSES
  1711. X    if (iscurses && isoff(glob_flags, CNTD_CMD)) {
  1712. X    if (new_hdrs - n_array[screen-1] < screen)
  1713. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1714. X    print("%s ...", buf);
  1715. X    } else
  1716. #endif /* CURSES */
  1717. X    if (noisy)
  1718. X        print("%s", buf); /* buf might have %'s in them!!! */
  1719. X    return 1;
  1720. }
  1721. X
  1722. /*
  1723. X * Look for new mail and read it in if any has arrived.
  1724. X * return 0 if no new mail, 1 if new mail and -1 if new mail is in system
  1725. X * folder, but current mbox is not system mbox.
  1726. X */
  1727. check_new_mail()
  1728. {
  1729. X    int        ret_value;
  1730. X
  1731. X    if (ret_value = mail_size()) {
  1732. #ifdef SUNTOOL
  1733. X    /* if our status has changed from icon to open window, then
  1734. X     * there will already be a message stating number of new
  1735. X     * messages.  reset `n' to msg_cnt so we don't restate
  1736. X     * the same # of new messages upon receipt of yet another new message.
  1737. X     */
  1738. X    if (istool && !(is_iconic = ((int) window_get(tool, FRAME_CLOSED))) &&
  1739. X        was_iconic)
  1740. X        last_msg_cnt = msg_cnt;
  1741. #endif /* SUNTOOL */
  1742. X    if (get_new_mail(0) && !show_new_mail())
  1743. X        return 0;
  1744. X    } else
  1745. #ifdef SUNTOOL
  1746. X    if (!istool || !is_iconic)
  1747. #endif /* SUNTOOL */
  1748. X        turnoff(glob_flags, NEW_MAIL);
  1749. X    if (last_spool_size > -1 && /* handle first case */
  1750. X        strcmp(mailfile, spoolfile) && last_spool_size < spool_size)
  1751. X    print("You have new mail in your system mailbox.\n"), ret_value = -1;
  1752. X    last_spool_size = spool_size;
  1753. X    return ret_value;
  1754. }
  1755. X
  1756. /*ARGSUSED*/   /* we ignore the sigstack, cpu-usage, etc... */
  1757. SIGRET
  1758. bus_n_seg(sig)
  1759. {
  1760. X    (void) signal(sig, SIG_DFL);
  1761. SHAR_EOF
  1762. true || echo 'restore of signals.c failed'
  1763. fi
  1764. echo 'End of  part 20'
  1765. echo 'File signals.c is continued in part 21'
  1766. echo 21 > _shar_seq_.tmp
  1767. exit 0
  1768. exit 0 # Just in case...
  1769. -- 
  1770. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1771. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1772. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1773. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1774.