3 * prompter.c -- simple prompting editor front-end
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
12 #include <h/signals.h>
15 #include <h/m_setjmp.h>
29 static struct swit switches[] = {
58 static struct termios tio;
59 #define ERASE tio.c_cc[VERASE]
60 #define KILL tio.c_cc[VKILL]
61 #define INTR tio.c_cc[VINTR]
63 static int wtuser = 0;
64 static int sigint = 0;
65 static jmp_buf sigenv;
70 int getln (char *, int);
71 static int chrcnv (char *);
72 static void chrdsp (char *, char);
73 static void intrser (int);
77 main (int argc, char **argv)
79 int body = 1, prepend = 1, rapid = 0;
80 int doteof = 0, fdi, fdo, i, state;
81 char *cp, *drft = NULL, *erasep = NULL;
82 char *killp = NULL, name[NAMESZ], field[BUFSIZ];
83 char buffer[BUFSIZ], tmpfil[BUFSIZ];
84 char **arguments, **argp;
89 setlocale(LC_ALL, "");
91 invo_name = r1bindex (argv[0], '/');
93 /* read user profile/context */
96 arguments = getarguments (invo_name, argc, argv, 1);
99 while ((cp = *argp++))
101 switch (smatch (++cp, switches)) {
103 ambigsw (cp, switches);
106 adios (NULL, "-%s unknown", cp);
109 snprintf (buffer, sizeof(buffer), "%s [switches] file",
111 print_help (buffer, switches, 1);
114 print_version(invo_name);
118 if (!(erasep = *argp++) || *erasep == '-')
119 adios (NULL, "missing argument to %s", argp[-2]);
122 if (!(killp = *argp++) || *killp == '-')
123 adios (NULL, "missing argument to %s", argp[-2]);
160 adios (NULL, "usage: %s [switches] file", invo_name);
161 if ((in = fopen (drft, "r")) == NULL)
162 adios (drft, "unable to open");
164 tfile = m_mktemp2(NULL, invo_name, NULL, &out);
165 if (tfile == NULL) adios("prompter", "unable to create temporary file");
166 chmod (tmpfil, 0600);
167 strncpy (tmpfil, tfile, sizeof(tmpfil));
170 * Are we changing the kill or erase character?
172 if (killp || erasep) {
173 cc_t save_erase, save_kill;
175 /* get the current terminal attributes */
178 /* save original kill, erase character for later */
182 /* set new kill, erase character in terminal structure */
183 KILL = killp ? chrcnv (killp) : save_kill;
184 ERASE = erasep ? chrcnv (erasep) : save_erase;
186 /* set the new terminal attributes */
187 tcsetattr(0, TCSADRAIN, &tio);
189 /* print out new kill erase characters */
190 chrdsp ("erase", ERASE);
191 chrdsp (", kill", KILL);
192 chrdsp (", intr", INTR);
197 * We set the kill and erase character back to original
198 * setup in terminal structure so we can easily
199 * restore it upon exit.
206 SIGNAL2 (SIGINT, intrser);
209 * Loop through the lines of the draft skeleton.
211 for (state = FLD;;) {
212 switch (state = m_getfld (state, name, field, sizeof(field), in)) {
217 * Check if the value of field contains anything
218 * other than space or tab.
220 for (cp = field; *cp; cp++)
221 if (*cp != ' ' && *cp != '\t')
224 /* If so, just add header line to draft */
225 if (*cp++ != '\n' || *cp != 0) {
226 printf ("%s:%s", name, field);
227 fprintf (out, "%s:%s", name, field);
228 while (state == FLDPLUS) {
230 m_getfld (state, name, field, sizeof(field), in);
231 printf ("%s", field);
232 fprintf (out, "%s", field);
235 /* Else, get value of header field */
236 printf ("%s: ", name);
238 i = getln (field, sizeof(field));
241 if (killp || erasep) {
242 tcsetattr(0, TCSADRAIN, &tio);
247 if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
248 fprintf (out, "%s:", name);
250 if (field[0] != ' ' && field[0] != '\t')
252 fprintf (out, "%s", field);
254 && (i = getln (field, sizeof(field))) >= 0);
260 if (state == FLDEOF) { /* moby hack */
261 fprintf (out, "--------\n");
262 printf ("--------\n");
274 fprintf (out, "--------\n");
275 if (field[0] == 0 || !prepend)
276 printf ("--------\n");
278 if (prepend && body) {
279 printf ("\n--------Enter initial text\n\n");
282 getln (buffer, sizeof(buffer));
283 if (doteof && buffer[0] == '.' && buffer[1] == '\n')
287 fprintf (out, "%s", buffer);
292 fprintf (out, "%s", field);
293 if (!rapid && !sigint)
294 printf ("%s", field);
295 } while (state == BODY &&
296 (state = m_getfld (state, name, field, sizeof(field), in)));
297 if (prepend || !body)
300 printf ("\n--------Enter additional text\n\n");
305 getln (field, sizeof(field));
306 if (doteof && field[0] == '.' && field[1] == '\n')
310 fprintf (out, "%s", field);
315 adios (NULL, "skeleton is poorly formatted");
321 printf ("--------\n");
326 SIGNAL (SIGINT, SIG_IGN);
328 if (killp || erasep) {
329 tcsetattr(0, TCSADRAIN, &tio);
332 if ((fdi = open (tmpfil, O_RDONLY)) == NOTOK)
333 adios (tmpfil, "unable to re-open");
334 if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
335 adios (drft, "unable to write");
336 cpydata (fdi, fdo, tmpfil, drft);
341 context_save (); /* save the context file */
348 getln (char *buffer, int n)
356 switch (m_setjmp (sigenv)) {
371 switch (c = getchar ()) {
374 longjmp (sigenv, DONE);
377 if (cp[-1] == QUOTE) {
402 longjmp (sigenv, NOTOK);
410 return (*cp != QUOTE ? *cp : m_atoi (++cp));
415 chrdsp (char *s, char c)
418 if (c < ' ' || c == 0177)
419 printf ("^%c", c ^ 0100);