summaryrefslogtreecommitdiff
path: root/usr.bin/mail/fio.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/mail/fio.c')
-rw-r--r--usr.bin/mail/fio.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/usr.bin/mail/fio.c b/usr.bin/mail/fio.c
index 3589a49c3f9..3fef0ff1b8a 100644
--- a/usr.bin/mail/fio.c
+++ b/usr.bin/mail/fio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $ */
+/* $OpenBSD: fio.c,v 1.19 2001/11/20 20:50:00 millert Exp $ */
/* $NetBSD: fio.c,v 1.8 1997/07/07 22:57:55 phil Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)fio.c 8.2 (Berkeley) 4/20/95";
#else
-static char rcsid[] = "$OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $";
+static char rcsid[] = "$OpenBSD: fio.c,v 1.19 2001/11/20 20:50:00 millert Exp $";
#endif
#endif /* not lint */
@@ -57,6 +57,8 @@ static char rcsid[] = "$OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $"
* File I/O.
*/
+static volatile sig_atomic_t fiosignal;
+
/*
* Wrapper for read() to catch EINTR.
*/
@@ -206,22 +208,67 @@ putline(obuf, linebuf, outlf)
* include the newline (or carriage return) at the end.
*/
int
-readline(ibuf, linebuf, linesize)
+readline(ibuf, linebuf, linesize, signo)
FILE *ibuf;
char *linebuf;
int linesize;
+ int *signo;
{
+ struct sigaction act;
+ struct sigaction savetstp;
+ struct sigaction savettou;
+ struct sigaction savettin;
+ struct sigaction saveint;
+ struct sigaction savehup;
+ sigset_t oset;
int n;
+ /*
+ * Setup signal handlers if the caller asked us to catch signals.
+ * Note that we do not restart system calls since we need the
+ * read to be interuptible.
+ */
+ if (signo) {
+ fiosignal = 0;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = fioint;
+ if (sigaction(SIGINT, NULL, &saveint) == 0 &&
+ saveint.sa_handler != SIG_IGN) {
+ (void)sigaction(SIGINT, &act, &saveint);
+ (void)sigprocmask(SIG_UNBLOCK, &intset, &oset);
+ }
+ if (sigaction(SIGHUP, NULL, &savehup) == 0 &&
+ savehup.sa_handler != SIG_IGN)
+ (void)sigaction(SIGHUP, &act, &savehup);
+ (void)sigaction(SIGTSTP, &act, &savetstp);
+ (void)sigaction(SIGTTOU, &act, &savettou);
+ (void)sigaction(SIGTTIN, &act, &savettin);
+ }
+
clearerr(ibuf);
- if (fgets(linebuf, linesize, ibuf) == NULL)
- return(-1);
+ if (fgets(linebuf, linesize, ibuf) == NULL) {
+ if (ferror(ibuf))
+ clearerr(ibuf);
+ n = -1;
+ } else {
+ n = strlen(linebuf);
+ if (n > 0 && linebuf[n - 1] == '\n')
+ linebuf[--n] = '\0';
+ if (n > 0 && linebuf[n - 1] == '\r')
+ linebuf[--n] = '\0';
+ }
+
+ if (signo) {
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+ (void)sigaction(SIGINT, &saveint, NULL);
+ (void)sigaction(SIGHUP, &savehup, NULL);
+ (void)sigaction(SIGTSTP, &savetstp, NULL);
+ (void)sigaction(SIGTTOU, &savettou, NULL);
+ (void)sigaction(SIGTTIN, &savettin, NULL);
+ *signo = fiosignal;
+ }
- n = strlen(linebuf);
- if (n > 0 && linebuf[n - 1] == '\n')
- linebuf[--n] = '\0';
- if (n > 0 && linebuf[n - 1] == '\r')
- linebuf[--n] = '\0';
return(n);
}
@@ -340,6 +387,34 @@ relsesigs()
}
/*
+ * Unblock and ignore a signal
+ */
+int
+ignoresig(sig, oact, oset)
+ int sig;
+ struct sigaction *oact;
+ sigset_t *oset;
+{
+ struct sigaction act;
+ sigset_t nset;
+ int error;
+
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ act.sa_handler = SIG_IGN;
+ error = sigaction(sig, &act, oact);
+
+ if (error == 0) {
+ sigemptyset(&nset);
+ sigaddset(&nset, sig);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, oset);
+ } else if (oset != NULL)
+ (void)sigprocmask(SIG_BLOCK, NULL, oset);
+
+ return(error);
+}
+
+/*
* Determine the size of the file possessed by
* the passed buffer.
*/
@@ -493,3 +568,15 @@ getdeadletter()
}
return(cp);
}
+
+/*
+ * Signal handler used by readline() to catch SIGINT, SIGHUP, SIGTSTP,
+ * SIGTTOU, SIGTTIN.
+ */
+void
+fioint(s)
+ int s;
+{
+
+ fiosignal = s;
+}