1 /*
2 * Copyright 2001, 2002, 2003, 2013 Adam Sampson <ats@offog.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <unistd.h>
18 #include <signal.h>
19 #include <time.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include "iolib.h"
26 #include "freedt.h"
27 #include "config.h"
28 const char *progname = "dumblog";
29 const char *proghelp =
30 "Usage: dumblog [OPTIONS] logfile\n"
31 "Log standard input to a file.\n\n"
32 "-c Prepend a timestamp to each line\n";
33
34 int stamp_ctime = 0;
35 char *logfile_name;
36 int logfile;
37 int return_code = 0;
38 buffer line = BUFFER;
39 buffer overflow = BUFFER;
40
flush_line()41 void flush_line() {
42 if (blength(&line) > 0) {
43 buffer out = BUFFER;
44
45 if (stamp_ctime) {
46 time_t t = time(NULL);
47 const char *s = ctime(&t);
48 bappendm(&out, s, strlen(s) - 1);
49 bappendc(&out, ' ');
50 }
51 bappend(&out, &line);
52 bappendc(&out, '\n');
53
54 while (1) {
55 if (writeba(logfile, &out) >= 0)
56 break;
57
58 warn2(logfile_name, "unable to write to logfile");
59 reliable_sleep(5);
60 }
61
62 bfree(&out);
63 }
64 bfree(&line);
65 }
66
open_logfile()67 void open_logfile() {
68 logfile = open(logfile_name, O_WRONLY | O_APPEND | O_CREAT | O_SYNC,
69 0644);
70 if (logfile < 0)
71 die2(logfile_name, "unable to open logfile");
72 }
73
close_logfile()74 void close_logfile() {
75 flush_line();
76
77 while (1) {
78 if (close(logfile) >= 0)
79 break;
80
81 warn2(logfile_name, "unable to close logfile");
82 reliable_sleep(5);
83 }
84 }
85
roll_handler(int dummy)86 void roll_handler(int dummy) {
87 close_logfile();
88 open_logfile();
89 }
90
quit_handler(int dummy)91 void quit_handler(int dummy) {
92 flush_line();
93 bappend(&line, &overflow);
94 close_logfile();
95 exit(return_code);
96 }
97
main(int argc,char ** argv)98 int main(int argc, char **argv) {
99 struct sigaction sa;
100
101 while (1) {
102 int c = getopt(argc, argv, "V?c");
103 if (c == -1)
104 break;
105 switch (c) {
106 case 'c':
107 stamp_ctime = 1;
108 break;
109 case 'V':
110 version();
111 default:
112 help();
113 }
114 }
115
116 if ((argc - optind) != 1)
117 help();
118 logfile_name = argv[optind];
119
120 sigemptyset(&sa.sa_mask);
121 sa.sa_flags = 0;
122
123 sa.sa_handler = roll_handler;
124 if (sigaction(SIGHUP, &sa, NULL) < 0)
125 die("unable to install sighup handler");
126 sa.sa_handler = quit_handler;
127 if (sigaction(SIGTERM, &sa, NULL) < 0)
128 die("unable to install sigterm handler");
129
130 open_logfile();
131
132 while (1) {
133 int rc = readlineb(fd_in, &line, 0, &overflow);
134 if (rc < 0) {
135 warn("unable to read from stdin");
136 return_code = 1;
137 quit_handler(0);
138 }
139 if (rc == 0)
140 break;
141
142 flush_line();
143 }
144
145 quit_handler(0);
146 return 0; /* NOTREACHED */
147 }
148
149