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()
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()
49 {
50     putc('\n', stdout);
51     signal(SIGINT, listen_int_handler);
52     longjmp(listen_jmpb, 1);
53 }
54
55 int ss_listen (sci_idx)
56     int sci_idx;
57 {
58     char *cp;
59     ss_data *info;
60     sigret_t (*sig_int)(), (*sig_cont)(), (*old_sig_cont)();
61     char input[BUFSIZ];
62     char buffer[BUFSIZ];
63     char *end = buffer;
64     int mask;
65     int code;
66     jmp_buf old_jmpb;
67     ss_data *old_info = current_info;
68     
69     current_info = info = ss_info(sci_idx);
70     sig_cont = (sigret_t (*)()) 0;
71     info->abort = 0;
72     mask = sigblock(sigmask(SIGINT));
73     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
74     sig_int = signal(SIGINT, listen_int_handler);
75     setjmp(listen_jmpb);
76     (void) sigsetmask(mask);
77     while(!info->abort) {
78         print_prompt();
79         *end = '\0';
80         old_sig_cont = sig_cont;
81         sig_cont = signal(SIGCONT, print_prompt);
82         if (sig_cont == print_prompt)
83             sig_cont = old_sig_cont;
84         if (fgets(input, BUFSIZ, stdin) != input) {
85             code = SS_ET_EOF;
86             goto egress;
87         }
88         cp = strchr(input, '\n');
89         if (cp) {
90             *cp = '\0';
91             if (cp == input)
92                 continue;
93         }
94         (void) signal(SIGCONT, sig_cont);
95         for (end = input; *end; end++)
96             ;
97
98         code = ss_execute_line (sci_idx, input);
99         if (code == SS_ET_COMMAND_NOT_FOUND) {
100             register char *c = input;
101             while (*c == ' ' || *c == '\t')
102                 c++;
103             cp = strchr (c, ' ');
104             if (cp)
105                 *cp = '\0';
106             cp = strchr (c, '\t');
107             if (cp)
108                 *cp = '\0';
109             ss_error (sci_idx, 0,
110                     "Unknown request \"%s\".  Type \"?\" for a request list.",
111                        c);
112         }
113     }
114     code = 0;
115 egress:
116     (void) signal(SIGINT, sig_int);
117     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
118     current_info = old_info;
119     return code;
120 }
121
122 void ss_abort_subsystem(sci_idx, code)
123     int sci_idx;
124     int code;
125 {
126     ss_info(sci_idx)->abort = 1;
127     ss_info(sci_idx)->exit_status = code;
128     
129 }
130
131 int ss_quit(argc, argv, sci_idx, infop)
132     int argc;
133     char **argv;
134     int sci_idx;
135     pointer infop;
136 {
137     ss_abort_subsystem(sci_idx, 0);
138 }