0
|
1 /* prompter.c - prompting editor front-end */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: prompter.c,v 1.2 2006/12/05 18:18:13 kono Exp $";
|
0
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include <stdio.h>
|
|
8 #include <errno.h>
|
|
9 #ifndef SYS5
|
|
10 #include <sgtty.h>
|
|
11 #else /* SYS5 */
|
|
12 #include <sys/types.h>
|
|
13 #include <termio.h>
|
|
14 #ifndef NOIOCTLH
|
|
15 #include <sys/ioctl.h>
|
|
16 #endif /* NOIOCTLH */
|
|
17 #endif /* SYS5 */
|
|
18 #if defined(BSD42) || defined(SVR4)
|
|
19 #include <setjmp.h>
|
|
20 #endif /* BSD42 || SVR4 */
|
|
21 #include <signal.h>
|
|
22 #ifdef LOCALE
|
|
23 #include <locale.h>
|
|
24 #endif
|
|
25
|
|
26
|
|
27 #define QUOTE '\\'
|
|
28 #ifndef CKILL
|
|
29 #define CKILL '@'
|
|
30 #endif /* not CKILL */
|
|
31 #ifndef CERASE
|
|
32 #define CERASE '#'
|
|
33 #endif /* not CERASE */
|
|
34
|
|
35 /* */
|
|
36
|
|
37 static struct swit switches[] = {
|
|
38 #define ERASESW 0
|
|
39 "erase chr", 0,
|
|
40 #define KILLSW 1
|
|
41 "kill chr", 0,
|
|
42
|
|
43 #define PREPSW 2
|
|
44 "prepend", 0,
|
|
45 #define NPREPSW 3
|
|
46 "noprepend", 0,
|
|
47
|
|
48 #define RAPDSW 4
|
|
49 "rapid", 0,
|
|
50 #define NRAPDSW 5
|
|
51 "norapid", 0,
|
|
52
|
|
53 #define BODYSW 6
|
|
54 "body", -4,
|
|
55 #define NBODYSW 7
|
|
56 "nobody", -6,
|
|
57
|
|
58 #define DOTSW 8
|
|
59 "doteof", 0,
|
|
60 #define NDOTSW 9
|
|
61 "nodoteof", 0,
|
|
62
|
|
63 #define HELPSW 10
|
|
64 "help", 4,
|
|
65
|
|
66 NULL, 0
|
|
67 };
|
|
68
|
|
69 /* */
|
|
70
|
|
71
|
|
72
|
|
73 #ifndef SYS5
|
|
74 #define ERASE sg.sg_erase
|
|
75 #define KILL sg.sg_kill
|
|
76 static struct sgttyb sg;
|
|
77
|
|
78 #define INTR tc.t_intrc
|
|
79 static struct tchars tc;
|
|
80 #else /* SYS5 */
|
|
81 #define ERASE sg.c_cc[VERASE]
|
|
82 #define KILL sg.c_cc[VKILL]
|
|
83 #define INTR sg.c_cc[VINTR]
|
|
84 static struct termio sg;
|
|
85 #endif /* SYS5 */
|
|
86
|
|
87
|
|
88 static TYPESIG intrser ();
|
|
89
|
|
90 static int wtuser = 0;
|
|
91 static int sigint = 0;
|
|
92
|
|
93 #if defined(BSD42) || defined(SVR4)
|
|
94 static jmp_buf sigenv;
|
|
95 #endif /* BSD42 || SVR4 */
|
|
96
|
|
97 /* */
|
|
98
|
|
99 /* ARGSUSED */
|
|
100
|
|
101 main (argc, argv)
|
|
102 int argc;
|
|
103 char *argv[];
|
|
104 {
|
|
105 int body = 1,
|
|
106 prepend = 1,
|
|
107 rapid = 0,
|
|
108 doteof = 0,
|
|
109 fdi,
|
|
110 fdo,
|
|
111 i,
|
|
112 state;
|
|
113 char *cp,
|
|
114 *drft = NULL,
|
|
115 *erasep = NULL,
|
|
116 *killp = NULL,
|
|
117 name[NAMESZ],
|
|
118 field[BUFSIZ],
|
|
119 buffer[BUFSIZ],
|
|
120 tmpfil[BUFSIZ],
|
|
121 **ap,
|
|
122 *arguments[MAXARGS],
|
|
123 **argp;
|
|
124 FILE *in, *out;
|
|
125
|
|
126 #ifdef LOCALE
|
|
127 setlocale(LC_ALL, "");
|
|
128 #endif
|
|
129 #ifdef JAPAN
|
|
130 ml_init();
|
|
131 #endif /* JAPAN */
|
|
132 invo_name = r1bindex (argv[0], '/');
|
|
133 if ((cp = m_find (invo_name)) != NULL) {
|
|
134 ap = brkstring (cp = getcpy (cp), " ", "\n");
|
|
135 ap = copyip (ap, arguments);
|
|
136 }
|
|
137 else
|
|
138 ap = arguments;
|
|
139 (void) copyip (argv + 1, ap);
|
|
140 argp = arguments;
|
|
141
|
|
142 /* */
|
|
143
|
|
144 while (cp = *argp++)
|
|
145 if (*cp == '-')
|
|
146 switch (smatch (++cp, switches)) {
|
|
147 case AMBIGSW:
|
|
148 ambigsw (cp, switches);
|
|
149 done (1);
|
|
150 case UNKWNSW:
|
|
151 adios (NULLCP, "-%s unknown", cp);
|
|
152 case HELPSW:
|
|
153 (void) sprintf (buffer, "%s [switches] file", invo_name);
|
|
154 help (buffer, switches);
|
|
155 done (1);
|
|
156
|
|
157 case ERASESW:
|
|
158 if (!(erasep = *argp++) || *erasep == '-')
|
|
159 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
160 continue;
|
|
161 case KILLSW:
|
|
162 if (!(killp = *argp++) || *killp == '-')
|
|
163 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
164 continue;
|
|
165
|
|
166 case PREPSW:
|
|
167 prepend++;
|
|
168 continue;
|
|
169 case NPREPSW:
|
|
170 prepend = 0;
|
|
171 continue;
|
|
172
|
|
173 case RAPDSW:
|
|
174 rapid++;
|
|
175 continue;
|
|
176 case NRAPDSW:
|
|
177 rapid = 0;
|
|
178 continue;
|
|
179
|
|
180 case BODYSW:
|
|
181 body++;
|
|
182 continue;
|
|
183 case NBODYSW:
|
|
184 body = 0;
|
|
185 continue;
|
|
186
|
|
187 case DOTSW:
|
|
188 doteof++;
|
|
189 continue;
|
|
190 case NDOTSW:
|
|
191 doteof = 0;
|
|
192 continue;
|
|
193 }
|
|
194 else
|
|
195 if (!drft)
|
|
196 drft = cp;
|
|
197
|
|
198 /* */
|
|
199
|
|
200 if (!drft)
|
|
201 adios (NULLCP, "usage: %s [switches] file", invo_name);
|
|
202 if ((in = fopen (drft, "r")) == NULL)
|
|
203 adios (drft, "unable to open");
|
|
204
|
|
205 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
206 if ((out = fopen (tmpfil, "w")) == NULL)
|
|
207 adios (tmpfil, "unable to create");
|
|
208 (void) chmod (tmpfil, 0600);
|
|
209
|
|
210 if (killp || erasep) {
|
|
211 #ifndef SYS5
|
|
212 int serase,
|
|
213 skill;
|
|
214 #else /* SYS5 */
|
|
215 char serase,
|
|
216 skill;
|
|
217 #endif /* SYS5 */
|
|
218
|
|
219 #ifndef SYS5
|
|
220 (void) ioctl (0, TIOCGETP, (char *) &sg);
|
|
221 (void) ioctl (0, TIOCGETC, (char *) &tc);
|
|
222 #else /* SYS5 */
|
|
223 (void) ioctl(0, TCGETA, &sg);
|
|
224 #endif /* SYS5 */
|
|
225 skill = KILL;
|
|
226 serase = ERASE;
|
|
227 KILL = killp ? chrcnv (killp) : skill;
|
|
228 ERASE = erasep ? chrcnv (erasep) : serase;
|
|
229 #ifndef SYS5
|
|
230 (void) ioctl (0, TIOCSETN, (char *) &sg);
|
|
231 #else /* SYS5 */
|
|
232 (void) ioctl(0, TCSETAW, &sg);
|
|
233 #endif /* SYS5 */
|
|
234
|
|
235 chrdsp ("erase", ERASE);
|
|
236 chrdsp (", kill", KILL);
|
|
237 chrdsp (", intr", INTR);
|
|
238 (void) putchar ('\n');
|
|
239 (void) fflush (stdout);
|
|
240
|
|
241 KILL = skill;
|
|
242 ERASE = serase;
|
|
243 }
|
|
244
|
|
245 /* */
|
|
246
|
|
247 sigint = 0;
|
|
248 setsig (SIGINT, intrser);
|
|
249
|
|
250 for (state = FLD;;) {
|
|
251 switch (state = m_getfld (state, name, field, sizeof field, in)) {
|
|
252 case FLD:
|
|
253 case FLDEOF:
|
|
254 case FLDPLUS:
|
|
255 for (cp = field; *cp; cp++)
|
|
256 if (*cp != ' ' && *cp != '\t')
|
|
257 break;
|
|
258 if (*cp++ != '\n' || *cp != 0) {
|
|
259 printf ("%s:%s", name, field);
|
|
260 fprintf (out, "%s:%s", name, field);
|
|
261 while (state == FLDPLUS) {
|
|
262 state =
|
|
263 m_getfld (state, name, field, sizeof field, in);
|
|
264 printf ("%s", field);
|
|
265 fprintf (out, "%s", field);
|
|
266 }
|
|
267 }
|
|
268 else {
|
|
269 printf ("%s: ", name);
|
|
270 (void) fflush (stdout);
|
|
271 i = getln (field, sizeof field);
|
|
272 if (i == -1) {
|
|
273 abort: ;
|
|
274 if (killp || erasep)
|
|
275 #ifndef SYS5
|
|
276 (void) ioctl (0, TIOCSETN, (char *) &sg);
|
|
277 #else /* SYS5 */
|
|
278 (void) ioctl (0, TCSETA, &sg);
|
|
279 #endif /* SYS5 */
|
|
280 (void) unlink (tmpfil);
|
|
281 done (1);
|
|
282 }
|
|
283 if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
|
|
284 fprintf (out, "%s:", name);
|
|
285 do {
|
|
286 if (field[0] != ' ' && field[0] != '\t')
|
|
287 (void) putc (' ', out);
|
|
288 fprintf (out, "%s", field);
|
|
289 } while (i == 1
|
|
290 && (i = getln (field, sizeof field)) >= 0);
|
|
291 if (i == -1)
|
|
292 goto abort;
|
|
293 }
|
|
294 }
|
|
295 if (state == FLDEOF) {/* moby hack */
|
|
296 fprintf (out, "--------\n");
|
|
297 printf ("--------\n");
|
|
298 if (!body)
|
|
299 break;
|
|
300 goto no_body;
|
|
301 }
|
|
302 continue;
|
|
303
|
|
304 case BODY:
|
|
305 case BODYEOF:
|
|
306 case FILEEOF:
|
|
307 if (!body)
|
|
308 break;
|
|
309 fprintf (out, "--------\n");
|
|
310 if (field[0] == 0 || !prepend)
|
|
311 printf ("--------\n");
|
|
312 if (field[0]) {
|
|
313 if (prepend && body) {
|
|
314 printf ("\n--------Enter initial text\n\n");
|
|
315 (void) fflush (stdout);
|
|
316 for (;;) {
|
|
317 (void) getln (buffer, sizeof buffer);
|
|
318 if (doteof && buffer[0] == '.' && buffer[1] == '\n')
|
|
319 break;
|
|
320 if (buffer[0] == 0)
|
|
321 break;
|
|
322 fprintf (out, "%s", buffer);
|
|
323 }
|
|
324 }
|
|
325
|
|
326 do {
|
|
327 fprintf (out, "%s", field);
|
|
328 if (!rapid && !sigint)
|
|
329 printf ("%s", field);
|
|
330 } while (state == BODY &&
|
|
331 (state = m_getfld (state, name, field, sizeof field, in)));
|
|
332 if (prepend || !body)
|
|
333 break;
|
|
334 else
|
|
335 printf ("\n--------Enter additional text\n\n");
|
|
336 }
|
|
337 no_body: ;
|
|
338 (void) fflush (stdout);
|
|
339 for (;;) {
|
|
340 (void) getln (field, sizeof field);
|
|
341 if (doteof && field[0] == '.' && field[1] == '\n')
|
|
342 break;
|
|
343 if (field[0] == 0)
|
|
344 break;
|
|
345 fprintf (out, "%s", field);
|
|
346 }
|
|
347 break;
|
|
348
|
|
349 default:
|
|
350 adios (NULLCP, "skeleton is poorly formatted");
|
|
351 }
|
|
352 break;
|
|
353 }
|
|
354
|
|
355 if (body)
|
|
356 printf ("--------\n");
|
|
357 (void) fflush (stdout);
|
|
358
|
|
359 (void) fclose (in);
|
|
360 (void) fclose (out);
|
|
361
|
|
362 (void) signal (SIGINT, SIG_IGN);
|
|
363
|
|
364 /* */
|
|
365
|
|
366 if (killp || erasep)
|
|
367 #ifndef SYS5
|
|
368 (void) ioctl (0, TIOCSETN, (char *) &sg);
|
|
369 #else /* SYS5 */
|
|
370 (void) ioctl (0, TCSETAW, &sg);
|
|
371 #endif /* SYS5 */
|
|
372
|
|
373 if ((fdi = open (tmpfil, 0)) == NOTOK)
|
|
374 adios (tmpfil, "unable to re-open");
|
|
375 if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
|
|
376 adios (drft, "unable to write");
|
|
377 cpydata (fdi, fdo, tmpfil, drft);
|
|
378 (void) close (fdi);
|
|
379 (void) close (fdo);
|
|
380 (void) unlink (tmpfil);
|
|
381
|
|
382 m_update ();
|
|
383
|
|
384 done (0);
|
|
385 }
|
|
386
|
|
387 /* */
|
|
388
|
|
389 getln (buffer, n)
|
|
390 char *buffer;
|
|
391 int n;
|
|
392 {
|
|
393 int c;
|
|
394 char *cp;
|
|
395
|
|
396 cp = buffer;
|
|
397 *cp = 0;
|
|
398
|
|
399 #if !defined(BSD42) && !defined(SVR4)
|
|
400 wtuser = 1;
|
|
401 #else /* BSD42 || SVR4 */
|
|
402 switch (setjmp (sigenv)) {
|
|
403 case OK:
|
|
404 wtuser = 1;
|
|
405 break;
|
|
406
|
|
407 case DONE:
|
|
408 wtuser = 0;
|
|
409 return 0;
|
|
410
|
|
411 default:
|
|
412 wtuser = 0;
|
|
413 return NOTOK;
|
|
414 }
|
|
415 #endif /* BSD42 || SVR4 */
|
|
416
|
|
417 for (;;)
|
|
418 switch (c = getchar ()) {
|
|
419 case EOF:
|
|
420 #if !defined(BSD42) && !defined(SVR4)
|
|
421 wtuser = 0;
|
|
422 return (errno != EINTR ? 0 : NOTOK);
|
|
423 #else /* BSD42 || SVR4 */
|
|
424 clearerr (stdin);
|
|
425 longjmp (sigenv, DONE);
|
|
426 #endif /* BSD42 || SVR4 */
|
|
427
|
|
428 case '\n':
|
|
429 if (cp[-1] == QUOTE) {
|
|
430 cp[-1] = c;
|
|
431 wtuser = 0;
|
|
432 return 1;
|
|
433 }
|
|
434 *cp++ = c;
|
|
435 *cp = 0;
|
|
436 wtuser = 0;
|
|
437 return 0;
|
|
438
|
|
439 default:
|
|
440 if (cp < buffer + n)
|
|
441 *cp++ = c;
|
|
442 *cp = 0;
|
|
443 }
|
|
444 }
|
|
445
|
|
446 /* */
|
|
447
|
|
448 /* ARGSUSED */
|
|
449
|
|
450 static TYPESIG intrser (i)
|
|
451 int i;
|
|
452 {
|
|
453 #ifndef BSD42
|
|
454 (void) signal (SIGINT, intrser);
|
|
455 #endif
|
|
456 #if !defined(BSD42) && !defined(SVR4)
|
|
457 if (!wtuser)
|
|
458 sigint++;
|
|
459 #else /* BSD42 || SVR4 */
|
|
460 if (wtuser)
|
|
461 longjmp (sigenv, NOTOK);
|
|
462 sigint++;
|
|
463 #endif /* BSD42 || SVR4 */
|
|
464 }
|
|
465
|
|
466
|
|
467 chrcnv (cp)
|
|
468 register char *cp;
|
|
469 {
|
|
470 return (*cp != QUOTE ? *cp : m_atoi (++cp));
|
|
471 }
|
|
472
|
|
473
|
|
474 chrdsp (s, c)
|
|
475 char *s,
|
|
476 c;
|
|
477 {
|
|
478 printf ("%s ", s);
|
|
479 if (c < ' ' || c == 0177)
|
|
480 printf ("^%c", c ^ 0100);
|
|
481 else
|
|
482 printf ("%c", c);
|
|
483 }
|