diff options
Diffstat (limited to 'lib/libss/listen.c')
-rw-r--r-- | lib/libss/listen.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/libss/listen.c b/lib/libss/listen.c new file mode 100644 index 0000000..8d157b0 --- /dev/null +++ b/lib/libss/listen.c @@ -0,0 +1,151 @@ +/* + * Listener loop for subsystem library libss.a. + * + * Header: /afs/rel-eng.athena.mit.edu/project/release/current/source/athena/athena.lib/ss/RCS/listen.c,v 1.2 90/07/12 12:28:58 epeisach Exp + * $Locker: $ + * + * Copyright 1987, 1988 by MIT Student Information Processing Board + * + * For copyright information, see copyright.h. + */ + +#include "copyright.h" +#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: /afs/rel-eng.athena.mit.edu/project/release/current/source/athena/athena.lib/ss/RCS/listen.c,v 1.2 90/07/12 12:28:58 epeisach Exp "; +#endif + +#ifdef POSIX +#define sigtype void +#else +#define sigtype int +#endif POSIX + +extern char *index(); + +static ss_data *current_info; +static jmp_buf listen_jmpb; + +static sigtype print_prompt() +{ +#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 sigtype listen_int_handler() +{ + putc('\n', stdout); + longjmp(listen_jmpb, 1); +} + +int ss_listen (sci_idx) + int sci_idx; +{ + register char *cp; + register sigtype (*sig_cont)(); + register ss_data *info; + sigtype (*sig_int)(), (*old_sig_cont)(); + char input[BUFSIZ]; + char expanded_input[BUFSIZ]; + char buffer[BUFSIZ]; + char *end = buffer; + int mask; + int code; + jmp_buf old_jmpb; + ss_data *old_info = current_info; + static sigtype print_prompt(); + + current_info = info = ss_info(sci_idx); + sig_cont = (sigtype (*)())0; + info->abort = 0; + mask = sigblock(sigmask(SIGINT)); + bcopy(listen_jmpb, old_jmpb, sizeof(jmp_buf)); + sig_int = signal(SIGINT, listen_int_handler); + setjmp(listen_jmpb); + (void) sigsetmask(mask); + while(!info->abort) { + print_prompt(); + *end = '\0'; + old_sig_cont = sig_cont; + sig_cont = signal(SIGCONT, print_prompt); +#ifdef mips + /* The mips compiler breaks on determining the types, + we help */ + if ( (sigtype *) sig_cont == (sigtype *) print_prompt) +#else + if ( sig_cont == print_prompt) +#endif + sig_cont = old_sig_cont; + if (fgets(input, BUFSIZ, stdin) != input) { + code = SS_ET_EOF; + goto egress; + } + cp = index(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 = index (c, ' '); + if (cp) + *cp = '\0'; + cp = index (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); + bcopy(old_jmpb, listen_jmpb, sizeof(jmp_buf)); + current_info = old_info; + return code; +} + +void ss_abort_subsystem(sci_idx, code) + int sci_idx; +{ + ss_info(sci_idx)->abort = 1; + ss_info(sci_idx)->exit_status = code; + +} + +int ss_quit(argc, argv, sci_idx, infop) + int argc; + char **argv; + int sci_idx; + pointer infop; +{ + ss_abort_subsystem(sci_idx, 0); +} |