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