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

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

Properties

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