#include <errno.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
-
-#define QUOTE '\\'
-
-#ifndef CKILL
-# define CKILL '@'
-#endif
-
-#ifndef CERASE
-# define CERASE '#'
-#endif
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sysexits.h>
static struct swit switches[] = {
-#define ERASESW 0
- { "erase chr", 0 },
-#define KILLSW 1
- { "kill chr", 0 },
-#define PREPSW 2
+#define PREPSW 0
{ "prepend", 0 },
-#define NPREPSW 3
- { "noprepend", 0 },
-#define RAPDSW 4
+#define NPREPSW 1
+ { "noprepend", 2 },
+#define RAPDSW 2
{ "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
+#define NRAPDSW 3
+ { "norapid", 2 },
+#define BODYSW 4
+ { "body", 0 },
+#define NBODYSW 5
+ { "nobody", 2 },
+#define VERSIONSW 6
+ { "Version", 0 },
+#define HELPSW 7
{ "help", 0 },
{ NULL, 0 }
};
-#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
-
-static int wtuser = 0;
-static int sigint = 0;
+volatile sig_atomic_t wtuser = 0;
+volatile sig_atomic_t sigint = 0;
static jmp_buf sigenv;
/*
** prototypes
*/
-int getln (char *, int);
-static int chrcnv (char *);
-static void chrdsp (char *, char);
-static RETSIGTYPE intrser (int);
+int getln(char *, int);
+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];
+ int qbody = 1, prepend = 1, rapid = 0;
+ int fdi, fdo, i, state;
+ char *cp, *drft = NULL;
+ char name[NAMESZ], field[BUFSIZ];
char buffer[BUFSIZ], tmpfil[BUFSIZ];
char **arguments, **argp;
FILE *in, *out;
char *tfile = NULL;
-#ifdef LOCALE
setlocale(LC_ALL, "");
-#endif
- invo_name = r1bindex (argv[0], '/');
+ invo_name = mhbasename(argv[0]);
/* read user profile/context */
context_read();
- arguments = getarguments (invo_name, argc, argv, 1);
+ arguments = getarguments(invo_name, argc, argv, 1);
argp = arguments;
- while ((cp = *argp++))
+ 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;
+ switch (smatch(++cp, switches)) {
+ case AMBIGSW:
+ ambigsw(cp, switches);
+ exit(EX_USAGE);
+ case UNKWNSW:
+ adios(EX_USAGE, NULL, "-%s unknown", cp);
+
+ case HELPSW:
+ snprintf(buffer, sizeof(buffer),
+ "%s [switches] file",
+ invo_name);
+ print_help(buffer, switches, 1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
+ case VERSIONSW:
+ print_version(invo_name);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
+ case PREPSW:
+ prepend++;
+ continue;
+ case NPREPSW:
+ prepend = 0;
+ continue;
+
+ case RAPDSW:
+ rapid++;
+ continue;
+ case NRAPDSW:
+ rapid = 0;
+ continue;
+
+ case BODYSW:
+ qbody++;
+ continue;
+ case NBODYSW:
+ qbody = 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");
+ if (!drft) {
+ adios(EX_USAGE, NULL, "usage: %s [switches] file", invo_name);
+ }
+ if ((in = fopen(drft, "r")) == NULL) {
+ adios(EX_IOERR, drft, "unable to open");
+ }
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));
-
- /*
- ** 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
-
- /* 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
-
- /* 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
-
- /* 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;
+ if (tfile == NULL) {
+ adios(EX_CANTCREAT, "prompter", "unable to create temporary file");
}
+ chmod(tmpfil, 0600);
+ strncpy(tmpfil, tfile, sizeof(tmpfil));
sigint = 0;
- SIGNAL2 (SIGINT, intrser);
+ 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) {
+ switch (state = m_getfld(state, name, field, sizeof(field),
+ in)) {
+ case FLD:
+ 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) {
+ 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
- }
- 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);
+ exit(EX_DATAERR);
}
-
- if (state == FLDEOF) { /* moby hack */
- fprintf (out, "--------\n");
- printf ("--------\n");
- if (!body)
- break;
- goto no_body;
+ if (i || (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;
}
- 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)
- break;
- fprintf (out, "%s", buffer);
- }
- }
+ continue;
- 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");
+ case BODY:
+ case FILEEOF:
+ fprintf(out, "--------\n");
+ if (qbody) {
+ if (!*field) {
+ printf("--------\n");
+ goto has_no_body;
}
-no_body:
- fflush (stdout);
- for (;;) {
- getln (field, sizeof(field));
- if (doteof && field[0] == '.' && field[1] == '\n')
- break;
- if (field[0] == 0)
- break;
- fprintf (out, "%s", field);
+
+ if (prepend) {
+ printf("--------Enter initial text\n");
+ fflush(stdout);
+ for (;;) {
+ getln(buffer, sizeof(buffer));
+ if (!*buffer)
+ break;
+ fprintf(out, "%s", buffer);
+ }
+ } else {
+ printf("--------\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 || !qbody)
break;
- default:
- adios (NULL, "skeleton is poorly formatted");
+ printf("--------Enter additional text\n");
+has_no_body:
+ fflush(stdout);
+ for (;;) {
+ getln(field, sizeof(field));
+ if (!*field)
+ break;
+ fprintf(out, "%s", field);
+ }
+ break;
+
+ default:
+ adios(EX_DATAERR, NULL, "skeleton is poorly formatted");
}
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 (qbody)
+ printf("--------\n");
+
+ fflush(stdout);
+ fclose(in);
+ fclose(out);
+ SIGNAL(SIGINT, SIG_IGN);
+
+ if ((fdi = open(tmpfil, O_RDONLY)) == NOTOK) {
+ adios(EX_IOERR, tmpfil, "unable to re-open");
}
+ if ((fdo = creat(drft, m_gmprot())) == NOTOK) {
+ adios(EX_IOERR, drft, "unable to write");
+ }
+ cpydata(fdi, fdo, tmpfil, drft);
+ close(fdi);
+ close(fdo);
+ unlink(tmpfil);
- 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;
+ context_save(); /* save the context file */
+ return EX_OK;
}
int
-getln (char *buffer, int n)
+getln(char *buffer, int n)
{
int c;
+ sig_atomic_t psigint = sigint;
char *cp;
cp = buffer;
- *cp = 0;
+ *cp = '\0';
- switch (setjmp (sigenv)) {
- case OK:
- wtuser = 1;
- break;
+ switch (setjmp(sigenv)) {
+ case 0:
+ wtuser = 1;
+ break;
- case DONE:
- wtuser = 0;
+ default:
+ wtuser = 0;
+ if (sigint == psigint) {
return 0;
-
- default:
- wtuser = 0;
+ } else {
+ sigint = psigint;
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;
+ switch (c = getchar()) {
+ case EOF:
+ clearerr(stdin);
+ longjmp(sigenv, DONE);
+
+ case '\n':
+ if (cp[-1] == '\\') {
+ cp[-1] = c;
wtuser = 0;
- return 0;
+ return 1;
+ }
+ *cp++ = c;
+ *cp = '\0';
+ wtuser = 0;
+ return 0;
- default:
- if (cp < buffer + n)
- *cp++ = c;
- *cp = 0;
+ default:
+ if (cp < buffer + n)
+ *cp++ = c;
+ *cp = '\0';
}
}
}
-static RETSIGTYPE
-intrser (int i)
-{
-#ifndef RELIABLE_SIGNALS
- SIGNAL (SIGINT, intrser);
-#endif
-
- if (wtuser)
- longjmp (sigenv, NOTOK);
- sigint++;
-}
-
-
-static int
-chrcnv (char *cp)
-{
- return (*cp != QUOTE ? *cp : m_atoi (++cp));
-}
-
-
static void
-chrdsp (char *s, char c)
+intrser(int i)
{
- printf ("%s ", s);
- if (c < ' ' || c == 0177)
- printf ("^%c", c ^ 0100);
- else
- printf ("%c", c);
+ if (wtuser) {
+ close(STDIN_FILENO);
+ }
+ sigint++;
}