SIGINFO is awesome, but it's even better when it actually does
something relevant.
This makes it print the total counts so far to stderr.
Useful? Feature creep? You decide.
Index: wc.c
===
RCS file: /cvs/src/usr.bin/wc/wc.c,v
retrieving revision 1.17
diff -u -p -d -r1.17 wc.c
--- wc.c16 Jan 2015 06:40:14 - 1.17
+++ wc.c25 Jun 2015 14:49:21 -
@@ -32,6 +32,9 @@
#include sys/param.h /* MAXBSIZE */
#include sys/stat.h
#include sys/file.h
+
+#include errno.h
+#include signal.h
#include stdio.h
#include stdlib.h
#include string.h
@@ -41,18 +44,23 @@
#include unistd.h
#include util.h
+int64_tlinect, wordct, charct;
int64_ttlinect, twordct, tcharct;
intdoline, doword, dochar, humanchar;
intrval;
extern char *__progname;
+volatile sig_atomic_t wants_info = 0;
-void print_counts(int64_t, int64_t, int64_t, char *);
-void format_and_print(long long);
+void handler(int);
+ssize_treread(int, void *, size_t);
+void print_counts(FILE *, int64_t, int64_t, int64_t, char *);
+void format_and_print(FILE *, long long);
void cnt(char *);
int
main(int argc, char *argv[])
{
+ struct sigaction act;
int ch;
setlocale(LC_ALL, );
@@ -90,6 +98,13 @@ main(int argc, char *argv[])
if (!doline !doword !dochar)
doline = doword = dochar = 1;
+ memset(act, 0, sizeof(act));
+ act.sa_handler = handler;
+ sigemptyset(act.sa_mask);
+ /* SA_RESTART specifically not set */
+ if (sigaction(SIGINFO, act, NULL) == -1)
+ err(1, sigaction);
+
if (!*argv) {
cnt((char *)NULL);
} else {
@@ -100,19 +115,43 @@ main(int argc, char *argv[])
} while(*++argv);
if (dototal)
- print_counts(tlinect, twordct, tcharct, total);
+ print_counts(stdout, tlinect, twordct, tcharct,
+ total);
}
exit(rval);
}
void
+handler(int sig __unused)
+{
+ wants_info = 1;
+}
+
+ssize_t
+reread(int d, void *buf, size_t nbytes)
+{
+ ssize_t len;
+
+restart:
+ len = read(d, buf, nbytes);
+ if (wants_info) {
+ print_counts(stderr, linect + tlinect, wordct + twordct,
+ charct + tcharct, total so far);
+ wants_info = 0;
+ }
+ if (len == -1 errno == EINTR)
+ goto restart;
+
+ return len;
+}
+
+void
cnt(char *file)
{
u_char *C;
short gotsp;
int len;
- int64_t linect, wordct, charct;
struct stat sbuf;
int fd;
u_char buf[MAXBSIZE];
@@ -135,7 +174,7 @@ cnt(char *file)
* the word count requires some logic.
*/
if (doline) {
- while ((len = read(fd, buf, MAXBSIZE)) 0) {
+ while ((len = reread(fd, buf, MAXBSIZE)) 0) {
charct += len;
for (C = buf; len--; ++C)
if (*C == '\n')
@@ -165,7 +204,7 @@ cnt(char *file)
|| ifmt == S_IFDIR) {
charct = sbuf.st_size;
} else {
- while ((len = read(fd, buf, MAXBSIZE))
0)
+ while ((len = reread(fd, buf,
MAXBSIZE)) 0)
charct += len;
if (len == -1) {
warn(%s, file);
@@ -177,7 +216,7 @@ cnt(char *file)
} else {
/* Do it the hard way... */
gotsp = 1;
- while ((len = read(fd, buf, MAXBSIZE)) 0) {
+ while ((len = reread(fd, buf, MAXBSIZE)) 0) {
/*
* This loses in the presence of multi-byte characters.
* To do it right would require a function to return a
@@ -211,7 +250,7 @@ cnt(char *file)
}
}
- print_counts(linect, wordct, charct, file);
+ print_counts(stdout, linect, wordct, charct, file);
/*
* Don't bother checking doline, doword, or dochar -- speeds
@@ -228,30 +267,30 @@ cnt(char *file)
}
void
-format_and_print(long long v)
+format_and_print(FILE *f, long long v)
{
if (humanchar) {
char result[FMT_SCALED_STRSIZE];
(void)fmt_scaled(v, result);
- (void)printf(%7s, result);
+ (void)fprintf(f, %7s, result);
} else {
- (void)printf( %7lld, v);
+ (void)fprintf(f, %7lld, v);
}
}
void
-print_counts(int64_t lines, int64_t words, int64_t chars, char *name)
+print_counts(FILE *f,