1 #define _POSIX_C_SOURCE 200809L
8 void die(const char *message
) {
9 fputs(message
, stderr
);
14 void die_err(const char *message
) {
19 char *encode_time(time_t t
) {
22 const size_t size
= 20;
23 char *out
= (char *)malloc(size
);
24 if (strftime(out
, size
, "%Y %m %d %H %M %S", &tm
) != size
- 1)
25 die("Couldn't format time");
33 const time_t NULL_TIME
= (time_t)-1;
35 static time_range_t
make_time_range(time_t t
) { return (time_range_t
){t
, t
}; }
37 static void extend_time_range(time_range_t
*r
, time_t t
) { r
->end
= t
; }
39 static char *read_line() {
41 int scanf_ret
= scanf("%m[^\n]", &line
);
42 if (scanf_ret
== EOF
&& ferror(stdin
))
43 die_err("Error reading");
44 int newline
= getchar();
45 if (newline
!= EOF
&& newline
!= (int)'\n')
46 die("Expected newline");
47 if (scanf_ret
== 0 && newline
== (int)'\n')
52 static void write_line(time_range_t
*range
, char *line
) {
55 if (printf("%ld %ld %s\n", range
->start
, range
->end
, line
) < 0)
56 die("Couldn't write");
57 if (fflush(stdout
) == EOF
)
58 die_err("Couldn't flush");
61 static int same(char *a
, char *b
) { return a
&& b
&& strcmp(a
, b
) == 0; }
64 char *current_line
= NULL
;
65 time_range_t current_time_range
= make_time_range(NULL_TIME
);
67 char *new_line
= read_line();
70 time_t now
= time(NULL
);
71 if (same(current_line
, new_line
)) {
73 extend_time_range(¤t_time_range
, now
);
75 write_line(¤t_time_range
, current_line
);
77 current_line
= new_line
;
78 current_time_range
= make_time_range(now
);
81 write_line(¤t_time_range
, current_line
);