Whamcloud - gitweb
Many files:
[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  * For copyright information, see copyright.h.
10  */
11
12 #include "copyright.h"
13 #include "ss_internal.h"
14 #include <stdio.h>
15 #include <setjmp.h>
16 #include <signal.h>
17 #include <sys/param.h>
18 #ifdef BSD
19 #include <sgtty.h>
20 #endif
21
22 #ifndef lint
23 static char const rcs_id[] =
24     "$Header$";
25 #endif
26
27 typedef void sigret_t;
28
29 static ss_data *current_info;
30 static jmp_buf listen_jmpb;
31
32 static sigret_t print_prompt(int sig)
33 {
34 #ifdef BSD
35     /* put input into a reasonable mode */
36     struct sgttyb ttyb;
37     if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) {
38         if (ttyb.sg_flags & (CBREAK|RAW)) {
39             ttyb.sg_flags &= ~(CBREAK|RAW);
40             (void) ioctl(0, TIOCSETP, &ttyb);
41         }
42     }
43 #endif
44     (void) fputs(current_info->prompt, stdout);
45     (void) fflush(stdout);
46 }
47
48 static sigret_t listen_int_handler(int sig)
49 {
50     putc('\n', stdout);
51     signal(SIGINT, listen_int_handler);
52     longjmp(listen_jmpb, 1);
53 }
54
55 int ss_listen (int sci_idx)
56 {
57     char *cp;
58     ss_data *info;
59     sigret_t (*sig_int)(int), (*sig_cont)(int), (*old_sig_cont)(int);
60     char input[BUFSIZ];
61     char buffer[BUFSIZ];
62     char *end = buffer;
63 #ifdef POSIX_SIGNALS
64     sigset_t omask, igmask;
65 #else
66     int mask;
67 #endif
68     int code;
69     jmp_buf old_jmpb;
70     ss_data *old_info = current_info;
71     
72     current_info = info = ss_info(sci_idx);
73     sig_cont = (sigret_t (*)(int)) 0;
74     info->abort = 0;
75 #ifdef POSIX_SIGNALS
76     sigemptyset(&igmask);
77     sigaddset(&igmask, SIGINT);
78     sigprocmask(SIG_BLOCK, &igmask, &omask);
79 #else
80     mask = sigblock(sigmask(SIGINT));
81 #endif
82     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
83     sig_int = signal(SIGINT, listen_int_handler);
84     setjmp(listen_jmpb);
85 #ifdef POSIX_SIGNALS
86     sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
87 #else
88     (void) sigsetmask(mask);
89 #endif
90     while(!info->abort) {
91         print_prompt(0);
92         *end = '\0';
93         old_sig_cont = sig_cont;
94         sig_cont = signal(SIGCONT, print_prompt);
95         if (sig_cont == print_prompt)
96             sig_cont = old_sig_cont;
97         if (fgets(input, BUFSIZ, stdin) != input) {
98             code = SS_ET_EOF;
99             goto egress;
100         }
101         cp = strchr(input, '\n');
102         if (cp) {
103             *cp = '\0';
104             if (cp == input)
105                 continue;
106         }
107         (void) signal(SIGCONT, sig_cont);
108         for (end = input; *end; end++)
109             ;
110
111         code = ss_execute_line (sci_idx, input);
112         if (code == SS_ET_COMMAND_NOT_FOUND) {
113             register char *c = input;
114             while (*c == ' ' || *c == '\t')
115                 c++;
116             cp = strchr (c, ' ');
117             if (cp)
118                 *cp = '\0';
119             cp = strchr (c, '\t');
120             if (cp)
121                 *cp = '\0';
122             ss_error (sci_idx, 0,
123                     "Unknown request \"%s\".  Type \"?\" for a request list.",
124                        c);
125         }
126     }
127     code = 0;
128 egress:
129     (void) signal(SIGINT, sig_int);
130     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
131     current_info = old_info;
132     return code;
133 }
134
135 void ss_abort_subsystem(int sci_idx, int code)
136 {
137     ss_info(sci_idx)->abort = 1;
138     ss_info(sci_idx)->exit_status = code;
139     
140 }
141
142 void ss_quit(int argc, const char * const *argv, int sci_idx, pointer infop)
143 {
144     ss_abort_subsystem(sci_idx, 0);
145 }