wmcore: set DESTDIR so binary installs correctly.
[dockapps.git] / wmpop3lb / wmpop3 / wmpop3.c
blobf2baeb475359b316e74dd9e7ae5602e1f3d461d2
1 /*
2 * wmpop3.c
3 * multi pop3 mail checker.
4 * written by Louis-Benoit JOURDAIN (lb@jourdain.org)
5 * based on the original work by Scott Holden (scotth@thezone.net)
7 */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <time.h>
18 #include <sys/socket.h>
19 #include <sys/stat.h>
20 #include <sys/param.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <sys/ioctl.h>
25 #include <X11/xpm.h>
26 #include <X11/Xlib.h>
27 #include <X11/extensions/shape.h>
29 #include <dirent.h>
31 #include <libdockapp/wmgeneral.h>
32 #include "Pop3Client.h"
34 #include "wmpop3.xpm"
36 char wminet_mask_bits[64*64];
37 int wminet_mask_width = 64;
38 int wminet_mask_height = 64;
40 char *ProgName;
42 char mailclient[32] = "pine";
43 char password[32];
44 char username[32];
45 char popserver[128];
46 int serverport = 110;
47 int mailCheckDelay = 10; /* default */
48 int autoChecking = YES; /* default */
49 int newMessagesOnly = YES; /* default */
50 int displaydelay = 1;
51 char tempdir[1024];
52 char config_file[256] = "not-defined";
53 int scrollspeed = 100;
55 Pop3 conf[6];
56 int nb_conf; /* number of configured pop servers */
57 int summess; /* total number of messages */
58 int color;
60 #ifdef _DEBUG
61 int haspassed = 0;
62 #endif
64 t_scrollbar scrollbar;
66 void usage(void);
67 void printversion(void);
68 void wmCheckMail_routine(int, char **);
69 int readConfigFile( char *filename );
71 void BlitString(char *name, int x, int y, int fragment);
72 void BlitNum(int num, int x, int y, int todelete);
74 int pop3DeleteMail(int num, Pop3 pc);
75 int pop3VerifStats(Pop3 pc);
77 /********************************
78 * Main Program
79 ********************************/
80 void deleteoldtmpfiles()
82 char buf[1024];
83 DIR *dir;
84 struct dirent *dp;
86 if (tempdir) {
87 if ((dir = opendir(tempdir))) {
88 chdir(tempdir);
89 while((dp = readdir(dir))) {
90 if (!strncmp(dp->d_name, TMPPREFIX, TMPPREFIXLEN)) {
91 sprintf(buf, "%s/%s", tempdir, dp->d_name);
92 #ifdef _DEBUG
93 printf(" delete old tmp file: %s\n", buf);
94 #endif
95 unlink(buf);
98 closedir(dir);
103 int main(int argc, char *argv[]) {
105 int i;
107 ProgName = argv[0];
108 if (strlen(ProgName) >= 5)
109 ProgName += (strlen(ProgName) - 5);
111 for (i=1; i<argc; i++) {
112 char *arg = argv[i];
114 if (*arg=='-') {
115 switch (arg[1]) {
116 case 'd' :
117 if (strcmp(arg+1, "display")) {
118 usage();
119 exit(1);
121 break;
122 case 'g' :
123 if (strcmp(arg+1, "geometry")) {
124 usage();
125 exit(1);
127 break;
128 case 'v' :
129 printversion();
130 exit(0);
131 break;
132 case 'c' :
133 if (argc > (i+1))
135 strcpy(config_file, argv[i+1]);
136 i++;
138 break;
139 default:
140 usage();
141 exit(0);
142 break;
146 wmCheckMail_routine(argc, argv);
148 return 0;
151 void build_line(char *buf, int num, int index, Pop3 pc)
153 int len;
154 int pos;
155 char tmp[256];
157 /* display spaces in case alias is less than 3 char long */
158 memset(tmp, ' ', sizeof(char) * 3);
159 memset(tmp + 3, 0, sizeof(char) * (256 - 3));
160 memcpy(tmp, pc->alias, strlen(pc->alias));
161 tmp[3] = ':';
162 pos = 4;
163 for (len = 0; len < MAIL_BUFLEN && pc->mails[num].from[len]; len++);
164 memcpy(tmp + pos, pc->mails[num].from, len);
165 tmp[pos + len] = '/';
166 pos += len + 1;
167 for (len = 0; len < MAIL_BUFLEN && pc->mails[num].subject[len]; len++);
168 memcpy(tmp + pos, pc->mails[num].subject, len);
169 len += pos;
170 tmp[len++] = ' ';
171 tmp[len++] = '*';
172 tmp[len++] = ' ';
173 tmp[len] = '\0';
174 pos = index % len;
175 if (len - pos < (NB_DISP + EXTRA)) { /* We are at the end of the string */
176 memcpy(buf, tmp + pos, len - pos);
177 memcpy(buf + len - pos, tmp, (NB_DISP + EXTRA) - len + pos);
179 else {
180 memcpy(buf, tmp + pos, NB_DISP + EXTRA);
184 void display_index(int mail_index, int line, Pop3 pc)
186 #ifdef _DEBUG
187 if (haspassed) {
188 printf(" mail_index: %d, line: %d, todelete: %d\n",
189 mail_index, line, pc->mails[mail_index].todelete);
191 #endif
192 if (pc->mails[mail_index].todelete) {
193 copyXPMArea(67, 12, 2, 5, 7, (line * 6) + TOP_MARGIN);
195 else {
196 copyXPMArea(69, 11, 2, 6, 7, (line * 6) + TOP_MARGIN - 1);
200 void ClearDisplay() {
201 int i;
203 copyXPMArea(72, 4, 3, 42, LEFT_MARGIN, 4);
204 copyXPMArea(72, 4, 50, 42, 9, 4 );
205 for (i = 0; i < NB_LINE; i++) {
206 copyXPMArea(69, 11, 2, 6, 7, (i * 6) + TOP_MARGIN - 1);
210 /* return < 0 if error
211 0 if no pb
212 else nb of mails which couldn't be deleted */
213 int DeleteMail(Pop3 pc)
215 int etat = 0;
216 int old_sizeOfAllMessages;
217 int i;
219 old_sizeOfAllMessages = pc->sizeOfAllMessages;
220 BlitString(pc->alias, 10, TOP_MARGIN, 0);
221 BlitString("connect", 10, 6*2 + TOP_MARGIN, 0);
222 RedrawWindow();
223 etat = pop3MakeConnection(pc, pc->popserver, pc->serverport);
224 if (-1 != etat) {
225 BlitString("login", 10, (6*3) + TOP_MARGIN, 0);
226 RedrawWindow();
227 etat = pop3Login(pc, pc->username, pc->password);
229 if (-1 != etat) {
230 BlitString("chk cont", 10, (6*4) + TOP_MARGIN, 0);
231 RedrawWindow();
232 etat = pop3VerifStats(pc);
234 if (-1 != etat) {
235 if (etat != old_sizeOfAllMessages) {
236 BlitString("mailbox", 10, TOP_MARGIN, 0);
237 BlitString("content", 10, 6 + TOP_MARGIN, 0);
238 BlitString("changed", 10, 6*2 + TOP_MARGIN, 0);
239 BlitString("between", 10, 6*3 + TOP_MARGIN, 0);
240 BlitString("updates", 10, 6*4 + TOP_MARGIN, 0);
241 BlitString("del can.", 10, 6*6 + TOP_MARGIN, 0);
242 RedrawWindow();
243 sleep(displaydelay);
244 for (i = 0, etat = 0; i < pc->numOfMessages; i++) {
245 etat += pc->mails[i].todelete;
248 else {
249 etat = 0;
250 for (i = 0; i < pc->numOfMessages; i++) {
251 if (pc->mails[i].todelete) {
252 etat += pop3DeleteMail(i + 1, pc);
257 pop3Quit(pc);
258 return (etat);
262 void launch_mail_client(int iS)
264 int i;
265 int j;
266 char str[16];
267 char **args;
269 ClearDisplay();
270 if ((args = conf[iS]->mailclient)) {
271 BlitString("starting", 10, TOP_MARGIN, 0);
272 for (i = 0; i < 5 && args[i]; i++) {
273 for (j = 0; j < 8 && args[i][j]; j++);
274 memcpy(str, args[i], j);
275 str[j] = '\0';
276 BlitString(str, 10, (i + 2)*6 + TOP_MARGIN, 0);
278 if (0 == fork()) {
279 if (execvp(args[0], args)) {
280 perror("execvp");
281 copyXPMArea(72, 4, 3, 42, LEFT_MARGIN, 4);
282 copyXPMArea(72, 4, 50, 6, 9, 4 );
283 copyXPMArea(69, 11, 2, 6, 7, TOP_MARGIN - 1);
284 BlitString("Error", 10, TOP_MARGIN, 0);
287 else {
288 conf[iS]->nextCheckTime = time(0) + 30;
291 else {
292 BlitString(" mail", 10, TOP_MARGIN, 0);
293 BlitString(" client", 10, 6 + TOP_MARGIN, 0);
294 BlitString("not set", 10, 6*2 + TOP_MARGIN, 0);
295 BlitString(" check", 15, 6*5 + TOP_MARGIN, 0);
296 BlitString("wmpop3rc", 10, 6*6 + TOP_MARGIN, 0);
298 RedrawWindow();
299 sleep(displaydelay);
303 void display_scrollbar(int index, int totalmessages,
304 int maxlines, int scrollmode)
306 int delta;
307 int scrollen;
308 int vertpos;
310 if (totalmessages <= maxlines) {
311 #ifdef _DEBUG
312 if (haspassed)
313 printf(" full scrollbar\n");
314 #endif
315 copyXPMArea((scrollmode) ? 68 : 65, 18, SCROLL_W,
316 SCROLL_H + (2 * SCROLL_EXT), SCROLL_LX, SCROLL_TY);
317 scrollbar.top = SCROLL_TY;
318 scrollbar.bottom = SCROLL_TY + SCROLL_H;
319 scrollbar.allowedspace = SCROLL_H;
321 else {
322 delta = totalmessages - maxlines;
323 /* determine the size of the scrollbar */
324 if (0 >= (scrollen = SCROLL_H - ((SCROLL_H / maxlines) * delta)))
325 scrollen = 1;
326 /* determine the position */
327 scrollbar.allowedspace = SCROLL_H - scrollen;
328 vertpos = scrollbar.allowedspace * index / delta;
329 copyXPMArea((scrollmode) ? 68 : 65, 18, SCROLL_W, SCROLL_EXT,
330 SCROLL_LX, vertpos + SCROLL_TY);
331 copyXPMArea((scrollmode) ? 68 : 65, 18 + SCROLL_EXT, SCROLL_W, scrollen,
332 SCROLL_LX, vertpos + SCROLL_TY + SCROLL_EXT);
333 copyXPMArea((scrollmode) ? 68 : 65, 18 + SCROLL_EXT + SCROLL_H,
334 SCROLL_W, SCROLL_EXT,
335 SCROLL_LX, vertpos + SCROLL_TY + SCROLL_EXT + scrollen);
336 scrollbar.top = vertpos + SCROLL_TY;
337 scrollbar.bottom = vertpos + SCROLL_TY + (SCROLL_EXT * 2) + scrollen;
339 #ifdef _DEBUG
340 if (haspassed) {
341 printf(" index: %d, totalmess:%d, mxli: %d, delta: %d, vertpos: %d, allowedspace: %d, sl:%d\n",
342 index, totalmessages, maxlines, delta, vertpos,
343 scrollbar.allowedspace, scrollen);
345 #endif
347 /* RedrawWindow(); */
350 int is_for_each_mail(char **command)
352 int i;
354 if (command) {
355 for (i = 0; command[i]; i++) {
356 if ('%' == command[i][0]) {
357 if (('f' == command[i][1]) ||
358 ('s' == command[i][1]) ||
359 ('m' == command[i][1]) ||
360 ('n' == command[i][1]))
361 return (1);
365 return (0);
368 char *quotify(char *str)
370 char *retour;
371 int len;
373 len = strlen(str);
374 if (NULL != (retour = (char *) malloc(sizeof(char) * len + 3))) {
375 retour[0] = '\'';
376 memcpy(retour + 1, str, len);
377 retour[len + 1] = '\'';
378 retour[len + 2] = '\0';
380 return (retour);
383 /* nb: number of the mail on the server - 1 (if -1: for all mails)
384 path: allocated buffer to store path of tmp file
385 newonly: only for new messages
386 onlyselected: only for selected messages
387 pc: main struct.
388 on success return 0 */
389 int writemailstofile(int nb, char *path, int newonly,
390 int onlyselected, Pop3 pc)
392 int fd;
393 int len;
394 int i;
395 int retour = 0;
396 int goforwritemail = 0;
397 int mustdisconnect = 0;
399 len = strlen(tempdir);
400 if (len) {
401 path[0] = '\0';
402 strcat(path, tempdir);
403 if ('/' != tempdir[len - 1])
404 strcat(path, "/");
405 strcat(path, TMPPREFIX);
406 strcat(path, "XXXXXX");
407 #ifdef _DEBUG
408 printf(" creating temporary file [%s]\n", path);
409 printf(" nb=%d, newonly=%d, onlyselected=%d\n",
410 nb, newonly, onlyselected);
411 #endif
412 if (-1 == (fd = mkstemp(path))) {
413 fprintf(stderr, "Error: writing mail to file\n");
414 perror(path);
415 retour++;
417 else {
418 /* to prevent connecting many times, do it now. */
419 if (NOT_CONNECTED == pc->connected) {
420 #ifdef _DEBUG
421 printf(" writemailstofile not connected, connecting\n");
422 #endif
423 if (pop3MakeConnection(pc,pc->popserver,pc->serverport) == -1){
424 return (1);
426 if (pop3Login(pc, pc->username, pc->password) == -1) {
427 return (1);
429 mustdisconnect = 1;
432 if (nb < 0) {
433 /* concatenate all the mails into 1 file */
434 for (i = 0; i < pc->numOfMessages; i++) {
435 goforwritemail = 0;
436 #ifdef _DEBUG
437 printf(" mail %d:", i);
438 #endif
439 if (!newonly && !onlyselected) {
440 #ifdef _DEBUG
441 printf(" !newonly && !onlyselected\n");
442 #endif
443 goforwritemail = 1;
445 else if (newonly) {
446 if (pc->mails[i].new &&
447 (!onlyselected || (onlyselected && pc->mails[i].todelete))) {
448 #ifdef _DEBUG
449 printf(" newonly\n");
450 #endif
451 goforwritemail = 1;
454 else if (onlyselected && pc->mails[i].todelete) {
455 #ifdef _DEBUG
456 printf(" onlyselected\n");
457 #endif
458 goforwritemail = 1;
460 if (goforwritemail) {
461 /* put the mail separator */
462 if (strlen(pc->mailseparator)) {
463 #ifdef _DEBUG
464 printf(" pc->mailseparator: [%s]\n", pc->mailseparator);
465 #endif
466 write(fd, pc->mailseparator, strlen(pc->mailseparator));
468 else {
469 #ifdef _DEBUG
470 printf(" TXT_SEPARATOR: [%s]\n", TXT_SEPARATOR);
471 #endif
472 write(fd, TXT_SEPARATOR, strlen(TXT_SEPARATOR));
474 if (pop3WriteOneMail(i + 1, fd, pc)) {
475 retour++;
481 else {
482 if (pop3WriteOneMail(nb + 1, fd, pc))
483 retour++;
485 close(fd);
486 /* close the connection if we've opened it */
487 if (mustdisconnect) {
488 #ifdef _DEBUG
489 printf(" writemailstofile disconnecting\n");
490 #endif
491 pop3Quit(pc);
495 else {
496 fprintf(stderr, "no tempdir configured, can't create file\n");
497 retour++;
499 return (retour);
503 * do_command_completion
504 * returned array should be freed by calling function
505 * if nbnewmail == 0, for %c option concatenate _all_ the messages
507 char **do_command_completion(int num, char **command,
508 int nbnewmail, Pop3 pc)
510 char **retour;
511 int i;
512 int yaerreur = 0;
513 char path[1024];
515 for (i = 0; command[i]; i++);
516 #ifdef _DEBUG
517 printf(" %d args to the command, mail num %d\n", i, num);
518 #endif
519 if (NULL == (retour = (char **) malloc (sizeof(char *) * i + 1))) {
520 return (NULL);
522 memset(retour, 0, sizeof(char *) * i + 1);
523 for (i = 0; command[i]; i++) {
524 #ifdef _DEBUG
525 printf(" arg %d: [%s]\n", i, command[i]);
526 #endif
527 if ('%' == command[i][0]) {
528 switch (command[i][1]) {
529 case 'T': /* total nb of mails */
530 if (NULL != (retour[i] = (char *) malloc(sizeof(char) * 8)))
531 sprintf(retour[i], "%d", pc->numOfMessages);
532 else
533 yaerreur = 1;
534 break;
535 case 't': /* total nb of new mails */
536 if (NULL != (retour[i] = (char *) malloc(sizeof(char) * 8)))
537 sprintf(retour[i], "%d", (nbnewmail < 0) ? 0 : 1);
538 else
539 yaerreur = 1;
540 break;
541 case 'C': /* concatenate all the selected mails in 1 file */
542 if (writemailstofile(-1, path, 0, SELECTONLY, pc))
543 yaerreur = 1;
544 else
545 if (NULL == (retour[i] = strdup(path))) {
546 yaerreur = 1;
548 break;
549 case 'c': /* concatenate all the mails in 1 file */
550 if (writemailstofile(-1, path, (nbnewmail > 0), NOSELECTONLY, pc))
551 yaerreur = 1;
552 else
553 if (NULL == (retour[i] = strdup(path))) {
554 yaerreur = 1;
556 break;
557 case 'f': /* from field */
558 #ifdef _DEBUG
559 printf(" from field: [%s]\n", pc->mails[num].from);
560 #endif
561 if (NULL == (retour[i] = quotify(pc->mails[num].from)))
562 yaerreur = 1;
563 break;
564 case 's': /* subject of the mail */
565 #ifdef _DEBUG
566 printf(" subject field: [%s]\n", pc->mails[num].subject);
567 #endif
568 if (NULL == (retour[i] = quotify(pc->mails[num].subject)))
569 yaerreur = 1;
570 break;
571 case 'm': /* copy the mail to tmp file */
572 if (0 <= num) {
573 if (writemailstofile(num, path, (nbnewmail > 0), NOSELECTONLY, pc))
574 yaerreur = 1;
575 else
576 if (NULL == (retour[i] = strdup(path))) {
577 yaerreur = 1;
580 break;
581 case 'n': /* number of the message on the mail server */
582 if (NULL != (retour[i] = (char *) malloc(sizeof(char) * 8)))
583 sprintf(retour[i], "%d", num + 1);
584 else
585 yaerreur = 1;
586 break;
587 case 'S': /* server name */
588 if (NULL == (retour[i] = strdup(pc->popserver)))
589 yaerreur = 1;
590 break;
591 case 'a': /* server alias */
592 if (NULL == (retour[i] = strdup(pc->alias)))
593 yaerreur = 1;
594 break;
595 case 'u': /* user name */
596 if (NULL == (retour[i] = strdup(pc->username)))
597 yaerreur = 1;
598 break;
599 case 'w': /* user password */
600 if (NULL == (retour[i] = strdup(pc->password)))
601 yaerreur = 1;
602 break;
603 case 'P': /* server port */
604 if (NULL != (retour[i] = (char *) malloc(sizeof(char) * 8)))
605 sprintf(retour[i], "%d", pc->serverport);
606 else
607 yaerreur = 1;
608 break;
609 case '%': /* % character, leave in place */
610 if (NULL == (retour[i] = strdup(command[i])))
611 yaerreur = 1;
612 break;
613 default:
614 break;
617 else {
618 #ifdef _DEBUG
619 printf(" just copying arg [%s]\n", command[i]);
620 #endif
621 if (NULL == (retour[i] = strdup(command[i])))
622 yaerreur = 1;
625 retour[i] = NULL;
626 #ifdef _DEBUG
627 printf(" retour: %ld\n", (long) retour);
628 #endif
629 if (!yaerreur)
630 return (retour);
631 else
632 return (NULL);
635 /* num is the index of the mail in the mail array
636 if num == -1, means that the command isn't for each mail */
639 void spawn_command(int num, char **command, int nbnewmail,
640 char *display, Pop3 pc)
642 char **tmpcommand;
643 char str[16];
644 int i, j;
646 if (display) {
647 ClearDisplay();
648 if (!command) {
649 BlitString(display, 10, 6 + TOP_MARGIN, 0);
650 BlitString("not set", 10, 6*2 + TOP_MARGIN, 0);
651 BlitString(" check", 15, 6*5 + TOP_MARGIN, 0);
652 BlitString("wmpop3rc", 10, 6*6 + TOP_MARGIN, 0);
654 else {
655 BlitString("starting", 10, TOP_MARGIN, 0);
656 for (i = 0; i < 5 && command[i]; i++) {
657 for (j = 0; j < 8 && command[i][j]; j++);
658 memcpy(str, command[i], j);
659 str[j] = '\0';
660 BlitString(str, 10, (i + 2)*6 + TOP_MARGIN, 0);
662 RedrawWindow();
665 if (command) {
666 /* check for any '%' sign in the command and complete it */
667 tmpcommand = do_command_completion(num, command, nbnewmail, pc);
668 if (tmpcommand) {
669 /* launch the command in a new process */
670 if (0 == fork()) {
671 #ifdef _DEBUG
672 printf(" spawning command: [");
673 for (i = 0; tmpcommand[i]; i++) {
674 printf(" %s ", tmpcommand[i]);
676 printf("]\n");
677 #endif
678 if (execvp(tmpcommand[0], tmpcommand)) {
679 perror("execvp");
682 else {
683 if (display) {
684 /* set the check delay to 30 seconds */
685 pc->nextCheckTime = time(0) + 30;
687 /* free the memory (in the parent process...) */
688 for (i = 0; tmpcommand[i]; i++) {
689 free (tmpcommand[i]);
691 free (tmpcommand);
694 else {
695 if (display) {
696 ClearDisplay();
697 BlitString(" Error", 15, TOP_MARGIN, 0);
698 BlitString(" While", 15, 6*2 + TOP_MARGIN, 0);
699 BlitString("parsing", 15, 6*3 + TOP_MARGIN, 0);
700 BlitString("command", 15, 6*4 +TOP_MARGIN, 0);
701 BlitString(display, 10, 6*6 + TOP_MARGIN, 0);
702 fprintf(stderr, "Error while parsing %s\n", display);
704 else
705 fprintf(stderr, "Error while parsing command\n");
708 if (display) {
709 RedrawWindow();
710 sleep(displaydelay);
715 * wmCheckMail_routine : This function is used to set up the X display
716 * for wmpop3 and check for mail every n number of minutes.
719 void wmCheckMail_routine(int argc, char **argv){
721 int buttonStatus = -1;
722 int iS;
723 Pop3 pc;
724 int i, j, k;
725 XEvent Event;
726 char str[256];
727 int index = 0;
728 int fragment = 0;
729 int index_vert = 0;
730 int oldnbmess = 0;
731 int nbsel;
732 int selectedmess;
733 int justreloaded;
734 long thistime;
735 char *linestodel[7];
736 int unreachable;
737 long sleeplenght;
738 int scrollmode = 0;
739 int nbnewmail;
740 char separ;
742 if( !strcmp( config_file, "not-defined") )
743 sprintf(config_file, "%s/.wmpop3rc", getenv("HOME"));
745 if( readConfigFile(config_file) == -1){
746 exit(0);
748 /* Set up timer for checking mail */
749 createXBMfromXPM(wminet_mask_bits, wmpop3_xpm
750 , wminet_mask_width, wminet_mask_height);
752 openXwindow(argc, argv, wmpop3_xpm, wminet_mask_bits
753 , wminet_mask_width, wminet_mask_height);
755 AddMouseRegion(0, 19, 49, 30, 58); /* check button */
756 AddMouseRegion(1, 46, 49, 50, 58 ); /* autocheck button */
757 AddMouseRegion(2, 53, 49, 57, 58 ); /* switch display button */
758 AddMouseRegion(3, 5, 49, 16, 58 ); /* delete button */
759 AddMouseRegion(4, 33, 49, 44, 53); /* top arrow */
760 AddMouseRegion(5, 33, 54, 44, 58); /* botton arrow */
761 /* add the mouse regions for each line */
762 for (i = 0; i < NB_LINE; i++) {
763 AddMouseRegion(6 + i, 9, (i*6) + TOP_MARGIN,
764 58, (i*6) + TOP_MARGIN + CHAR_HEIGHT);
768 /* Check if Autochecking is on or off */
769 if(autoChecking == NO ){
770 copyXPMArea(142, 38, 7, 11, 45, 48);
772 else {
773 copyXPMArea(142, 49, 7, 11, 45, 48);
776 RedrawWindow();
778 summess = 0;
780 deleteoldtmpfiles();
782 sleeplenght = (long) 20000L + (20000L - (20000L * scrollspeed / 100));
783 while (1) {
784 RSET_COLOR;
785 for (iS = 0; iS < nb_conf; iS++) {
786 pc = conf[iS];
787 if( (((time(0) > pc->nextCheckTime) ||
788 (pc->nextCheckTime == 0)) && ( autoChecking == YES))
789 || (pc->forcedCheck == YES)){
790 justreloaded = 1;
791 ClearDisplay();
792 BlitString(pc->alias, 10, TOP_MARGIN, 0);
793 BlitString("connect", 10, (6*2) + TOP_MARGIN, 0);
794 RedrawWindow();
795 pc->status = 0;
796 if(pop3MakeConnection(pc,pc->popserver,pc->serverport) == -1){
797 pc->status = 1;
799 if (!pc->status) {
800 BlitString("login", 10, (6*3) + TOP_MARGIN, 0);
801 RedrawWindow();
802 if (pop3Login(pc, pc->username, pc->password) == -1 )
803 pc->status = 2;
805 if (!pc->status) {
806 BlitString("get mail", 10, (6*4) + TOP_MARGIN, 0);
807 RedrawWindow();
808 if (pop3CheckMail(pc) == -1)
809 pc->status = 3;
811 pc->nextCheckTime = time(0) + (pc->mailCheckDelay * SEC_IN_MIN);
812 index = 0;
813 pc->forcedCheck = NO;
814 /* check if new mail has arrived */
815 for (i = 0, nbnewmail = 0; i < pc->numOfMessages; i++)
816 if (pc->mails[i].new)
817 nbnewmail++;
818 /* launch the new mail command */
819 if (pc->newmailcommand && (-1 != pc->sizechanged)) {
820 if (nbnewmail) {
821 #ifdef _DEBUG
822 printf(" %d New mail(s) ha(s)(ve) arrived!\n", nbnewmail);
823 #endif
824 if (is_for_each_mail(pc->newmailcommand)) {
825 for (i = 0; i < pc->numOfMessages; i++)
826 if (pc->mails[i].new)
827 spawn_command(i, pc->newmailcommand, nbnewmail, NULL, pc);
829 else {
830 spawn_command(-1, pc->newmailcommand, nbnewmail, NULL, pc);
834 /* close the connection */
835 pop3Quit(pc);
836 pc->sizechanged = 0;
839 waitpid(0, NULL, WNOHANG);
840 /* reset the number of messages */
841 unreachable = 1;
842 for (summess = 0, iS = 0; iS < nb_conf; iS++) {
843 pc = conf[iS];
844 if (!pc->status) {
845 unreachable = 0;
846 summess += pc->numOfMessages;
849 /* set the offset from the beginning of the list */
850 if (summess != oldnbmess) {
851 oldnbmess = summess;
852 if (summess < NB_LINE)
853 index_vert = 0;
854 else {
855 index_vert = summess - NB_LINE;
858 memset(str, 0, 128);
859 /* clear the display */
860 ClearDisplay();
861 nbsel = 0;
862 for (iS = 0; iS < nb_conf; iS++) {
863 pc = conf[iS];
864 for (i = 0; i < summess && i < pc->numOfMessages; i++) {
865 #ifdef _DEBUG
866 if (haspassed) {
867 printf(" %s, mails[%d], todelete=%d\n",
868 pc->alias, i, pc->mails[i].todelete);
870 #endif
871 nbsel += pc->mails[i].todelete;
874 if (justreloaded) {
875 /* make sure we display the correct buttons */
876 justreloaded = 0;
877 if ((NO == newMessagesOnly) && nbsel)
878 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
879 else
880 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
882 if (newMessagesOnly == YES ){
883 /* Show messages waiting */
884 RSET_COLOR;
885 for (color = 0, iS = 0; iS < nb_conf; iS++) {
886 pc = conf[iS];
887 if (pc->countunreadonly)
888 separ = '-';
889 else
890 separ = ':';
891 switch(pc->status) {
892 case 1:
893 sprintf(str, "%-3s%cC*ER", pc->alias, separ);
894 break;
895 case 2:
896 sprintf(str, "%-3s%cL*ER", pc->alias, separ);
897 break;
898 case 3:
899 sprintf(str, "%-3s%cM*ER", pc->alias, separ);
900 break;
901 default:
902 sprintf(str, "%-3s%c %3d", pc->alias, separ,
903 (pc->countunreadonly) ? pc->numOfUnreadMessages :
904 pc->numOfMessages);
905 break;
907 BlitString(str, 10, (int) (6*iS) + TOP_MARGIN, 0);
908 SWAP_COLOR;
910 RSET_COLOR;
911 sprintf(str, "sel.: %2d", nbsel);
912 BlitString(str, 10, (int) (6*6) + TOP_MARGIN, 0);
914 else {
915 RSET_COLOR;
916 if (0 == summess) {
917 if (unreachable) {
918 BlitString(" error", 10, TOP_MARGIN, 0);
920 else {
921 BlitString("No Mesg", 10, TOP_MARGIN, 0);
923 if (autoChecking == YES) {
924 BlitString(" next", 10, 6*2 + TOP_MARGIN, 0);
925 BlitString(" update", 10, 6*3 + TOP_MARGIN, 0);
926 j = SEC_IN_MIN * 1000;
927 thistime = time(0);
928 for (i = 0, k = 0; i < nb_conf; i++) {
929 if ((conf[i]->nextCheckTime - thistime) < j) {
930 j = conf[i]->nextCheckTime - thistime;
931 k = i;
934 sprintf(str, " is:%s", conf[k]->alias);
935 BlitString(str, 10, 6*4 + TOP_MARGIN, 0);
936 BlitString(" in", 10, 6*5 + TOP_MARGIN, 0);
937 sprintf(str, "%-5d s.", j);
938 BlitString(str, 10, 6*6 + TOP_MARGIN, 0);
941 else {
942 RSET_COLOR;
943 /* iS = index in the conf struct
944 i = index of the mail
945 j = line nb on display */
946 memset(linestodel, 0, sizeof(char *));
947 for (iS = 0, j = 0; iS < nb_conf && j < NB_LINE + index_vert; iS++) {
948 pc = conf[iS];
949 for (i = 0; (j < NB_LINE + index_vert) && i < pc->numOfMessages;
950 j++, i++) {
951 if (j >= index_vert) {
952 build_line(str, i, index, pc);
953 BlitString(str, 10, ((j - index_vert) * 6) + TOP_MARGIN,
954 fragment);
955 display_index(i, (j - index_vert), pc);
956 /* store the address of the delete flag, so that it will */
957 /* be easier to modify it afterwards */
958 linestodel[j - index_vert] = &(pc->mails[i].todelete);
961 SWAP_COLOR;
963 display_scrollbar(index_vert, summess, NB_LINE, scrollmode);
965 fragment++;
966 if (0 == (fragment % (CHAR_WIDTH + 1))) {
967 index++;
968 fragment = 0;
969 /* printf("index=%d, fragment=%d\n", index, fragment); */
972 #ifdef _DEBUG
973 haspassed = 0;
974 #endif
976 RedrawWindow();
978 RSET_COLOR;
979 /* X Events */
980 while (XPending(display)){
981 XNextEvent(display, &Event);
982 switch (Event.type) {
983 case Expose:
984 RedrawWindow();
985 break;
986 case DestroyNotify:
987 XCloseDisplay(display);
988 exit(0);
989 break;
990 case MotionNotify:
991 if (scrollmode) {
992 #ifdef _DEBUG
993 printf(" ca bouge... index_vert before = %d, %d x %d, allowedspace: %d, summess: %d\n",
994 index_vert,
995 Event.xbutton.x, Event.xbutton.y,
996 scrollbar.allowedspace,
997 summess);
999 #endif
1000 if (summess > NB_LINE) {
1001 index_vert = scrollbar.orig_index_vert +
1002 ((Event.xbutton.y - scrollbar.orig_y) * (summess - NB_LINE) /
1003 scrollbar.allowedspace);
1004 if (0 > index_vert)
1005 index_vert = 0;
1006 if (index_vert + NB_LINE > summess)
1007 index_vert = summess - NB_LINE;
1009 #ifdef _DEBUG
1010 printf(" deplacement de %d pixels --> index_vert = %d\n",
1011 Event.xbutton.y - scrollbar.orig_y, index_vert);
1012 #endif
1014 break;
1015 case ButtonPress:
1016 buttonStatus = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
1017 if (buttonStatus >= 0){
1018 switch (buttonStatus){
1019 case 0 : /* check / open button pressed */
1020 if ((NO == newMessagesOnly) && nbsel)
1021 copyXPMArea(128, 60 ,14 ,11 ,18 ,48 );
1022 else
1023 copyXPMArea(128,38 ,14 ,11 ,18 ,48 );
1024 break;
1025 case 1 : /* autocheck button pressed */
1026 break;
1027 case 2: /* switch display button pressed */
1028 break;
1029 case 3: /* delete button pressed */
1030 copyXPMArea(127, 15, 14, 11, 4, 48);
1031 break;
1032 case 4: /* top arrow button pressed */
1033 break;
1034 case 5: /* bottom arrow button pressed */
1035 break;
1036 default:
1037 break;
1039 RedrawWindow();
1041 else if (SCROLL_LX <= Event.xbutton.x && SCROLL_RX >= Event.xbutton.x
1042 && scrollbar.top <= Event.xbutton.y &&
1043 scrollbar.bottom >= Event.xbutton.y) {
1044 scrollbar.orig_y = Event.xbutton.y;
1045 scrollbar.orig_index_vert = index_vert;
1046 scrollmode = 1;
1048 break;
1049 case ButtonRelease:
1050 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
1052 if (buttonStatus == i && buttonStatus >= 0){
1053 switch (buttonStatus){
1054 case 0 : /* check button */
1055 if (nbsel && !newMessagesOnly) {
1056 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
1057 /* this is where you launch the open mail command */
1058 for (iS = 0; iS < nb_conf; iS++) {
1059 pc = conf[iS];
1060 for (i = 0, selectedmess = 0; i < pc->numOfMessages; i++) {
1061 if (pc->mails[i].todelete) {
1062 selectedmess = 1;
1063 break;
1066 if (selectedmess) {
1067 #ifdef _DEBUG
1068 printf(" launching selectedmesgcommand command for conf %d\n",
1069 iS);
1070 #endif
1072 if (is_for_each_mail(pc->selectedmesgcommand)) {
1073 #ifdef _DEBUG
1074 if (!pc->numOfMessages) {
1075 printf(" command is for each mail but there's no mail\n");
1077 else
1078 printf(" command is for each mail\n");
1079 #endif
1080 for (i = 0; i < pc->numOfMessages; i++)
1081 spawn_command(i, pc->selectedmesgcommand, 0,
1082 "selectm.", pc);
1084 else {
1085 spawn_command(-1, pc->selectedmesgcommand, 0,
1086 "selectm.", pc);
1091 else {
1092 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
1093 for (iS = 0; iS < nb_conf; iS++)
1094 conf[iS]->forcedCheck = YES;
1096 break;
1097 case 1 : /* autocheck Button */
1098 if (autoChecking == YES){
1099 autoChecking = NO;
1100 copyXPMArea(142, 38, 7, 11, 45, 48);
1102 else {
1103 autoChecking = YES;
1104 for (iS = 0; iS < nb_conf; iS++)
1105 conf[iS]->nextCheckTime = time(0) +
1106 (conf[iS]->mailCheckDelay * SEC_IN_MIN);
1107 copyXPMArea(142, 49, 7, 11, 45, 48);
1109 break;
1110 case 2: /* switch display Button */
1111 index = 0;
1112 /* change view on # of messages */
1113 if( newMessagesOnly == YES ) {
1114 newMessagesOnly = NO;
1115 copyXPMArea(149,38 , 7 , 11, 52, 48);
1116 if (nbsel) {
1117 copyXPMArea(128,49,14,11,18,48);
1119 else {
1120 copyXPMArea(128,27,14,11,18,48);
1123 else {
1124 newMessagesOnly = YES;
1125 copyXPMArea(149,49 , 7 , 11, 52, 48);
1126 copyXPMArea(128,27,14,11,18,48);
1128 #ifdef _DEBUG
1129 haspassed = 1;
1130 #endif
1131 break;
1132 case 3: /* delete button */
1133 copyXPMArea(143, 15, 14, 11, 4, 48);
1134 j = 0;
1135 RSET_COLOR;
1136 for (iS = 0; iS < nb_conf; iS++) {
1137 pc = conf[iS];
1138 for (i = 0, k = 0; i < pc->numOfMessages; i++)
1139 k += pc->mails[i].todelete;
1140 if (k) {
1141 /* clear the display */
1142 ClearDisplay();
1143 k = DeleteMail(pc);
1144 if (k < 0) {
1145 sprintf(pc->delstatus, "%-3s: Err", pc->alias);
1147 else if (k > 0) {
1148 sprintf(pc->delstatus, "%-3s/D:%2d", pc->alias, k);
1150 else
1151 sprintf(pc->delstatus, "%-3s: ok", pc->alias);
1152 pc->forcedCheck = YES;
1154 else {
1155 sprintf(pc->delstatus, "%-3s:none", pc->alias);
1158 /* clear the display */
1159 ClearDisplay();
1160 RSET_COLOR;
1161 for (iS = 0; iS < nb_conf; iS++) {
1162 BlitString(conf[iS]->delstatus, 10, 6*iS + TOP_MARGIN, 0);
1163 SWAP_COLOR;
1165 RedrawWindow();
1166 sleep(displaydelay);
1167 break;
1168 case 4: /* top arrow button pressed */
1169 index_vert--;
1170 if (0 > index_vert)
1171 index_vert = 0;
1172 #ifdef _DEBUG
1173 haspassed = 1;
1174 #endif
1175 break;
1176 case 5: /* bottom arrow button pressed */
1177 if (summess > NB_LINE) {
1178 index_vert++;
1179 if (index_vert + NB_LINE > summess)
1180 index_vert = summess - NB_LINE;
1182 #ifdef _DEBUG
1183 haspassed = 1;
1184 #endif
1185 break;
1186 default:
1187 if (newMessagesOnly == NO) { /* message view mode */
1188 if ((5 < buttonStatus) && (buttonStatus <= 5 + NB_LINE)) {
1189 if ((buttonStatus - 6 + index_vert) < summess) {
1190 /* first update lines to del */
1191 *(linestodel[buttonStatus - 6]) =
1192 1 - *(linestodel[buttonStatus - 6]);
1193 #ifdef _DEBUG
1194 printf(" button %d pressed, j'update lines to del\n",
1195 buttonStatus - 6);
1196 haspassed = 1;
1197 #endif
1198 nbsel = 0;
1199 for (iS = 0; iS < nb_conf; iS++) {
1200 pc = conf[iS];
1201 for (i = 0; i < pc->numOfMessages; i++) {
1202 nbsel += pc->mails[i].todelete;
1203 #ifdef _DEBUG
1204 printf(" conf %d, mail %d, todelete = %d\n",
1205 iS, i, pc->mails[i].todelete);
1206 #endif
1209 /* display open or reload buttons */
1210 if (nbsel) {
1211 copyXPMArea(128,49,14,11,18,48);
1213 else {
1214 copyXPMArea(128,27,14,11,18,48);
1219 else { /* summary view mode */
1220 if ((5 < buttonStatus) && (buttonStatus <= 5 + nb_conf)) {
1221 if ((Event.xbutton.x > 10) &&
1222 (Event.xbutton.x < (10 + (4 * (CHAR_WIDTH + 1))))) {
1223 #ifdef _DEBUG
1224 printf(" launching command for conf %d\n",
1225 buttonStatus - 6);
1226 #endif
1227 pc = conf[buttonStatus - 6];
1228 if (is_for_each_mail(pc->mailclient)) {
1229 #ifdef _DEBUG
1230 if (!pc->numOfMessages) {
1231 printf(" command is for each mail but there's no mail\n");
1233 #endif
1234 for (i = 0; i < pc->numOfMessages; i++)
1235 spawn_command(i, pc->mailclient, nbnewmail,
1236 "mailcli.", pc);
1238 else {
1239 spawn_command(-1, pc->mailclient, nbnewmail,
1240 "mailcli.", pc);
1243 else if ((Event.xbutton.x > (10 + (4 * (CHAR_WIDTH + 1)))) &&
1244 (Event.xbutton.x < (10 + (8 * (CHAR_WIDTH + 1))))) {
1245 /* swap view mode */
1246 conf[buttonStatus - 6]->countunreadonly =
1247 1 - conf[buttonStatus - 6]->countunreadonly;
1248 #ifdef _DEBUG
1249 printf(" swapping view mode for conf %d: %s\n",
1250 buttonStatus - 6,
1251 (conf[buttonStatus - 6]->countunreadonly) ?
1252 "UnreadMessages" : "TotalMessages");
1254 #endif
1257 else if ((5 + NB_LINE) == buttonStatus) {
1258 /* status summary line pressed */
1259 if ((Event.xbutton.x > 10) &&
1260 (Event.xbutton.x < (10 + (4 * (CHAR_WIDTH + 1))))) {
1261 /* select all messages */
1262 for (iS = 0; iS < nb_conf; iS++) {
1263 for (pc = conf[iS], i = 0; i < pc->numOfMessages; i++) {
1264 pc->mails[i].todelete = 1;
1268 else if ((Event.xbutton.x > (10 + (4 * (CHAR_WIDTH + 1)))) &&
1269 (Event.xbutton.x < (10 + (8 * (CHAR_WIDTH + 1))))) {
1270 /* unselect all messages */
1271 for (iS = 0; iS < nb_conf; iS++) {
1272 for (pc = conf[iS], i = 0; i < pc->numOfMessages; i++) {
1273 pc->mails[i].todelete = 0;
1279 break;
1282 else {
1283 if (buttonStatus >= 0) {
1284 /* button has been pressed correctly but released somewhere else */
1285 switch(buttonStatus) {
1286 case 0: /* check button was pressed */
1287 if ((NO == newMessagesOnly) && nbsel)
1288 copyXPMArea(128,49 ,14 ,11 ,18 ,48 );
1289 else
1290 copyXPMArea(128,27 ,14 ,11 ,18 ,48 );
1291 break;
1292 case 3: /* delete button was pressed */
1293 copyXPMArea(143, 15, 14, 11, 4, 48);
1294 break;
1298 RedrawWindow();
1299 buttonStatus = -1;
1300 scrollmode = 0;
1301 break;
1304 usleep(sleeplenght);
1310 * usage : Prints proper command parameters of wmpop3.
1312 void usage(void)
1314 fprintf(stdout, "\nWMPop3LB - Louis-Benoit JOURDAIN (wmpop3lb@jourdain.org)\n");
1315 fprintf(stdout, "based on the work by Scott Holden <scotth@thezone.net>\n\n");
1316 fprintf(stdout, "usage:\n");
1317 fprintf(stdout, " -display <display name>\n");
1318 fprintf(stdout, " -geometry +XPOS+YPOS initial window position\n");
1319 fprintf(stdout, " -c <filename> use specified config file\n");
1320 fprintf(stdout, " -h this help screen\n");
1321 fprintf(stdout, " -v print the version number\n");
1322 fprintf(stdout, "\n");
1325 void printversion(void)
1327 fprintf(stdout, "wmpop3 v%s\n", WMPOP3_VERSION);
1330 // Blits a string at given co-ordinates
1331 void BlitString(char *name, int x, int y, int fragment)
1333 int i;
1334 int c;
1335 int k;
1336 int row;
1338 /* printf("--name: [%s] \n", name); */
1339 for (i = 0, k = x; name[i]; i++) {
1340 c = toupper(name[i]);
1341 if (c >= 'A' && c <= 'Z') { /* its a letter */
1342 c -= 'A';
1343 row = LETTERS;
1345 else if (c >= '0' && c <= '9') { /* its a number */
1346 c -= '0';
1347 row = NUMBERS;
1349 else switch(c) {
1350 case '-':
1351 c = 26;
1352 row = LETTERS;
1353 break;
1354 case '*':
1355 c = 27;
1356 row = LETTERS;
1357 break;
1358 case ':':
1359 c = 10;
1360 row = NUMBERS;
1361 break;
1362 case '/':
1363 c = 11;
1364 row = NUMBERS;
1365 break;
1366 case '@':
1367 c = 12;
1368 row = NUMBERS;
1369 break;
1370 case '%':
1371 c = 15;
1372 row = NUMBERS;
1373 break;
1374 case ' ':
1375 c = 13;
1376 row = NUMBERS;
1377 break;
1378 case '.':
1379 c = 28;
1380 row = LETTERS;
1381 break;
1382 default:
1383 c = 14;
1384 row = NUMBERS;
1385 break;
1387 /* printf("c:%2d (%c), fragment: %d, i:%d, k=%d ",
1388 c, name[i], fragment, i, k); */
1389 if (i > 0 && i < NB_DISP) {
1390 copyXPMArea(c * CHAR_WIDTH, CH_COLOR(row), CHAR_WIDTH + 1, CHAR_HEIGHT,
1391 k, y);
1392 /* printf(" - k1: %d += %d + 1", k, CHAR_WIDTH); */
1393 k += CHAR_WIDTH + 1;
1395 else if (0 == i) {
1396 copyXPMArea(c * CHAR_WIDTH + fragment, CH_COLOR(row),
1397 CHAR_WIDTH + 1 - fragment, CHAR_HEIGHT,
1398 k, y);
1399 /* printf(" - k2: %d += %d + 1 - %d", k, CHAR_WIDTH, fragment); */
1400 k += CHAR_WIDTH + 1 - fragment;
1402 else if (fragment && (NB_DISP == i)) {
1403 copyXPMArea(c * CHAR_WIDTH, CH_COLOR(row), fragment + 1, CHAR_HEIGHT,
1404 k, y);
1405 /* printf(" - k3: %d += %d ", k, fragment); */
1406 k += fragment;
1408 /* printf(" -- apres k=%d\n", k); */
1413 /* Blits number to given coordinates...*/
1415 void BlitNum(int num, int x, int y, int todelete)
1417 if (todelete)
1418 num += 19;
1419 copyXPMArea(((num - 1) * (SN_CHAR_W + 1)) + 1, CH_COLOR(SMALL_NUM),
1420 SN_CHAR_W, CHAR_HEIGHT + 1, x, y);
1423 int parsestring(char *buf, char *data, int max, FILE *fp)
1425 char *deb;
1426 char *end;
1427 char *bal;
1428 int go = 1;
1429 int linelen = 0;
1431 /* trim the leading spaces */
1432 memset(data, 0, max);
1433 for (deb = buf; *deb && isspace(*deb); deb++);
1434 if (!*deb)
1435 return (-1);
1436 if ('"' == *deb) {
1437 ++deb;
1438 bal = data;
1439 while (go) {
1440 #ifdef _DEBUG
1441 printf(" line to parse: [%s]\n", deb);
1442 #endif
1443 /* get to the end of the line */
1444 for (end = deb; *end && ('"' != *end); end++);
1445 if (!*end) { /* this is a multiline entry */
1446 linelen += (int) (end - deb);
1447 if (linelen > max) {
1448 #ifdef _DEBUG
1449 printf(" maximum line length reached\n");
1450 #endif
1451 return (-1);
1453 memcpy(bal, deb, (int) (end - deb));
1454 bal = data + linelen;
1455 if (fgets(buf, CONF_BUFLEN, fp)) {
1456 deb = buf;
1458 else { /* end of file reached */
1459 return (-1);
1462 else {
1463 memcpy(bal, deb, end - deb);
1464 go = 0;
1468 else {
1469 for (end = deb; *end && !isspace(*end); end++);
1470 memcpy(data, deb, ((end - deb) > max) ? max : end - deb);
1472 #ifdef _DEBUG
1473 printf(" parsed string (len=%d) : [%s]\n", strlen(data), data);
1474 #endif
1475 return (0);
1478 int parsenum(char *buf, int *data)
1480 char *deb;
1481 char *end;
1482 char temp[32];
1484 memset(temp, 0, 32);
1485 for (deb = buf; *deb && isspace(*deb); deb++);
1486 if (!*deb)
1487 return (-1);
1488 if ('"' == *deb) {
1489 for (end = ++deb; *end && ('"' != *end); end++);
1490 if (!*end)
1491 return (-1);
1492 memcpy(temp, deb, end - deb);
1493 *data = atoi(temp);
1495 else {
1496 for (end = deb; *end && !isspace(*end); end++);
1497 memcpy(temp, deb, end - deb);
1498 *data = atoi(temp);
1500 return (0);
1503 char **build_arg_list(char *buf, int len)
1505 int espaces;
1506 int i, j;
1507 char **retour;
1509 /* count number of args */
1510 for (espaces = 0, i = 0; buf[i] && i < len; i++)
1511 if (isspace(buf[i]))
1512 espaces++;
1513 /* allocate space for the structure */
1514 if (NULL == (retour = (char **) malloc(sizeof(char *) * espaces + 2)))
1515 return (NULL);
1516 /* get each arg one by one */
1517 for (i = 0, j = 0; j < len && i < 256; i++) {
1518 /* get the end of the arg */
1519 for (espaces = j; espaces < len && !isspace(buf[espaces]); espaces++);
1520 /* allocate space for the arg */
1521 if (0 == (retour[i] = malloc(sizeof(char) * (espaces - j) + 1))) {
1522 /* free what has been allocated */
1523 for (j = 0; j < i; j++)
1524 free(retour[j]);
1525 return (NULL);
1527 memcpy(retour[i], buf + j, espaces - j);
1528 retour[i][espaces - j] = '\0';
1529 j = espaces + 1;
1531 retour[i] = 0;
1532 return (retour);
1536 int readConfigFile( char *filename ){
1537 char buf[CONF_BUFLEN];
1538 char tmp[CONF_BUFLEN];
1539 FILE *fp;
1540 char *bal;
1542 if( (fp = fopen( filename, "r")) == 0 ){
1543 sprintf(config_file, "%s/.wmpop3rc", getenv("HOME"));
1544 fprintf(stderr, "-Config file does not exit : %s\n",config_file);
1545 fprintf(stderr, "+Trying to create new config file.\n");
1546 if((fp = fopen(config_file,"w")) == 0){
1547 fprintf(stderr, "-Error creating new config file\n");
1548 return -1;
1550 fprintf(fp, "#####################################################\n");
1551 fprintf(fp, "# wmpop3lb configuration file #\n");
1552 fprintf(fp, "# #\n");
1553 fprintf(fp, "# for more information about wmpop3lb, please see: #\n");
1554 fprintf(fp, "# http://wmpop3lb.jourdain.org #\n");
1555 fprintf(fp, "# or send a mail to #\n");
1556 fprintf(fp, "# wmpop3lb@jourdain.org #\n");
1557 fprintf(fp, "#####################################################\n");
1558 fprintf(fp, "autochecking 0 # 1 enables, 0 disables\n");
1559 fprintf(fp, "displaydelay 2 # nb of seconds error info is displayed\n");
1560 fprintf(fp, "scrollspeed 100 # percentage of original scrool speed\n");
1561 fprintf(fp, "tempdir /tmp # directory for tmp files\n");
1562 fprintf(fp, "viewallmessages 0 # 0 Shows the from and subject\n");
1563 fprintf(fp, "# 1 Shows the number of messages\n");
1564 fprintf(fp, "#\n# Replace all values with appropriate data\n#\n");
1565 fprintf(fp, "[Server] # server section\n");
1566 fprintf(fp, "alias \"3 alphanum. char. long alias\"\n");
1567 fprintf(fp, "popserver \" pop3 server name \"\n");
1568 fprintf(fp, "port 110 # default port\n");
1569 fprintf(fp, "username \" pop3 login name \"\n");
1570 fprintf(fp, "password \" pop3 password \"\n");
1571 fprintf(fp, "mailcheckdelay 10 # default mail check time in minutes\n");
1572 fprintf(fp, "countUnreadOnly 0 # count unread messages only\n");
1573 fprintf(fp, "mailclient \"netscape -mail\" # for example...\n");
1574 fprintf(fp, "newmailcommand \" specify new mail command \"\n");
1575 fprintf(fp, "selectedmesgcommand \"specify command for selected mess\"\n");
1576 fprintf(fp, "mailseparator \" separator when concatening messages\"\n");
1577 fprintf(fp, "maxdlsize -1 # (no limit)\n");
1578 fprintf(fp, "#\n# start new [server] section below (up to a total of 6)\n");
1579 fprintf(stderr, "+New config file created : ~/.wmpop3rc\n\n");
1580 fprintf(stderr, "+ ~/.wmpop3rc must be configured before running wmpop3.\n");
1581 fclose(fp);
1582 return -1;
1585 nb_conf = 0;
1586 tempdir[0] = '\0';
1588 while ((nb_conf < 7) && fgets(buf, CONF_BUFLEN, fp) != 0) {
1589 if (buf[0] != '#') {
1590 if (!nb_conf && !strncasecmp( buf, "autochecking", 12) ){
1591 if (parsenum(buf + 12, &autoChecking))
1592 fprintf(stderr, "syntax error for parameter autochecking\n");
1594 else if (!nb_conf && !strncasecmp( buf, "scrollspeed", 11) ){
1595 if (parsenum(buf + 11, &scrollspeed))
1596 fprintf(stderr, "syntax error for parameter scrollspeed\n");
1598 else if (!nb_conf && !strncasecmp( buf, "displaydelay", 12) ){
1599 if (parsenum(buf + 12, &displaydelay))
1600 fprintf(stderr, "syntax error for parameter displaydelay\n");
1602 else if (!nb_conf && !strncasecmp(buf, "tempdir", 7)) {
1603 if (parsestring(buf + 7, tempdir, 1024, fp))
1604 fprintf(stderr, "syntax error for parameter tempdir\n");
1606 else if (!strncasecmp(buf, "[server]", 8)) {
1607 nb_conf++;
1608 if (!(conf[nb_conf - 1] = pop3Create(nb_conf))) {
1609 fprintf(stderr, "Can't allocate memory for config structure\n");
1610 fclose(fp);
1611 return (-1);
1614 else if (nb_conf && !strncasecmp(buf, "username", 8) ) {
1615 if (parsestring(buf + 8, conf[nb_conf -1]->username, 256, fp))
1616 fprintf(stderr, "section %d: invalid syntax for username\n",
1617 nb_conf);
1619 else if (nb_conf && !strncasecmp( buf, "password", 8) ){
1620 if (parsestring(buf + 8, conf[nb_conf - 1]->password, 256, fp))
1621 fprintf(stderr, "section %d: invalid syntax for password\n",
1622 nb_conf);
1624 else if (nb_conf && !strncasecmp(buf, "alias", 5) ) {
1625 if (parsestring(buf + 5, conf[nb_conf -1]->alias, 3, fp))
1626 fprintf(stderr, "section %d: invalid syntax for alias\n", nb_conf);
1628 else if (nb_conf && !strncasecmp( buf, "popserver", 9) ){
1629 if (parsestring(buf + 9, conf[nb_conf - 1]->popserver, 128, fp))
1630 fprintf(stderr, "section %d: invalid syntax for popserver\n",
1631 nb_conf);
1633 else if (nb_conf && !strncasecmp( buf, "port", 4) ){
1634 if (parsenum(buf + 4, &(conf[nb_conf - 1]->serverport)))
1635 fprintf(stderr, "section %d: Invalid popserver port number.\n",
1636 nb_conf);
1638 else if (!nb_conf && !strncasecmp( buf, "viewallmessages", 15) ){
1639 if (parsenum(buf + 15, &newMessagesOnly))
1640 fprintf(stderr, "section %d: Invalid number ( viewallmessages )\n",
1641 nb_conf);
1643 else if (nb_conf && !strncasecmp(buf, "countunreadonly", 15)) {
1644 if (parsenum(buf + 15, &(conf[nb_conf - 1]->countunreadonly)))
1645 fprintf(stderr, "section %d: Invalid number ( countunreadonly )\n",
1646 nb_conf);
1648 else if (nb_conf && !strncasecmp( buf, "mailcheckdelay", 14) ){
1649 if (parsenum(buf + 14, &(conf[nb_conf -1]->mailCheckDelay)))
1650 fprintf(stderr, "section %d: Invalid delay time.\n", nb_conf);
1652 else if (nb_conf && !strncasecmp(buf, "mailclient", 10)) {
1653 if (parsestring(buf + 10, tmp, 256, fp))
1654 fprintf(stderr, "section %d: Invalid syntax for mailclient.\n",
1655 nb_conf);
1656 else
1657 conf[nb_conf - 1]->mailclient = build_arg_list(tmp, strlen(tmp));
1659 else if (nb_conf && !strncasecmp(buf, "newmailcommand", 14)) {
1660 if (parsestring(buf + 14, tmp, 256, fp))
1661 fprintf(stderr,"section %d: Invalid syntax for newmailcommand.\n",
1662 nb_conf);
1663 else
1664 conf[nb_conf - 1]->newmailcommand =
1665 build_arg_list(tmp, strlen(tmp));
1667 else if (nb_conf && !strncasecmp(buf, "selectedmesgcommand", 19)) {
1668 if (parsestring(buf + 19, tmp, 256, fp))
1669 fprintf(stderr,
1670 "section %d: Invalid syntax for selectedmesgcommand.\n",
1671 nb_conf);
1672 else
1673 conf[nb_conf - 1]->selectedmesgcommand =
1674 build_arg_list(tmp, strlen(tmp));
1676 else if (nb_conf && !strncasecmp(buf, "mailseparator", 13)) {
1677 if (parsestring(buf + 13, conf[nb_conf - 1]->mailseparator, 256, fp))
1678 fprintf(stderr, "section %d: Invalid syntax for mailseparator\n",
1679 nb_conf);
1681 else if (nb_conf && !strncasecmp( buf, "maxdlsize", 9) ){
1682 if (parsenum(buf + 9, &(conf[nb_conf -1]->maxdlsize)))
1683 fprintf(stderr, "section %d: Invalid maxdlsize.\n", nb_conf);
1685 else if (nb_conf) {
1686 if (*buf && (isalpha(*buf) || isalnum(*buf)))
1687 fprintf(stderr, "section %d: Unknown indentifier : [%s]\n",
1688 nb_conf, buf);
1690 else {
1691 for (bal = buf; *bal && !isalnum(*bal); bal++);
1692 if (*bal)
1693 fprintf(stderr, "identifier outside Server section: [%s]\n", buf);
1697 fclose(fp);
1698 return 0;