+#
+
+/*
+ * Mail -- a mail program
+ *
+ * Generally useful tty stuff.
+ */
+
+#include "rcv.h"
+#include <sgtty.h>
+
+static char *SccsId = "@(#)tty.c 1.1 %G%";
+
+static int c_erase; /* Current erase char */
+static int c_kill; /* Current kill char */
+#ifndef TIOCSTI
+static int ttyset; /* We must now do erase/kill */
+#endif
+
+/*
+ * Read all relevant header fields.
+ */
+
+grabh(hp, gflags)
+ struct header *hp;
+{
+ struct sgttyb ttybuf;
+#ifndef TIOCSTI
+ int (*savesigs[2])();
+#endif
+ register int s;
+ int errs;
+
+ errs = 0;
+#ifndef TIOCSTI
+ ttyset = 0;
+#endif
+ if (gtty(fileno(stdin), &ttybuf) < 0) {
+ perror("gtty");
+ return(-1);
+ }
+ c_erase = ttybuf.sg_erase;
+ c_kill = ttybuf.sg_kill;
+#ifndef TIOCSTI
+ ttybuf.sg_erase = 0;
+ ttybuf.sg_kill = 0;
+ for (s = SIGINT; s <= SIGQUIT; s++)
+ if ((savesigs[s-SIGINT] = signal(s, SIG_IGN)) == SIG_DFL)
+ signal(s, SIG_DFL);
+#endif
+ if (gflags & GTO) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_to != NOSTR)
+ ttyset++, stty(fileno(stdin), &ttybuf);
+#endif
+ hp->h_to = readtty("To: ", hp->h_to);
+ if (hp->h_to != NOSTR)
+ hp->h_seq++;
+ }
+ if (gflags & GSUBJECT) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_subject != NOSTR)
+ ttyset++, stty(fileno(stdin), &ttybuf);
+#endif
+ hp->h_subject = readtty("Subject: ", hp->h_subject);
+ if (hp->h_subject != NOSTR)
+ hp->h_seq++;
+ }
+ if (gflags & GCC) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_cc != NOSTR)
+ ttyset++, stty(fileno(stdin), &ttybuf);
+#endif
+ hp->h_cc = readtty("Cc: ", hp->h_cc);
+ if (hp->h_cc != NOSTR)
+ hp->h_seq++;
+ }
+ if (gflags & GBCC) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_bcc != NOSTR)
+ ttyset++, stty(fileno(stdin), &ttybuf);
+#endif
+ hp->h_bcc = readtty("Bcc: ", hp->h_bcc);
+ if (hp->h_bcc != NOSTR)
+ hp->h_seq++;
+ }
+#ifndef TIOCSTI
+ ttybuf.sg_erase = c_erase;
+ ttybuf.sg_kill = c_kill;
+ if (ttyset)
+ stty(fileno(stdin), &ttybuf);
+ for (s = SIGINT; s <= SIGQUIT; s++)
+ signal(s, savesigs[s-SIGINT]);
+#endif
+ return(errs);
+}
+
+/*
+ * Read up a header from standard input.
+ * The source string has the preliminary contents to
+ * be read.
+ *
+ */
+
+char *
+readtty(pr, src)
+ char pr[], src[];
+{
+ char canonb[BUFSIZ];
+ int c, ch;
+ register char *cp, *cp2;
+
+ fputs(pr, stdout); fflush(stdout);
+ if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
+ printf("too long to edit\n");
+ return(src);
+ }
+#ifndef TIOCSTI
+ if (src != NOSTR)
+ cp = copy(src, canonb);
+ else
+ cp = copy("", canonb);
+ fputs(canonb, stdout);
+ fflush(stdout);
+#else
+ for (cp = src; c = *cp; cp++) {
+ if (c == c_erase || c == c_kill) {
+ ch = '\\';
+ ioctl(0, TIOCSTI, &ch);
+ }
+ ioctl(0, TIOCSTI, &c);
+ }
+ cp = canonb;
+#endif
+ cp2 = fgets(cp, BUFSIZ - (cp - canonb), stdin);
+ canonb[strlen(canonb) - 1] = '\0';
+#ifndef TIOCSTI
+ if (cp2 == NOSTR || *cp2 == '\0')
+ return(src);
+ cp = cp2;
+ if (!ttyset)
+ return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
+ while (*cp != '\0') {
+ c = *cp++;
+ if (c == c_erase) {
+ if (cp2 == canonb)
+ continue;
+ if (cp2[-1] == '\\') {
+ cp2[-1] = c;
+ continue;
+ }
+ cp2--;
+ continue;
+ }
+ if (c == c_kill) {
+ if (cp2 == canonb)
+ continue;
+ if (cp2[-1] == '\\') {
+ cp2[-1] = c;
+ continue;
+ }
+ cp2 = canonb;
+ continue;
+ }
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+#endif
+ if (equal("", canonb))
+ return(NOSTR);
+ return(savestr(canonb));
+}