Mercurial > hg > toybox
annotate lib/xwrap.c @ 1327:85f297591693 draft
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 31 May 2014 12:33:24 -0500 |
parents | 955169e818d0 |
children | 9fd2bcedbeb5 |
rev | line source |
---|---|
951 | 1 /* xwrap.c - wrappers around existing library functions. |
2 * | |
3 * Functions with the x prefix are wrappers that either succeed or kill the | |
4 * program with an error message, but never return failure. They usually have | |
5 * the same arguments and return value as the function they wrap. | |
6 * | |
7 * Copyright 2006 Rob Landley <rob@landley.net> | |
8 */ | |
9 | |
10 #include "toys.h" | |
11 | |
12 // Strcpy with size checking: exit if there's not enough space for the string. | |
13 void xstrncpy(char *dest, char *src, size_t size) | |
14 { | |
1105
1bca28705a87
Give xstrncpy() a more informative error message.
Rob Landley <rob@landley.net>
parents:
1053
diff
changeset
|
15 if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size); |
951 | 16 strcpy(dest, src); |
17 } | |
18 | |
19 void xexit(void) | |
20 { | |
21 if (toys.rebound) longjmp(*toys.rebound, 1); | |
22 else exit(toys.exitval); | |
23 } | |
24 | |
25 // Die unless we can allocate memory. | |
26 void *xmalloc(size_t size) | |
27 { | |
28 void *ret = malloc(size); | |
29 if (!ret) error_exit("xmalloc"); | |
30 | |
31 return ret; | |
32 } | |
33 | |
34 // Die unless we can allocate prezeroed memory. | |
35 void *xzalloc(size_t size) | |
36 { | |
37 void *ret = xmalloc(size); | |
38 memset(ret, 0, size); | |
39 return ret; | |
40 } | |
41 | |
42 // Die unless we can change the size of an existing allocation, possibly | |
43 // moving it. (Notice different arguments from libc function.) | |
44 void *xrealloc(void *ptr, size_t size) | |
45 { | |
46 ptr = realloc(ptr, size); | |
47 if (!ptr) error_exit("xrealloc"); | |
48 | |
49 return ptr; | |
50 } | |
51 | |
52 // Die unless we can allocate a copy of this many bytes of string. | |
53 char *xstrndup(char *s, size_t n) | |
54 { | |
55 char *ret = xmalloc(++n); | |
56 strncpy(ret, s, n); | |
57 ret[--n]=0; | |
58 | |
59 return ret; | |
60 } | |
61 | |
62 // Die unless we can allocate a copy of this string. | |
63 char *xstrdup(char *s) | |
64 { | |
65 return xstrndup(s, strlen(s)); | |
66 } | |
67 | |
68 // Die unless we can allocate enough space to sprintf() into. | |
1183
0752b2d58909
Rename xmsprintf() to just xmprintf().
Rob Landley <rob@landley.net>
parents:
1170
diff
changeset
|
69 char *xmprintf(char *format, ...) |
951 | 70 { |
71 va_list va, va2; | |
72 int len; | |
73 char *ret; | |
74 | |
75 va_start(va, format); | |
76 va_copy(va2, va); | |
77 | |
78 // How long is it? | |
79 len = vsnprintf(0, 0, format, va); | |
80 len++; | |
81 va_end(va); | |
82 | |
83 // Allocate and do the sprintf() | |
84 ret = xmalloc(len); | |
85 vsnprintf(ret, len, format, va2); | |
86 va_end(va2); | |
87 | |
88 return ret; | |
89 } | |
90 | |
91 void xprintf(char *format, ...) | |
92 { | |
93 va_list va; | |
94 va_start(va, format); | |
95 | |
96 vprintf(format, va); | |
1318
955169e818d0
Isaac Dunham suggested xprintf() should call fflush() instead of ferror(), and posix-2008 doesn't say if fflush() covers ferror() (or can return success when the stream's error state is set), so call both.
Rob Landley <rob@landley.net>
parents:
1235
diff
changeset
|
97 if (fflush(stdout) || ferror(stdout)) perror_exit("write"); |
951 | 98 } |
99 | |
100 void xputs(char *s) | |
101 { | |
1318
955169e818d0
Isaac Dunham suggested xprintf() should call fflush() instead of ferror(), and posix-2008 doesn't say if fflush() covers ferror() (or can return success when the stream's error state is set), so call both.
Rob Landley <rob@landley.net>
parents:
1235
diff
changeset
|
102 if (EOF == puts(s) || fflush(stdout) || ferror(stdout)) perror_exit("write"); |
951 | 103 } |
104 | |
105 void xputc(char c) | |
106 { | |
1318
955169e818d0
Isaac Dunham suggested xprintf() should call fflush() instead of ferror(), and posix-2008 doesn't say if fflush() covers ferror() (or can return success when the stream's error state is set), so call both.
Rob Landley <rob@landley.net>
parents:
1235
diff
changeset
|
107 if (EOF == fputc(c, stdout) || fflush(stdout) || ferror(stdout)) |
955169e818d0
Isaac Dunham suggested xprintf() should call fflush() instead of ferror(), and posix-2008 doesn't say if fflush() covers ferror() (or can return success when the stream's error state is set), so call both.
Rob Landley <rob@landley.net>
parents:
1235
diff
changeset
|
108 perror_exit("write"); |
951 | 109 } |
110 | |
111 void xflush(void) | |
112 { | |
1318
955169e818d0
Isaac Dunham suggested xprintf() should call fflush() instead of ferror(), and posix-2008 doesn't say if fflush() covers ferror() (or can return success when the stream's error state is set), so call both.
Rob Landley <rob@landley.net>
parents:
1235
diff
changeset
|
113 if (fflush(stdout) || ferror(stdout)) perror_exit("write");; |
951 | 114 } |
115 | |
1327
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
116 pid_t xfork(void) |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
117 { |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
118 pid_t pid = fork(); |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
119 |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
120 if (pid < 0) perror_exit("fork"); |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
121 |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
122 return pid; |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
123 } |
85f297591693
Introduce xfork() and make commands use it, and make some WEXITSTATUS() use WIFEXITED() and WTERMSIG()+127.
Rob Landley <rob@landley.net>
parents:
1318
diff
changeset
|
124 |
952
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
125 // Call xexec with a chunk of optargs, starting at skip. (You can't just |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
126 // call xexec() directly because toy_init() frees optargs.) |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
127 void xexec_optargs(int skip) |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
128 { |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
129 char **s = toys.optargs; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
130 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
131 toys.optargs = 0; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
132 xexec(s+skip); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
133 } |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
134 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
135 |
951 | 136 // Die unless we can exec argv[] (or run builtin command). Note that anything |
137 // with a path isn't a builtin, so /bin/sh won't match the builtin sh. | |
138 void xexec(char **argv) | |
139 { | |
1032
40d0c96a8e89
Add scripts/single.sh to build individual non-multiplexed standalone commands.
Rob Landley <rob@landley.net>
parents:
1028
diff
changeset
|
140 if (CFG_TOYBOX) toy_exec(argv); |
951 | 141 execvp(argv[0], argv); |
142 | |
143 perror_exit("exec %s", argv[0]); | |
144 } | |
145 | |
146 void xaccess(char *path, int flags) | |
147 { | |
148 if (access(path, flags)) perror_exit("Can't access '%s'", path); | |
149 } | |
150 | |
151 // Die unless we can delete a file. (File must exist to be deleted.) | |
152 void xunlink(char *path) | |
153 { | |
154 if (unlink(path)) perror_exit("unlink '%s'", path); | |
155 } | |
156 | |
157 // Die unless we can open/create a file, returning file descriptor. | |
158 int xcreate(char *path, int flags, int mode) | |
159 { | |
160 int fd = open(path, flags, mode); | |
161 if (fd == -1) perror_exit("%s", path); | |
162 return fd; | |
163 } | |
164 | |
165 // Die unless we can open a file, returning file descriptor. | |
166 int xopen(char *path, int flags) | |
167 { | |
168 return xcreate(path, flags, 0); | |
169 } | |
170 | |
171 void xclose(int fd) | |
172 { | |
173 if (close(fd)) perror_exit("xclose"); | |
174 } | |
175 | |
176 int xdup(int fd) | |
177 { | |
178 if (fd != -1) { | |
179 fd = dup(fd); | |
180 if (fd == -1) perror_exit("xdup"); | |
181 } | |
182 return fd; | |
183 } | |
184 | |
991
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
185 FILE *xfdopen(int fd, char *mode) |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
186 { |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
187 FILE *f = fdopen(fd, mode); |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
188 |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
189 if (!f) perror_exit("xfdopen"); |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
190 |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
191 return f; |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
192 } |
252caf3d2b88
Forgot to check in xfdopen(). My bad.
Rob Landley <rob@landley.net>
parents:
956
diff
changeset
|
193 |
951 | 194 // Die unless we can open/create a file, returning FILE *. |
195 FILE *xfopen(char *path, char *mode) | |
196 { | |
197 FILE *f = fopen(path, mode); | |
198 if (!f) perror_exit("No file %s", path); | |
199 return f; | |
200 } | |
201 | |
202 // Die if there's an error other than EOF. | |
203 size_t xread(int fd, void *buf, size_t len) | |
204 { | |
205 ssize_t ret = read(fd, buf, len); | |
206 if (ret < 0) perror_exit("xread"); | |
207 | |
208 return ret; | |
209 } | |
210 | |
211 void xreadall(int fd, void *buf, size_t len) | |
212 { | |
213 if (len != readall(fd, buf, len)) perror_exit("xreadall"); | |
214 } | |
215 | |
216 // There's no xwriteall(), just xwrite(). When we read, there may or may not | |
217 // be more data waiting. When we write, there is data and it had better go | |
218 // somewhere. | |
219 | |
220 void xwrite(int fd, void *buf, size_t len) | |
221 { | |
222 if (len != writeall(fd, buf, len)) perror_exit("xwrite"); | |
223 } | |
224 | |
225 // Die if lseek fails, probably due to being called on a pipe. | |
226 | |
227 off_t xlseek(int fd, off_t offset, int whence) | |
228 { | |
229 offset = lseek(fd, offset, whence); | |
230 if (offset<0) perror_exit("lseek"); | |
231 | |
232 return offset; | |
233 } | |
234 | |
235 char *xgetcwd(void) | |
236 { | |
237 char *buf = getcwd(NULL, 0); | |
238 if (!buf) perror_exit("xgetcwd"); | |
239 | |
240 return buf; | |
241 } | |
242 | |
243 void xstat(char *path, struct stat *st) | |
244 { | |
245 if(stat(path, st)) perror_exit("Can't stat %s", path); | |
246 } | |
247 | |
248 // Cannonicalize path, even to file with one or more missing components at end. | |
249 // if exact, require last path component to exist | |
250 char *xabspath(char *path, int exact) | |
251 { | |
252 struct string_list *todo, *done = 0; | |
253 int try = 9999, dirfd = open("/", 0);; | |
254 char buf[4096], *ret; | |
255 | |
256 // If this isn't an absolute path, start with cwd. | |
257 if (*path != '/') { | |
258 char *temp = xgetcwd(); | |
259 | |
260 splitpath(path, splitpath(temp, &todo)); | |
261 free(temp); | |
262 } else splitpath(path, &todo); | |
263 | |
264 // Iterate through path components | |
265 while (todo) { | |
266 struct string_list *new = llist_pop(&todo), **tail; | |
267 ssize_t len; | |
268 | |
269 if (!try--) { | |
270 errno = ELOOP; | |
271 goto error; | |
272 } | |
273 | |
274 // Removable path componenents. | |
275 if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { | |
276 int x = new->str[1]; | |
277 | |
278 free(new); | |
279 if (x) { | |
280 if (done) free(llist_pop(&done)); | |
281 len = 0; | |
282 } else continue; | |
283 | |
284 // Is this a symlink? | |
285 } else len=readlinkat(dirfd, new->str, buf, 4096); | |
286 | |
287 if (len>4095) goto error; | |
288 if (len<1) { | |
289 int fd; | |
290 char *s = ".."; | |
291 | |
292 // For .. just move dirfd | |
293 if (len) { | |
294 // Not a symlink: add to linked list, move dirfd, fail if error | |
295 if ((exact || todo) && errno != EINVAL) goto error; | |
296 new->next = done; | |
297 done = new; | |
298 if (errno == EINVAL && !todo) break; | |
299 s = new->str; | |
300 } | |
301 fd = openat(dirfd, s, 0); | |
302 if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; | |
303 close(dirfd); | |
304 dirfd = fd; | |
305 continue; | |
306 } | |
307 | |
308 // If this symlink is to an absolute path, discard existing resolved path | |
309 buf[len] = 0; | |
310 if (*buf == '/') { | |
311 llist_traverse(done, free); | |
312 done=0; | |
313 close(dirfd); | |
314 dirfd = open("/", 0); | |
315 } | |
316 free(new); | |
317 | |
318 // prepend components of new path. Note symlink to "/" will leave new NULL | |
319 tail = splitpath(buf, &new); | |
320 | |
321 // symlink to "/" will return null and leave tail alone | |
322 if (new) { | |
323 *tail = todo; | |
324 todo = new; | |
325 } | |
326 } | |
327 close(dirfd); | |
328 | |
329 // At this point done has the path, in reverse order. Reverse list while | |
330 // calculating buffer length. | |
331 | |
332 try = 2; | |
333 while (done) { | |
334 struct string_list *temp = llist_pop(&done);; | |
335 | |
336 if (todo) try++; | |
337 try += strlen(temp->str); | |
338 temp->next = todo; | |
339 todo = temp; | |
340 } | |
341 | |
342 // Assemble return buffer | |
343 | |
344 ret = xmalloc(try); | |
345 *ret = '/'; | |
346 ret [try = 1] = 0; | |
347 while (todo) { | |
348 if (try>1) ret[try++] = '/'; | |
349 try = stpcpy(ret+try, todo->str) - ret; | |
350 free(llist_pop(&todo)); | |
351 } | |
352 | |
353 return ret; | |
354 | |
355 error: | |
356 close(dirfd); | |
357 llist_traverse(todo, free); | |
358 llist_traverse(done, free); | |
359 | |
360 return NULL; | |
361 } | |
362 | |
363 // Resolve all symlinks, returning malloc() memory. | |
364 char *xrealpath(char *path) | |
365 { | |
366 char *new = realpath(path, NULL); | |
367 if (!new) perror_exit("realpath '%s'", path); | |
368 return new; | |
369 } | |
370 | |
371 void xchdir(char *path) | |
372 { | |
373 if (chdir(path)) error_exit("chdir '%s'", path); | |
374 } | |
375 | |
1156
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
376 void xchroot(char *path) |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
377 { |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
378 if (chroot(path)) error_exit("chroot '%s'", path); |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
379 xchdir("/"); |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
380 } |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
381 |
1129
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
382 struct passwd *xgetpwuid(uid_t uid) |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
383 { |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
384 struct passwd *pwd = getpwuid(uid); |
1130
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
385 if (!pwd) error_exit("bad uid %ld", (long)uid); |
1129
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
386 return pwd; |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
387 } |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
388 |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
389 struct group *xgetgrgid(gid_t gid) |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
390 { |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
391 struct group *group = getgrgid(gid); |
1130
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
392 if (!group) error_exit("bad gid %ld", (long)gid); |
1129
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
393 return group; |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
394 } |
c644f85444d0
Move xgetpwuid() and xgetgrgid() into xwrap.c
Rob Landley <rob@landley.net>
parents:
1105
diff
changeset
|
395 |
1130
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
396 struct passwd *xgetpwnam(char *name) |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
397 { |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
398 struct passwd *up = getpwnam(name); |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
399 if (!up) error_exit("bad user '%s'", name); |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
400 return up; |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
401 } |
6df194c6de88
Add xgetpwnam() to lib/xwrap.c.
Rob Landley <rob@landley.net>
parents:
1129
diff
changeset
|
402 |
1156
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
403 // setuid() can fail (for example, too many processes belonging to that user), |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
404 // which opens a security hole if the process continues as the original user. |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
405 |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
406 void xsetuser(struct passwd *pwd) |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
407 { |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
408 if (initgroups(pwd->pw_name, pwd->pw_gid) || setgid(pwd->pw_uid) |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
409 || setuid(pwd->pw_uid)) perror_exit("xsetuser '%s'", pwd->pw_name); |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
410 } |
faf7117c4489
Fix some issues raised (albeit indirectly) by Isaac Dunham.
Rob Landley <rob@landley.net>
parents:
1130
diff
changeset
|
411 |
951 | 412 // This can return null (meaning file not found). It just won't return null |
413 // for memory allocation reasons. | |
414 char *xreadlink(char *name) | |
415 { | |
416 int len, size = 0; | |
417 char *buf = 0; | |
418 | |
419 // Grow by 64 byte chunks until it's big enough. | |
420 for(;;) { | |
421 size +=64; | |
422 buf = xrealloc(buf, size); | |
423 len = readlink(name, buf, size); | |
424 | |
425 if (len<0) { | |
426 free(buf); | |
427 return 0; | |
428 } | |
429 if (len<size) { | |
430 buf[len]=0; | |
431 return buf; | |
432 } | |
433 } | |
434 } | |
435 | |
1170
8afe1fde9314
Pass through all the readfile() arguments from xreadfile().
Rob Landley <rob@landley.net>
parents:
1156
diff
changeset
|
436 char *xreadfile(char *name, char *buf, off_t len) |
951 | 437 { |
1170
8afe1fde9314
Pass through all the readfile() arguments from xreadfile().
Rob Landley <rob@landley.net>
parents:
1156
diff
changeset
|
438 if (!(buf = readfile(name, buf, len))) perror_exit("Bad '%s'", name); |
8afe1fde9314
Pass through all the readfile() arguments from xreadfile().
Rob Landley <rob@landley.net>
parents:
1156
diff
changeset
|
439 |
951 | 440 return buf; |
441 } | |
442 | |
443 int xioctl(int fd, int request, void *data) | |
444 { | |
445 int rc; | |
446 | |
447 errno = 0; | |
448 rc = ioctl(fd, request, data); | |
449 if (rc == -1 && errno) perror_exit("ioctl %x", request); | |
450 | |
451 return rc; | |
452 } | |
453 | |
454 // Open a /var/run/NAME.pid file, dying if we can't write it or if it currently | |
455 // exists and is this executable. | |
456 void xpidfile(char *name) | |
457 { | |
458 char pidfile[256], spid[32]; | |
459 int i, fd; | |
460 pid_t pid; | |
461 | |
462 sprintf(pidfile, "/var/run/%s.pid", name); | |
463 // Try three times to open the sucker. | |
464 for (i=0; i<3; i++) { | |
1028 | 465 fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); |
951 | 466 if (fd != -1) break; |
467 | |
468 // If it already existed, read it. Loop for race condition. | |
469 fd = open(pidfile, O_RDONLY); | |
470 if (fd == -1) continue; | |
471 | |
472 // Is the old program still there? | |
473 spid[xread(fd, spid, sizeof(spid)-1)] = 0; | |
474 close(fd); | |
475 pid = atoi(spid); | |
1053
501fd74c028e
Fix for xpidfile spotted by Felix Janda.
Rob Landley <rob@landley.net>
parents:
1043
diff
changeset
|
476 if (pid < 1 || (kill(pid, 0) && errno == ESRCH)) unlink(pidfile); |
951 | 477 |
478 // An else with more sanity checking might be nice here. | |
479 } | |
480 | |
481 if (i == 3) error_exit("xpidfile %s", name); | |
482 | |
483 xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); | |
484 close(fd); | |
485 } | |
486 | |
487 // Copy the rest of in to out and close both files. | |
488 | |
489 void xsendfile(int in, int out) | |
490 { | |
491 long len; | |
492 char buf[4096]; | |
493 | |
494 if (in<0) return; | |
495 for (;;) { | |
496 len = xread(in, buf, 4096); | |
497 if (len<1) break; | |
498 xwrite(out, buf, len); | |
499 } | |
500 } | |
952
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
501 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
502 // parse fractional seconds with optional s/m/h/d suffix |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
503 long xparsetime(char *arg, long units, long *fraction) |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
504 { |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
505 double d; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
506 long l; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
507 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
508 if (CFG_TOYBOX_FLOAT) d = strtod(arg, &arg); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
509 else l = strtoul(arg, &arg, 10); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
510 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
511 // Parse suffix |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
512 if (*arg) { |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
513 int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
514 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
515 if (i == -1) error_exit("Unknown suffix '%c'", *arg); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
516 if (CFG_TOYBOX_FLOAT) d *= ismhd[i]; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
517 else l *= ismhd[i]; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
518 } |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
519 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
520 if (CFG_TOYBOX_FLOAT) { |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
521 l = (long)d; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
522 if (fraction) *fraction = units*(d-l); |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
523 } else if (fraction) *fraction = 0; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
524 |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
525 return l; |
ce0519f6457c
Add timeout, factoring out common code from sleep.
Rob Landley <rob@landley.net>
parents:
951
diff
changeset
|
526 } |
1235
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
527 |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
528 // Compile a regular expression into a regex_t |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
529 void xregcomp(regex_t *preg, char *regex, int cflags) |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
530 { |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
531 int rc = regcomp(preg, regex, cflags); |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
532 |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
533 if (rc) { |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
534 regerror(rc, preg, libbuf, sizeof(libbuf)); |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
535 error_exit("xregcomp: %s", libbuf); |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
536 } |
63db77909fc8
Group headers by standard (POSIX or LSB) or function (internationalization, networking). Move headers standards ignore (but which have been there >15 years) to lib/portability.h. Fold xregcomp into lib since it's posix.
Rob Landley <rob@landley.net>
parents:
1219
diff
changeset
|
537 } |