]>
Commit | Line | Data |
---|---|---|
1 | #define _POSIX_C_SOURCE 199309L | |
2 | ||
3 | #include <errno.h> | |
4 | #include <stdio.h> | |
5 | #include <stdlib.h> | |
6 | #include <string.h> | |
7 | #include <time.h> | |
8 | #include <unistd.h> | |
9 | ||
10 | #include "common.h" | |
11 | ||
12 | const int BUF_SIZE = 1024; | |
13 | ||
14 | const char PROMPT[] = "\33[H" /* Move cursor 'home' */ | |
15 | "\33[J" /* Clear screen */ | |
16 | "> "; | |
17 | const char ACKNOWLEDGE[] = "[OK]"; | |
18 | const struct timespec ACKNOWLEDGE_DELAY = {0, 300000000}; | |
19 | ||
20 | typedef struct { | |
21 | int interactive; | |
22 | } conf_t; | |
23 | ||
24 | conf_t parse_command_line(int argc, char *argv[]) { | |
25 | conf_t conf = {0}; | |
26 | ||
27 | if (argc == 2 && strcmp(argv[1], "-i") == 0 && isatty(2)) | |
28 | conf.interactive = 1; | |
29 | ||
30 | return conf; | |
31 | } | |
32 | ||
33 | static void read_line(conf_t conf, char *buf) { | |
34 | if (conf.interactive) | |
35 | if (fputs(PROMPT, stderr) == EOF) | |
36 | die("I/O error writing prompt"); | |
37 | if (fgets(buf, BUF_SIZE, stdin) == NULL) { | |
38 | if (ferror(stdin)) | |
39 | die("I/O error reading line"); | |
40 | if (feof(stdin)) { | |
41 | buf[0] = '\0'; /* Unclear if fgets does this already */ | |
42 | return; | |
43 | } | |
44 | die("Unexpected error reading line"); | |
45 | } | |
46 | } | |
47 | ||
48 | static void write_line(conf_t conf, const char *line) { | |
49 | const char *now = encode_time(time(NULL)); | |
50 | FILE *f = fopen(FILENAME, "a"); | |
51 | if (f == NULL) | |
52 | die_err("Error opening output file"); | |
53 | if (fputs(now, f) == EOF) | |
54 | die("Error writing to output file"); | |
55 | if (fputc(' ', f) == EOF) | |
56 | die("Error writing to output file"); | |
57 | if (fputs(line, f) == EOF) | |
58 | die("Error writing to output file"); | |
59 | if (fclose(f) != 0) | |
60 | die_err("Error closing output file"); | |
61 | if (conf.interactive) { | |
62 | if (fputs(ACKNOWLEDGE, stderr) == EOF) | |
63 | die("Error writing acknowledgment"); | |
64 | if (nanosleep(&ACKNOWLEDGE_DELAY, NULL) == -1 && errno != EINTR) | |
65 | die_err("Error sleeping"); | |
66 | } | |
67 | } | |
68 | ||
69 | int main(int argc, char *argv[]) { | |
70 | conf_t conf = parse_command_line(argc, argv); | |
71 | char buf[BUF_SIZE]; | |
72 | for (read_line(conf, buf); buf[0]; read_line(conf, buf)) { | |
73 | write_line(conf, buf); | |
74 | } | |
75 | return 0; | |
76 | } |