• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
print_prompt(int sig __SS_ATTR ((unused)))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 
listen_int_handler(int sig __SS_ATTR ((unused)))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 
ss_listen(int sci_idx)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 
ss_abort_subsystem(int sci_idx,int code)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 
ss_quit(int argc __SS_ATTR ((unused)),const char * const * argv __SS_ATTR ((unused)),int sci_idx,pointer infop __SS_ATTR ((unused)))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 
cmd_generator(const char * text,int state)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 
ss_rl_completion(const char * text,int start,int end __SS_ATTR ((unused)))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