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 "ss_internal.h"
     20 #include <stdio.h>
     21 #include <setjmp.h>
     22 #include <signal.h>
     23 #include <sys/param.h>
     24 
     25 typedef void sigret_t;
     26 
     27 static ss_data *current_info;
     28 static jmp_buf listen_jmpb;
     29 static sigret_t (*sig_cont)(int);
     30 
     31 static sigret_t print_prompt(int sig __SS_ATTR((unused)))
     32 {
     33     if (current_info->redisplay)
     34 	    (*current_info->redisplay)();
     35     else {
     36 	    (void) fputs(current_info->prompt, stdout);
     37 	    (void) fflush(stdout);
     38     }
     39 }
     40 
     41 static sigret_t listen_int_handler(int sig __SS_ATTR((unused)))
     42 {
     43     putc('\n', stdout);
     44     signal(SIGINT, listen_int_handler);
     45     longjmp(listen_jmpb, 1);
     46 }
     47 
     48 int ss_listen (int sci_idx)
     49 {
     50     char *cp;
     51     ss_data *info;
     52     sigret_t (*sig_int)(int), (*old_sig_cont)(int);
     53     char input[BUFSIZ];
     54     sigset_t omask, igmask;
     55     int code;
     56     jmp_buf old_jmpb;
     57     ss_data *old_info = current_info;
     58     char *line;
     59 
     60     current_info = info = ss_info(sci_idx);
     61     sig_cont = (sigret_t (*)(int)) 0;
     62     info->abort = 0;
     63     sigemptyset(&igmask);
     64     sigaddset(&igmask, SIGINT);
     65     sigprocmask(SIG_BLOCK, &igmask, &omask);
     66     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
     67     sig_int = signal(SIGINT, listen_int_handler);
     68     setjmp(listen_jmpb);
     69     sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
     70 
     71     while(!info->abort) {
     72 	old_sig_cont = sig_cont;
     73 	sig_cont = signal(SIGCONT, print_prompt);
     74 	if (sig_cont == print_prompt)
     75 	    sig_cont = old_sig_cont;
     76 	if (info->readline) {
     77 		line = (*info->readline)(current_info->prompt);
     78 	} else {
     79 		print_prompt(0);
     80 		if (fgets(input, BUFSIZ, stdin) == input)
     81 			line = input;
     82 		else
     83 			line = NULL;
     84 
     85 		input[BUFSIZ-1] = 0;
     86 	}
     87 	if (line == NULL) {
     88 		code = SS_ET_EOF;
     89 		(void) signal(SIGCONT, sig_cont);
     90 		goto egress;
     91 	}
     92 
     93 	cp = strchr(line, '\n');
     94 	if (cp) {
     95 	    *cp = '\0';
     96 	    if (cp == line)
     97 		continue;
     98 	}
     99 	(void) signal(SIGCONT, sig_cont);
    100 	if (info->add_history)
    101 		(*info->add_history)(line);
    102 
    103 	code = ss_execute_line (sci_idx, line);
    104 	if (code == SS_ET_COMMAND_NOT_FOUND) {
    105 	    register char *c = line;
    106 	    while (*c == ' ' || *c == '\t')
    107 		c++;
    108 	    cp = strchr (c, ' ');
    109 	    if (cp)
    110 		*cp = '\0';
    111 	    cp = strchr (c, '\t');
    112 	    if (cp)
    113 		*cp = '\0';
    114 	    ss_error (sci_idx, 0,
    115 		    "Unknown request \"%s\".  Type \"?\" for a request list.",
    116 		       c);
    117 	}
    118 	if (info->readline)
    119 		free(line);
    120     }
    121     code = 0;
    122 egress:
    123     (void) signal(SIGINT, sig_int);
    124     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
    125     current_info = old_info;
    126     return code;
    127 }
    128 
    129 void ss_abort_subsystem(int sci_idx, int code)
    130 {
    131     ss_info(sci_idx)->abort = 1;
    132     ss_info(sci_idx)->exit_status = code;
    133 
    134 }
    135 
    136 void ss_quit(int argc __SS_ATTR((unused)),
    137 	     const char * const *argv __SS_ATTR((unused)),
    138 	     int sci_idx, pointer infop __SS_ATTR((unused)))
    139 {
    140     ss_abort_subsystem(sci_idx, 0);
    141 }
    142 
    143 #ifdef HAVE_DLOPEN
    144 #define get_request(tbl,idx)    ((tbl) -> requests + (idx))
    145 
    146 static char *cmd_generator(const char *text, int state)
    147 {
    148 	static int	len;
    149 	static ss_request_table **rqtbl;
    150 	static int	curr_rqt;
    151 	static char const * const * name;
    152 	ss_request_entry *request;
    153 	char		*ret;
    154 
    155 	if (state == 0) {
    156 		len = strlen(text);
    157 		rqtbl = current_info->rqt_tables;
    158 		if (!rqtbl || !*rqtbl)
    159 			return 0;
    160 		curr_rqt = 0;
    161 		name = 0;
    162 	}
    163 
    164 	while (1) {
    165 		if (!name || !*name) {
    166 			request = get_request(*rqtbl, curr_rqt++);
    167 			name = request->command_names;
    168 			if (!name) {
    169 				rqtbl++;
    170 				if (*rqtbl) {
    171 					curr_rqt = 0;
    172 					continue;
    173 				} else
    174 					break;
    175 			}
    176 		}
    177 		if (strncmp(*name, text, len) == 0) {
    178 			ret = malloc(strlen(*name)+1);
    179 			if (ret)
    180 				strcpy(ret, *name);
    181 			name++;
    182 			return ret;
    183 		}
    184 		name++;
    185 	}
    186 
    187 	return 0;
    188 }
    189 
    190 char **ss_rl_completion(const char *text, int start,
    191 			int end __SS_ATTR((unused)))
    192 {
    193 	if ((start == 0) && current_info->rl_completion_matches)
    194 		return (*current_info->rl_completion_matches)
    195 			(text, cmd_generator);
    196 	return 0;
    197 }
    198 #endif
    199 
    200