Contents of /trunk/mkinitrd-magellan/busybox/runit/runit_lib.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 17948 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 17948 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* |
2 | Copyright (c) 2001-2006, Gerrit Pape |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | |
8 | 1. Redistributions of source code must retain the above copyright notice, |
9 | this list of conditions and the following disclaimer. |
10 | 2. Redistributions in binary form must reproduce the above copyright |
11 | notice, this list of conditions and the following disclaimer in the |
12 | documentation and/or other materials provided with the distribution. |
13 | 3. The name of the author may not be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
19 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */ |
29 | /* Collected into one file from runit's many tiny files */ |
30 | /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */ |
31 | |
32 | #include <sys/poll.h> |
33 | #include <sys/file.h> |
34 | #include "libbb.h" |
35 | #include "runit_lib.h" |
36 | |
37 | /*** buffer.c ***/ |
38 | |
39 | void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len) |
40 | { |
41 | s->x = buf; |
42 | s->fd = fd; |
43 | s->op = op; |
44 | s->p = 0; |
45 | s->n = len; |
46 | } |
47 | |
48 | |
49 | /*** buffer_get.c ***/ |
50 | |
51 | static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len) |
52 | { |
53 | int r; |
54 | |
55 | for (;;) { |
56 | r = op(fd,buf,len); |
57 | if (r == -1) if (errno == EINTR) continue; |
58 | return r; |
59 | } |
60 | } |
61 | |
62 | static int getthis(buffer *s,char *buf,unsigned len) |
63 | { |
64 | if (len > s->p) len = s->p; |
65 | s->p -= len; |
66 | memcpy(buf,s->x + s->n,len); |
67 | s->n += len; |
68 | return len; |
69 | } |
70 | |
71 | int buffer_feed(buffer *s) |
72 | { |
73 | int r; |
74 | |
75 | if (s->p) return s->p; |
76 | r = oneread(s->op,s->fd,s->x,s->n); |
77 | if (r <= 0) return r; |
78 | s->p = r; |
79 | s->n -= r; |
80 | if (s->n > 0) memmove(s->x + s->n,s->x,r); |
81 | return r; |
82 | } |
83 | |
84 | int buffer_bget(buffer *s,char *buf,unsigned len) |
85 | { |
86 | int r; |
87 | |
88 | if (s->p > 0) return getthis(s,buf,len); |
89 | if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); |
90 | r = buffer_feed(s); if (r <= 0) return r; |
91 | return getthis(s,buf,len); |
92 | } |
93 | |
94 | int buffer_get(buffer *s,char *buf,unsigned len) |
95 | { |
96 | int r; |
97 | |
98 | if (s->p > 0) return getthis(s,buf,len); |
99 | if (s->n <= len) return oneread(s->op,s->fd,buf,len); |
100 | r = buffer_feed(s); if (r <= 0) return r; |
101 | return getthis(s,buf,len); |
102 | } |
103 | |
104 | char *buffer_peek(buffer *s) |
105 | { |
106 | return s->x + s->n; |
107 | } |
108 | |
109 | void buffer_seek(buffer *s,unsigned len) |
110 | { |
111 | s->n += len; |
112 | s->p -= len; |
113 | } |
114 | |
115 | |
116 | /*** buffer_put.c ***/ |
117 | |
118 | static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len) |
119 | { |
120 | int w; |
121 | |
122 | while (len) { |
123 | w = op(fd,(char*)buf,len); |
124 | if (w == -1) { |
125 | if (errno == EINTR) continue; |
126 | return -1; /* note that some data may have been written */ |
127 | } |
128 | if (w == 0) ; /* luser's fault */ |
129 | buf += w; |
130 | len -= w; |
131 | } |
132 | return 0; |
133 | } |
134 | |
135 | int buffer_flush(buffer *s) |
136 | { |
137 | int p; |
138 | |
139 | p = s->p; |
140 | if (!p) return 0; |
141 | s->p = 0; |
142 | return allwrite(s->op,s->fd,s->x,p); |
143 | } |
144 | |
145 | int buffer_putalign(buffer *s,const char *buf,unsigned len) |
146 | { |
147 | unsigned n; |
148 | |
149 | while (len > (n = s->n - s->p)) { |
150 | memcpy(s->x + s->p,buf,n); |
151 | s->p += n; |
152 | buf += n; |
153 | len -= n; |
154 | if (buffer_flush(s) == -1) return -1; |
155 | } |
156 | /* now len <= s->n - s->p */ |
157 | memcpy(s->x + s->p,buf,len); |
158 | s->p += len; |
159 | return 0; |
160 | } |
161 | |
162 | int buffer_put(buffer *s,const char *buf,unsigned len) |
163 | { |
164 | unsigned n; |
165 | |
166 | n = s->n; |
167 | if (len > n - s->p) { |
168 | if (buffer_flush(s) == -1) return -1; |
169 | /* now s->p == 0 */ |
170 | if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; |
171 | while (len > s->n) { |
172 | if (n > len) n = len; |
173 | if (allwrite(s->op,s->fd,buf,n) == -1) return -1; |
174 | buf += n; |
175 | len -= n; |
176 | } |
177 | } |
178 | /* now len <= s->n - s->p */ |
179 | memcpy(s->x + s->p,buf,len); |
180 | s->p += len; |
181 | return 0; |
182 | } |
183 | |
184 | int buffer_putflush(buffer *s,const char *buf,unsigned len) |
185 | { |
186 | if (buffer_flush(s) == -1) return -1; |
187 | return allwrite(s->op,s->fd,buf,len); |
188 | } |
189 | |
190 | int buffer_putsalign(buffer *s,const char *buf) |
191 | { |
192 | return buffer_putalign(s,buf,strlen(buf)); |
193 | } |
194 | |
195 | int buffer_puts(buffer *s,const char *buf) |
196 | { |
197 | return buffer_put(s,buf,strlen(buf)); |
198 | } |
199 | |
200 | int buffer_putsflush(buffer *s,const char *buf) |
201 | { |
202 | return buffer_putflush(s,buf,strlen(buf)); |
203 | } |
204 | |
205 | |
206 | /*** buffer_read.c ***/ |
207 | |
208 | int buffer_unixread(int fd,char *buf,unsigned len) |
209 | { |
210 | return read(fd,buf,len); |
211 | } |
212 | |
213 | |
214 | /*** buffer_write.c ***/ |
215 | |
216 | int buffer_unixwrite(int fd,char *buf,unsigned len) |
217 | { |
218 | return write(fd,buf,len); |
219 | } |
220 | |
221 | |
222 | /*** byte_chr.c ***/ |
223 | |
224 | unsigned byte_chr(char *s,unsigned n,int c) |
225 | { |
226 | char ch; |
227 | char *t; |
228 | |
229 | ch = c; |
230 | t = s; |
231 | for (;;) { |
232 | if (!n) break; if (*t == ch) break; ++t; --n; |
233 | if (!n) break; if (*t == ch) break; ++t; --n; |
234 | if (!n) break; if (*t == ch) break; ++t; --n; |
235 | if (!n) break; if (*t == ch) break; ++t; --n; |
236 | } |
237 | return t - s; |
238 | } |
239 | |
240 | |
241 | /*** coe.c ***/ |
242 | |
243 | int coe(int fd) |
244 | { |
245 | return fcntl(fd,F_SETFD,FD_CLOEXEC); |
246 | } |
247 | |
248 | |
249 | /*** fd_copy.c ***/ |
250 | |
251 | int fd_copy(int to,int from) |
252 | { |
253 | if (to == from) return 0; |
254 | if (fcntl(from,F_GETFL,0) == -1) return -1; |
255 | close(to); |
256 | if (fcntl(from,F_DUPFD,to) == -1) return -1; |
257 | return 0; |
258 | } |
259 | |
260 | |
261 | /*** fd_move.c ***/ |
262 | |
263 | int fd_move(int to,int from) |
264 | { |
265 | if (to == from) return 0; |
266 | if (fd_copy(to,from) == -1) return -1; |
267 | close(from); |
268 | return 0; |
269 | } |
270 | |
271 | |
272 | /*** fifo.c ***/ |
273 | |
274 | int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); } |
275 | |
276 | |
277 | /*** fmt_ptime.c ***/ |
278 | |
279 | unsigned fmt_ptime(char *s, struct taia *ta) { |
280 | struct tm *t; |
281 | unsigned long u; |
282 | |
283 | if (ta->sec.x < 4611686018427387914ULL) return 0; /* impossible? */ |
284 | u = ta->sec.x -4611686018427387914ULL; |
285 | if (!(t = gmtime((time_t*)&u))) return 0; |
286 | fmt_ulong(s, 1900 + t->tm_year); |
287 | s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2); |
288 | s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2); |
289 | s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2); |
290 | s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2); |
291 | s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2); |
292 | s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9); |
293 | return 25; |
294 | } |
295 | |
296 | unsigned fmt_taia(char *s, struct taia *t) { |
297 | static char pack[TAIA_PACK]; |
298 | |
299 | taia_pack(pack, t); |
300 | *s++ = '@'; |
301 | bin2hex(s, pack, 12); |
302 | return 25; |
303 | } |
304 | |
305 | |
306 | /*** fmt_uint.c ***/ |
307 | |
308 | unsigned fmt_uint(char *s,unsigned u) |
309 | { |
310 | return fmt_ulong(s,u); |
311 | } |
312 | |
313 | |
314 | /*** fmt_uint0.c ***/ |
315 | |
316 | unsigned fmt_uint0(char *s,unsigned u,unsigned n) |
317 | { |
318 | unsigned len; |
319 | len = fmt_uint(FMT_LEN,u); |
320 | while (len < n) { if (s) *s++ = '0'; ++len; } |
321 | if (s) fmt_uint(s,u); |
322 | return len; |
323 | } |
324 | |
325 | |
326 | /*** fmt_ulong.c ***/ |
327 | |
328 | unsigned fmt_ulong(char *s,unsigned long u) |
329 | { |
330 | unsigned len; unsigned long q; |
331 | len = 1; q = u; |
332 | while (q > 9) { ++len; q /= 10; } |
333 | if (s) { |
334 | s += len; |
335 | do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */ |
336 | } |
337 | return len; |
338 | } |
339 | |
340 | |
341 | /*** tai_now.c ***/ |
342 | |
343 | void tai_now(struct tai *t) |
344 | { |
345 | tai_unix(t,time((time_t *) 0)); |
346 | } |
347 | |
348 | |
349 | /*** tai_pack.c ***/ |
350 | |
351 | void tai_pack(char *s,const struct tai *t) |
352 | { |
353 | uint64_t x; |
354 | |
355 | x = t->x; |
356 | s[7] = x & 255; x >>= 8; |
357 | s[6] = x & 255; x >>= 8; |
358 | s[5] = x & 255; x >>= 8; |
359 | s[4] = x & 255; x >>= 8; |
360 | s[3] = x & 255; x >>= 8; |
361 | s[2] = x & 255; x >>= 8; |
362 | s[1] = x & 255; x >>= 8; |
363 | s[0] = x; |
364 | } |
365 | |
366 | |
367 | /*** tai_sub.c ***/ |
368 | |
369 | void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) |
370 | { |
371 | t->x = u->x - v->x; |
372 | } |
373 | |
374 | |
375 | /*** tai_unpack.c ***/ |
376 | |
377 | void tai_unpack(const char *s,struct tai *t) |
378 | { |
379 | uint64_t x; |
380 | |
381 | x = (unsigned char) s[0]; |
382 | x <<= 8; x += (unsigned char) s[1]; |
383 | x <<= 8; x += (unsigned char) s[2]; |
384 | x <<= 8; x += (unsigned char) s[3]; |
385 | x <<= 8; x += (unsigned char) s[4]; |
386 | x <<= 8; x += (unsigned char) s[5]; |
387 | x <<= 8; x += (unsigned char) s[6]; |
388 | x <<= 8; x += (unsigned char) s[7]; |
389 | t->x = x; |
390 | } |
391 | |
392 | |
393 | /*** taia_add.c ***/ |
394 | |
395 | /* XXX: breaks tai encapsulation */ |
396 | |
397 | void taia_add(struct taia *t,const struct taia *u,const struct taia *v) |
398 | { |
399 | t->sec.x = u->sec.x + v->sec.x; |
400 | t->nano = u->nano + v->nano; |
401 | t->atto = u->atto + v->atto; |
402 | if (t->atto > 999999999UL) { |
403 | t->atto -= 1000000000UL; |
404 | ++t->nano; |
405 | } |
406 | if (t->nano > 999999999UL) { |
407 | t->nano -= 1000000000UL; |
408 | ++t->sec.x; |
409 | } |
410 | } |
411 | |
412 | |
413 | /*** taia_approx.c ***/ |
414 | |
415 | double taia_approx(const struct taia *t) |
416 | { |
417 | return tai_approx(&t->sec) + taia_frac(t); |
418 | } |
419 | |
420 | |
421 | /*** taia_frac.c ***/ |
422 | |
423 | double taia_frac(const struct taia *t) |
424 | { |
425 | return (t->atto * 0.000000001 + t->nano) * 0.000000001; |
426 | } |
427 | |
428 | |
429 | /*** taia_less.c ***/ |
430 | |
431 | /* XXX: breaks tai encapsulation */ |
432 | |
433 | int taia_less(const struct taia *t,const struct taia *u) |
434 | { |
435 | if (t->sec.x < u->sec.x) return 1; |
436 | if (t->sec.x > u->sec.x) return 0; |
437 | if (t->nano < u->nano) return 1; |
438 | if (t->nano > u->nano) return 0; |
439 | return t->atto < u->atto; |
440 | } |
441 | |
442 | |
443 | /*** taia_now.c ***/ |
444 | |
445 | void taia_now(struct taia *t) |
446 | { |
447 | struct timeval now; |
448 | gettimeofday(&now,(struct timezone *) 0); |
449 | tai_unix(&t->sec,now.tv_sec); |
450 | t->nano = 1000 * now.tv_usec + 500; |
451 | t->atto = 0; |
452 | } |
453 | |
454 | |
455 | /*** taia_pack.c ***/ |
456 | |
457 | void taia_pack(char *s,const struct taia *t) |
458 | { |
459 | unsigned long x; |
460 | |
461 | tai_pack(s,&t->sec); |
462 | s += 8; |
463 | |
464 | x = t->atto; |
465 | s[7] = x & 255; x >>= 8; |
466 | s[6] = x & 255; x >>= 8; |
467 | s[5] = x & 255; x >>= 8; |
468 | s[4] = x; |
469 | x = t->nano; |
470 | s[3] = x & 255; x >>= 8; |
471 | s[2] = x & 255; x >>= 8; |
472 | s[1] = x & 255; x >>= 8; |
473 | s[0] = x; |
474 | } |
475 | |
476 | |
477 | /*** taia_sub.c ***/ |
478 | |
479 | /* XXX: breaks tai encapsulation */ |
480 | |
481 | void taia_sub(struct taia *t,const struct taia *u,const struct taia *v) |
482 | { |
483 | unsigned long unano = u->nano; |
484 | unsigned long uatto = u->atto; |
485 | |
486 | t->sec.x = u->sec.x - v->sec.x; |
487 | t->nano = unano - v->nano; |
488 | t->atto = uatto - v->atto; |
489 | if (t->atto > uatto) { |
490 | t->atto += 1000000000UL; |
491 | --t->nano; |
492 | } |
493 | if (t->nano > unano) { |
494 | t->nano += 1000000000UL; |
495 | --t->sec.x; |
496 | } |
497 | } |
498 | |
499 | |
500 | /*** taia_uint.c ***/ |
501 | |
502 | /* XXX: breaks tai encapsulation */ |
503 | |
504 | void taia_uint(struct taia *t,unsigned s) |
505 | { |
506 | t->sec.x = s; |
507 | t->nano = 0; |
508 | t->atto = 0; |
509 | } |
510 | |
511 | |
512 | /*** stralloc_cat.c ***/ |
513 | #if 0 |
514 | |
515 | int stralloc_cat(stralloc *sato,const stralloc *safrom) |
516 | { |
517 | return stralloc_catb(sato,safrom->s,safrom->len); |
518 | } |
519 | |
520 | |
521 | /*** stralloc_catb.c ***/ |
522 | |
523 | int stralloc_catb(stralloc *sa,const char *s,unsigned n) |
524 | { |
525 | if (!sa->s) return stralloc_copyb(sa,s,n); |
526 | if (!stralloc_readyplus(sa,n + 1)) return 0; |
527 | memcpy(sa->s + sa->len,s,n); |
528 | sa->len += n; |
529 | sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ |
530 | return 1; |
531 | } |
532 | |
533 | |
534 | /*** stralloc_cats.c ***/ |
535 | |
536 | int stralloc_cats(stralloc *sa,const char *s) |
537 | { |
538 | return stralloc_catb(sa,s,strlen(s)); |
539 | } |
540 | |
541 | |
542 | /*** stralloc_eady.c ***/ |
543 | |
544 | GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) |
545 | GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) |
546 | |
547 | |
548 | /*** stralloc_opyb.c ***/ |
549 | |
550 | int stralloc_copyb(stralloc *sa,const char *s,unsigned n) |
551 | { |
552 | if (!stralloc_ready(sa,n + 1)) return 0; |
553 | memcpy(sa->s,s,n); |
554 | sa->len = n; |
555 | sa->s[n] = 'Z'; /* ``offensive programming'' */ |
556 | return 1; |
557 | } |
558 | |
559 | |
560 | /*** stralloc_opys.c ***/ |
561 | |
562 | int stralloc_copys(stralloc *sa,const char *s) |
563 | { |
564 | return stralloc_copyb(sa,s,strlen(s)); |
565 | } |
566 | |
567 | |
568 | /*** stralloc_pend.c ***/ |
569 | |
570 | GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) |
571 | |
572 | #endif /* stralloc */ |
573 | |
574 | /*** iopause.c ***/ |
575 | |
576 | void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp) |
577 | { |
578 | struct taia t; |
579 | int millisecs; |
580 | double d; |
581 | int i; |
582 | |
583 | if (taia_less(deadline,stamp)) |
584 | millisecs = 0; |
585 | else { |
586 | t = *stamp; |
587 | taia_sub(&t,deadline,&t); |
588 | d = taia_approx(&t); |
589 | if (d > 1000.0) d = 1000.0; |
590 | millisecs = d * 1000.0 + 20.0; |
591 | } |
592 | |
593 | for (i = 0;i < len;++i) |
594 | x[i].revents = 0; |
595 | |
596 | poll(x,len,millisecs); |
597 | /* XXX: some kernels apparently need x[0] even if len is 0 */ |
598 | /* XXX: how to handle EAGAIN? are kernels really this dumb? */ |
599 | /* XXX: how to handle EINVAL? when exactly can this happen? */ |
600 | } |
601 | |
602 | |
603 | /*** lock_ex.c ***/ |
604 | |
605 | int lock_ex(int fd) |
606 | { |
607 | return flock(fd,LOCK_EX); |
608 | } |
609 | |
610 | |
611 | /*** lock_exnb.c ***/ |
612 | |
613 | int lock_exnb(int fd) |
614 | { |
615 | return flock(fd,LOCK_EX | LOCK_NB); |
616 | } |
617 | |
618 | |
619 | /*** open_append.c ***/ |
620 | |
621 | int open_append(const char *fn) |
622 | { |
623 | return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); |
624 | } |
625 | |
626 | |
627 | /*** open_read.c ***/ |
628 | |
629 | int open_read(const char *fn) |
630 | { |
631 | return open(fn, O_RDONLY|O_NDELAY); |
632 | } |
633 | |
634 | |
635 | /*** open_trunc.c ***/ |
636 | |
637 | int open_trunc(const char *fn) |
638 | { |
639 | return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); |
640 | } |
641 | |
642 | |
643 | /*** open_write.c ***/ |
644 | |
645 | int open_write(const char *fn) |
646 | { |
647 | return open(fn, O_WRONLY|O_NDELAY); |
648 | } |
649 | |
650 | |
651 | /*** openreadclose.c ***/ |
652 | #if 0 |
653 | int openreadclose(const char *fn,stralloc *sa,unsigned bufsize) |
654 | { |
655 | int fd; |
656 | fd = open_read(fn); |
657 | if (fd == -1) { |
658 | if (errno == ENOENT) return 0; |
659 | return -1; |
660 | } |
661 | if (readclose(fd,sa,bufsize) == -1) return -1; |
662 | return 1; |
663 | } |
664 | #endif |
665 | |
666 | |
667 | /*** pathexec_env.c ***/ |
668 | #if 0 |
669 | static stralloc plus; |
670 | static stralloc tmp; |
671 | |
672 | int pathexec_env(const char *s,const char *t) |
673 | { |
674 | if (!s) return 1; |
675 | if (!stralloc_copys(&tmp,s)) return 0; |
676 | if (t) { |
677 | if (!stralloc_cats(&tmp,"=")) return 0; |
678 | if (!stralloc_cats(&tmp,t)) return 0; |
679 | } |
680 | if (!stralloc_0(&tmp)) return 0; |
681 | return stralloc_cat(&plus,&tmp); |
682 | } |
683 | |
684 | void pathexec(char **argv) |
685 | { |
686 | char **e; |
687 | unsigned elen; |
688 | unsigned i; |
689 | unsigned j; |
690 | unsigned split; |
691 | unsigned t; |
692 | |
693 | if (!stralloc_cats(&plus,"")) return; |
694 | |
695 | elen = 0; |
696 | for (i = 0;environ[i];++i) |
697 | ++elen; |
698 | for (i = 0;i < plus.len;++i) |
699 | if (!plus.s[i]) |
700 | ++elen; |
701 | |
702 | e = malloc((elen + 1) * sizeof(char *)); |
703 | if (!e) return; |
704 | |
705 | elen = 0; |
706 | for (i = 0;environ[i];++i) |
707 | e[elen++] = environ[i]; |
708 | |
709 | j = 0; |
710 | for (i = 0;i < plus.len;++i) |
711 | if (!plus.s[i]) { |
712 | split = str_chr(plus.s + j,'='); |
713 | for (t = 0;t < elen;++t) |
714 | if (memcmp(plus.s + j,e[t],split) == 0) |
715 | if (e[t][split] == '=') { |
716 | --elen; |
717 | e[t] = e[elen]; |
718 | break; |
719 | } |
720 | if (plus.s[j + split]) |
721 | e[elen++] = plus.s + j; |
722 | j = i + 1; |
723 | } |
724 | e[elen] = 0; |
725 | |
726 | pathexec_run(*argv,argv,e); |
727 | free(e); |
728 | } |
729 | #endif |
730 | |
731 | /*** pathexec_run.c ***/ |
732 | #if 0 |
733 | static stralloc tmp; |
734 | |
735 | void pathexec_run(const char *file,char *const *argv,char *const *envp) |
736 | { |
737 | const char *path; |
738 | unsigned split; |
739 | int savederrno; |
740 | |
741 | if (file[str_chr(file,'/')]) { |
742 | execve(file,argv,envp); |
743 | return; |
744 | } |
745 | |
746 | path = getenv("PATH"); |
747 | if (!path) path = "/bin:/usr/bin"; |
748 | |
749 | savederrno = 0; |
750 | for (;;) { |
751 | split = str_chr(path,':'); |
752 | if (!stralloc_copyb(&tmp,path,split)) return; |
753 | if (!split) |
754 | if (!stralloc_cats(&tmp,".")) return; |
755 | if (!stralloc_cats(&tmp,"/")) return; |
756 | if (!stralloc_cats(&tmp,file)) return; |
757 | if (!stralloc_0(&tmp)) return; |
758 | |
759 | execve(tmp.s,argv,envp); |
760 | if (errno != ENOENT) { |
761 | savederrno = errno; |
762 | if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return; |
763 | } |
764 | |
765 | if (!path[split]) { |
766 | if (savederrno) errno = savederrno; |
767 | return; |
768 | } |
769 | path += split; |
770 | path += 1; |
771 | } |
772 | } |
773 | #endif |
774 | |
775 | /*** pmatch.c ***/ |
776 | |
777 | unsigned pmatch(const char *p, const char *s, unsigned len) { |
778 | for (;;) { |
779 | char c = *p++; |
780 | if (!c) return !len; |
781 | switch (c) { |
782 | case '*': |
783 | if (!(c = *p)) return 1; |
784 | for (;;) { |
785 | if (!len) return 0; |
786 | if (*s == c) break; |
787 | ++s; --len; |
788 | } |
789 | continue; |
790 | case '+': |
791 | if ((c = *p++) != *s) return 0; |
792 | for (;;) { |
793 | if (!len) return 1; |
794 | if (*s != c) break; |
795 | ++s; --len; |
796 | } |
797 | continue; |
798 | /* |
799 | case '?': |
800 | if (*p == '?') { |
801 | if (*s != '?') return 0; |
802 | ++p; |
803 | } |
804 | ++s; --len; |
805 | continue; |
806 | */ |
807 | default: |
808 | if (!len) return 0; |
809 | if (*s != c) return 0; |
810 | ++s; --len; |
811 | continue; |
812 | } |
813 | } |
814 | return 0; |
815 | } |
816 | |
817 | |
818 | /*** prot.c ***/ |
819 | |
820 | int prot_gid(int gid) |
821 | { |
822 | gid_t x = gid; |
823 | if (setgroups(1,&x) == -1) return -1; |
824 | return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ |
825 | } |
826 | |
827 | int prot_uid(int uid) |
828 | { |
829 | return setuid(uid); |
830 | } |
831 | |
832 | |
833 | /*** readclose.c ***/ |
834 | #if 0 |
835 | int readclose_append(int fd,stralloc *sa,unsigned bufsize) |
836 | { |
837 | int r; |
838 | for (;;) { |
839 | if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } |
840 | r = read(fd,sa->s + sa->len,bufsize); |
841 | if (r == -1) if (errno == EINTR) continue; |
842 | if (r <= 0) { close(fd); return r; } |
843 | sa->len += r; |
844 | } |
845 | } |
846 | |
847 | int readclose(int fd,stralloc *sa,unsigned bufsize) |
848 | { |
849 | if (!stralloc_copys(sa,"")) { close(fd); return -1; } |
850 | return readclose_append(fd,sa,bufsize); |
851 | } |
852 | #endif |
853 | |
854 | /*** scan_ulong.c ***/ |
855 | |
856 | unsigned scan_ulong(const char *s,unsigned long *u) |
857 | { |
858 | unsigned pos = 0; |
859 | unsigned long result = 0; |
860 | unsigned long c; |
861 | while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { |
862 | result = result * 10 + c; |
863 | ++pos; |
864 | } |
865 | *u = result; |
866 | return pos; |
867 | } |
868 | |
869 | |
870 | /*** seek_set.c ***/ |
871 | |
872 | int seek_set(int fd,seek_pos pos) |
873 | { |
874 | if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0; |
875 | } |
876 | |
877 | |
878 | /*** sig.c ***/ |
879 | |
880 | int sig_alarm = SIGALRM; |
881 | int sig_child = SIGCHLD; |
882 | int sig_cont = SIGCONT; |
883 | int sig_hangup = SIGHUP; |
884 | int sig_int = SIGINT; |
885 | int sig_pipe = SIGPIPE; |
886 | int sig_term = SIGTERM; |
887 | |
888 | void (*sig_defaulthandler)(int) = SIG_DFL; |
889 | void (*sig_ignorehandler)(int) = SIG_IGN; |
890 | |
891 | |
892 | /*** sig_block.c ***/ |
893 | |
894 | void sig_block(int sig) |
895 | { |
896 | sigset_t ss; |
897 | sigemptyset(&ss); |
898 | sigaddset(&ss,sig); |
899 | sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); |
900 | } |
901 | |
902 | void sig_unblock(int sig) |
903 | { |
904 | sigset_t ss; |
905 | sigemptyset(&ss); |
906 | sigaddset(&ss,sig); |
907 | sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); |
908 | } |
909 | |
910 | void sig_blocknone(void) |
911 | { |
912 | sigset_t ss; |
913 | sigemptyset(&ss); |
914 | sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); |
915 | } |
916 | |
917 | |
918 | /*** sig_catch.c ***/ |
919 | |
920 | void sig_catch(int sig,void (*f)(int)) |
921 | { |
922 | struct sigaction sa; |
923 | sa.sa_handler = f; |
924 | sa.sa_flags = 0; |
925 | sigemptyset(&sa.sa_mask); |
926 | sigaction(sig,&sa,(struct sigaction *) 0); |
927 | } |
928 | |
929 | |
930 | /*** sig_pause.c ***/ |
931 | |
932 | void sig_pause(void) |
933 | { |
934 | sigset_t ss; |
935 | sigemptyset(&ss); |
936 | sigsuspend(&ss); |
937 | } |
938 | |
939 | |
940 | /*** str_chr.c ***/ |
941 | |
942 | unsigned str_chr(const char *s,int c) |
943 | { |
944 | char ch; |
945 | const char *t; |
946 | |
947 | ch = c; |
948 | t = s; |
949 | for (;;) { |
950 | if (!*t) break; if (*t == ch) break; ++t; |
951 | if (!*t) break; if (*t == ch) break; ++t; |
952 | if (!*t) break; if (*t == ch) break; ++t; |
953 | if (!*t) break; if (*t == ch) break; ++t; |
954 | } |
955 | return t - s; |
956 | } |
957 | |
958 | |
959 | /*** wait_nohang.c ***/ |
960 | |
961 | int wait_nohang(int *wstat) |
962 | { |
963 | return waitpid(-1,wstat,WNOHANG); |
964 | } |
965 | |
966 | |
967 | /*** wait_pid.c ***/ |
968 | |
969 | int wait_pid(int *wstat, int pid) |
970 | { |
971 | int r; |
972 | |
973 | do |
974 | r = waitpid(pid,wstat,0); |
975 | while ((r == -1) && (errno == EINTR)); |
976 | return r; |
977 | } |