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