Home | History | Annotate | Download | only in ss
      1 /*
      2  * Listener loop for subsystem library libss.a.
      3  *
      4  *	$Header$
      5  *	$Locker$
      6  *
      7  * Copyright 1987, 1988 by MIT Student Information Processing Board
      8  *
      9  * Permission to use, copy, modify, and distribute this software and
     10  * its documentation for any purpose is hereby granted, provided that
     11  * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
     12  * advertising or publicity pertaining to distribution of the software
     13  * without specific, written prior permission.  M.I.T. and the
     14  * M.I.T. S.I.P.B. make no representations about the suitability of
     15  * this software for any purpose.  It is provided "as is" without
     16  * express or implied warranty.
     17  */
     18 
     19 #include "config.h"
     20 #include "ss_internal.h"
     21 #include <stdio.h>
     22 #include <setjmp.h>
     23 #include <signal.h>
     24 #include <sys/param.h>
     25 
     26 typedef void sigret_t;
     27 
     28 static ss_data *current_info;
     29 static jmp_buf listen_jmpb;
     30 static sigret_t (*sig_cont)(int);
     31 
     32 static sigret_t print_prompt(int sig __SS_ATTR((unused)))
     33 {
     34     if (current_info->redisplay)
     35 	    (*current_info->redisplay)();
     36     else {
     37 	    (void) fputs(current_info->prompt, stdout);
     38 	    (void) fflush(stdout);
     39     }
     40 }
     41 
     42 static sigret_t listen_int_handler(int sig __SS_ATTR((unused)))
     43 {
     44     putc('\n', stdout);
     45     signal(SIGINT, listen_int_handler);
     46     longjmp(listen_jmpb, 1);
     47 }
     48 
     49 int ss_listen (int sci_idx)
     50 {
     51     char *cp;
     52     ss_data *info;
     53     sigret_t (*sig_int)(int), (*old_sig_cont)(int);
     54     char input[BUFSIZ];
     55     sigset_t omask, igmask;
     56     int code;
     57     jmp_buf old_jmpb;
     58     ss_data *old_info = current_info;
     59     char *line;
     60 
     61     current_info = info = ss_info(sci_idx);
     62     sig_cont = (sigret_t (*)(int)) 0;
     63     info->abort = 0;
     64     sigemptyset(&igmask);
     65     sigaddset(&igmask, SIGINT);
     66     sigprocmask(SIG_BLOCK, &igmask, &omask);
     67     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
     68     sig_int = signal(SIGINT, listen_int_handler);
     69     setjmp(listen_jmpb);
     70     sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
     71 
     72     while(!info->abort) {
     73 	old_sig_cont = sig_cont;
     74 	sig_cont = signal(SIGCONT, print_prompt);
     75 	if (sig_cont == print_prompt)
     76 	    sig_cont = old_sig_cont;
     77 	if (info->readline) {
     78 		line = (*info->readline)(current_info->prompt);
     79 	} else {
     80 		print_prompt(0);
     81 		if (fgets(input, BUFSIZ, stdin) == input)
     82 			line = input;
     83 		else
     84 			line = NULL;
     85 
     86 		input[BUFSIZ-1] = 0;
     87 	}
     88 	if (line == NULL) {
     89 		code = SS_ET_EOF;
     90 		(void) signal(SIGCONT, sig_cont);
     91 		goto egress;
     92 	}
     93 
     94 	cp = strchr(line, '\n');
     95 	if (cp) {
     96 	    *cp = '\0';
     97 	    if (cp == line)
     98 		continue;
     99 	}
    100 	(void) signal(SIGCONT, sig_cont);
    101 	if (info->add_history)
    102 		(*info->add_history)(line);
    103 
    104 	code = ss_execute_line (sci_idx, line);
    105 	if (code == SS_ET_COMMAND_NOT_FOUND) {
    106 	    register char *c = line;
    107 	    while (*c == ' ' || *c == '\t')
    108 		c++;
    109 	    cp = strchr (c, ' ');
    110 	    if (cp)
    111 		*cp = '\0';
    112 	    cp = strchr (c, '\t');
    113 	    if (cp)
    114 		*cp = '\0';
    115 	    ss_error (sci_idx, 0,
    116 		    "Unknown request \"%s\".  Type \"?\" for a request list.",
    117 		       c);
    118 	}
    119 	if (info->readline)
    120 		free(line);
    121     }
    122     code = 0;
    123 egress:
    124     (void) signal(SIGINT, sig_int);
    125     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
    126     current_info = old_info;
    127     return code;
    128 }
    129 
    130 void ss_abort_subsystem(int sci_idx, int code)
    131 {
    132     ss_info(sci_idx)->abort = 1;
    133     ss_info(sci_idx)->exit_status = code;
    134 
    135 }
    136 
    137 void ss_quit(int argc __SS_ATTR((unused)),
    138 	     const char * const *argv __SS_ATTR((unused)),
    139 	     int sci_idx, pointer infop __SS_ATTR((unused)))
    140 {
    141     ss_abort_subsystem(sci_idx, 0);
    142 }
    143 
    144 #ifdef HAVE_DLOPEN
    145 #define get_request(tbl,idx)    ((tbl) -> requests + (idx))
    146 
    147 static char *cmd_generator(const char *text, int state)
    148 {
    149 	static int	len;
    150 	static ss_request_table **rqtbl;
    151 	static int	curr_rqt;
    152 	static char const * const * name;
    153 	ss_request_entry *request;
    154 	char		*ret;
    155 
    156 	if (state == 0) {
    157 		len = strlen(text);
    158 		rqtbl = current_info->rqt_tables;
    159 		if (!rqtbl || !*rqtbl)
    160 			return 0;
    161 		curr_rqt = 0;
    162 		name = 0;
    163 	}
    164 
    165 	while (1) {
    166 		if (!name || !*name) {
    167 			request = get_request(*rqtbl, curr_rqt++);
    168 			name = request->command_names;
    169 			if (!name) {
    170 				rqtbl++;
    171 				if (*rqtbl) {
    172 					curr_rqt = 0;
    173 					continue;
    174 				} else
    175 					break;
    176 			}
    177 		}
    178 		if (strncmp(*name, text, len) == 0) {
    179 			ret = malloc(strlen(*name)+1);
    180 			if (ret)
    181 				strcpy(ret, *name);
    182 			name++;
    183 			return ret;
    184 		}
    185 		name++;
    186 	}
    187 
    188 	return 0;
    189 }
    190 
    191 char **ss_rl_completion(const char *text, int start,
    192 			int end __SS_ATTR((unused)))
    193 {
    194 	if ((start == 0) && current_info->rl_completion_matches)
    195 		return (*current_info->rl_completion_matches)
    196 			(text, cmd_generator);
    197 	return 0;
    198 }
    199 #endif
    200 
    201