home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / signals.c < prev    next >
C/C++ Source or Header  |  1992-10-30  |  13KB  |  468 lines

  1. /* @(#)signals.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. #ifdef SUNTOOL
  6. extern int compose_destroy;
  7. #endif
  8.  
  9. static int was_stopped;
  10.  
  11. #ifndef SYSV
  12. extern char *sys_siglist[];
  13. #else
  14. /* sys-v doesn't have normal sys_siglist */
  15. static char    *sys_siglist[] = {
  16. /* no error */  "no error",
  17. /* SIGHUP */    "hangup",
  18. /* SIGINT */    "interrupt (rubout)",
  19. /* SIGQUIT */    "quit (ASCII FS)",
  20. /* SIGILL */    "illegal instruction (not reset when caught)",
  21. /* SIGTRAP */    "trace trap (not reset when caught)",
  22. /* SIGIOT */    "IOT instruction",
  23. /* SIGEMT */    "EMT instruction",
  24. /* SIGFPE */    "floating point exception",
  25. /* SIGKILL */    "kill (cannot be caught or ignored)",
  26. /* SIGBUS */    "bus error",
  27. /* SIGSEGV */    "segmentation violation",
  28. /* SIGSYS */    "bad argument to system call",
  29. /* SIGPIPE */    "write on a pipe with no one to read it",
  30. /* SIGALRM */    "alarm clock",
  31. /* SIGTERM */    "software termination signal from kill",
  32. /* SIGUSR1 */    "user defined signal 1",
  33. /* SIGUSR2 */    "user defined signal 2",
  34. /* SIGCLD */    "death of a child",
  35. /* SIGPWR */    "power-fail restart"
  36. };
  37. #endif /* SYSV */
  38.  
  39. SIGRET
  40. intrpt(sig)
  41. {
  42.     if (!was_stopped)
  43.     Debug("interrupt() caught: %d\n", sig);
  44.     mac_flush();
  45.     turnon(glob_flags, WAS_INTR);
  46. }
  47.  
  48. /*
  49.  * catch signals to reset state of the machine.  Always print signal caught.
  50.  * If signals are ignored, return.  If we're running the shell, longjmp back.
  51.  */
  52. /*ARGSUSED*/
  53. SIGRET
  54. catch(sig)
  55. {
  56.     if (!was_stopped)
  57.     Debug("Caught signal: %d\n", sig);
  58.     (void) signal(sig, catch);
  59.     if (ison(glob_flags, IGN_SIGS) && sig != SIGTERM && sig != SIGHUP)
  60.     return;
  61.     mac_flush();
  62.     turnoff(glob_flags, IS_PIPE);
  63.     if (istool || sig == SIGTERM || sig == SIGHUP) {
  64. #ifdef SUNTOOL
  65.     if (istool > 1) { /* istool is 2 if tool is complete */
  66.         if (compose_destroy) {
  67.         if (sig == SIGTERM) /* tty_sw is dying */
  68.             return;
  69.         if (sig == SIGHUP) { /* compose frame went away */
  70.             compose_destroy = 0;
  71.             compose_frame = 0;
  72.             return;
  73.         }
  74.         }
  75. #ifndef SUN_4_0
  76.         /* spurious SIGHUPs in 3.5 */
  77.         if (sig == SIGHUP && window_get(tool, WIN_SHOW))
  78.         return;
  79. #endif /* SUN_4_0 */
  80.         istool = 1;
  81.     }
  82. #endif /* SUNTOOL */
  83.     if (!was_stopped)
  84.         print("%s: %s\n", prog_name, sys_siglist[sig]);
  85.     (void) setjmp(jmpbuf);
  86.     if (ison(glob_flags, IS_GETTING))
  87.         rm_edfile(-1);
  88.     cleanup(sig);
  89.     }
  90.     if (!was_stopped)
  91.     print("%s: %s\n", prog_name, sys_siglist[sig]);
  92.     if (ison(glob_flags, DO_SHELL)) {
  93.     /* wrapcolumn may have been trashed -- restore it */
  94.     if (ison(glob_flags, IS_GETTING)) {
  95.         char *fix = do_set(set_options, "wrapcolumn");
  96.         if (fix && *fix)
  97.         wrapcolumn = atoi(fix);
  98.     }
  99.     turnoff(glob_flags, IS_GETTING);
  100. #ifdef SYSV
  101.     /* Interrupting "await" leaves an alarm timer running, which
  102.      * some SysV systems mishandle.  Clean up.
  103.      */
  104.     if (!istool)
  105.         (void) signal(SIGALRM, SIG_IGN);
  106. #endif /* SYSV */
  107.     longjmp(jmpbuf, 1);
  108.     } else {
  109.     if (!was_stopped)
  110.         puts("exiting");
  111.     cleanup(sig);
  112.     }
  113. }
  114.  
  115. #ifdef SIGCONT
  116. #ifdef SIGTTOU
  117. jmp_buf ttoubuf;
  118.  
  119. SIGRET
  120. tostop(sig)
  121. {
  122.     (void) signal(SIGTTOU, SIG_DFL);
  123.     if (was_stopped)
  124.     longjmp(ttoubuf, 1);
  125. }
  126. #endif /* SIGTTOU */
  127.  
  128. SIGRET
  129. stop_start(sig)
  130. {
  131.     extern FILE *ed_fp;
  132.  
  133.     Debug("Caught signal: %d", sig);
  134.     if (sig == SIGCONT) {
  135.     (void) signal(SIGTSTP, stop_start);
  136.     (void) signal(SIGCONT, stop_start);
  137. #ifdef SIGTTOU
  138.     /* Restoring echo mode may cause a SIGTTOU if mush was killed
  139.      * while in the background.  Jump around the echo_off() call if
  140.      * we get a TTOU when attempting it.  Leave was_stopped on in
  141.      * this case, and don't do all the associated prompting.
  142.      */
  143.     (void) signal(SIGTTOU, tostop);
  144.     if (setjmp(ttoubuf) == 0) {
  145.         echo_off();
  146.         was_stopped = 0;
  147.     }
  148. #ifdef CURSES
  149.     else
  150.         iscurses = 0;
  151. #endif /* CURSES */
  152. #endif /* SIGTTOU */
  153.     if (istool || was_stopped || ison(glob_flags, IGN_SIGS) && !iscurses)
  154.         return;
  155.     /* we're not in an editor but we're editing a letter */
  156.     if (ison(glob_flags, IS_GETTING)) {
  157.         if (ed_fp)
  158.         print("(Continue editing letter)\n");
  159.     }
  160. #ifdef CURSES
  161.     else if (iscurses)
  162.         if (ison(glob_flags, IGN_SIGS)) {
  163.         clr_bot_line();
  164.         if (msg_cnt)
  165.             puts(compose_hdr(current_msg));
  166.         mail_status(1), addstr("...continue... ");
  167.         refresh();
  168.         } else {
  169.         int curlin = max(1, current_msg - n_array[0] + 1);
  170.         redraw();
  171.         print("Continue");
  172.         move(curlin, 0);
  173.         refresh();
  174.         /* make sure we lose reverse video on continuation */
  175.         if (ison(glob_flags, REV_VIDEO) && msg_cnt) {
  176.             char buf[256];
  177.             (void) strncpy(buf, compose_hdr(current_msg), COLS-1);
  178.             buf[COLS-1] = 0; /* strncpy does not null terminate */
  179.             mvaddstr(curlin, 0, buf);
  180.         }
  181.         }
  182. #endif /* CURSES */
  183.     else
  184.         mail_status(1), (void) fflush(stdout);
  185.     } else {
  186. #ifdef CURSES
  187.     if (iscurses) {
  188.         /* when user stops mush, the current header is not in reverse
  189.          * video -- note that a refresh() has not been called in curses.c!
  190.          * so, make sure that when a continue is called, the reverse video
  191.          * for the current message returns.
  192.          */
  193.         turnon(glob_flags, WAS_INTR);
  194.         if (isoff(glob_flags, IGN_SIGS) && ison(glob_flags, REV_VIDEO) &&
  195.             msg_cnt) {
  196.         int curlin = max(1, current_msg - n_array[0] + 1);
  197.         char buf[256];
  198.         scrn_line(curlin, buf);
  199.         STANDOUT(curlin, 0, buf);
  200.         }
  201.         print("Stopping...");
  202.     }
  203. #endif /* CURSES */
  204.     echo_on();
  205.     (void) signal(SIGTSTP, SIG_DFL);
  206.     (void) signal(SIGCONT, stop_start);
  207.     was_stopped = 1;
  208.     (void) kill(getpid(), sig);
  209.     }
  210. }
  211. #endif /* SIGCONT */
  212.  
  213. /*ARGSUSED*/
  214. void
  215. cleanup(sig)
  216. {
  217.     char buf[128], c;
  218.  
  219.     if (sig != SIGTERM && sig != SIGHUP && ison(glob_flags, IGN_SIGS))
  220.     c = 'n';
  221.     else
  222.     c = 'y';
  223.  
  224. #ifdef CURSES
  225.     if (iscurses && sig != SIGHUP)
  226.     iscurses = FALSE, endwin();
  227. #endif /* CURSES */
  228.  
  229.     if (!was_stopped)
  230.     echo_on();
  231.  
  232.     if (ison(glob_flags, IS_GETTING))
  233.     turnoff(glob_flags, IS_GETTING), dead_letter(sig);
  234.     droplocks();
  235.     if ((sig == SIGSEGV || sig == SIGBUS) && isoff(glob_flags, IGN_SIGS)
  236.         && *tempfile && !istool) {
  237.     (void) fprintf(stderr, "remove %s [y]? ", tempfile), (void) fflush(stderr);
  238.     if (fgets(buf, sizeof(buf), stdin))
  239.         c = lower(*buf);
  240.     }
  241.     if (c != 'n' && *tempfile) {
  242.     if (sig == SIGHUP && do_set(set_options, "hangup") &&
  243.         copyback(NULL, TRUE) && isoff(glob_flags, CORRUPTED))
  244.         (void) unlink(tempfile);
  245.     else if (unlink(tempfile) && !sig && errno != ENOENT)
  246.         error(tempfile);
  247.     }
  248.     if (sig == SIGSEGV || sig == SIGBUS) {
  249.     if (isoff(glob_flags, IGN_SIGS) && !istool) {
  250.         (void) fprintf(stderr, "coredump [n]? "), (void) fflush(stderr);
  251.         if (fgets(buf, sizeof(buf), stdin))
  252.         c = lower(*buf);
  253.     }
  254.     if (c == 'y') {
  255.         if (!istool)
  256.         puts("dumping core for debugging");
  257.         abort();
  258.     }
  259.     }
  260. #ifdef CSH_FILEC_FIX
  261.     if (isoff(glob_flags, ECHO_FLAG) && isoff(glob_flags, REDIRECT)) {
  262.     c = 0;
  263.     (void)ioctl(0, TIOCFLUSH, &c);
  264.     }
  265. #endif /* CSH_FILEC_FIX */
  266.     exit(sig);
  267. }
  268.  
  269. long    last_spool_size = -1;    /* declared here cuz it's initialized here */
  270.  
  271. #ifdef SUNTOOL
  272. Notify_value
  273. do_check()
  274. {
  275.     if (isoff(glob_flags, IGN_SIGS))
  276.     (void) check_new_mail();
  277.     return (NOTIFY_DONE) ;
  278. }
  279. #endif /* SUNTOOL */
  280.  
  281. /*
  282.  * Get any new mail that has arrived.  This function assumes that a
  283.  * call to mail_size() has already been done, so that last_spool_size
  284.  * can be compared to spool_size to decide what should be done.
  285.  *
  286.  * The value for last_spool_size is updated to the new spool_size only
  287.  * if update_size is TRUE.  check_new_mail() depends on the -1 initial
  288.  * value of last_spool_size for correct "New mail" messages, so it
  289.  * uses FALSE and updates last_spool_size itself.
  290.  */
  291. get_new_mail(update_size)
  292. int update_size;
  293. {
  294.     if (last_spool_size > spool_size && !strcmp(mailfile, spoolfile)) {
  295.     print("Someone changed \"%s\"!  ", mailfile);
  296.     if (update_size)
  297.         return 1;    /* Don't reinit if called from copyback() */
  298.     print_more("Reinitializing...\n");
  299.     if (isoff(glob_flags, READ_ONLY))
  300.         (void) emptyfile(&tmpf, tempfile);
  301.     current_msg = msg_cnt = 0;
  302.     turnoff(glob_flags, CORRUPTED);
  303.     }
  304.     if (ison(glob_flags, CORRUPTED))
  305.     return 0;
  306.     if (load_folder(mailfile, 1, NULL) < 1) {
  307.     print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile);
  308.     turnon(glob_flags, CORRUPTED);
  309.     return update_size;
  310.     /* NOTE: The above is used to stop check_new_mail() from calling
  311.      * show_new_mail(), while still allowing copyback() to detect the
  312.      * possible error and to query about updating the folder.  There
  313.      * should be a better-defined way to handle this.
  314.      */
  315.     }
  316.     /* Prevent both bogus "new mail" messages and missed new mail */
  317.     last_size = msg[msg_cnt].m_offset;
  318.     if (!strcmp(mailfile, spoolfile)) {
  319.     spool_size = last_size;
  320.     if (last_spool_size != spool_size)
  321.         turnon(glob_flags, NEW_MAIL);
  322.     } else if (last_spool_size < spool_size)
  323.     turnon(glob_flags, NEW_MAIL);
  324.     if (msg_cnt && current_msg < 0)
  325.     current_msg = 0;
  326.     if (last_spool_size != spool_size) {
  327.     if (update_size)
  328.         last_spool_size = spool_size;
  329.     return 1;
  330.     }
  331.     return 0;
  332. }
  333.  
  334. #ifdef SUNTOOL
  335. int is_iconic, was_iconic;
  336. #endif /* SUNTOOL */
  337.  
  338. /*
  339.  * Display a summary when new mail has come in.  sprintf it all into one
  340.  * buffer and print that instead of separate print statements to allow
  341.  * the tool mode to make one print statement. The reason for this is that
  342.  * when the tool is refreshed (caused by a resize, reopen, move, top, etc)
  343.  * the last thing printed is displayed -- display the entire line.
  344.  */
  345. show_new_mail()
  346. {
  347.     char        buf[BUFSIZ];
  348.     register char  *p = buf;
  349.     int           noisy = !chk_option("quiet", "newmail");
  350. #ifdef CURSES
  351.     int new_hdrs = last_msg_cnt;
  352. #endif /* CURSES */
  353.  
  354.     if (msg_cnt == last_msg_cnt)
  355.     return 1;    /* Nothing to print */
  356. #ifdef SUNTOOL
  357.     if (istool) {
  358.     mail_status(0);
  359.     (void) do_hdrs(0, DUBL_NULL, NULL);
  360.     if (noisy && !chk_option("quiet", "tool"))
  361.         bell();
  362.     }
  363. #endif /* SUNTOOL */
  364.     if (msg_cnt < last_msg_cnt) {
  365.     last_msg_cnt = msg_cnt;
  366.     if (!istool)
  367.         mail_status(0);
  368.     if (iscurses && isoff(glob_flags, CNTD_CMD))
  369.         (void) do_hdrs(0, DUBL_NULL, NULL);
  370.     return 0;
  371.     }
  372.     if (noisy) {
  373.     p += Strcpy(p, "New mail ");
  374.     if (msg_cnt - last_msg_cnt <= 1)
  375.         p += strlen(sprintf(p, "(#%d) ", msg_cnt));
  376.     else
  377.         p += strlen(sprintf(p, "(#%d thru #%d)\n", last_msg_cnt+1,msg_cnt));
  378.     }
  379. #ifdef SUNTOOL
  380.     /*
  381.      * If mush is in tool mode and in icon form, don't update
  382.      * last_msg_cnt so that when the tool is opened, print() will
  383.      * print the correct number of "new" messages.
  384.      */
  385.     if (istool && (was_iconic = (int) window_get(tool, FRAME_CLOSED)))
  386.     (void) strcpy(p, "\n");
  387.     else
  388. #endif /* SUNTOOL */
  389.     {
  390.     if (!noisy || iscurses && isoff(glob_flags, CNTD_CMD))
  391.         last_msg_cnt = msg_cnt;
  392.     else while (last_msg_cnt < msg_cnt) {
  393.         char *p2 = compose_hdr(last_msg_cnt++) + 9;
  394.         if (strlen(p2) + (p - buf) >= BUFSIZ-5) {
  395.         (void) strcpy(p, "...\n");
  396.         /* force a break by setting last_msg_cnt correctly */
  397.         last_msg_cnt = msg_cnt;
  398.         } else
  399.         p += strlen(sprintf(p, " %s\n", p2));
  400.     }
  401.     }
  402. #ifdef CURSES
  403.     if (iscurses && isoff(glob_flags, CNTD_CMD)) {
  404.     if (new_hdrs - n_array[screen-1] < screen)
  405.         (void) do_hdrs(0, DUBL_NULL, NULL);
  406.     print("%s ...", buf);
  407.     } else
  408. #endif /* CURSES */
  409.     if (noisy)
  410.         print("%s", buf); /* buf might have %'s in them!!! */
  411.     return 1;
  412. }
  413.  
  414. /*
  415.  * Look for new mail and read it in if any has arrived.
  416.  * return 0 if no new mail, 1 if new mail and -1 if new mail is in system
  417.  * folder, but current mbox is not system mbox.
  418.  */
  419. check_new_mail()
  420. {
  421.     int ret_value;
  422. #ifdef POP3_SUPPORT
  423.     static long last_check = -1;  /* We checked at startup */
  424.  
  425.     if (last_check < 0)
  426.     last_check = time((long *)0);
  427.     
  428.     if (istool || time((long *)0) - last_check > time_out) {
  429.     popchkmail();
  430.     last_check = time((long *)0);
  431.     }
  432. #endif /* POP3_SUPPORT */
  433.  
  434.     if (ret_value = mail_size()) {
  435. #ifdef SUNTOOL
  436.     /* if our status has changed from icon to open window, then
  437.      * there will already be a message stating number of new
  438.      * messages.  reset `n' to msg_cnt so we don't restate
  439.      * the same # of new messages upon receipt of yet another new message.
  440.      */
  441.     if (istool && !(is_iconic = ((int) window_get(tool, FRAME_CLOSED))) &&
  442.         was_iconic)
  443.         last_msg_cnt = msg_cnt;
  444. #endif /* SUNTOOL */
  445.     if (get_new_mail(0) && !show_new_mail())
  446.         return 0;
  447.     } else
  448. #ifdef SUNTOOL
  449.     if (!istool || !is_iconic)
  450. #endif /* SUNTOOL */
  451.         turnoff(glob_flags, NEW_MAIL);
  452.     if (last_spool_size > -1 && /* handle first case */
  453.         strcmp(mailfile, spoolfile) && last_spool_size < spool_size)
  454.     print("You have new mail in your system mailbox.\n"), ret_value = -1;
  455.     last_spool_size = spool_size;
  456.     return ret_value;
  457. }
  458.  
  459. /*ARGSUSED*/   /* we ignore the sigstack, cpu-usage, etc... */
  460. SIGRET
  461. bus_n_seg(sig)
  462. {
  463.     (void) signal(sig, SIG_DFL);
  464.     (void) fprintf(stderr, "%s: %s\n", prog_name,
  465.     (sig == SIGSEGV)? "Segmentation violation": "Bus error");
  466.     cleanup(sig);
  467. }
  468.