/
wtime.c
209 lines (180 loc) · 5.25 KB
/
wtime.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define __USE_XOPEN // strptime
#include <time.h>
#include <assert.h>
#define LBUF_SIZE 128
typedef enum { EMPTY, STARTED, STOPPED, UNKNOWN } Tstate;
char usage[] = "wt [-t task] [-h|-a|-s|-c|-r [<start>[<end>]]]\nFor more info see the man page.\n";
static int fgetlastl(FILE * fd, char *lbuf, int size)
{
int lines = 0;
if (ftell(fd) != 0)
fseek(fd, 0, SEEK_SET);
while (fgets(lbuf, size, fd) != NULL)
lines++;
return (lines);
}
static Tstate cur_state(FILE * fd)
{
char lbuf[LBUF_SIZE];
int words = 0;
int buflen;
if (fgetlastl(fd, lbuf, LBUF_SIZE) == 0)
return EMPTY;
// count 'words' in the last line
buflen = strlen(lbuf);
for (int i = 0; i < buflen; i++) {
// beggining of word
if (!isspace(lbuf[i]) && (i == 0 || isspace(lbuf[i - 1])))
words++;
}
if (words == 1)
return STARTED;
else if (words == 2)
return STOPPED;
else
return UNKNOWN;
}
static void start_counting(FILE * fd)
{
time_t tnow = time(NULL);
fseek(fd, 0, SEEK_END);
fprintf(fd, "%i\n", (int) tnow);
}
static void stop_counting(FILE * fd)
{
int tnow = (int) time(NULL);
fseek(fd, -1, SEEK_END);
fprintf(fd, " %i\n", tnow);
}
static void print_elapsed(FILE * fd)
{
char buf[LBUF_SIZE];
int tnow = (int) time(NULL);
int tprev = 0;
fgetlastl(fd, buf, LBUF_SIZE);
sscanf(buf, "%i", &tprev);
printf("%i\n", (tnow - tprev));
}
static void print_report(FILE * fd, time_t start, time_t end)
{
assert(start <= end);
char lbuf[LBUF_SIZE];
char *ret;
int c;
int tstart, tend, tsum = 0, tnow = time(NULL);
if (ftell(fd) != 0)
fseek(fd, 0, SEEK_SET);
while ((ret = fgets(lbuf, LBUF_SIZE, fd)) != NULL) {
c = sscanf(lbuf, "%i %i", &tstart, &tend);
if (tstart >= start && tend <= end) {
// one match means a count in progress
if (c == 1) {
tsum += (tnow - tstart);
} else {
tsum += (tend - tstart);
}
}
}
printf("%i\n", (int) tsum);
}
int main(int argc, char *argv[])
{
FILE *fd = NULL;
Tstate prev_state;
char filename[256];
time_t rstart, rend, tnow;
struct tm tm;
char tag[32] = "default";
char *home = getenv("HOME");
// check for explicit tag name
if (argc > 2 && argv[1][1] == 't') {
strncpy(tag, argv[2], sizeof(tag));
argc -= 2;
argv += 2;
}
if (argc < 2) {
printf("usage: %s", usage);
exit(EXIT_SUCCESS);
}
snprintf(filename, sizeof(filename), "%s/.wtimed/%s", home, tag);
if ((fd = fopen(filename, "r+")) == NULL) {
if ((fd = fopen(filename, "w+")) == NULL) {
fprintf(stderr, "Error while opening data file '%s'.\n", filename);
exit(EXIT_FAILURE);
}
}
if (argv[1][0] != '-') {
fprintf(stderr, "Unknown parameter: %s\n", argv[1]);
} else {
if ((prev_state = cur_state(fd)) == UNKNOWN) {
fprintf(stderr, "Corrupted data file '%s'.\n", filename);
exit(EXIT_FAILURE);
}
switch (argv[1][1]) {
case 'h':
printf("usage: %s", usage);
break;
case 'a':
if (prev_state == STARTED)
fprintf(stderr, "We are allready counting.\n");
else
start_counting(fd);
break;
case 's':
if (prev_state != STARTED)
fprintf(stderr, "We are not counting.\n");
else
stop_counting(fd);
break;
case 'r':
if (argc == 4) { // end
if (strptime(argv[3], "%d-%m-%Y", &tm) == NULL) {
fprintf(stderr, "Malformated end date\n");
exit(EXIT_FAILURE);
}
tm.tm_min = tm.tm_sec = 59;
tm.tm_hour = 23;
rend = mktime(&tm);
} else {
rend = time(NULL);
}
if (argc >= 3) { // start
if (strptime(argv[2], "%d-%m-%Y", &tm) == NULL) {
fprintf(stderr, "Malformated start date\n");
exit(EXIT_FAILURE);
}
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
rstart = mktime(&tm);
} else { // beginning of month
tnow = time(NULL);
tm = *localtime(&tnow);
tm.tm_mday = 1;
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
rstart = mktime(&tm);
}
if (rstart > rend) {
fprintf(stderr, "Start date is further then end date.\n");
exit(EXIT_FAILURE);
}
print_report(fd, rstart, rend);
break;
case 'c':
if (prev_state != STARTED) {
fprintf(stderr, "We are not counting.\n");
exit(EXIT_FAILURE);
} else
print_elapsed(fd);
break;
default:
fprintf(stderr, "Unknown parameter: %s\n", argv[1]);
break;
}
}
if (fd)
fclose(fd);
return (0);
}