Renamed -version switch to -Version to remove the conflict with -verbose.
[mmh] / uip / prompter.c
index fa1bfae..6db0455 100644 (file)
@@ -1,9 +1,10 @@
-
 /*
- * prompter.c -- simple prompting editor front-end
- *
- * $Id$
- */
+** prompter.c -- simple prompting editor front-end
+**
+** This code is Copyright (c) 2002, by the authors of nmh.  See the
+** COPYRIGHT file in the root directory of the nmh distribution for
+** complete copyright information.
+*/
 
 #include <h/mh.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <setjmp.h>
 
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#else
-# ifdef HAVE_TERMIO_H
-#  include <termio.h>
-# else
-#  include <sgtty.h>
-# endif
-#endif
+#include <termios.h>
 
-#define        QUOTE '\\'
+#define QUOTE '\\'
 
-#ifndef        CKILL
+#ifndef CKILL
 # define CKILL '@'
 #endif
 
-#ifndef        CERASE
+#ifndef CERASE
 # define CERASE '#'
 #endif
 
 static struct swit switches[] = {
-#define        ERASESW 0
-    { "erase chr", 0 },
-#define        KILLSW  1
-    { "kill chr", 0 },
-#define        PREPSW  2
-    { "prepend", 0 },
-#define        NPREPSW 3
-    { "noprepend", 0 },        
-#define        RAPDSW  4
-    { "rapid", 0 },
-#define        NRAPDSW 5
-    { "norapid", 0 },
-#define        BODYSW  6
-    { "body", -4 },
-#define        NBODYSW 7
-    { "nobody", -6 },
-#define        DOTSW   8
-    { "doteof", 0 },
-#define        NDOTSW  9
-    { "nodoteof", 0 },
+#define ERASESW  0
+       { "erase chr", 0 },
+#define KILLSW  1
+       { "kill chr", 0 },
+#define PREPSW  2
+       { "prepend", 0 },
+#define NPREPSW  3
+       { "noprepend", 0 },
+#define RAPDSW  4
+       { "rapid", 0 },
+#define NRAPDSW  5
+       { "norapid", 0 },
+#define BODYSW  6
+       { "body", -4 },
+#define NBODYSW  7
+       { "nobody", -6 },
+#define DOTSW  8
+       { "doteof", 0 },
+#define NDOTSW  9
+       { "nodoteof", 0 },
 #define VERSIONSW 10
-    { "version", 0 },
-#define        HELPSW  11
-    { "help", 4 },
-    { NULL, 0 }
+       { "Version", 0 },
+#define HELPSW  11
+       { "help", 0 },
+       { NULL, 0 }
 };
 
-extern int errno;
 
-#ifdef HAVE_TERMIOS_H
 static struct termios tio;
-# define ERASE tio.c_cc[VERASE]
-# define KILL  tio.c_cc[VKILL]
-# define INTR  tio.c_cc[VINTR]
-#else
-# ifdef HAVE_TERMIO_H
-static struct termio tio;
-#  define ERASE tio.c_cc[VERASE]
-#  define KILL  tio.c_cc[VKILL]
-#  define INTR  tio.c_cc[VINTR]
-# else
-static struct sgttyb tio;
-static struct tchars tc;
-#  define ERASE tio.sg_erase
-#  define KILL  tio.sg_kill
-#  define INTR  tc.t_intrc
-# endif
-#endif
+#define ERASE tio.c_cc[VERASE]
+#define KILL  tio.c_cc[VKILL]
+#define INTR  tio.c_cc[VINTR]
 
 static int wtuser = 0;
 static int sigint = 0;
 static jmp_buf sigenv;
 
 /*
- * prototypes
- */
-int getln (char *, int);
-static int chrcnv (char *);
-static void chrdsp (char *, char);
-static RETSIGTYPE intrser (int);
+** prototypes
+*/
+int getln(char *, int);
+static int chrcnv(char *);
+static void chrdsp(char *, char);
+static void intrser(int);
 
 
 int
