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