| /* |
| * Listener loop for subsystem library libss.a. |
| * |
| * $Header$ |
| * $Locker$ |
| * |
| * Copyright 1987, 1988 by MIT Student Information Processing Board |
| * |
| * Permission to use, copy, modify, and distribute this software and |
| * its documentation for any purpose is hereby granted, provided that |
| * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in |
| * advertising or publicity pertaining to distribution of the software |
| * without specific, written prior permission. M.I.T. and the |
| * M.I.T. S.I.P.B. make no representations about the suitability of |
| * this software for any purpose. It is provided "as is" without |
| * express or implied warranty. |
| */ |
| |
| #include "ss_internal.h" |
| #include <stdio.h> |
| #include <setjmp.h> |
| #include <signal.h> |
| #include <sys/param.h> |
| #ifdef BSD |
| #include <sgtty.h> |
| #endif |
| |
| #ifndef lint |
| static char const rcs_id[] = |
| "$Header$"; |
| #endif |
| |
| typedef void sigret_t; |
| |
| static ss_data *current_info; |
| static jmp_buf listen_jmpb; |
| |
| static sigret_t print_prompt(int sig) |
| { |
| #ifdef BSD |
| /* put input into a reasonable mode */ |
| struct sgttyb ttyb; |
| if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) { |
| if (ttyb.sg_flags & (CBREAK|RAW)) { |
| ttyb.sg_flags &= ~(CBREAK|RAW); |
| (void) ioctl(0, TIOCSETP, &ttyb); |
| } |
| } |
| #endif |
| (void) fputs(current_info->prompt, stdout); |
| (void) fflush(stdout); |
| } |
| |
| static sigret_t listen_int_handler(int sig) |
| { |
| putc('\n', stdout); |
| signal(SIGINT, listen_int_handler); |
| longjmp(listen_jmpb, 1); |
| } |
| |
| int ss_listen (int sci_idx) |
| { |
| char *cp; |
| ss_data *info; |
| sigret_t (*sig_int)(int), (*sig_cont)(int), (*old_sig_cont)(int); |
| char input[BUFSIZ]; |
| char buffer[BUFSIZ]; |
| char *end = buffer; |
| #ifdef POSIX_SIGNALS |
| sigset_t omask, igmask; |
| #else |
| int mask; |
| #endif |
| int code; |
| jmp_buf old_jmpb; |
| ss_data *old_info = current_info; |
| |
| current_info = info = ss_info(sci_idx); |
| sig_cont = (sigret_t (*)(int)) 0; |
| info->abort = 0; |
| #ifdef POSIX_SIGNALS |
| sigemptyset(&igmask); |
| sigaddset(&igmask, SIGINT); |
| sigprocmask(SIG_BLOCK, &igmask, &omask); |
| #else |
| mask = sigblock(sigmask(SIGINT)); |
| #endif |
| memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf)); |
| sig_int = signal(SIGINT, listen_int_handler); |
| setjmp(listen_jmpb); |
| #ifdef POSIX_SIGNALS |
| sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); |
| #else |
| (void) sigsetmask(mask); |
| #endif |
| while(!info->abort) { |
| print_prompt(0); |
| *end = '\0'; |
| old_sig_cont = sig_cont; |
| sig_cont = signal(SIGCONT, print_prompt); |
| if (sig_cont == print_prompt) |
| sig_cont = old_sig_cont; |
| if (fgets(input, BUFSIZ, stdin) != input) { |
| code = SS_ET_EOF; |
| goto egress; |
| } |
| cp = strchr(input, '\n'); |
| if (cp) { |
| *cp = '\0'; |
| if (cp == input) |
| continue; |
| } |
| (void) signal(SIGCONT, sig_cont); |
| for (end = input; *end; end++) |
| ; |
| |
| code = ss_execute_line (sci_idx, input); |
| if (code == SS_ET_COMMAND_NOT_FOUND) { |
| register char *c = input; |
| while (*c == ' ' || *c == '\t') |
| c++; |
| cp = strchr (c, ' '); |
| if (cp) |
| *cp = '\0'; |
| cp = strchr (c, '\t'); |
| if (cp) |
| *cp = '\0'; |
| ss_error (sci_idx, 0, |
| "Unknown request \"%s\". Type \"?\" for a request list.", |
| c); |
| } |
| } |
| code = 0; |
| egress: |
| (void) signal(SIGINT, sig_int); |
| memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf)); |
| current_info = old_info; |
| return code; |
| } |
| |
| void ss_abort_subsystem(int sci_idx, int code) |
| { |
| ss_info(sci_idx)->abort = 1; |
| ss_info(sci_idx)->exit_status = code; |
| |
| } |
| |
| void ss_quit(int argc, const char * const *argv, int sci_idx, pointer infop) |
| { |
| ss_abort_subsystem(sci_idx, 0); |
| } |