-main (int argc, char **argv)
+main(int argc, char **argv)
 {
-    int body = 1, prepend = 1, rapid = 0;
-    int doteof = 0, fdi, fdo, i, state;
-    char *cp, *drft = NULL, *erasep = NULL;
-    char *killp = NULL, name[NAMESZ], field[BUFSIZ];
-    char buffer[BUFSIZ], tmpfil[BUFSIZ];
-    char **arguments, **argp;
-    FILE *in, *out;
+       int body = 1, prepend = 1, rapid = 0;
+       int doteof = 0, fdi, fdo, i, state;
+       char *cp, *drft = NULL, *erasep = NULL;
+       char *killp = NULL, name[NAMESZ], field[BUFSIZ];
+       char buffer[BUFSIZ], tmpfil[BUFSIZ];
+       char **arguments, **argp;
+       FILE *in, *out;
+       char *tfile = NULL;
 
 #ifdef LOCALE
-    setlocale(LC_ALL, "");
+       setlocale(LC_ALL, "");
 #endif
-    invo_name = r1bindex (argv[0], '/');
-
-    /* read user profile/context */
-    context_read();
-
-    arguments = getarguments (invo_name, argc, argv, 1);
-    argp = arguments;
-
-    while ((cp = *argp++))
-       if (*cp == '-') {
-           switch (smatch (++cp, switches)) {
-               case AMBIGSW: 
-                   ambigsw (cp, switches);
-                   done (1);
-               case UNKWNSW: 
-                   adios (NULL, "-%s unknown", cp);
-
-               case HELPSW: 
-                   snprintf (buffer, sizeof(buffer), "%s [switches] file",
-                       invo_name);
-                   print_help (buffer, switches, 1);
-                   done (1);
-               case VERSIONSW:
-                   print_version(invo_name);
-                   done (1);
-
-               case ERASESW: 
-                   if (!(erasep = *argp++) || *erasep == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
-                   continue;
-               case KILLSW: 
-                   if (!(killp = *argp++) || *killp == '-')
-                       adios (NULL, "missing argument to %s", argp[-2]);
-                   continue;
-
-               case PREPSW: 
-                   prepend++;
-                   continue;
-               case NPREPSW: 
-                   prepend = 0;
-                   continue;
-
-               case RAPDSW: 
-                   rapid++;
-                   continue;
-               case NRAPDSW: 
-                   rapid = 0;
-                   continue;
-
-               case BODYSW: 
-                   body++;
-                   continue;
-               case NBODYSW: 
-                   body = 0;
-                   continue;
-
-               case DOTSW: 
-                   doteof++;
-                   continue;
-               case NDOTSW: 
-                   doteof = 0;
-                   continue;
-           }
-       } else {
-           if (!drft)
-               drft = cp;
-       }
+       invo_name = mhbasename(argv[0]);
+
+       /* read user profile/context */
+       context_read();
+
+       arguments = getarguments(invo_name, argc, argv, 1);
+       argp = arguments;
+
+       while ((cp = *argp++))
+               if (*cp == '-') {
+                       switch (smatch(++cp, switches)) {
+                       case AMBIGSW:
+                               ambigsw(cp, switches);
+                               done(1);
+                       case UNKWNSW:
+                               adios(NULL, "-%s unknown", cp);
+
+                       case HELPSW:
+                               snprintf(buffer, sizeof(buffer),
+                                               "%s [switches] file",
+                                               invo_name);
+                               print_help(buffer, switches, 1);
+                               done(1);
+                       case VERSIONSW:
+                               print_version(invo_name);
+                               done(1);
+
+                       case ERASESW:
+                               if (!(erasep = *argp++) || *erasep == '-')
+                                       adios(NULL, "missing argument to %s",
+                                                       argp[-2]);
+                               continue;
+                       case KILLSW:
+                               if (!(killp = *argp++) || *killp == '-')
+                                       adios(NULL, "missing argument to %s",
+                                                       argp[-2]);
+                               continue;
+
+                       case PREPSW:
+                               prepend++;
+                               continue;
+                       case NPREPSW:
+                               prepend = 0;
+                               continue;
+
+                       case RAPDSW:
+                               rapid++;
+                               continue;
+                       case NRAPDSW:
+                               rapid = 0;
+                               continue;
+
+                       case BODYSW:
+                               body++;
+                               continue;
+                       case NBODYSW:
+                               body = 0;
+                               continue;
+
+                       case DOTSW:
+                               doteof++;
+                               continue;
+                       case NDOTSW:
+                               doteof = 0;
+                               continue;
+                       }
+               } else if (!drft) {
+                       drft = cp;
+               }
 
-    if (!drft)
-       adios (NULL, "usage: %s [switches] file", invo_name);
-    if ((in = fopen (drft, "r")) == NULL)
-       adios (drft, "unable to open");
-
-    strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
-    if ((out = fopen (tmpfil, "w")) == NULL)
-       adios (tmpfil, "unable to create");
-    chmod (tmpfil, 0600);
-
-    /*
-     * Are we changing the kill or erase character?
-     */
-    if (killp || erasep) {
-#ifdef HAVE_TERMIOS_H
-       cc_t save_erase, save_kill;
-#else
-       int save_erase, save_kill;
-#endif
+       if (!drft)
+               adios(NULL, "usage: %s [switches] file", invo_name);
+       if ((in = fopen(drft, "r")) == NULL)
+               adios(drft, "unable to open");
 
-       /* get the current terminal attributes */
-#ifdef HAVE_TERMIOS_H
-       tcgetattr(0, &tio);
-#else
-# ifdef HAVE_TERMIO_H
-       ioctl(0, TCGETA, &tio);
-# else
-       ioctl (0, TIOCGETP, (char *) &tio);
-       ioctl (0, TIOCGETC, (char *) &tc);
-# endif
-#endif
+       tfile = m_mktemp2(NULL, invo_name, NULL, &out);
+       if (tfile == NULL)
+               adios("prompter", "unable to create temporary file");
+       chmod(tmpfil, 0600);
+       strncpy(tmpfil, tfile, sizeof(tmpfil));
 
-       /* save original kill, erase character for later */
-       save_kill = KILL;
-       save_erase = ERASE;
-
-       /* set new kill, erase character in terminal structure */
-       KILL = killp ? chrcnv (killp) : save_kill;
-       ERASE = erasep ? chrcnv (erasep) : save_erase;
-
-       /* set the new terminal attributes */
-#ifdef HAVE_TERMIOS_H
-        tcsetattr(0, TCSADRAIN, &tio);
-#else
-# ifdef HAVE_TERMIO_H
-       ioctl(0, TCSETAW, &tio);
-# else
-       ioctl (0, TIOCSETN, (char *) &tio);
-# endif
-#endif
+       /*
+       ** Are we changing the kill or erase character?
+       */
+       if (killp || erasep) {
+               cc_t save_erase, save_kill;
 
-       /* print out new kill erase characters */
-       chrdsp ("erase", ERASE);
-       chrdsp (", kill", KILL);
-       chrdsp (", intr", INTR);
-       putchar ('\n');
-       fflush (stdout);
+               /* get the current terminal attributes */
+               tcgetattr(0, &tio);
+
+               /* save original kill, erase character for later */
+               save_kill = KILL;
+               save_erase = ERASE;
+
+               /* set new kill, erase character in terminal structure */
+               KILL = killp ? chrcnv(killp) : save_kill;
+               ERASE = erasep ? chrcnv(erasep) : save_erase;
+
+               /* set the new terminal attributes */
+                tcsetattr(0, TCSADRAIN, &tio);
+
+               /* print out new kill erase characters */
+               chrdsp("erase", ERASE);
+               chrdsp(", kill", KILL);
+               chrdsp(", intr", INTR);
+               putchar('\n');
+               fflush(stdout);
 
-       /*
-        * We set the kill and erase character back to original
-        * setup in terminal structure so we can easily
-        * restore it upon exit.
-        */
-       KILL = save_kill;
-       ERASE = save_erase;
-    }
-
-    sigint = 0;
-    SIGNAL2 (SIGINT, intrser);
-
-    /*
-     * Loop through the lines of the draft skeleton.
-     */
-    for (state = FLD;;) {
-       switch (state = m_getfld (state, name, field, sizeof(field), in)) {
-           case FLD: 
-           case FLDEOF: 
-           case FLDPLUS: 
                /*
-                * Check if the value of field contains anything
-                * other than space or tab.
-                */
-               for (cp = field; *cp; cp++)
-                   if (*cp != ' ' && *cp != '\t')
-                       break;
+               ** We set the kill and erase character back to original
+               ** setup in terminal structure so we can easily
+               ** restore it upon exit.
+               */
+               KILL = save_kill;
+               ERASE = save_erase;
+       }
 
-               /* If so, just add header line to draft */
-               if (*cp++ != '\n' || *cp != 0) {
-                   printf ("%s:%s", name, field);
-                   fprintf (out, "%s:%s", name, field);
-                   while (state == FLDPLUS) {
-                       state =
-                           m_getfld (state, name, field, sizeof(field), in);
-                       printf ("%s", field);
-                       fprintf (out, "%s", field);
-                   }
-               } else {
-                   /* Else, get value of header field */
-                   printf ("%s: ", name);
-                   fflush (stdout);
-                   i = getln (field, sizeof(field));
-                   if (i == -1) {
+       sigint = 0;
+       SIGNAL2(SIGINT, intrser);
+
+       /*
+       ** Loop through the lines of the draft skeleton.
+       */
+       for (state = FLD;;) {
+               switch (state = m_getfld(state, name, field, sizeof(field),
+                               in)) {
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       /*
+                       ** Check if the value of field contains
+                       ** anything other than space or tab.
+                       */
+                       for (cp = field; *cp; cp++)
+                               if (*cp != ' ' && *cp != '\t')
+                                       break;
+
+                       /* If so, just add header line to draft */
+                       if (*cp++ != '\n' || *cp != 0) {
+                               printf("%s:%s", name, field);
+                               fprintf(out, "%s:%s", name, field);
+                               while (state == FLDPLUS) {
+                                       state = m_getfld(state, name, field,
+                                                       sizeof(field), in);
+                                       printf("%s", field);
+                                       fprintf(out, "%s", field);
+                               }
+                       } else {
+                               /* Else, get value of header field */
+                               printf("%s: ", name);
+                               fflush(stdout);
+                               i = getln(field, sizeof(field));
+                               if (i == -1) {
 abort:
-                       if (killp || erasep) {
-#ifdef HAVE_TERMIOS_H
-                           tcsetattr(0, TCSADRAIN, &tio);
-#else
-# ifdef HAVE_TERMIO
-                           ioctl (0, TCSETA, &tio);
-# else
-                           ioctl (0, TIOCSETN, (char *) &tio);
-# endif
-#endif
+                                       if (killp || erasep) {
+                                               tcsetattr(0, TCSADRAIN, &tio);
+                                       }
+                                       unlink(tmpfil);
+                                       done(1);
+                               }
+                               if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
+                                       fprintf(out, "%s:", name);
+                                       do {
+                                               if (field[0] != ' ' && field[0] != '\t')
+                                                       putc(' ', out);
+                                               fprintf(out, "%s", field);
+                                       } while (i == 1 && (i = getln(field, sizeof(field))) >= 0);
+                                       if (i == -1)
+                                               goto abort;
+                               }
                        }
-                       unlink (tmpfil);
-                       done (1);
-                   }
-                   if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
-                       fprintf (out, "%s:", name);
-                       do {
-                           if (field[0] != ' ' && field[0] != '\t')
-                               putc (' ', out);
-                           fprintf (out, "%s", field);
-                       } while (i == 1
-                                   && (i = getln (field, sizeof(field))) >= 0);
-                       if (i == -1)
-                           goto abort;
-                   }
-               }
 
-               if (state == FLDEOF) {  /* moby hack */
-                   fprintf (out, "--------\n");
-                   printf ("--------\n");
-                   if (!body)
-                       break;
-                   goto no_body;
-               }
-               continue;
-
-           case BODY: 
-           case BODYEOF:
-           case FILEEOF: 
-               if (!body)
-                   break;
-               fprintf (out, "--------\n");
-               if (field[0] == 0 || !prepend)
-                   printf ("--------\n");
-               if (field[0]) {
-                   if (prepend && body) {
-                       printf ("\n--------Enter initial text\n\n");
-                       fflush (stdout);
-                       for (;;) {
-                           getln (buffer, sizeof(buffer));
-                           if (doteof && buffer[0] == '.' && buffer[1] == '\n')
-                               break;
-                           if (buffer[0] == 0)
+                       if (state == FLDEOF) {  /* moby hack */
+                               fprintf(out, "--------\n");
+                               printf("--------\n");
+                               if (!body)
+                                       break;
+                               goto no_body;
+                       }
+                       continue;
+
+               case BODY:
+               case BODYEOF:
+               case FILEEOF:
+                       if (!body)
                                break;
-                           fprintf (out, "%s", buffer);
+                       fprintf(out, "--------\n");
+                       if (field[0] == 0 || !prepend)
+                               printf("--------\n");
+                       if (field[0]) {
+                               if (prepend && body) {
+                                       printf("\n--------Enter initial text\n\n");
+                                       fflush(stdout);
+                                       for (;;) {
+                                               getln(buffer, sizeof(buffer));
+                                               if (doteof && buffer[0] == '.' && buffer[1] == '\n')
+                                                       break;
+                                               if (buffer[0] == 0)
+                                                       break;
+                                               fprintf(out, "%s", buffer);
+                                       }
+                               }
+
+                               do {
+                                       fprintf(out, "%s", field);
+                                       if (!rapid && !sigint)
+                                               printf("%s", field);
+                               } while (state == BODY && (state = m_getfld(state, name, field, sizeof(field), in)));
+                               if (prepend || !body)
+                                       break;
+                               else
+                                       printf ("\n--------Enter additional text\n\n");
                        }
-                   }
-
-                   do {
-                       fprintf (out, "%s", field);
-                       if (!rapid && !sigint)
-                           printf ("%s", field);
-                   } while (state == BODY &&
-                           (state = m_getfld (state, name, field, sizeof(field), in)));
-                   if (prepend || !body)
-                       break;
-                   else
-                       printf ("\n--------Enter additional text\n\n");
-               }
 no_body:
-               fflush (stdout);
-               for (;;) {
-                   getln (field, sizeof(field));
-                   if (doteof && field[0] == '.' && field[1] == '\n')
-                       break;
-                   if (field[0] == 0)
+                       fflush(stdout);
+                       for (;;) {
+                               getln(field, sizeof(field));
+                               if (doteof && field[0] == '.' && field[1] == '\n')
+                                       break;
+                               if (field[0] == 0)
+                                       break;
+                                fprintf(out, "%s", field);
+                       }
                        break;
-                   fprintf (out, "%s", field);
+
+               default:
+                       adios(NULL, "skeleton is poorly formatted");
                }
                break;
+       }
+
+       if (body)
+               printf("--------\n");
+
+       fflush(stdout);
+       fclose(in);
+       fclose(out);
+       SIGNAL(SIGINT, SIG_IGN);
 
-           default: 
-               adios (NULL, "skeleton is poorly formatted");
+       if (killp || erasep) {
+                tcsetattr(0, TCSADRAIN, &tio);
        }
-       break;
-    }
-
-    if (body)
-       printf ("--------\n");
-
-    fflush (stdout);
-    fclose (in);
-    fclose (out);
-    SIGNAL (SIGINT, SIG_IGN);
-
-    if (killp || erasep) {
-#ifdef HAVE_TERMIOS_H
-        tcsetattr(0, TCSADRAIN, &tio);
-#else
-# ifdef HAVE_TERMIO_H
-       ioctl (0, TCSETAW, &tio);
-# else
-       ioctl (0, TIOCSETN, (char *) &tio);
-# endif
-#endif
-    }
-
-    if ((fdi = open (tmpfil, O_RDONLY)) == NOTOK)
-       adios (tmpfil, "unable to re-open");
-    if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
-       adios (drft, "unable to write");
-    cpydata (fdi, fdo, tmpfil, drft);
-    close (fdi);
-    close (fdo);
-    unlink (tmpfil);
-
-    context_save ();   /* save the context file */
-    done (0);
+
+       if ((fdi = open(tmpfil, O_RDONLY)) == NOTOK)
+               adios(tmpfil, "unable to re-open");
+       if ((fdo = creat(drft, m_gmprot())) == NOTOK)
+               adios(drft, "unable to write");
+       cpydata(fdi, fdo, tmpfil, drft);
+       close(fdi);
+       close(fdo);
+       unlink(tmpfil);
+
+       context_save();  /* save the context file */
+       done(0);
+       return 1;
 }
 
 
 int
-getln (char *buffer, int n)
+getln(char *buffer, int n)
 {
-    int c;
-    char *cp;
-
-    cp = buffer;
-    *cp = 0;
-
-    switch (setjmp (sigenv)) {
-       case OK: 
-           wtuser = 1;
-           break;
-
-       case DONE: 
-           wtuser = 0;
-           return 0;
-
-       default: 
-           wtuser = 0;
-           return NOTOK;
-    }
-
-    for (;;) {
-       switch (c = getchar ()) {
-           case EOF: 
-               clearerr (stdin);
-               longjmp (sigenv, DONE);
-
-           case '\n': 
-               if (cp[-1] == QUOTE) {
-                   cp[-1] = c;
-                   wtuser = 0;
-                   return 1;
-               }
-               *cp++ = c;
-               *cp = 0;
+       int c;
+       char *cp;
+
+       cp = buffer;
+       *cp = 0;
+
+       switch (setjmp(sigenv)) {
+       case OK:
+               wtuser = 1;
+               break;
+
+       case DONE:
                wtuser = 0;
                return 0;
 
-           default: 
-               if (cp < buffer + n)
-                   *cp++ = c;
-               *cp = 0;
+       default:
+               wtuser = 0;
+               return NOTOK;
+       }
+
+       for (;;) {
+               switch (c = getchar()) {
+               case EOF:
+                       clearerr(stdin);
+                       longjmp(sigenv, DONE);
+
+               case '\n':
+                       if (cp[-1] == QUOTE) {
+                               cp[-1] = c;
+                               wtuser = 0;
+                               return 1;
+                       }
+                       *cp++ = c;
+                       *cp = 0;
+                       wtuser = 0;
+                       return 0;
+
+               default:
+                       if (cp < buffer + n)
+                               *cp++ = c;
+                       *cp = 0;
+               }
        }
-    }
 }
 
 
-static RETSIGTYPE
-intrser (int i)
+static void
+intrser(int i)
 {
-#ifndef        RELIABLE_SIGNALS
-    SIGNAL (SIGINT, intrser);
-#endif
-
-    if (wtuser)
-       longjmp (sigenv, NOTOK);
-    sigint++;
+       if (wtuser)
+               longjmp(sigenv, NOTOK);
+       sigint++;
 }
 
 
 static int
-chrcnv (char *cp)
+chrcnv(char *cp)
 {
-    return (*cp != QUOTE ? *cp : m_atoi (++cp));
+       return (*cp != QUOTE ? *cp : m_atoi(++cp));
 }
 
 
 static void
-chrdsp (char *s, char c)
+chrdsp(char *s, char c)
 {
-    printf ("%s ", s);
-    if (c < ' ' || c == 0177)
-       printf ("^%c", c ^ 0100);
-    else
-       printf ("%c", c);
+       printf("%s ", s);
+       if (c < ' ' || c == 0177)
+               printf("^%c", c ^ 0100);
+       else
+               printf("%c", c);
 }