#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);
+static void intrser(int);
int
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 = mhbasename(argv[0]);
/* read user profile/context */
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);
+ exit(EX_USAGE);
case UNKWNSW:
- adios(NULL, "-%s unknown", cp);
+ adios(EX_USAGE, NULL, "-%s unknown", cp);
case HELPSW:
snprintf(buffer, sizeof(buffer),
"%s [switches] file",
invo_name);
print_help(buffer, switches, 1);
- done(1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
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;
+ exit(argc == 2 ? EX_OK : EX_USAGE);
case PREPSW:
prepend++;
continue;
case BODYSW:
- body++;
+ qbody++;
continue;
case NBODYSW:
- body = 0;
- continue;
-
- case DOTSW:
- doteof++;
- continue;
- case NDOTSW:
- doteof = 0;
+ 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");
+ if (tfile == NULL) {
+ adios(EX_CANTCREAT, "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;
- }
-
sigint = 0;
SIGNAL2(SIGINT, intrser);
break;
/* If so, just add header line to draft */
- if (*cp++ != '\n' || *cp != 0) {
+ if (*cp++ != '\n' || *cp) {
printf("%s:%s", name, field);
fprintf(out, "%s:%s", name, field);
while (state == FLDPLUS) {
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);
+ exit(EX_DATAERR);
}
- if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
+ if (i || (field[0]!='\n' && field[0]!='\0')) {
fprintf(out, "%s:", name);
do {
if (field[0] != ' ' && field[0] != '\t')
}
if (state == FLDEOF) { /* moby hack */
+ /* draft has no body separator; only headers */
fprintf(out, "--------\n");
- printf("--------\n");
- if (!body)
+ if (!qbody)
break;
- goto no_body;
+ printf("--------\n");
+ goto has_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");
+ if (qbody) {
+ if (!*field) {
+ printf("--------\n");
+ goto has_no_body;
+ }
+
+ if (prepend) {
+ printf("--------Enter initial text\n");
fflush(stdout);
for (;;) {
getln(buffer, sizeof(buffer));
- if (doteof && buffer[0] == '.' && buffer[1] == '\n')
- break;
- if (buffer[0] == 0)
+ 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 || !body)
- break;
- else
- printf ("\n--------Enter additional text\n\n");
}
-no_body:
+
+ 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;
+
+ printf("--------Enter additional text\n");
+has_no_body:
fflush(stdout);
for (;;) {
getln(field, sizeof(field));
- if (doteof && field[0] == '.' && field[1] == '\n')
- break;
- if (field[0] == 0)
+ if (!*field)
break;
- fprintf(out, "%s", field);
+ fprintf(out, "%s", field);
}
break;
default:
- adios(NULL, "skeleton is poorly formatted");
+ adios(EX_DATAERR, NULL, "skeleton is poorly formatted");
}
break;
}
- if (body)
+ if (qbody)
printf("--------\n");
fflush(stdout);
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(EX_IOERR, tmpfil, "unable to re-open");
+ }
+ if ((fdo = creat(drft, m_gmprot())) == NOTOK) {
+ adios(EX_IOERR, drft, "unable to write");
}
-
- 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;
+ return EX_OK;
}
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:
+ case 0:
wtuser = 1;
break;
- case DONE:
- wtuser = 0;
- return 0;
-
default:
wtuser = 0;
- return NOTOK;
+ if (sigint == psigint) {
+ return 0;
+ } else {
+ sigint = psigint;
+ return NOTOK;
+ }
}
for (;;) {
longjmp(sigenv, DONE);
case '\n':
- if (cp[-1] == QUOTE) {
+ if (cp[-1] == '\\') {
cp[-1] = c;
wtuser = 0;
return 1;
}
*cp++ = c;
- *cp = 0;
+ *cp = '\0';
wtuser = 0;
return 0;
default:
if (cp < buffer + n)
*cp++ = c;
- *cp = 0;
+ *cp = '\0';
}
}
}
-static RETSIGTYPE
+static void
intrser(int i)
{
-#ifndef RELIABLE_SIGNALS
- SIGNAL(SIGINT, intrser);
-#endif
-
- if (wtuser)
- longjmp(sigenv, NOTOK);
+ if (wtuser) {
+ close(STDIN_FILENO);
+ }
sigint++;
}
-
-
-static int
-chrcnv(char *cp)
-{
- return (*cp != QUOTE ? *cp : m_atoi(++cp));
-}
-
-
-static void
-chrdsp(char *s, char c)
-{
- printf("%s ", s);
- if (c < ' ' || c == 0177)
- printf("^%c", c ^ 0100);
- else
- printf("%c", c);
-}