source: trunk/minix/commands/yap/getcomm.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.6 KB
Line 
1/* Copyright (c) 1985 Ceriel J.H. Jacobs */
2
3/*
4 * Command reader, also executes shell escapes
5 */
6
7# ifndef lint
8static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/getcomm.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
9# endif
10
11# define _GETCOMM_
12
13# include <ctype.h>
14# include "in_all.h"
15# include "term.h"
16# include "process.h"
17# include "getcomm.h"
18# include "commands.h"
19# include "prompt.h"
20# include "main.h"
21# include "output.h"
22# include "getline.h"
23# include "machine.h"
24# include "keys.h"
25# include "display.h"
26# include "assert.h"
27
28#if USG_OPEN
29#include <fcntl.h>
30#endif
31#if POSIX_OPEN
32#include <sys/types.h>
33#include <fcntl.h>
34#endif
35
36char *strcpy(),
37 *getenv();
38
39STATIC int killchar();
40
41/*
42 * Read a line from the terminal, doing line editing.
43 * The parameter s contains the prompt for the line.
44 */
45
46char *
47readline(s) char *s; {
48
49 static char buf[80];
50 register char *p = buf;
51 register int ch;
52 register int pos;
53
54 clrbline();
55 putline(s);
56 pos = strlen(s);
57 while ((ch = getch()) != '\n' && ch != '\r') {
58 if (ch == -1) {
59 /*
60 * Can only occur because of an interrupted read.
61 */
62 ch = erasech;
63 interrupt = 0;
64 }
65 if (ch == erasech) {
66 /*
67 * Erase last char
68 */
69 if (p == buf) {
70 /*
71 * There was none, so return
72 */
73 return (char *) 0;
74 }
75 pos -= killchar(*--p);
76 if (*p != '\\') continue;
77 }
78 if (ch == killch) {
79 /*
80 * Erase the whole line
81 */
82 if (!(p > buf && *(p-1) == '\\')) {
83 while (p > buf) {
84 pos -= killchar(*--p);
85 }
86 continue;
87 }
88 pos -= killchar(*--p);
89 }
90 if (p > &buf[78] || pos >= COLS - 2) {
91 /*
92 * Line does not fit.
93 * Simply refuse to make it any longer
94 */
95 pos -= killchar(*--p);
96 }
97 *p++ = ch;
98 if (ch < ' ' || ch >= 0177) {
99 fputch('^');
100 pos++;
101 ch ^= 0100;
102 }
103 fputch(ch);
104 pos++;
105 }
106 fputch('\r');
107 *p++ = '\0';
108 flush();
109 return buf;
110}
111
112/*
113 * Erase a character from the command line.
114 */
115
116STATIC int
117killchar(c) {
118
119 backspace();
120 putch(' ');
121 backspace();
122 if (c < ' ' || c >= 0177) {
123 (VOID) killchar(' ');
124 return 2;
125 }
126 return 1;
127}
128
129/*
130 * Do a shell escape, after expanding '%' and '!'.
131 */
132
133VOID
134shellescape(p, esc_char) register char *p; {
135
136 register char *p2; /* walks through command */
137 register int id; /* procid of child */
138 register int cnt; /* prevent array bound errors */
139 register int lastc = 0; /* will contain the previous char */
140# ifdef SIGTSTP
141 VOID (*savetstp)();
142# endif
143 static char previous[256]; /* previous command */
144 char comm[256]; /* space for command */
145 int piped[2];
146
147 p2 = comm;
148 *p2++ = esc_char;
149 cnt = 253;
150 while (*p) {
151 /*
152 * expand command
153 */
154 switch(*p++) {
155 case '!':
156 /*
157 * An unescaped ! expands to the previous
158 * command, but disappears if there is none
159 */
160 if (lastc != '\\') {
161 if (*previous) {
162 id = strlen(previous);
163 if ((cnt -= id) <= 0) break;
164 (VOID) strcpy(p2,previous);
165 p2 += id;
166 }
167 }
168 else {
169 *(p2-1) = '!';
170 }
171 continue;
172 case '%':
173 /*
174 * An unescaped % will expand to the current
175 * filename, but disappears is there is none
176 */
177 if (lastc != '\\') {
178 if (nopipe) {
179 id = strlen(currentfile);
180 if ((cnt -= id) <= 0) break;
181 (VOID) strcpy(p2,currentfile);
182 p2 += id;
183 }
184 }
185 else {
186 *(p2-1) = '%';
187 }
188 continue;
189 default:
190 lastc = *(p-1);
191 if (cnt-- <= 0) break;
192 *p2++ = lastc;
193 continue;
194 }
195 break;
196 }
197 clrbline();
198 *p2 = '\0';
199 if (!stupid) {
200 /*
201 * Display expanded command
202 */
203 cputline(comm);
204 putline("\r\n");
205 }
206 flush();
207 (VOID) strcpy(previous,comm + 1);
208 resettty();
209 if (esc_char == '|' && pipe(piped) < 0) {
210 error("Cannot create pipe");
211 return;
212 }
213 if ((id = fork()) < 0) {
214 error("Cannot fork");
215 return;
216 }
217 if (id == 0) {
218 /*
219 * Close files, as child might need the file descriptors
220 */
221 cls_files();
222 if (esc_char == '|') {
223 close(piped[1]);
224#if USG_OPEN || POSIX_OPEN
225 close(0);
226 fcntl(piped[0], F_DUPFD, 0);
227#else
228 dup2(piped[0], 0);
229#endif
230 close(piped[0]);
231 }
232 execl("/bin/sh", "sh", "-c", comm + 1, (char *) 0);
233 exit(1);
234 }
235 (VOID) signal(SIGINT,SIG_IGN);
236 (VOID) signal(SIGQUIT,SIG_IGN);
237# ifdef SIGTSTP
238 if ((savetstp = signal(SIGTSTP,SIG_IGN)) != SIG_IGN) {
239 (VOID) signal(SIGTSTP,SIG_DFL);
240 }
241# endif
242 if (esc_char == '|') {
243 (VOID) close(piped[0]);
244 (VOID) signal(SIGPIPE, SIG_IGN);
245 wrt_fd(piped[1]);
246 (VOID) close(piped[1]);
247 }
248 while ((lastc = wait((int *) 0)) != id && lastc >= 0) {
249 /*
250 * Wait for child, making sure it is the one we expected ...
251 */
252 }
253 (VOID) signal(SIGINT,catchdel);
254 (VOID) signal(SIGQUIT,quit);
255# ifdef SIGTSTP
256 (VOID) signal(SIGTSTP, savetstp);
257# endif
258 inittty();
259}
260
261/*
262 * Get all those commands ...
263 */
264
265int
266getcomm (plong) long *plong; {
267 int c;
268 long count;
269 char *p;
270 int i;
271 int j;
272 char buf[10];
273
274 for (;;) {
275 count = 0;
276 give_prompt();
277 while (isdigit((c = getch()))) {
278 count = count * 10 + (c - '0');
279 }
280 *plong = count;
281 p = buf;
282 for (;;) {
283 if (c == -1) {
284 /*
285 * This should never happen, but it does,
286 * when the user gives a TSTP signal (^Z) or
287 * an interrupt while the program is trying
288 * to read a character from the terminal.
289 * In this case, the read is interrupted, so
290 * we end up here.
291 * Right, we will have to read again.
292 */
293 if (interrupt) return 1;
294 break;
295 }
296 *p++ = c;
297 *p = 0;
298 if ((i = match(buf, &j, currmap->k_mach)) > 0) {
299 /*
300 * The key sequence matched. We have a command
301 */
302 return j;
303 }
304 if (i == 0) return 0;
305 /*
306 * We have a prefix of a command.
307 */
308 assert(i == FSM_ISPREFIX);
309 c = getch();
310 }
311 }
312 /* NOTREACHED */
313}
Note: See TracBrowser for help on using the repository browser.