Back to index

courier  0.68.2
maildirkw.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2003-2004 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 
00007 #if    HAVE_CONFIG_H
00008 #include      "config.h"
00009 #endif
00010 #include      <stdio.h>
00011 #include      <string.h>
00012 #include      <stdlib.h>
00013 #include      <errno.h>
00014 
00015 #if HAVE_UNISTD_H
00016 #include <unistd.h>
00017 #endif
00018 #include <sys/stat.h>
00019 #include      "maildirkeywords.h"
00020 #include      "maildirwatch.h"
00021 
00022 static void usage()
00023 {
00024        printf("Usage: maildirkw [ options ] maildir [+/-]flag [+/-]flag...\n");
00025        exit(1);
00026 }
00027 
00028 static int doit_locked(const char *maildir,
00029                      const char *filename,
00030                      int lockflag, int plusminus,
00031                      char **argv,
00032                      int optind, int argc)
00033 {
00034        char *tmpname, *newname;
00035 
00036        if (!plusminus)
00037        {
00038               struct libmail_kwHashtable kwh;
00039               struct libmail_kwMessage *kwm;
00040 
00041               struct libmail_kwGeneric g;
00042               int rc;
00043 
00044               libmail_kwgInit(&g);
00045 
00046               /* Make sure courierimapkeywords directory exists */
00047 
00048               libmail_kwEnabled=0;
00049               rc=libmail_kwgReadMaildir(&g, maildir);
00050               libmail_kwEnabled=1;
00051               libmail_kwgDestroy(&g);
00052 
00053               if (rc)
00054                      return -1;
00055 
00056 
00057               libmail_kwhInit(&kwh);
00058 
00059               if (!(kwm=libmail_kwmCreate()))
00060               {
00061                      perror("libmail_kwmCreate");
00062                      return -1;
00063               }
00064 
00065               while (optind < argc)
00066                      if (libmail_kwmSetName(&kwh, kwm,
00067                                           argv[optind++]) < 0)
00068                      {
00069                             libmail_kwmDestroy(kwm);
00070                             perror("libmail_kwmSetName");
00071                             return -1;
00072                      }
00073 
00074               if (maildir_kwSave(maildir, filename, kwm,
00075                                &tmpname, &newname, 0) < 0)
00076               {
00077                      perror(maildir);
00078                      libmail_kwmDestroy(kwm);
00079                      return -1;
00080               }
00081               libmail_kwmDestroy(kwm);
00082 
00083               if (rename(tmpname, newname) < 0)
00084               {
00085                      perror(newname);
00086                      free(tmpname);
00087                      free(newname);
00088                      return -1;
00089               }
00090               free(tmpname);
00091               free(newname);
00092               return 0;
00093        }
00094        else
00095        {
00096               struct libmail_kwGeneric g;
00097               int rc;
00098               struct libmail_kwGenericEntry *e;
00099               struct libmail_kwMessage *kwm, *kwm_alloced;
00100 
00101               libmail_kwgInit(&g);
00102 
00103               rc=libmail_kwgReadMaildir(&g, maildir);
00104 
00105               if (rc != 0)
00106                      return rc;
00107 
00108               e=libmail_kwgFindByName(&g, filename);
00109 
00110               kwm_alloced=NULL;
00111 
00112               if (e && e->keywords)
00113                      kwm=e->keywords;
00114               else
00115               {
00116                      if ((kwm=kwm_alloced=libmail_kwmCreate()) == NULL)
00117                      {
00118                             perror("libmail_kwmCreate");
00119                             libmail_kwgDestroy(&g);
00120                             return -1;
00121                      }
00122               }
00123 
00124               while (optind < argc)
00125               {
00126                      const char *f=argv[optind++];
00127 
00128                      if ( plusminus == '+')
00129                      {
00130                             if (libmail_kwmSetName(&g.kwHashTable,
00131                                                  kwm, f) < 0)
00132                             {
00133                                    perror("libmail_kwmSetName");
00134                                    if (kwm_alloced)
00135                                           libmail_kwmDestroy(kwm_alloced
00136                                                            );
00137                                    libmail_kwgDestroy(&g);
00138                                    return -1;
00139                             }
00140                      } else
00141                      {
00142                             struct libmail_keywordEntry *kwe=
00143                                    libmail_kweFind(&g.kwHashTable,
00144                                                  f, 0);
00145 
00146                             if (kwe)
00147                                    libmail_kwmClear(kwm, kwe);
00148                      }
00149               }
00150 
00151               rc=maildir_kwSave(maildir, filename, kwm,
00152                               &tmpname, &newname, 1);
00153 
00154               if (rc == 0)
00155               {
00156                      if (link(tmpname, newname) == 0)
00157                      {
00158                             struct stat stat_buf;
00159 
00160                             if (stat(tmpname, &stat_buf) == 0 &&
00161                                 stat_buf.st_nlink == 2)
00162                                    unlink(tmpname);
00163                             else
00164                                    rc=1; /* What's up? */
00165                      }
00166                      else
00167                      {
00168                             if (errno == EEXIST)
00169                                    rc=1;
00170                             else
00171                                    rc= -1;
00172                             unlink(tmpname);
00173                      }
00174               }
00175 
00176               if (kwm_alloced)
00177                      libmail_kwmDestroy(kwm_alloced);
00178               libmail_kwgDestroy(&g);
00179 
00180               return rc;
00181        }
00182 }
00183 
00184 static int list_locked(const char *maildir)
00185 {
00186        struct libmail_kwGeneric g;
00187        int rc;
00188        size_t n;
00189 
00190        libmail_kwgInit(&g);
00191 
00192        rc=libmail_kwgReadMaildir(&g, maildir);
00193 
00194        if (rc)
00195               return rc;
00196 
00197        for (n=0; n<g.nMessages; n++)
00198        {
00199               struct libmail_kwGenericEntry *e=
00200                      libmail_kwgFindByIndex(&g, n);
00201               struct libmail_kwMessageEntry *k;
00202 
00203               if (!e)
00204                      continue;
00205 
00206               printf("%s", e->filename);
00207 
00208               for (k=e->keywords ? e->keywords->firstEntry:NULL; k;
00209                    k=k->next)
00210                      printf(" %s", keywordName(k->libmail_keywordEntryPtr));
00211               printf("\n");
00212        }
00213        return 0;
00214 }
00215 
00216 static int doit(const char *maildir, const char *filename, int lockflag,
00217               int plusminus,
00218               char **argv, int optind, int argc)
00219 {
00220        if (lockflag)
00221        {
00222               struct maildirwatch *w=maildirwatch_alloc(maildir);
00223               int tryAnyway;
00224               char *lockname;
00225               int rc;
00226 
00227               if (!w)
00228               {
00229                      perror(maildir);
00230                      return -1;
00231               }
00232 
00233               lockname=maildir_lock(maildir, w, &tryAnyway);
00234 
00235               if (!lockname)
00236               {
00237                      perror(maildir);
00238                      if (!tryAnyway)
00239                      {
00240                             maildirwatch_free(w);
00241                             maildirwatch_cleanup();
00242                             return -1;
00243                      }
00244               }
00245 
00246               rc=doit_locked(maildir, filename, 1, plusminus,
00247                             argv, optind, argc);
00248               if (lockname)
00249               {
00250                      unlink(lockname);
00251                      free(lockname);
00252               }
00253               maildirwatch_free(w);
00254               maildirwatch_cleanup();
00255               return rc;
00256        }
00257 
00258        return doit_locked(maildir, filename, 0, plusminus,
00259                         argv, optind, argc);
00260 }
00261 
00262 static int dolist(const char *maildir, int lockflag)
00263 {
00264        if (lockflag)
00265        {
00266               struct maildirwatch *w=maildirwatch_alloc(maildir);
00267               int tryAnyway;
00268               char *lockname;
00269               int rc;
00270 
00271               if (!w)
00272               {
00273                      perror(maildir);
00274                      return -1;
00275               }
00276 
00277               lockname=maildir_lock(maildir, w, &tryAnyway);
00278 
00279               if (!lockname)
00280               {
00281                      perror(maildir);
00282                      if (!tryAnyway)
00283                      {
00284                             maildirwatch_free(w);
00285                             maildirwatch_cleanup();
00286                             return -1;
00287                      }
00288               }
00289 
00290               rc=list_locked(maildir);
00291               if (lockname)
00292               {
00293                      unlink(lockname);
00294                      free(lockname);
00295               }
00296               maildirwatch_free(w);
00297               maildirwatch_cleanup();
00298               return rc;
00299        }
00300 
00301        return list_locked(maildir);
00302 }
00303 
00304 int main(int argc, char *argv[])
00305 {
00306        int lockflag=0;
00307        int optc;
00308        const char *maildir;
00309        const char *filename;
00310        int list=0;
00311        int plusminus=0;
00312        int n;
00313 
00314        libmail_kwCaseSensitive=0;
00315 
00316        while ((optc=getopt(argc, argv, "arLlhc")) != -1)
00317               switch (optc) {
00318               case 'c':
00319                      libmail_kwCaseSensitive=1;
00320                      break;
00321               case 'l':
00322                      lockflag=1;
00323                      break;
00324               case 'L':
00325                      list=1;
00326                      break;
00327               case 'a':
00328                      plusminus='+';
00329                      break;
00330               case 'r':
00331                      plusminus='-';
00332                      break;
00333               default:
00334                      usage();
00335               }
00336 
00337        if (optind >= argc)
00338               usage();
00339 
00340        maildir=argv[optind++];
00341 
00342        if (list)
00343        {
00344               exit (dolist(maildir, lockflag));
00345        }
00346 
00347        if (optind >= argc)
00348               usage();
00349 
00350        filename=argv[optind++];
00351 
00352        while ((n=doit(maildir, filename, lockflag, plusminus,
00353                      argv, optind, argc)) > 0)
00354               ;
00355 
00356        exit(-n);
00357        return (0);
00358 }