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