+/* prompter.c - prompting editor front-end */
+
+#include "../h/mh.h"
+#include <stdio.h>
+#include <errno.h>
+#ifndef SYS5
+#include <sgtty.h>
+#else SYS5
+#include <sys/types.h>
+#include <termio.h>
+#include <sys/ioctl.h>
+#endif SYS5
+#ifdef BSD42
+#include <setjmp.h>
+#endif BSD42
+#include <signal.h>
+
+
+#define QUOTE '\\'
+#ifndef CKILL
+#define CKILL '@'
+#endif not CKILL
+#ifndef CERASE
+#define CERASE '#'
+#endif not CERASE
+
+/* \f */
+
+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 HELPSW 8
+ "help", 4,
+
+ NULL, NULL
+};
+
+/* \f */
+
+extern int errno;
+
+
+#ifndef SYS5
+#define ERASE sg.sg_erase
+#define KILL sg.sg_kill
+static struct sgttyb sg;
+
+#define INTR tc.t_intrc
+static struct tchars tc;
+#else SYS5
+#define ERASE sg.c_cc[VERASE]
+#define KILL sg.c_cc[VKILL]
+#define INTR sg.c_cc[VINTR]
+static struct termio sg;
+#endif SYS5
+
+
+int intrser ();
+
+static int wtuser = 0;
+static int sigint = 0;
+
+#ifdef BSD42
+static jmp_buf sigenv;
+#endif BSD42
+
+/* \f */
+
+/* ARGSUSED */
+
+main (argc, argv)
+int argc;
+char *argv[];
+{
+ int body = 1,
+ prepend = 1,
+ rapid = 0,
+ fdi,
+ fdo,
+ i,
+ state;
+ char *cp,
+ *drft = NULL,
+ *erasep = NULL,
+ *killp = NULL,
+ name[NAMESZ],
+ field[BUFSIZ],
+ buffer[BUFSIZ],
+ tmpfil[BUFSIZ],
+ **ap,
+ *arguments[MAXARGS],
+ **argp;
+ FILE *in, *out;
+
+ invo_name = r1bindex (argv[0], '/');
+ if ((cp = m_find (invo_name)) != NULL) {
+ ap = brkstring (cp = getcpy (cp), " ", "\n");
+ ap = copyip (ap, arguments);
+ }
+ else
+ ap = arguments;
+ (void) copyip (argv + 1, ap);
+ argp = arguments;
+
+/* \f */
+
+ while (cp = *argp++)
+ if (*cp == '-')
+ switch (smatch (++cp, switches)) {
+ case AMBIGSW:
+ ambigsw (cp, switches);
+ done (1);
+ case UNKWNSW:
+ adios (NULLCP, "-%s unknown", cp);
+ case HELPSW:
+ (void) sprintf (buffer, "%s [switches] file", invo_name);
+ help (buffer, switches);
+ done (1);
+
+ case ERASESW:
+ if (!(erasep = *argp++) || *erasep == '-')
+ adios (NULLCP, "missing argument to %s", argp[-2]);
+ continue;
+ case KILLSW:
+ if (!(killp = *argp++) || *killp == '-')
+ adios (NULLCP, "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;
+ }
+ else
+ if (!drft)
+ drft = cp;
+
+/* \f */
+
+ if (!drft)
+ adios (NULLCP, "usage: %s [switches] file", invo_name);
+ if ((in = fopen (drft, "r")) == NULL)
+ adios (drft, "unable to open");
+
+ (void) strcpy (tmpfil, m_tmpfil (invo_name));
+ if ((out = fopen (tmpfil, "w")) == NULL)
+ adios (tmpfil, "unable to create");
+ (void) chmod (tmpfil, 0600);
+
+ if (killp || erasep) {
+#ifndef SYS5
+ int serase,
+ skill;
+#else SYS5
+ char serase,
+ skill;
+#endif SYS5
+
+#ifndef SYS5
+ (void) ioctl (0, TIOCGETP, (char *) &sg);
+ (void) ioctl (0, TIOCGETC, (char *) &tc);
+#else SYS5
+ (void) ioctl(0, TCGETA, &sg);
+#endif SYS5
+ skill = KILL;
+ serase = ERASE;
+ KILL = killp ? chrcnv (killp) : skill;
+ ERASE = erasep ? chrcnv (erasep) : serase;
+#ifndef SYS5
+ (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else SYS5
+ (void) ioctl(0, TCSETAW, &sg);
+#endif SYS5
+
+ chrdsp ("erase", ERASE);
+ chrdsp (", kill", KILL);
+ chrdsp (", intr", INTR);
+ (void) putchar ('\n');
+ (void) fflush (stdout);
+
+ KILL = skill;
+ ERASE = serase;
+ }
+
+/* \f */
+
+ sigint = 0;
+ setsig (SIGINT, intrser);
+
+ for (state = FLD;;) {
+ switch (state = m_getfld (state, name, field, sizeof field, in)) {
+ case FLD:
+ case FLDEOF:
+ case FLDPLUS:
+ for (cp = field; *cp; cp++)
+ if (*cp != ' ' && *cp != '\t')
+ break;
+ if (*cp++ != '\n' || *cp != NULL) {
+ 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 {
+ printf ("%s: ", name);
+ (void) fflush (stdout);
+ i = getln (field, sizeof field);
+ if (i == -1) {
+abort: ;
+ if (killp || erasep)
+#ifndef SYS5
+ (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else SYS5
+ (void) ioctl (0, TCSETA, &sg);
+#endif SYS5
+ (void) unlink (tmpfil);
+ done (1);
+ }
+ if (i != 0 || (field[0] != '\n' && field[0] != NULL)) {
+ fprintf (out, "%s:", name);
+ do {
+ if (field[0] != ' ' && field[0] != '\t')
+ (void) 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:
+ fprintf (out, "--------\n");
+ if (field[0] == NULL || !prepend)
+ printf ("--------\n");
+ if (field[0]) {
+ if (prepend && body) {
+ printf ("\n--------Enter initial text\n\n");
+ (void) fflush (stdout);
+ for (;;) {
+ (void) getln (buffer, sizeof buffer);
+ if (buffer[0] == NULL)
+ 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");
+ }
+no_body: ;
+ (void) fflush (stdout);
+ for (;;) {
+ (void) getln (field, sizeof field);
+ if (field[0] == NULL)
+ break;
+ fprintf (out, "%s", field);
+ }
+ break;
+
+ default:
+ adios (NULLCP, "skeleton is poorly formatted");
+ }
+ break;
+ }
+
+ if (body)
+ printf ("--------\n");
+ (void) fflush (stdout);
+
+ (void) fclose (in);
+ (void) fclose (out);
+
+ (void) signal (SIGINT, SIG_IGN);
+
+/* \f */
+
+ if (killp || erasep)
+#ifndef SYS5
+ (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else SYS5
+ (void) ioctl (0, TCSETAW, &sg);
+#endif SYS5
+
+ if ((fdi = open (tmpfil, 0)) == NOTOK)
+ adios (tmpfil, "unable to re-open");
+ if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
+ adios (drft, "unable to write");
+ cpydata (fdi, fdo, tmpfil, drft);
+ (void) close (fdi);
+ (void) close (fdo);
+ (void) unlink (tmpfil);
+
+ m_update ();
+
+ done (0);
+}
+
+/* \f */
+
+getln (buffer, n)
+register char *buffer;
+register int n;
+{
+ int c;
+ char *cp;
+
+ cp = buffer;
+ *cp = NULL;
+
+#ifndef BSD42
+ wtuser = 1;
+#else BSD42
+ switch (setjmp (sigenv)) {
+ case OK:
+ wtuser = 1;
+ break;
+
+ case DONE:
+ wtuser = 0;
+ return 0;
+
+ default:
+ wtuser = 0;
+ return NOTOK;
+ }
+#endif BSD42
+
+ for (;;)
+ switch (c = getchar ()) {
+ case EOF:
+#ifndef BSD42
+ wtuser = 0;
+ return (errno != EINTR ? 0 : NOTOK);
+#else BSD42
+ clearerr (stdin);
+ longjmp (sigenv, DONE);
+#endif BSD42
+
+ case '\n':
+ if (cp[-1] == QUOTE) {
+ cp[-1] = c;
+ wtuser = 0;
+ return 1;
+ }
+ *cp++ = c;
+ *cp = NULL;
+ wtuser = 0;
+ return 0;
+
+ default:
+ if (cp < buffer + n)
+ *cp++ = c;
+ *cp = NULL;
+ }
+}
+
+/* \f */
+
+/* ARGSUSED */
+
+static int intrser (i)
+int i;
+{
+#ifndef BSD42
+ (void) signal (SIGINT, intrser);
+ if (!wtuser)
+ sigint++;
+#else BSD42
+ if (wtuser)
+ longjmp (sigenv, NOTOK);
+ sigint++;
+#endif BSD42
+}
+
+
+chrcnv (cp)
+register char *cp;
+{
+ return (*cp != QUOTE ? *cp : m_atoi (++cp));
+}
+
+
+chrdsp (s, c)
+char *s,
+ c;
+{
+ printf ("%s ", s);
+ if (c < ' ' || c == 0177)
+ printf ("^%c", c ^ 0100);
+ else
+ printf ("%c", c);
+}