path.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
       ---
       path.c (4206B)
       ---
            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 <sys/stat.h>
           10 #include <sys/types.h>
           11 #include <stdarg.h>
           12 #include <fcntl.h>
           13 #include <string.h>
           14 
           15 #include "arg.h"
           16 #include "ind.h"
           17 #include "path.h"
           18 
           19 enum {
           20         PATH_MKFILE = 0x00,
           21         PATH_MKDIR
           22 };
           23 
           24 char *
           25 path_chkmk(char *base, char *spath, int mode, int cmode)
           26 {
           27         struct stat sbuf;
           28         char *path, *home;
           29         int fd;
           30 
           31         if (base != NULL) {
           32                 home = expandhome(base);
           33                 path = smprintf("%s/%s", home, spath);
           34                 free(home);
           35         } else {
           36                 path = memdup(spath, strlen(spath)+1);
           37         }
           38 
           39         if (stat(path, &sbuf) < 0) {
           40                 switch(mode) {
           41                 case PATH_MKFILE:
           42                         fd = open(path, O_WRONLY|O_CREAT|O_TRUNC,
           43                                         (cmode >= 0)? \
           44                                         cmode : (S_IRUSR|S_IWUSR));
           45                         if (fd < 0)
           46                                 edie("open");
           47                         close(fd);
           48                         break;
           49                 case PATH_MKDIR:
           50                         if (mkdir(path, (cmode >= 0)? \
           51                                         cmode : S_IRWXU) < 0) {
           52                                 edie("mkdir");
           53                         }
           54                         break;
           55                 default:
           56                         die("path_chkmkdir: Unknown mode.\n");
           57                 }
           58         }
           59 
           60         return path;
           61 }
           62 
           63 char *
           64 path_chkmkfile(char *base, char *path, int mode)
           65 {
           66         return path_chkmk(base, path, PATH_MKFILE, mode);
           67 }
           68 
           69 char *
           70 path_chkmkdir(char *base, char *path, int mode)
           71 {
           72         return path_chkmk(base, path, PATH_MKDIR, mode);
           73 }
           74 
           75 char *
           76 path_mkrppath(char *rppath)
           77 {
           78         return path_chkmkdir("~", (rppath)? rppath : RPPATH, -1);
           79 }
           80 
           81 char *
           82 path_mkbasepath(char *cfgn)
           83 {
           84         char *path, *rpath, *cwd;
           85         struct stat sbuf;
           86 
           87         cwd = getcwd(NULL, 0);
           88         if (cwd == NULL)
           89                 edie("getcwd");
           90 
           91         path = path_mkrppath(NULL);
           92         if (chdir(path) < 0)
           93                 edie("chdir");
           94         if (lstat("default", &sbuf) < 0) {
           95                 if (cfgn == NULL || !strcmp(cfgn, "default")) {
           96                         die("You are trying to create a 'default'"
           97                                 " configuration while no other configuration"
           98                                 " exists."
           99                                 " Please use _rppath -ic somecfg_ to"
          100                                 " initialize the configuration 'somecfg' and"
          101                                 " make it the default using _rpcfg -e"
          102                                 " somecfg_. Then this error message"
          103                                 " disappears.\n");
          104                 }
          105         } else {
          106                 if (!S_ISLNK(sbuf.st_mode)) {
          107                         die("There seems to be some 'default' configuration"
          108                                 " folder. This should be a symlink. Please go"
          109                                 " to '%s' and check this. If no other folder"
          110                                 " exists, it might help to run"
          111                                 " _mv default somecfg_ and _rpcfg -e"
          112                                 " somecfg_. The last command will create the"
          113                                 " symlink to 'default' and this error message"
          114                                 " disappears. If nothing helps, remove the"
          115                                 " 'default' directory and reinitialize your"
          116                                 " configuration using a different name.\n",
          117                                 path);
          118                 }
          119         }
          120 
          121         rpath = path_chkmkdir(path, (cfgn)? cfgn : "default", -1);
          122         free(path);
          123 
          124         if (chdir(cwd) < 0)
          125                 edie("chdir");
          126         free(cwd);
          127 
          128         return rpath;
          129 }
          130 
          131 char *
          132 path_mkcfgfile(char *cfgn)
          133 {
          134         char *path, *rpath;
          135 
          136         path = path_mkbasepath(cfgn);
          137         rpath = path_chkmkfile(path, "config", -1);
          138         free(path);
          139 
          140         return rpath;
          141 }
          142 
          143 char *
          144 path_mkmarkfile(char *cfgn, char *markn)
          145 {
          146         char *path, *mpath;
          147 
          148         if (markn == NULL)
          149                 return NULL;
          150 
          151         path = path_mkbasepath(cfgn);
          152         mpath = path_chkmkdir(path, "marks", -1);
          153         free(path);
          154 
          155         path = path_chkmkfile(mpath, markn, -1);
          156         free(mpath);
          157 
          158         return path;
          159 }
          160 
          161 char *
          162 path_mkincfile(char *cfgn)
          163 {
          164         char *path, *rpath;
          165 
          166         path = path_mkbasepath(cfgn);
          167         rpath = path_chkmkfile(path, "status", -1);
          168         free(path);
          169 
          170         return rpath;
          171 }
          172 
          173 void
          174 pathusage(char *argv0)
          175 {
          176         die("usage: %s [-bhi] [-c cfg]\n", argv0);
          177 }
          178 
          179 int
          180 pathmain(int argc, char *argv[])
          181 {
          182         int status;
          183         char *cfgn, *path, *argv0;
          184 
          185         enum {
          186                 PRINTBASE = 0x01,
          187                 INITBASE = 0x02,
          188         };
          189 
          190         status = 0;
          191         cfgn = NULL;
          192 
          193         ARGBEGIN(argv0) {
          194         case 'b':
          195                 status |= PRINTBASE;
          196                 break;
          197         case 'c':
          198                 cfgn = EARGF(pathusage(argv0));
          199                 break;
          200         case 'i':
          201                 status |= INITBASE;
          202                 break;
          203         default:
          204                 pathusage(argv0);
          205         } ARGEND;
          206 
          207         if (status & PRINTBASE) {
          208                 path = path_mkbasepath(cfgn);
          209                 printf("%s\n", path);
          210                 free(path);
          211                 return 0;
          212         }
          213 
          214         if (status & INITBASE) {
          215                 /* Will initialize all subpathnames. */
          216                 path = path_mkbasepath(cfgn);
          217                 free(path_chkmkfile(path, "config", -1));
          218                 free(path_chkmkfile(path, "status", -1));
          219                 free(path_chkmkdir(path, "drafts", -1));
          220                 free(path_chkmkdir(path, "marks", -1));
          221                 free(path_chkmkdir(path, "tmpl", -1));
          222 
          223                 printf("The directory '%s' has been initialized.\n", path);
          224                 free(path);
          225                 return 0;
          226         }
          227 
          228         pathusage(argv0);
          229 
          230         return 0;
          231 }
          232