ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CreditCardReminder/CreditCardReminder.c
Revision: 744
Committed: 2006-04-08T00:22:17-07:00 (19 years, 3 months ago) by douglas
Content type: text/x-c
File size: 6799 byte(s)
Log Message:
Oops!

File Contents

# User Rev Content
1 douglas 740 // Credit Card Reminder
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7 douglas 743 #include <assert.h>
8     #include <errno.h>
9 douglas 744 #include <sys/types.h>
10 douglas 743 #include <regex.h>
11 douglas 742 #include <setjmp.h>
12     #include <stdio.h>
13 douglas 743 #include <sys/stat.h>
14 douglas 742 #include <time.h>
15    
16 douglas 740 #include <c-client/c-client.h>
17    
18 douglas 743 static jmp_buf environment;
19 douglas 742 static char *error = NULL;
20    
21 douglas 743 static int check(int value, jmp_buf environment)
22 douglas 742 {
23 douglas 743 if (value == -1)
24     longjmp(environment, 1);
25    
26     return value;
27     }
28    
29     static char *fcheck(char *value, FILE *stream, jmp_buf environment)
30     {
31     if (!value)
32     {
33     if (ferror(stream))
34     longjmp(environment, 1);
35     else
36     {
37     clearerr(stdin);
38     printf("\n");
39    
40     return "";
41     }
42     }
43    
44     return value;
45     }
46    
47     static void *mcheck(void *value, jmp_buf environment)
48     {
49 douglas 742 if (value == NIL)
50     longjmp(environment, 2);
51    
52     return value;
53     }
54    
55 douglas 743 static int regcheck(int value, const regex_t *regex, jmp_buf environment)
56 douglas 742 {
57 douglas 743 if (value && value != REG_NOMATCH)
58     {
59     char exception[regerror(value, regex, NULL, 0)];
60 douglas 742
61 douglas 743 regerror(value, regex, exception, sizeof (exception));
62     longjmp(environment, (int)exception);
63     }
64 douglas 742
65 douglas 743 return value;
66     }
67    
68     inline static unsigned short mdate(const struct tm *date)
69     {
70     return ((date->tm_year + 1900 - BASEYEAR) << 9) + ((date->tm_mon + 1) << 5) + date->tm_mday;
71     }
72    
73     static void getnext(const struct tm *today, jmp_buf environment)
74     {
75     struct tm date = *today;
76    
77 douglas 742 --date.tm_mon;
78    
79     timegm(&date);
80    
81 douglas 743 # include <c-client/linkage.c>
82    
83     MAILSTREAM *stream = mcheck(mail_open(NIL, "{reptile.douglasthrift.net/novalidate-cert/tls}", OP_READONLY | OP_DEBUG), environment);
84     STRINGLIST from = { .text = { .data = (unsigned char *)"wellsfargo.com", .size = 14 } }, body = { .text = { .data = (unsigned char *)" is due on ", .size = 11 } };
85     SEARCHPGM search = { .from = &from, .body = &body, .since = mdate(&date) };
86     SORTPGM sort = { .reverse = 1, .function = SORTARRIVAL };
87     unsigned long *messages = mcheck(mail_sort(stream, "ISO-8859-1", &search, &sort, SE_UID), environment);
88     regex_t due;
89    
90     regcheck(regcomp(&due, "^.* is due on ([01][0-9]/[0-3][0-9]/[0-9]{4}).*$", REG_EXTENDED), &due, environment);
91    
92     for (unsigned long *message = messages; *message != 0; ++message)
93     {
94     unsigned long size;
95     char *body = mcheck(mail_fetchbody_full(stream, *message, "1", &size, FT_UID | FT_PEEK), environment);
96     regmatch_t match[2] = { { .rm_eo = size } };
97    
98     if (!regcheck(regexec(&due, body, 2, match, REG_STARTEND), &due, environment))
99     {
100     char date[match[1].rm_eo - match[1].rm_so + 1];
101    
102     strlcpy(date, body + match[1].rm_so, sizeof (date));
103     assert(sizeof (date) == 11);
104    
105     struct tm due;
106    
107     strptime(date, "%m/%d/%Y", &due);
108     strftime(date, sizeof (date), "%F", &due);
109    
110     char *path;
111    
112     check(asprintf(&path, "%s/.CreditCardReminder.data", getenv("HOME")), environment);
113    
114     FILE *file = fopen(path, "w");
115    
116     if (!file)
117     longjmp(environment, 1);
118    
119     free(path);
120     check(fprintf(file, "%s\n", date), environment);
121     check(fclose(file), environment);
122    
123     break;
124     }
125     }
126    
127     fs_give((void *)&messages);
128     mail_close(stream);
129 douglas 742 }
130    
131 douglas 740 int main(int argc, char *argv[])
132     {
133 douglas 742 int exception;
134    
135     switch (exception = setjmp(environment))
136     {
137     case 0:
138     break;
139     case 1:
140     perror(argv[0]);
141    
142     return 1;
143     case 2:
144     fprintf(stderr, "%s: %s\n", argv[0], error);
145     free(error);
146    
147     return 1;
148     default:
149     fprintf(stderr, "%s: %s\n", argv[0], (char *)exception);
150    
151     return 1;
152     }
153    
154 douglas 743 umask(0077);
155 douglas 740
156 douglas 743 struct tm today, next = { .tm_mday = 1, .tm_year = 70 };
157 douglas 742
158 douglas 743 {
159     time_t now = time(NULL);
160 douglas 742
161 douglas 743 gmtime_r(&now, &today);
162 douglas 742
163 douglas 743 today.tm_sec = 0;
164     today.tm_min = 0;
165     today.tm_hour = 0;
166     }
167    
168     {
169     jmp_buf environment_;
170    
171     switch (exception = setjmp(environment_))
172     {
173     case 0:
174     break;
175     case 1:
176     if (errno == ENOENT)
177     {
178     getnext(&today, environment);
179    
180     break;
181     }
182     default:
183     longjmp(environment, exception);
184     }
185    
186     char *path;
187    
188     check(asprintf(&path, "%s/.CreditCardReminder.data", getenv("HOME")), environment);
189    
190     FILE *file = fopen(path, "r");
191    
192     if (!file)
193     longjmp(environment_, 1);
194    
195     free(path);
196    
197     size_t size;
198     char *line = fcheck(fgetln(file, &size), file, environment);
199    
200     line[--size] = '\0';
201    
202     if (!strptime(line, "%F", &next))
203     longjmp(environment, 1);
204    
205     check(fclose(file), environment);
206     }
207    
208     char date[11];
209    
210     strftime(date, sizeof (date), "%F", &next);
211     fprintf(stderr, "%s\n", date);
212    
213 douglas 740 return 0;
214     }
215    
216     void mm_flags(MAILSTREAM *stream, unsigned long number)
217     {
218 douglas 742 printf("flags:\n number = %lu\n", number);
219 douglas 740 }
220    
221     void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
222     {
223 douglas 742 printf("mailbox %s:\n", mailbox);
224    
225     if (status->flags & SA_MESSAGES)
226     printf(" messages = %lu\n", status->messages);
227    
228     if (status->flags & SA_RECENT)
229     printf(" recent = %lu\n", status->recent);
230    
231     if (status->flags & SA_UNSEEN)
232     printf(" unseen = %lu\n", status->unseen);
233    
234     if (status->flags & SA_UIDNEXT)
235     printf(" uidnext = %lu\n", status->uidnext);
236    
237     if (status->flags & SA_UIDVALIDITY)
238     printf(" uidvalidity = %lu\n", status->uidvalidity);
239 douglas 740 }
240    
241     void mm_searched(MAILSTREAM *stream, unsigned long number)
242     {
243 douglas 742 printf("searched:\n number = %lu\n", number);
244 douglas 740 }
245    
246     void mm_exists(MAILSTREAM *stream, unsigned long number)
247     {
248 douglas 742 printf("exists:\n number = %lu\n", number);
249 douglas 740 }
250    
251     void mm_expunged(MAILSTREAM *stream, unsigned long number)
252     {
253 douglas 742 printf("expunged:\n number = %lu\n", number);
254 douglas 740 }
255    
256     void mm_list(MAILSTREAM *stream, int delim, char *name, long attrib)
257     {
258 douglas 742 printf("list");
259 douglas 740 }
260    
261     void mm_lsub(MAILSTREAM *stream, int delim, char *name, long attrib)
262     {
263 douglas 742 printf("lsub");
264 douglas 740 }
265    
266     void mm_notify(MAILSTREAM *stream, char *string, long errflg)
267     {
268 douglas 742 char *flag;
269    
270     asprintf(&flag, "%li", errflg);
271     printf("notify %s:\n string = %s\n", errflg == NIL ? "NIL" : errflg == WARN ? "WARN" : errflg == ERROR ? "ERROR" : flag, string);
272     free(flag);
273 douglas 740 }
274    
275     void mm_log(char *string, long errflg)
276     {
277 douglas 743 /* char *flag;
278 douglas 742
279     asprintf(&flag, "%li", errflg);
280     printf("log %s:\n string = %s\n", errflg == NIL ? "NIL" : errflg == PARSE ? "PARSE" : errflg == WARN ? "WARN" : errflg == ERROR ? "ERROR" : flag, string);
281 douglas 743 free(flag);*/
282 douglas 742
283     if (errflg == ERROR)
284     asprintf(&error, "%s", string);
285 douglas 740 }
286    
287     void mm_dlog(char *string)
288     {
289 douglas 743 printf("%s\n", string);
290 douglas 740 }
291    
292     void mm_login(NETMBX *mb, char *user, char *pwd, long trial)
293     {
294 douglas 742 strcpy(user, "douglas");
295 douglas 743
296     char *path;
297    
298     check(asprintf(&path, "%s/.CreditCardReminder.pass", getenv("HOME")), environment);
299    
300     FILE *file = fopen(path, "r");
301    
302     if (!file)
303     longjmp(environment, 1);
304    
305     free(path);
306    
307     size_t size;
308     char *line = fcheck(fgetln(file, &size), file, environment);
309    
310     strlcpy(pwd, line, size);
311 douglas 740 }
312    
313     void mm_critical(MAILSTREAM *stream)
314     {
315 douglas 742 printf("critical\n");
316 douglas 740 }
317    
318     void mm_nocritical(MAILSTREAM *stream)
319     {
320 douglas 742 printf("nocritical\n");
321 douglas 740 }
322    
323     long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
324     {
325 douglas 742 printf("diskerror:\n errcode = %li\n serious = %li\n", errcode, serious);
326    
327 douglas 740 return 1;
328     }
329    
330     void mm_fatal(char *string)
331     {
332 douglas 742 printf("fatal:\n string = %s\n", string);
333 douglas 740 }

Properties

Name Value
svn:eol-style native
svn:keywords Id