Whamcloud - gitweb
Fix pkg-config files: use Requires.private and fix the include directory
[tools/e2fsprogs.git] / lib / ss / listen.c
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