1 #define _POSIX_C_SOURCE 199309L
13 const int BUF_SIZE
= 1024;
15 const char PROMPT
[] = "\33[H" /* Move cursor 'home' */
16 "\33[J" /* Clear screen */
18 const char ACKNOWLEDGE
[] = "[OK]";
19 const char WAITING
[] = "[Waiting on lock...]\n";
20 const struct timespec ACKNOWLEDGE_DELAY
= {0, 300000000};
26 conf_t
parse_command_line(int argc
, char *argv
[]) {
29 if (argc
== 2 && strcmp(argv
[1], "-i") == 0 && isatty(2))
35 static void read_line(conf_t
*conf
, char *buf
) {
36 if (conf
->interactive
)
37 if (fputs(PROMPT
, stderr
) == EOF
)
38 die("I/O error writing prompt");
39 if (fgets(buf
, BUF_SIZE
, stdin
) == NULL
) {
41 die("I/O error reading line");
43 buf
[0] = '\0'; /* Unclear if fgets does this already */
46 die("Unexpected error reading line");
50 static void write_line(const char *now
, FILE *f
, const char *line
) {
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");
61 static void take_lock(FILE *f
) {
63 lock
.l_type
= F_WRLCK
;
64 lock
.l_whence
= SEEK_SET
;
69 die_err("Couldn't get file descriptor for locking");
70 if (fcntl(fd
, F_SETLK
, &lock
) == 0)
72 if (errno
!= EACCES
&& errno
!= EAGAIN
)
73 die_err("Couldn't take lock");
74 if (fputs(WAITING
, stderr
) == EOF
)
75 die("Error writing waiting message");
76 if (fcntl(fd
, F_SETLKW
, &lock
) == 0)
78 die_err("Couldn't take lock");
81 static void write_acknowledgment(conf_t
*conf
) {
82 if (conf
->interactive
) {
83 if (fputs(ACKNOWLEDGE
, stderr
) == EOF
)
84 die("Error writing acknowledgment");
85 if (nanosleep(&ACKNOWLEDGE_DELAY
, NULL
) == -1 && errno
!= EINTR
)
86 die_err("Error sleeping");
90 static void lock_and_write_line(conf_t
*conf
, const char *line
) {
91 const char *now
= encode_time(time(NULL
));
92 FILE *f
= fopen(FILENAME
, "a");
95 write_line(now
, f
, line
);
98 die_err("Error closing output file");
100 write_acknowledgment(conf
);
103 int main(int argc
, char *argv
[]) {
104 conf_t conf
= parse_command_line(argc
, argv
);
106 for (read_line(&conf
, buf
); buf
[0]; read_line(&conf
, buf
)) {
107 lock_and_write_line(&conf
, buf
);