inc.c - rohrpost - A commandline mail client to change the world as we see it.
 (HTM) git clone git://r-36.net/rohrpost
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       inc.c (6325B)
       ---
            1 /*
            2  * Copy me if you can.
            3  * by 20h
            4  */
            5 
            6 #include <unistd.h>
            7 #include <stdio.h>
            8 #include <stdlib.h>
            9 #include <string.h>
           10 #include <strings.h>
           11 #include <sys/types.h>
           12 #include <sys/wait.h>
           13 
           14 #include "ind.h"
           15 #include "arg.h"
           16 #include "cfg.h"
           17 #include "llist.h"
           18 #include "imap.h"
           19 #include "mark.h"
           20 #include "inc.h"
           21 #include "path.h"
           22 
           23 inc_t *
           24 inc_init(char *cfgn)
           25 {
           26         inc_t *incs;
           27         char *path;
           28 
           29         if (cfgn == NULL)
           30                 cfgn = "default";
           31 
           32         path = path_mkincfile(cfgn);
           33         incs = inc_read(path);
           34         if (incs == NULL)
           35                 incs = inc_new();
           36         incs->path = memdups(path);
           37         free(path);
           38 
           39         incs->name = memdups(cfgn);
           40 
           41         return incs;
           42 }
           43 
           44 void
           45 inc_stop(inc_t *incs)
           46 {
           47         char *path;
           48 
           49         if (incs->changed) {
           50                 path = path_mkincfile(incs->name);
           51                 if (inc_write(incs, path) == NULL)
           52                         edie("inc_write");
           53                 free(path);
           54         }
           55 
           56         inc_free(incs);
           57 }
           58 
           59 llist_t *
           60 inc_getstatus(inc_t *incs, char *mailbox)
           61 {
           62         llistelem_t *statuse;
           63 
           64         statuse = inc_get(incs, mailbox);
           65         if (statuse == NULL || statuse->data == NULL) {
           66                 return NULL;
           67         }
           68 
           69         return llist_splitstr((char *)statuse->data, "\t");
           70 }
           71 
           72 char *
           73 inc_getstatuselem(inc_t *incs, char *mailbox, char *elem)
           74 {
           75         llist_t *status;
           76         llistelem_t *relem;
           77         char *rstr;
           78 
           79         status = inc_getstatus(incs, mailbox);
           80         if (status == NULL)
           81                 return NULL;
           82 
           83         if (!strcasecmp(elem, "messages")) {
           84                 relem = llist_getn(status, 0);
           85         } else if (!strcasecmp(elem, "unseen")) {
           86                 relem = llist_getn(status, 1);
           87         } else if (!strcasecmp(elem, "recent")) {
           88                 relem = llist_getn(status, 2);
           89         } else {
           90                 llist_efree(status);
           91                 return NULL;
           92         }
           93         if (relem == NULL || relem->key == NULL) {
           94                 llist_efree(status);
           95                 return NULL;
           96         }
           97         rstr = memdups(relem->key);
           98         llist_efree(status);
           99 
          100         return rstr;
          101 }
          102 
          103 char *
          104 inc_getstr(char *cfgn, char *mailbox, char *elem)
          105 {
          106         inc_t *incs;
          107         char *ret;
          108 
          109         incs = inc_init(cfgn);
          110         if (incs == NULL)
          111                 return NULL;
          112         ret = inc_getstatuselem(incs, mailbox, elem);
          113         inc_free(incs);
          114 
          115         return ret;
          116 }
          117 
          118 void
          119 inc_setstatus(inc_t *incs, char *mailbox, char *msgs, char *unseen,
          120                 char *recent)
          121 {
          122         char *statuss;
          123 
          124         statuss = smprintf("%s\t%s\t%s", msgs, unseen, recent);
          125         inc_set(incs, mailbox, statuss);
          126         free(statuss);
          127 }
          128 
          129 int
          130 inc_updatefolder(imap_t *imap, char *folder, inc_t *gincs)
          131 {
          132         llist_t *statusl;
          133         llistelem_t *elem;
          134         char *msgs, *unseen, *recent;
          135         inc_t *incs;
          136 
          137         if (gincs == NULL) {
          138                 incs = inc_new();
          139         } else {
          140                 incs = gincs;
          141         }
          142 
          143         statusl = imap_status(imap, folder);
          144         if (statusl == NULL)
          145                 return 1;
          146 
          147         msgs = "";
          148         recent = "";
          149         unseen = "";
          150         elem = llist_ciget(statusl, "messages");
          151         if (elem != NULL)
          152                 msgs = (char *)elem->data;
          153         elem = llist_ciget(statusl, "recent");
          154         if (elem != NULL)
          155                 recent = (char *)elem->data;
          156         elem = llist_ciget(statusl, "unseen");
          157         if (elem != NULL)
          158                 unseen = (char *)elem->data;
          159         inc_setstatus(incs, folder, msgs, unseen, recent);
          160 
          161         if (gincs == NULL)
          162                 inc_stop(incs);
          163         llist_free(statusl);
          164 
          165         return 0;
          166 }
          167 
          168 void
          169 inc_mkunseen(imap_t *imap, char *cfgn, char *folder)
          170 {
          171         llist_t *results;
          172         mark_t *marks;
          173         char *str;
          174 
          175         marks = mark_init(cfgn, folder);
          176         if (marks == NULL)
          177                 die("Could not initialize marks for '%s'.\n", folder);
          178 
          179         if (imap_select(imap, folder))
          180                 imap_die(imap, "imap_select");
          181         results = imap_search(imap, "UNSEEN");
          182         if (results != NULL) {
          183                 str = llist_joinstr(results, " ");
          184                 llist_free(results);
          185                 if (str != NULL) {
          186                         mark_set(marks, "u", str);
          187                         free(str);
          188                 }
          189                 mark_stop(marks);
          190         }
          191 }
          192 
          193 void
          194 inc_print(char *folder, char *msgs, char *unseen, char *recent)
          195 {
          196         printf("%s\t%s\t%s\t%s\n", folder, msgs, unseen, recent);
          197 }
          198 
          199 void
          200 incusage(char *argv0)
          201 {
          202         die("usage: %s [-auqnh] [-c cfg] [[-r|] folder]\n", argv0);
          203 }
          204 
          205 int
          206 incmain(int argc, char *argv[])
          207 {
          208         config_t *cfg;
          209         imap_t *imap;
          210         inc_t *incs;
          211         int status;
          212         char *user, *pass, *netspec, *msgs, *recent, *unseen, *ncmd, *cfgn, *argv0;
          213         llist_t *folders, *ffolders;
          214         llistelem_t *folder;
          215 
          216         enum {
          217                 BEQUIET = 0x01,
          218                 RUNNOTIFY = 0x02,
          219                 GENUNSEEN = 0x04,
          220                 SHOWALL = 0x08,
          221                 DOREGEXP = 0x10,
          222 
          223                 NOARGS = 0x20
          224         };
          225 
          226         status = 0;
          227         cfgn = NULL;
          228 
          229         ARGBEGIN(argv0) {
          230         case 'a':
          231                 status |= SHOWALL;
          232                 break;
          233         case 'c':
          234                 cfgn = EARGF(incusage(argv0));
          235                 break;
          236         case 'n':
          237                 status |= RUNNOTIFY;
          238                 break;
          239         case 'q':
          240                 status |= BEQUIET;
          241                 break;
          242         case 'r':
          243                 status |= DOREGEXP;
          244                 break;
          245         case 'u':
          246                 status |= GENUNSEEN;
          247                 break;
          248         default:
          249                 incusage(argv0);
          250         } ARGEND;
          251 
          252         cfg = config_init(cfgn);
          253         user = config_checkgetstr(cfg, "imapuser");
          254         pass = config_checkgetstr(cfg, "imappass");
          255         netspec = config_checkgetstr(cfg, "imapnet");
          256         ncmd = config_getstr(cfg, "runnotify");
          257         config_free(cfg);
          258 
          259         imap = imap_new(netspec, user, pass);
          260         free(user);
          261         free(pass);
          262         free(netspec);
          263 
          264         if (imap_init(imap))
          265                 imap_die(imap, "imap_init");
          266         if (argc > 0) {
          267                 folders = imap_listfolders(imap);
          268                 if (folders == NULL)
          269                         imap_die(imap, "imap_subscribed");
          270 
          271                 if (status & DOREGEXP) {
          272                         ffolders = llist_find(folders, argv[0]);
          273                 } else {
          274                         folder = llist_get(folders, argv[0]);
          275                         if (folder != NULL) {
          276                                 ffolders = llist_new();
          277                                 llist_add(ffolders, folder->key, folder->data,
          278                                                 folder->datalen);
          279                         }
          280                 }
          281                 if (ffolders == NULL)
          282                         die("Could not find any mailbox '%s'.\n", argv[0]);
          283                 status |= SHOWALL;
          284         } else {
          285                 folders = imap_subscribed(imap);
          286                 if (folders == NULL)
          287                         imap_die(imap, "imap_subscribed");
          288 
          289                 ffolders = folders;
          290         }
          291         llist_sort(ffolders);
          292 
          293         if (!(status & BEQUIET))
          294                 inc_print("Folder", "Msgs", "Unseen", "Recent");
          295         incs = inc_init(cfgn);
          296         forllist(ffolders, folder) {
          297                 if (folder->key == NULL)
          298                         continue;
          299 
          300                 if (inc_updatefolder(imap, folder->key, incs))
          301                         continue;
          302 
          303                 msgs = inc_getstatuselem(incs, folder->key, "messages");
          304                 recent = inc_getstatuselem(incs, folder->key, "recent");
          305                 unseen = inc_getstatuselem(incs, folder->key, "unseen");
          306 
          307                 if (status & SHOWALL || (recent != NULL && atoi(recent) > 0) \
          308                                 || (unseen != NULL && atoi(unseen) > 0)) {
          309                         if (!(status & BEQUIET))
          310                                 inc_print(folder->key, msgs, unseen, recent);
          311 
          312                         if (status & GENUNSEEN)
          313                                 inc_mkunseen(imap, cfgn, folder->key);
          314                         if (status & RUNNOTIFY && ncmd) {
          315                                 runcmd(ncmd, NULL, NULL, NULL, 0);
          316                                 wait(NULL);
          317                         }
          318                 }
          319                 if (msgs != NULL)
          320                         free(msgs);
          321                 if (recent != NULL)
          322                         free(recent);
          323                 if (unseen != NULL)
          324                         free(unseen);
          325         }
          326         inc_stop(incs);
          327 
          328         if (argc > 0)
          329                 llist_free(ffolders);
          330         if (ncmd != NULL)
          331                 free(ncmd);
          332         llist_free(folders);
          333 
          334         imap_close(imap);
          335         imap_free(imap);
          336         return 0;
          337 }
          338