/* * 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 #include #include #include #ifdef BSD #include #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 (*sig_cont)(int); 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), (*old_sig_cont)(int); char input[BUFSIZ]; #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); 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; (void) signal(SIGCONT, sig_cont); goto egress; } input[BUFSIZ-1] = 0; cp = strchr(input, '\n'); if (cp) { *cp = '\0'; if (cp == input) continue; } (void) signal(SIGCONT, sig_cont); 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); }