Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/runit
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- Location:
- branches/2.2.9/mindi-busybox/runit
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/runit/Config.in
r1765 r2725 1 # DO NOT EDIT. This file is generated from Config.src 1 2 # 2 3 # For a description of the syntax of this configuration file, … … 6 7 menu "Runit Utilities" 7 8 9 10 8 11 config RUNSV 9 12 bool "runsv" 10 default n13 default y 11 14 help 12 15 runsv starts and monitors a service and optionally an appendant log … … 15 18 config RUNSVDIR 16 19 bool "runsvdir" 17 default n20 default y 18 21 help 19 22 runsvdir starts a runsv process for each subdirectory, or symlink to … … 21 24 subdirectories, and restarts a runsv process if it terminates. 22 25 26 config FEATURE_RUNSVDIR_LOG 27 bool "Enable scrolling argument log" 28 depends on RUNSVDIR 29 default n 30 help 31 Enable feature where second parameter of runsvdir holds last error 32 message (viewable via top/ps). Otherwise (feature is off 33 or no parameter), error messages go to stderr only. 34 23 35 config SV 24 36 bool "sv" 25 default n37 default y 26 38 help 27 39 sv reports the current status and controls the state of services 28 40 monitored by the runsv supervisor. 29 41 42 config SV_DEFAULT_SERVICE_DIR 43 string "Default directory for services" 44 default "/var/service" 45 depends on SV 46 help 47 Default directory for services. 48 Defaults to "/var/service" 49 30 50 config SVLOGD 31 51 bool "svlogd" 32 default n52 default y 33 53 help 34 54 svlogd continuously reads log data from its standard input, optionally … … 38 58 config CHPST 39 59 bool "chpst" 40 default n60 default y 41 61 help 42 62 chpst changes the process state according to the given options, and … … 45 65 config SETUIDGID 46 66 bool "setuidgid" 67 default y 47 68 help 48 69 Sets soft resource limits as specified by options … … 50 71 config ENVUIDGID 51 72 bool "envuidgid" 73 default y 52 74 help 53 75 Sets $UID to account's uid and $GID to account's gid … … 55 77 config ENVDIR 56 78 bool "envdir" 79 default y 57 80 help 58 81 Sets various environment variables as specified by files … … 61 84 config SOFTLIMIT 62 85 bool "softlimit" 86 default y 63 87 help 64 88 Sets soft resource limits as specified by options -
branches/2.2.9/mindi-busybox/runit/Kbuild
r1765 r2725 1 # DO NOT EDIT. This file is generated from Kbuild.src 1 2 # Makefile for busybox 2 3 # 3 4 # Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> 4 5 # 5 # Licensed under the GPL v2, see the file LICENSE in this tarball.6 # Licensed under GPLv2, see file LICENSE in this source tree. 6 7 7 8 lib-y:= 8 lib-$(CONFIG_RUNSV) += runsv.o runit_lib.o 9 lib-$(CONFIG_RUNSVDIR) += runsvdir.o runit_lib.o 10 lib-$(CONFIG_SV) += sv.o runit_lib.o 11 lib-$(CONFIG_SVLOGD) += svlogd.o runit_lib.o 9 10 11 12 lib-$(CONFIG_RUNSV) += runsv.o 13 lib-$(CONFIG_RUNSVDIR) += runsvdir.o 14 lib-$(CONFIG_SV) += sv.o 15 lib-$(CONFIG_SVLOGD) += svlogd.o 12 16 lib-$(CONFIG_CHPST) += chpst.o 13 17 -
branches/2.2.9/mindi-busybox/runit/chpst.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* Dependencies on runit_lib.c removed */ 30 30 31 31 #include "libbb.h" 32 32 33 #include <dirent.h> 34 35 // Must match constants in chpst_main! 36 #define OPT_verbose (option_mask32 & 0x2000) 37 #define OPT_pgrp (option_mask32 & 0x4000) 38 #define OPT_nostdin (option_mask32 & 0x8000) 39 #define OPT_nostdout (option_mask32 & 0x10000) 40 #define OPT_nostderr (option_mask32 & 0x20000) 41 42 static char *set_user; 43 static char *env_user; 44 static const char *env_dir; 45 static long limitd = -2; 46 static long limits = -2; 47 static long limitl = -2; 48 static long limita = -2; 49 static long limito = -2; 50 static long limitp = -2; 51 static long limitf = -2; 52 static long limitc = -2; 53 static long limitr = -2; 54 static long limitt = -2; 55 static int nicelvl; 56 static const char *root; 57 58 static void suidgid(char *user) 59 { 60 struct bb_uidgid_t ugid; 61 62 if (!get_uidgid(&ugid, user, 1)) { 63 bb_error_msg_and_die("unknown user/group: %s", user); 64 } 65 if (setgroups(1, &ugid.gid) == -1) 66 bb_perror_msg_and_die("setgroups"); 67 xsetgid(ugid.gid); 68 xsetuid(ugid.uid); 69 } 70 71 static void euidgid(char *user) 72 { 73 struct bb_uidgid_t ugid; 74 75 if (!get_uidgid(&ugid, user, 1)) { 76 bb_error_msg_and_die("unknown user/group: %s", user); 77 } 78 xsetenv("GID", utoa(ugid.gid)); 79 xsetenv("UID", utoa(ugid.uid)); 80 } 81 82 static void edir(const char *directory_name) 33 /* 34 Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit. 35 36 Only softlimit and chpst are taking options: 37 38 # common 39 -o N Limit number of open files per process 40 -p N Limit number of processes per uid 41 -m BYTES Same as -d BYTES -s BYTES -l BYTES [-a BYTES] 42 -d BYTES Limit data segment 43 -f BYTES Limit output file sizes 44 -c BYTES Limit core file size 45 # softlimit 46 -a BYTES Limit total size of all segments 47 -s BYTES Limit stack segment 48 -l BYTES Limit locked memory size 49 -r BYTES Limit resident set size 50 -t N Limit CPU time 51 # chpst 52 -u USER[:GRP] Set uid and gid 53 -U USER[:GRP] Set $UID and $GID in environment 54 -e DIR Set environment variables as specified by files in DIR 55 -/ DIR Chroot to DIR 56 -n NICE Add NICE to nice value 57 -v Verbose 58 -P Create new process group 59 -0 -1 -2 Close fd 0,1,2 60 61 Even though we accept all these options for both softlimit and chpst, 62 they are not to be advertised on their help texts. 63 We have enough problems with feature creep in other people's 64 software, don't want to add our own. 65 66 envdir, envuidgid, setuidgid take no options, but they reuse code which 67 handles -e, -U and -u. 68 */ 69 70 enum { 71 OPT_a = (1 << 0) * ENABLE_SOFTLIMIT, 72 OPT_c = (1 << 1) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 73 OPT_d = (1 << 2) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 74 OPT_f = (1 << 3) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 75 OPT_l = (1 << 4) * ENABLE_SOFTLIMIT, 76 OPT_m = (1 << 5) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 77 OPT_o = (1 << 6) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 78 OPT_p = (1 << 7) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 79 OPT_r = (1 << 8) * ENABLE_SOFTLIMIT, 80 OPT_s = (1 << 9) * ENABLE_SOFTLIMIT, 81 OPT_t = (1 << 10) * ENABLE_SOFTLIMIT, 82 OPT_u = (1 << 11) * (ENABLE_CHPST || ENABLE_SETUIDGID), 83 OPT_U = (1 << 12) * (ENABLE_CHPST || ENABLE_ENVUIDGID), 84 OPT_e = (1 << 13) * (ENABLE_CHPST || ENABLE_ENVDIR), 85 OPT_root = (1 << 14) * ENABLE_CHPST, 86 OPT_n = (1 << 15) * ENABLE_CHPST, 87 OPT_v = (1 << 16) * ENABLE_CHPST, 88 OPT_P = (1 << 17) * ENABLE_CHPST, 89 OPT_0 = (1 << 18) * ENABLE_CHPST, 90 OPT_1 = (1 << 19) * ENABLE_CHPST, 91 OPT_2 = (1 << 20) * ENABLE_CHPST, 92 }; 93 94 /* TODO: use recursive_action? */ 95 static NOINLINE void edir(const char *directory_name) 83 96 { 84 97 int wdir; … … 89 102 wdir = xopen(".", O_RDONLY | O_NDELAY); 90 103 xchdir(directory_name); 91 dir = opendir("."); 92 if (!dir) 93 bb_perror_msg_and_die("opendir %s", directory_name); 104 dir = xopendir("."); 94 105 for (;;) { 106 char buf[256]; 107 char *tail; 108 int size; 109 95 110 errno = 0; 96 111 d = readdir(dir); … … 101 116 break; 102 117 } 103 if (d->d_name[0] == '.') continue; 118 if (d->d_name[0] == '.') 119 continue; 104 120 fd = open(d->d_name, O_RDONLY | O_NDELAY); 105 121 if (fd < 0) { 106 if ((errno == EISDIR) && env_dir) {107 if ( OPT_verbose)122 if ((errno == EISDIR) && directory_name) { 123 if (option_mask32 & OPT_v) 108 124 bb_perror_msg("warning: %s/%s is a directory", 109 directory_name, d->d_name);110 continue;111 } else112 bb_perror_msg_and_die("open %s/%s",113 125 directory_name, d->d_name); 114 }115 if (fd >= 0) {116 char buf[256];117 char *tail;118 int size;119 120 size = safe_read(fd, buf, sizeof(buf)-1);121 if (size < 0)122 bb_perror_msg_and_die("read %s/%s",123 directory_name, d->d_name);124 if (size == 0) {125 unsetenv(d->d_name);126 126 continue; 127 127 } 128 buf[size] = '\n'; 129 tail = memchr(buf, '\n', sizeof(buf)); 130 /* skip trailing whitespace */; 131 while (1) { 132 if (tail[0]==' ') tail[0] = '\0'; 133 if (tail[0]=='\t') tail[0] = '\0'; 134 if (tail[0]=='\n') tail[0] = '\0'; 135 if (tail == buf) break; 136 tail--; 137 } 138 xsetenv(d->d_name, buf); 139 } 128 bb_perror_msg_and_die("open %s/%s", 129 directory_name, d->d_name); 130 } 131 size = full_read(fd, buf, sizeof(buf)-1); 132 close(fd); 133 if (size < 0) 134 bb_perror_msg_and_die("read %s/%s", 135 directory_name, d->d_name); 136 if (size == 0) { 137 unsetenv(d->d_name); 138 continue; 139 } 140 buf[size] = '\n'; 141 tail = strchr(buf, '\n'); 142 /* skip trailing whitespace */ 143 while (1) { 144 *tail = '\0'; 145 tail--; 146 if (tail < buf || !isspace(*tail)) 147 break; 148 } 149 xsetenv(d->d_name, buf); 140 150 } 141 151 closedir(dir); 142 if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir"); 152 if (fchdir(wdir) == -1) 153 bb_perror_msg_and_die("fchdir"); 143 154 close(wdir); 144 155 } … … 148 159 struct rlimit r; 149 160 150 if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit"); 161 /* Never fails under Linux (except if you pass it bad arguments) */ 162 getrlimit(what, &r); 151 163 if ((l < 0) || (l > r.rlim_max)) 152 164 r.rlim_cur = r.rlim_max; 153 165 else 154 166 r.rlim_cur = l; 155 if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit"); 167 if (setrlimit(what, &r) == -1) 168 bb_perror_msg_and_die("setrlimit"); 156 169 } 157 170 158 static void slimit(void) 171 int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 172 int chpst_main(int argc UNUSED_PARAM, char **argv) 159 173 { 160 if (limitd >= -1) { 174 struct bb_uidgid_t ugid; 175 char *set_user = set_user; /* for compiler */ 176 char *env_user = env_user; 177 char *env_dir = env_dir; 178 char *root; 179 char *nicestr; 180 unsigned limita; 181 unsigned limitc; 182 unsigned limitd; 183 unsigned limitf; 184 unsigned limitl; 185 unsigned limitm; 186 unsigned limito; 187 unsigned limitp; 188 unsigned limitr; 189 unsigned limits; 190 unsigned limitt; 191 unsigned opt; 192 193 if ((ENABLE_CHPST && applet_name[0] == 'c') 194 || (ENABLE_SOFTLIMIT && applet_name[1] == 'o') 195 ) { 196 // FIXME: can we live with int-sized limits? 197 // can we live with 40000 days? 198 // if yes -> getopt converts strings to numbers for us 199 opt_complementary = "-1:a+:c+:d+:f+:l+:m+:o+:p+:r+:s+:t+"; 200 opt = getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:u:U:e:" 201 IF_CHPST("/:n:vP012"), 202 &limita, &limitc, &limitd, &limitf, &limitl, 203 &limitm, &limito, &limitp, &limitr, &limits, &limitt, 204 &set_user, &env_user, &env_dir 205 IF_CHPST(, &root, &nicestr)); 206 argv += optind; 207 if (opt & OPT_m) { // -m means -asld 208 limita = limits = limitl = limitd = limitm; 209 opt |= (OPT_s | OPT_l | OPT_a | OPT_d); 210 } 211 } else { 212 option_mask32 = opt = 0; 213 argv++; 214 if (!*argv) 215 bb_show_usage(); 216 } 217 218 // envdir? 219 if (ENABLE_ENVDIR && applet_name[3] == 'd') { 220 env_dir = *argv++; 221 opt |= OPT_e; 222 } 223 224 // setuidgid? 225 if (ENABLE_SETUIDGID && applet_name[1] == 'e') { 226 set_user = *argv++; 227 opt |= OPT_u; 228 } 229 230 // envuidgid? 231 if (ENABLE_ENVUIDGID && applet_name[0] == 'e' && applet_name[3] == 'u') { 232 env_user = *argv++; 233 opt |= OPT_U; 234 } 235 236 // we must have PROG [ARGS] 237 if (!*argv) 238 bb_show_usage(); 239 240 // set limits 241 if (opt & OPT_d) { 161 242 #ifdef RLIMIT_DATA 162 243 limit(RLIMIT_DATA, limitd); 163 244 #else 164 if (OPT_verbose) bb_error_msg("system does not support %s", 165 "RLIMIT_DATA"); 166 #endif 167 } 168 if (limits >= -1) { 245 if (opt & OPT_v) 246 bb_error_msg("system does not support RLIMIT_%s", 247 "DATA"); 248 #endif 249 } 250 if (opt & OPT_s) { 169 251 #ifdef RLIMIT_STACK 170 252 limit(RLIMIT_STACK, limits); 171 253 #else 172 if (OPT_verbose) bb_error_msg("system does not support %s", 173 "RLIMIT_STACK"); 174 #endif 175 } 176 if (limitl >= -1) { 254 if (opt & OPT_v) 255 bb_error_msg("system does not support RLIMIT_%s", 256 "STACK"); 257 #endif 258 } 259 if (opt & OPT_l) { 177 260 #ifdef RLIMIT_MEMLOCK 178 261 limit(RLIMIT_MEMLOCK, limitl); 179 262 #else 180 if (OPT_verbose) bb_error_msg("system does not support %s", 181 "RLIMIT_MEMLOCK"); 182 #endif 183 } 184 if (limita >= -1) { 263 if (opt & OPT_v) 264 bb_error_msg("system does not support RLIMIT_%s", 265 "MEMLOCK"); 266 #endif 267 } 268 if (opt & OPT_a) { 185 269 #ifdef RLIMIT_VMEM 186 270 limit(RLIMIT_VMEM, limita); … … 189 273 limit(RLIMIT_AS, limita); 190 274 #else 191 if ( OPT_verbose)192 bb_error_msg("system does not support %s",193 " RLIMIT_VMEM");194 #endif 195 #endif 196 } 197 if ( limito >= -1) {275 if (opt & OPT_v) 276 bb_error_msg("system does not support RLIMIT_%s", 277 "VMEM"); 278 #endif 279 #endif 280 } 281 if (opt & OPT_o) { 198 282 #ifdef RLIMIT_NOFILE 199 283 limit(RLIMIT_NOFILE, limito); … … 202 286 limit(RLIMIT_OFILE, limito); 203 287 #else 204 if ( OPT_verbose)205 bb_error_msg("system does not support %s",206 " RLIMIT_NOFILE");207 #endif 208 #endif 209 } 210 if ( limitp >= -1) {288 if (opt & OPT_v) 289 bb_error_msg("system does not support RLIMIT_%s", 290 "NOFILE"); 291 #endif 292 #endif 293 } 294 if (opt & OPT_p) { 211 295 #ifdef RLIMIT_NPROC 212 296 limit(RLIMIT_NPROC, limitp); 213 297 #else 214 if (OPT_verbose) bb_error_msg("system does not support %s", 215 "RLIMIT_NPROC"); 216 #endif 217 } 218 if (limitf >= -1) { 298 if (opt & OPT_v) 299 bb_error_msg("system does not support RLIMIT_%s", 300 "NPROC"); 301 #endif 302 } 303 if (opt & OPT_f) { 219 304 #ifdef RLIMIT_FSIZE 220 305 limit(RLIMIT_FSIZE, limitf); 221 306 #else 222 if (OPT_verbose) bb_error_msg("system does not support %s", 223 "RLIMIT_FSIZE"); 224 #endif 225 } 226 if (limitc >= -1) { 307 if (opt & OPT_v) 308 bb_error_msg("system does not support RLIMIT_%s", 309 "FSIZE"); 310 #endif 311 } 312 if (opt & OPT_c) { 227 313 #ifdef RLIMIT_CORE 228 314 limit(RLIMIT_CORE, limitc); 229 315 #else 230 if (OPT_verbose) bb_error_msg("system does not support %s", 231 "RLIMIT_CORE"); 232 #endif 233 } 234 if (limitr >= -1) { 316 if (opt & OPT_v) 317 bb_error_msg("system does not support RLIMIT_%s", 318 "CORE"); 319 #endif 320 } 321 if (opt & OPT_r) { 235 322 #ifdef RLIMIT_RSS 236 323 limit(RLIMIT_RSS, limitr); 237 324 #else 238 if (OPT_verbose) bb_error_msg("system does not support %s", 239 "RLIMIT_RSS"); 240 #endif 241 } 242 if (limitt >= -1) { 325 if (opt & OPT_v) 326 bb_error_msg("system does not support RLIMIT_%s", 327 "RSS"); 328 #endif 329 } 330 if (opt & OPT_t) { 243 331 #ifdef RLIMIT_CPU 244 332 limit(RLIMIT_CPU, limitt); 245 333 #else 246 if (OPT_verbose) bb_error_msg("system does not support %s", 247 "RLIMIT_CPU"); 248 #endif 249 } 334 if (opt & OPT_v) 335 bb_error_msg("system does not support RLIMIT_%s", 336 "CPU"); 337 #endif 338 } 339 340 if (opt & OPT_P) 341 setsid(); 342 343 if (opt & OPT_e) 344 edir(env_dir); 345 346 // FIXME: chrooted jail must have /etc/passwd if we move this after chroot! 347 // OTOH chroot fails for non-roots! 348 // SOLUTION: cache uid/gid before chroot, apply uid/gid after 349 if (opt & OPT_U) { 350 xget_uidgid(&ugid, env_user); 351 xsetenv("GID", utoa(ugid.gid)); 352 xsetenv("UID", utoa(ugid.uid)); 353 } 354 355 if (opt & OPT_u) { 356 xget_uidgid(&ugid, set_user); 357 } 358 359 if (opt & OPT_root) { 360 xchdir(root); 361 xchroot("."); 362 } 363 364 if (opt & OPT_u) { 365 if (setgroups(1, &ugid.gid) == -1) 366 bb_perror_msg_and_die("setgroups"); 367 xsetgid(ugid.gid); 368 xsetuid(ugid.uid); 369 } 370 371 if (opt & OPT_n) { 372 errno = 0; 373 if (nice(xatoi(nicestr)) == -1) 374 bb_perror_msg_and_die("nice"); 375 } 376 377 if (opt & OPT_0) 378 close(STDIN_FILENO); 379 if (opt & OPT_1) 380 close(STDOUT_FILENO); 381 if (opt & OPT_2) 382 close(STDERR_FILENO); 383 384 BB_EXECVP_or_die(argv); 250 385 } 251 252 /* argv[0] */253 static void setuidgid(int, char **);254 static void envuidgid(int, char **);255 static void envdir(int, char **);256 static void softlimit(int, char **);257 258 int chpst_main(int argc, char **argv);259 int chpst_main(int argc, char **argv)260 {261 if (applet_name[3] == 'd') envdir(argc, argv);262 if (applet_name[1] == 'o') softlimit(argc, argv);263 if (applet_name[0] == 's') setuidgid(argc, argv);264 if (applet_name[0] == 'e') envuidgid(argc, argv);265 // otherwise we are chpst266 267 {268 char *m,*d,*o,*p,*f,*c,*r,*t,*n;269 getopt32(argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",270 &set_user,&env_user,&env_dir,271 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);272 // if (option_mask32 & 0x1) // -u273 // if (option_mask32 & 0x2) // -U274 // if (option_mask32 & 0x4) // -e275 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m276 if (option_mask32 & 0x10) limitd = xatoul(d); // -d277 if (option_mask32 & 0x20) limito = xatoul(o); // -o278 if (option_mask32 & 0x40) limitp = xatoul(p); // -p279 if (option_mask32 & 0x80) limitf = xatoul(f); // -f280 if (option_mask32 & 0x100) limitc = xatoul(c); // -c281 if (option_mask32 & 0x200) limitr = xatoul(r); // -r282 if (option_mask32 & 0x400) limitt = xatoul(t); // -t283 // if (option_mask32 & 0x800) // -/284 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n285 // The below consts should match #defines at top!286 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v287 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P288 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0289 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1290 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2291 }292 argv += optind;293 if (!argv || !*argv) bb_show_usage();294 295 if (OPT_pgrp) setsid();296 if (env_dir) edir(env_dir);297 if (root) {298 xchdir(root);299 if (chroot(".") == -1)300 bb_perror_msg_and_die("chroot");301 }302 slimit();303 if (nicelvl) {304 errno = 0;305 if (nice(nicelvl) == -1)306 bb_perror_msg_and_die("nice");307 }308 if (env_user) euidgid(env_user);309 if (set_user) suidgid(set_user);310 if (OPT_nostdin) close(0);311 if (OPT_nostdout) close(1);312 if (OPT_nostderr) close(2);313 BB_EXECVP(argv[0], argv);314 bb_perror_msg_and_die("exec %s", argv[0]);315 }316 317 static void setuidgid(int argc, char **argv)318 {319 const char *account;320 321 account = *++argv;322 if (!account) bb_show_usage();323 if (!*++argv) bb_show_usage();324 suidgid((char*)account);325 BB_EXECVP(argv[0], argv);326 bb_perror_msg_and_die("exec %s", argv[0]);327 }328 329 static void envuidgid(int argc, char **argv)330 {331 const char *account;332 333 account = *++argv;334 if (!account) bb_show_usage();335 if (!*++argv) bb_show_usage();336 euidgid((char*)account);337 BB_EXECVP(argv[0], argv);338 bb_perror_msg_and_die("exec %s", argv[0]);339 }340 341 static void envdir(int argc, char **argv)342 {343 const char *dir;344 345 dir = *++argv;346 if (!dir) bb_show_usage();347 if (!*++argv) bb_show_usage();348 edir(dir);349 BB_EXECVP(argv[0], argv);350 bb_perror_msg_and_die("exec %s", argv[0]);351 }352 353 static void softlimit(int argc, char **argv)354 {355 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;356 getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:",357 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);358 if (option_mask32 & 0x001) limita = xatoul(a); // -a359 if (option_mask32 & 0x002) limitc = xatoul(c); // -c360 if (option_mask32 & 0x004) limitd = xatoul(d); // -d361 if (option_mask32 & 0x008) limitf = xatoul(f); // -f362 if (option_mask32 & 0x010) limitl = xatoul(l); // -l363 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m364 if (option_mask32 & 0x040) limito = xatoul(o); // -o365 if (option_mask32 & 0x080) limitp = xatoul(p); // -p366 if (option_mask32 & 0x100) limitr = xatoul(r); // -r367 if (option_mask32 & 0x200) limits = xatoul(s); // -s368 if (option_mask32 & 0x400) limitt = xatoul(t); // -t369 argv += optind;370 if (!argv[0]) bb_show_usage();371 slimit();372 BB_EXECVP(argv[0], argv);373 bb_perror_msg_and_die("exec %s", argv[0]);374 } -
branches/2.2.9/mindi-busybox/runit/runit_lib.h
r1765 r2725 26 26 */ 27 27 28 extern unsigned byte_chr(char *s,unsigned n,int c); 29 30 extern int coe(int); 31 32 #define direntry struct dirent 33 34 //struct tai { 35 // uint64_t x; 36 //}; 37 // 38 //#define tai_unix(t,u) ((void) ((t)->x = 0x400000000000000aULL + (uint64_t) (u))) 39 // 40 //#define TAI_PACK 8 41 //extern void tai_unpack(const char *,struct tai *); 42 // 43 //extern void tai_uint(struct tai *,unsigned); 44 // 45 //struct taia { 46 // struct tai sec; 47 // unsigned long nano; /* 0...999999999 */ 48 // unsigned long atto; /* 0...999999999 */ 49 //}; 50 // 51 //extern void taia_now(struct taia *); 52 // 53 //extern void taia_add(struct taia *,const struct taia *,const struct taia *); 54 //extern void taia_addsec(struct taia *,const struct taia *,int); 55 //extern void taia_sub(struct taia *,const struct taia *,const struct taia *); 56 //extern void taia_half(struct taia *,const struct taia *); 57 //extern int taia_less(const struct taia *,const struct taia *); 58 // 59 //#define TAIA_PACK 16 60 //extern void taia_pack(char *,const struct taia *); 61 // 62 //extern void taia_uint(struct taia *,unsigned); 63 // 64 //typedef struct pollfd iopause_fd; 65 //#define IOPAUSE_READ POLLIN 66 //#define IOPAUSE_WRITE POLLOUT 67 // 68 //extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *); 69 70 extern int lock_ex(int); 71 extern int lock_un(int); 72 extern int lock_exnb(int); 73 74 extern int open_read(const char *); 75 extern int open_excl(const char *); 76 extern int open_append(const char *); 77 extern int open_trunc(const char *); 78 extern int open_write(const char *); 79 80 extern unsigned pmatch(const char *, const char *, unsigned); 81 82 #define str_diff(s,t) strcmp((s), (t)) 83 #define str_equal(s,t) (!strcmp((s), (t))) 28 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 84 29 85 30 /* … … 87 32 */ 88 33 typedef struct svstatus_t { 89 uint64_t time_be64 ATTRIBUTE_PACKED;90 uint32_t time_nsec_be32 ATTRIBUTE_PACKED;91 uint32_t pid_le32 ATTRIBUTE_PACKED;34 uint64_t time_be64 PACKED; 35 uint32_t time_nsec_be32 PACKED; 36 uint32_t pid_le32 PACKED; 92 37 uint8_t paused; 93 uint8_t want; 38 uint8_t want; /* 'u' or 'd' */ 94 39 uint8_t got_term; 95 40 uint8_t run_or_finish; … … 98 43 char ERR_svstatus_must_be_20_bytes[sizeof(svstatus_t) == 20 ? 1 : -1]; 99 44 }; 45 46 POP_SAVED_FUNCTION_VISIBILITY -
branches/2.2.9/mindi-busybox/runit/runsv.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* TODO: depends on runit_lib.c - review and reduce/eliminate */ 30 30 … … 61 61 /* Compare possibly overflowing unsigned counters */ 62 62 #define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0) 63 64 static int selfpipe[2];65 63 66 64 /* state */ … … 81 79 smallint state; 82 80 smallint ctrl; 83 smallint want;81 smallint sd_want; 84 82 smallint islog; 85 83 struct timespec start; … … 87 85 int fdcontrol; 88 86 int fdcontrolwrite; 87 int wstat; 89 88 }; 90 89 91 static struct svdir svd[2]; 92 static smallint sigterm; 93 static smallint haslog; 94 static smallint pidchanged = 1; 95 static int logpipe[2]; 96 static char *dir; 90 struct globals { 91 smallint haslog; 92 smallint sigterm; 93 smallint pidchanged; 94 struct fd_pair selfpipe; 95 struct fd_pair logpipe; 96 char *dir; 97 struct svdir svd[2]; 98 } FIX_ALIASING; 99 #define G (*(struct globals*)&bb_common_bufsiz1) 100 #define haslog (G.haslog ) 101 #define sigterm (G.sigterm ) 102 #define pidchanged (G.pidchanged ) 103 #define selfpipe (G.selfpipe ) 104 #define logpipe (G.logpipe ) 105 #define dir (G.dir ) 106 #define svd (G.svd ) 107 #define INIT_G() do { \ 108 pidchanged = 1; \ 109 } while (0) 97 110 98 111 static void fatal2_cannot(const char *m1, const char *m2) … … 116 129 } 117 130 118 static void s_child(int sig_no )119 { 120 write(selfpipe [1], "", 1);121 } 122 123 static void s_term(int sig_no )131 static void s_child(int sig_no UNUSED_PARAM) 132 { 133 write(selfpipe.wr, "", 1); 134 } 135 136 static void s_term(int sig_no UNUSED_PARAM) 124 137 { 125 138 sigterm = 1; 126 write(selfpipe[1], "", 1); /* XXX */ 127 } 128 129 static char *add_str(char *p, const char *to_add) 139 write(selfpipe.wr, "", 1); /* XXX */ 140 } 141 142 /* libbb candidate */ 143 static char *bb_stpcpy(char *p, const char *to_add) 130 144 { 131 145 while ((*p = *to_add) != '\0') { … … 138 152 static int open_trunc_or_warn(const char *name) 139 153 { 140 int fd = open_trunc(name); 154 /* Why O_NDELAY? */ 155 int fd = open(name, O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0644); 141 156 if (fd < 0) 142 157 bb_perror_msg("%s: warning: cannot open %s", 143 158 dir, name); 144 159 return fd; 145 }146 147 static int rename_or_warn(const char *old, const char *new)148 {149 if (rename(old, new) == -1) {150 bb_perror_msg("%s: warning: cannot rename %s to %s",151 dir, old, new);152 return -1;153 }154 return 0;155 160 } 156 161 … … 188 193 switch (s->state) { 189 194 case S_DOWN: 190 p = add_str(p, "down");195 p = bb_stpcpy(p, "down"); 191 196 break; 192 197 case S_RUN: 193 p = add_str(p, "run");198 p = bb_stpcpy(p, "run"); 194 199 break; 195 200 case S_FINISH: 196 p = add_str(p, "finish");201 p = bb_stpcpy(p, "finish"); 197 202 break; 198 203 } 199 if (s->ctrl & C_PAUSE) p = add_str(p, ", paused"); 200 if (s->ctrl & C_TERM) p = add_str(p, ", got TERM"); 204 if (s->ctrl & C_PAUSE) 205 p = bb_stpcpy(p, ", paused"); 206 if (s->ctrl & C_TERM) 207 p = bb_stpcpy(p, ", got TERM"); 201 208 if (s->state != S_DOWN) 202 switch (s-> want) {209 switch (s->sd_want) { 203 210 case W_DOWN: 204 p = add_str(p, ", want down");211 p = bb_stpcpy(p, ", want down"); 205 212 break; 206 213 case W_EXIT: 207 p = add_str(p, ", want exit");214 p = bb_stpcpy(p, ", want exit"); 208 215 break; 209 216 } … … 223 230 if (s->ctrl & C_PAUSE) 224 231 status.paused = 1; 225 if (s-> want == W_UP)232 if (s->sd_want == W_UP) 226 233 status.want = 'u'; 227 234 else … … 246 253 static unsigned custom(struct svdir *s, char c) 247 254 { 248 int pid;255 pid_t pid; 249 256 int w; 250 257 char a[10]; 251 258 struct stat st; 252 char *prog[2]; 253 254 if (s->islog)return 0;259 260 if (s->islog) 261 return 0; 255 262 strcpy(a, "control/?"); 256 a[8] = c; 263 a[8] = c; /* replace '?' */ 257 264 if (stat(a, &st) == 0) { 258 265 if (st.st_mode & S_IXUSR) { 259 pid = fork();266 pid = vfork(); 260 267 if (pid == -1) { 261 warn_cannot(" fork for control/?");268 warn_cannot("vfork for control/?"); 262 269 return 0; 263 270 } 264 if (!pid) { 265 if (haslog && dup2(logpipe[1], 1) == -1) 271 if (pid == 0) { 272 /* child */ 273 if (haslog && dup2(logpipe.wr, 1) == -1) 266 274 warn_cannot("setup stdout for control/?"); 267 prog[0] = a; 268 prog[1] = NULL; 269 execve(a, prog, environ); 275 execl(a, a, (char *) NULL); 270 276 fatal_cannot("run control/?"); 271 277 } 272 while (wait_pid(&w, pid) == -1) {273 if (errno == EINTR) continue;278 /* parent */ 279 if (safe_waitpid(pid, &w, 0) == -1) { 274 280 warn_cannot("wait for child control/?"); 275 281 return 0; 276 282 } 277 return !wait_exitcode(w);283 return WEXITSTATUS(w) == 0; 278 284 } 279 285 } else { … … 291 297 update_status(s); 292 298 } 293 if (s-> want == W_DOWN) {299 if (s->sd_want == W_DOWN) { 294 300 kill(s->pid, SIGCONT); 295 301 custom(s, 'd'); 296 302 return; 297 303 } 298 if (s-> want == W_EXIT) {304 if (s->sd_want == W_EXIT) { 299 305 kill(s->pid, SIGCONT); 300 306 custom(s, 'x'); … … 305 311 { 306 312 int p; 307 char *run[2]; 308 309 if (s->state == S_FINISH) 310 run[0] = (char*)"./finish"; 311 else { 312 run[0] = (char*)"./run"; 313 const char *arg[4]; 314 char exitcode[sizeof(int)*3 + 2]; 315 316 if (s->state == S_FINISH) { 317 /* Two arguments are given to ./finish. The first one is ./run exit code, 318 * or -1 if ./run didnt exit normally. The second one is 319 * the least significant byte of the exit status as determined by waitpid; 320 * for instance it is 0 if ./run exited normally, and the signal number 321 * if ./run was terminated by a signal. If runsv cannot start ./run 322 * for some reason, the exit code is 111 and the status is 0. 323 */ 324 arg[0] = "./finish"; 325 arg[1] = "-1"; 326 if (WIFEXITED(s->wstat)) { 327 *utoa_to_buf(WEXITSTATUS(s->wstat), exitcode, sizeof(exitcode)) = '\0'; 328 arg[1] = exitcode; 329 } 330 //arg[2] = "0"; 331 //if (WIFSIGNALED(s->wstat)) { 332 arg[2] = utoa(WTERMSIG(s->wstat)); 333 //} 334 arg[3] = NULL; 335 } else { 336 arg[0] = "./run"; 337 arg[1] = NULL; 313 338 custom(s, 'u'); 314 339 } 315 run[1] = NULL;316 340 317 341 if (s->pid != 0) 318 342 stopservice(s); /* should never happen */ 319 while ((p = fork()) == -1) {320 warn_cannot(" fork, sleeping");343 while ((p = vfork()) == -1) { 344 warn_cannot("vfork, sleeping"); 321 345 sleep(5); 322 346 } … … 324 348 /* child */ 325 349 if (haslog) { 350 /* NB: bug alert! right order is close, then dup2 */ 326 351 if (s->islog) { 327 xdup2(logpipe[0], 0);328 close(logpipe[1]);329 352 xchdir("./log"); 353 close(logpipe.wr); 354 xdup2(logpipe.rd, 0); 330 355 } else { 331 xdup2(logpipe[1], 1); 332 close(logpipe[0]); 333 } 334 } 335 signal(SIGCHLD, SIG_DFL); 336 signal(SIGTERM, SIG_DFL); 356 close(logpipe.rd); 357 xdup2(logpipe.wr, 1); 358 } 359 } 360 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 361 /*bb_signals(0 362 + (1 << SIGCHLD) 363 + (1 << SIGTERM) 364 , SIG_DFL);*/ 337 365 sig_unblock(SIGCHLD); 338 366 sig_unblock(SIGTERM); 339 execvp(*run, run); 340 fatal2_cannot(s->islog ? "start log/" : "start ", *run); 341 } 367 execv(arg[0], (char**) arg); 368 fatal2_cannot(s->islog ? "start log/" : "start ", arg[0]); 369 } 370 /* parent */ 342 371 if (s->state != S_FINISH) { 343 372 gettimeofday_ns(&s->start); … … 356 385 switch (c) { 357 386 case 'd': /* down */ 358 s-> want = W_DOWN;387 s->sd_want = W_DOWN; 359 388 update_status(s); 360 389 if (s->pid && s->state != S_FINISH) … … 362 391 break; 363 392 case 'u': /* up */ 364 s-> want = W_UP;393 s->sd_want = W_UP; 365 394 update_status(s); 366 395 if (s->pid == 0) … … 370 399 if (s->islog) 371 400 break; 372 s-> want = W_EXIT;401 s->sd_want = W_EXIT; 373 402 update_status(s); 374 403 /* FALLTHROUGH */ … … 391 420 if (s->pid && !custom(s, c)) 392 421 kill(s->pid, SIGCONT); 393 if (s->ctrl & C_PAUSE) 394 s->ctrl &= ~C_PAUSE; 422 s->ctrl &= ~C_PAUSE; 395 423 update_status(s); 396 424 break; 397 425 case 'o': /* once */ 398 s-> want = W_DOWN;426 s->sd_want = W_DOWN; 399 427 update_status(s); 400 428 if (!s->pid) … … 427 455 } 428 456 429 int runsv_main(int argc, char **argv) ;430 int runsv_main(int argc , char **argv)457 int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 458 int runsv_main(int argc UNUSED_PARAM, char **argv) 431 459 { 432 460 struct stat s; … … 435 463 char buf[256]; 436 464 437 if (!argv[1] || argv[2])438 bb_show_usage(); 439 dir = argv[1];440 441 xpipe (selfpipe);442 c oe(selfpipe[0]);443 c oe(selfpipe[1]);444 ndelay_on(selfpipe [0]);445 ndelay_on(selfpipe [1]);465 INIT_G(); 466 467 dir = single_argv(argv); 468 469 xpiped_pair(selfpipe); 470 close_on_exec_on(selfpipe.rd); 471 close_on_exec_on(selfpipe.wr); 472 ndelay_on(selfpipe.rd); 473 ndelay_on(selfpipe.wr); 446 474 447 475 sig_block(SIGCHLD); 448 sig_catch(SIGCHLD, s_child);476 bb_signals_recursive_norestart(1 << SIGCHLD, s_child); 449 477 sig_block(SIGTERM); 450 sig_catch(SIGTERM, s_term);478 bb_signals_recursive_norestart(1 << SIGTERM, s_term); 451 479 452 480 xchdir(dir); … … 454 482 if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */ 455 483 if (C_NOOP) svd[0].ctrl = C_NOOP; 456 if (W_UP) svd[0]. want = W_UP;484 if (W_UP) svd[0].sd_want = W_UP; 457 485 /* bss: svd[0].islog = 0; */ 458 486 /* bss: svd[1].pid = 0; */ 459 487 gettimeofday_ns(&svd[0].start); 460 if (stat("down", &s) != -1) svd[0].want = W_DOWN; 488 if (stat("down", &s) != -1) 489 svd[0].sd_want = W_DOWN; 461 490 462 491 if (stat("log", &s) == -1) { … … 471 500 svd[1].state = S_DOWN; 472 501 svd[1].ctrl = C_NOOP; 473 svd[1]. want = W_UP;502 svd[1].sd_want = W_UP; 474 503 svd[1].islog = 1; 475 504 gettimeofday_ns(&svd[1].start); 476 505 if (stat("log/down", &s) != -1) 477 svd[1]. want = W_DOWN;478 xpipe (logpipe);479 c oe(logpipe[0]);480 c oe(logpipe[1]);506 svd[1].sd_want = W_DOWN; 507 xpiped_pair(logpipe); 508 close_on_exec_on(logpipe.rd); 509 close_on_exec_on(logpipe.wr); 481 510 } 482 511 } … … 496 525 svd[0].fdlock = xopen3("log/supervise/lock"+4, 497 526 O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 498 if ( lock_exnb(svd[0].fdlock) == -1)527 if (flock(svd[0].fdlock, LOCK_EX | LOCK_NB) == -1) 499 528 fatal_cannot("lock supervise/lock"); 500 c oe(svd[0].fdlock);529 close_on_exec_on(svd[0].fdlock); 501 530 if (haslog) { 502 531 if (mkdir("log/supervise", 0700) == -1) { … … 520 549 svd[1].fdlock = xopen3("log/supervise/lock", 521 550 O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 522 if ( lock_ex(svd[1].fdlock) == -1)551 if (flock(svd[1].fdlock, LOCK_EX) == -1) 523 552 fatal_cannot("lock log/supervise/lock"); 524 c oe(svd[1].fdlock);553 close_on_exec_on(svd[1].fdlock); 525 554 } 526 555 527 556 mkfifo("log/supervise/control"+4, 0600); 528 557 svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY); 529 c oe(svd[0].fdcontrol);558 close_on_exec_on(svd[0].fdcontrol); 530 559 svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY); 531 c oe(svd[0].fdcontrolwrite);560 close_on_exec_on(svd[0].fdcontrolwrite); 532 561 update_status(&svd[0]); 533 562 if (haslog) { 534 563 mkfifo("log/supervise/control", 0600); 535 564 svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY); 536 c oe(svd[1].fdcontrol);565 close_on_exec_on(svd[1].fdcontrol); 537 566 svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY); 538 c oe(svd[1].fdcontrolwrite);567 close_on_exec_on(svd[1].fdcontrolwrite); 539 568 update_status(&svd[1]); 540 569 } 541 570 mkfifo("log/supervise/ok"+4, 0600); 542 571 fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); 543 c oe(fd);572 close_on_exec_on(fd); 544 573 if (haslog) { 545 574 mkfifo("log/supervise/ok", 0600); 546 575 fd = xopen("log/supervise/ok", O_RDONLY|O_NDELAY); 547 c oe(fd);576 close_on_exec_on(fd); 548 577 } 549 578 for (;;) { … … 553 582 554 583 if (haslog) 555 if (!svd[1].pid && svd[1]. want == W_UP)584 if (!svd[1].pid && svd[1].sd_want == W_UP) 556 585 startservice(&svd[1]); 557 586 if (!svd[0].pid) 558 if (svd[0]. want == W_UP || svd[0].state == S_FINISH)587 if (svd[0].sd_want == W_UP || svd[0].state == S_FINISH) 559 588 startservice(&svd[0]); 560 589 561 x[0].fd = selfpipe [0];590 x[0].fd = selfpipe.rd; 562 591 x[0].events = POLLIN; 563 592 x[1].fd = svd[0].fdcontrol; … … 572 601 sig_block(SIGCHLD); 573 602 574 while (read(selfpipe [0], &ch, 1) == 1)603 while (read(selfpipe.rd, &ch, 1) == 1) 575 604 continue; 576 605 577 606 for (;;) { 578 int child;607 pid_t child; 579 608 int wstat; 580 609 581 child = wait_ nohang(&wstat);610 child = wait_any_nohang(&wstat); 582 611 if (!child) 583 612 break; … … 585 614 break; 586 615 if (child == svd[0].pid) { 616 svd[0].wstat = wstat; 587 617 svd[0].pid = 0; 588 618 pidchanged = 1; 589 svd[0].ctrl &= ~C_TERM;619 svd[0].ctrl &= ~C_TERM; 590 620 if (svd[0].state != S_FINISH) { 591 fd = open _read("finish");621 fd = open("finish", O_RDONLY|O_NDELAY); 592 622 if (fd != -1) { 593 623 close(fd); … … 606 636 if (haslog) { 607 637 if (child == svd[1].pid) { 638 svd[0].wstat = wstat; 608 639 svd[1].pid = 0; 609 640 pidchanged = 1; … … 617 648 } 618 649 } 619 } 650 } /* for (;;) */ 620 651 if (read(svd[0].fdcontrol, &ch, 1) == 1) 621 652 ctrl(&svd[0], ch); … … 629 660 } 630 661 631 if (svd[0]. want == W_EXIT && svd[0].state == S_DOWN) {662 if (svd[0].sd_want == W_EXIT && svd[0].state == S_DOWN) { 632 663 if (svd[1].pid == 0) 633 _exit( 0);634 if (svd[1]. want != W_EXIT) {635 svd[1]. want = W_EXIT;664 _exit(EXIT_SUCCESS); 665 if (svd[1].sd_want != W_EXIT) { 666 svd[1].sd_want = W_EXIT; 636 667 /* stopservice(&svd[1]); */ 637 668 update_status(&svd[1]); 638 close(logpipe [1]);639 close(logpipe [0]);640 } 641 } 642 } 669 close(logpipe.wr); 670 close(logpipe.rd); 671 } 672 } 673 } /* for (;;) */ 643 674 /* not reached */ 644 675 return 0; -
branches/2.2.9/mindi-busybox/runit/runsvdir.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* TODO: depends on runit_lib.c - review and reduce/eliminate */ 30 30 … … 36 36 #define MAXSERVICES 1000 37 37 38 /* Should be not needed - all dirs are on same FS, right? */ 39 #define CHECK_DEVNO_TOO 0 40 38 41 struct service { 42 #if CHECK_DEVNO_TOO 39 43 dev_t dev; 44 #endif 40 45 ino_t ino; 41 46 pid_t pid; … … 43 48 }; 44 49 45 struct service *sv; 46 static char *svdir; 47 static int svnum; 48 static char *rplog; 49 static int rploglen; 50 static int logpipe[2]; 51 static struct pollfd pfd[1]; 52 static unsigned stamplog; 53 static smallint check = 1; 54 static smallint exitsoon; 55 static smallint set_pgrp; 50 struct globals { 51 struct service *sv; 52 char *svdir; 53 int svnum; 54 #if ENABLE_FEATURE_RUNSVDIR_LOG 55 char *rplog; 56 int rploglen; 57 struct fd_pair logpipe; 58 struct pollfd pfd[1]; 59 unsigned stamplog; 60 #endif 61 } FIX_ALIASING; 62 #define G (*(struct globals*)&bb_common_bufsiz1) 63 #define sv (G.sv ) 64 #define svdir (G.svdir ) 65 #define svnum (G.svnum ) 66 #define rplog (G.rplog ) 67 #define rploglen (G.rploglen ) 68 #define logpipe (G.logpipe ) 69 #define pfd (G.pfd ) 70 #define stamplog (G.stamplog ) 71 #define INIT_G() do { \ 72 } while (0) 56 73 57 74 static void fatal2_cannot(const char *m1, const char *m2) 58 75 { 59 bb_perror_msg_and_die("%s: fatal: can not %s%s", svdir, m1, m2);76 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2); 60 77 /* was exiting 100 */ 61 78 } … … 66 83 static void warn2_cannot(const char *m1, const char *m2) 67 84 { 68 warn3x("cannot ", m1, m2); 69 } 85 warn3x("can't ", m1, m2); 86 } 87 #if ENABLE_FEATURE_RUNSVDIR_LOG 70 88 static void warnx(const char *m1) 71 89 { 72 90 warn3x(m1, "", ""); 73 91 } 74 75 static void s_term(int sig_no) 76 { 77 exitsoon = 1; 78 } 79 static void s_hangup(int sig_no) 80 { 81 exitsoon = 2; 82 } 83 84 static void runsv(int no, const char *name) 92 #endif 93 94 /* inlining + vfork -> bigger code */ 95 static NOINLINE pid_t runsv(const char *name) 85 96 { 86 97 pid_t pid; 87 char *prog[3]; 88 89 prog[0] = (char*)"runsv"; 90 prog[1] = (char*)name; 91 prog[2] = NULL; 98 99 /* If we got signaled, stop spawning children at once! */ 100 if (bb_got_signal) 101 return 0; 92 102 93 103 pid = vfork(); 94 95 104 if (pid == -1) { 96 105 warn2_cannot("vfork", ""); 97 return ;106 return 0; 98 107 } 99 108 if (pid == 0) { 100 109 /* child */ 101 if ( set_pgrp)110 if (option_mask32 & 1) /* -P option? */ 102 111 setsid(); 103 signal(SIGHUP, SIG_DFL); 104 signal(SIGTERM, SIG_DFL); 105 execvp(prog[0], prog); 112 /* man execv: 113 * "Signals set to be caught by the calling process image 114 * shall be set to the default action in the new process image." 115 * Therefore, we do not need this: */ 116 #if 0 117 bb_signals(0 118 | (1 << SIGHUP) 119 | (1 << SIGTERM) 120 , SIG_DFL); 121 #endif 122 execlp("runsv", "runsv", name, (char *) NULL); 106 123 fatal2_cannot("start runsv ", name); 107 124 } 108 sv[no].pid = pid; 109 } 110 111 static void runsvdir(void) 125 return pid; 126 } 127 128 /* gcc 4.3.0 does better with NOINLINE */ 129 static NOINLINE int do_rescan(void) 112 130 { 113 131 DIR *dir; 114 direntry*d;132 struct dirent *d; 115 133 int i; 116 134 struct stat s; 135 int need_rescan = 0; 117 136 118 137 dir = opendir("."); 119 138 if (!dir) { 120 139 warn2_cannot("open directory ", svdir); 121 return ;140 return 1; /* need to rescan again soon */ 122 141 } 123 142 for (i = 0; i < svnum; i++) 124 143 sv[i].isgone = 1; 125 errno = 0; 126 while ((d = readdir(dir))) { 144 145 while (1) { 146 errno = 0; 147 d = readdir(dir); 148 if (!d) 149 break; 127 150 if (d->d_name[0] == '.') 128 151 continue; 129 152 if (stat(d->d_name, &s) == -1) { 130 153 warn2_cannot("stat ", d->d_name); 131 errno = 0;132 154 continue; 133 155 } 134 156 if (!S_ISDIR(s.st_mode)) 135 157 continue; 158 /* Do we have this service listed already? */ 136 159 for (i = 0; i < svnum; i++) { 137 if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { 138 sv[i].isgone = 0; 139 if (!sv[i].pid) 140 runsv(i, d->d_name); 141 break; 142 } 143 } 144 if (i == svnum) { 145 /* new service */ 160 if ((sv[i].ino == s.st_ino) 161 #if CHECK_DEVNO_TOO 162 && (sv[i].dev == s.st_dev) 163 #endif 164 ) { 165 if (sv[i].pid == 0) /* restart if it has died */ 166 goto run_ith_sv; 167 sv[i].isgone = 0; /* "we still see you" */ 168 goto next_dentry; 169 } 170 } 171 { /* Not found, make new service */ 146 172 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); 147 173 if (!svnew) { 148 warn 3x("cannot start runsv ", d->d_name,149 " too many services");174 warn2_cannot("start runsv ", d->d_name); 175 need_rescan = 1; 150 176 continue; 151 177 } 152 178 sv = svnew; 153 179 svnum++; 154 memset(&sv[i], 0, sizeof(sv[i])); 180 #if CHECK_DEVNO_TOO 181 sv[i].dev = s.st_dev; 182 #endif 155 183 sv[i].ino = s.st_ino; 156 sv[i].dev = s.st_dev; 157 /*sv[i].pid = 0;*/ 158 /*sv[i].isgone = 0;*/ 159 runsv(i, d->d_name); 160 check = 1; 161 } 162 } 163 if (errno) { 184 run_ith_sv: 185 sv[i].pid = runsv(d->d_name); 186 sv[i].isgone = 0; 187 } 188 next_dentry: ; 189 } 190 i = errno; 191 closedir(dir); 192 if (i) { /* readdir failed */ 164 193 warn2_cannot("read directory ", svdir); 165 closedir(dir); 166 check = 1; 167 return; 168 } 169 closedir(dir); 170 171 /* SIGTERM removed runsv's */ 194 return 1; /* need to rescan again soon */ 195 } 196 197 /* Send SIGTERM to runsv whose directories 198 * were no longer found (-> must have been removed) */ 172 199 for (i = 0; i < svnum; i++) { 173 200 if (!sv[i].isgone) … … 175 202 if (sv[i].pid) 176 203 kill(sv[i].pid, SIGTERM); 177 sv[i] = sv[--svnum]; 178 check = 1; 179 } 180 } 181 182 static int setup_log(void) 183 { 184 rploglen = strlen(rplog); 185 if (rploglen < 7) { 186 warnx("log must have at least seven characters"); 187 return 0; 188 } 189 if (pipe(logpipe)) { 190 warnx("cannot create pipe for log"); 191 return -1; 192 } 193 coe(logpipe[1]); 194 coe(logpipe[0]); 195 ndelay_on(logpipe[0]); 196 ndelay_on(logpipe[1]); 197 if (dup2(logpipe[1], 2) == -1) { 198 warnx("cannot set filedescriptor for log"); 199 return -1; 200 } 201 pfd[0].fd = logpipe[0]; 202 pfd[0].events = POLLIN; 203 stamplog = monotonic_sec(); 204 return 1; 205 } 206 207 int runsvdir_main(int argc, char **argv); 208 int runsvdir_main(int argc, char **argv) 204 svnum--; 205 sv[i] = sv[svnum]; 206 i--; /* so that we don't skip new sv[i] (bug was here!) */ 207 } 208 return need_rescan; 209 } 210 211 int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 212 int runsvdir_main(int argc UNUSED_PARAM, char **argv) 209 213 { 210 214 struct stat s; … … 214 218 int wstat; 215 219 int curdir; 216 int pid;220 pid_t pid; 217 221 unsigned deadline; 218 222 unsigned now; 219 223 unsigned stampcheck; 220 char ch;221 224 int i; 222 223 argv++; 224 if (!*argv) 225 bb_show_usage(); 226 if (argv[0][0] == '-') { 227 switch (argv[0][1]) { 228 case 'P': set_pgrp = 1; 229 case '-': ++argv; 230 } 231 if (!*argv) 232 bb_show_usage(); 233 } 234 235 sig_catch(SIGTERM, s_term); 236 sig_catch(SIGHUP, s_hangup); 225 int need_rescan = 1; 226 char *opt_s_argv[3]; 227 228 INIT_G(); 229 230 opt_complementary = "-1"; 231 opt_s_argv[0] = NULL; 232 opt_s_argv[2] = NULL; 233 getopt32(argv, "Ps:", &opt_s_argv[0]); 234 argv += optind; 235 236 bb_signals(0 237 | (1 << SIGTERM) 238 | (1 << SIGHUP) 239 /* For busybox's init, SIGTERM == reboot, 240 * SIGUSR1 == halt 241 * SIGUSR2 == poweroff 242 * so we need to intercept SIGUSRn too. 243 * Note that we do not implement actual reboot 244 * (killall(TERM) + umount, etc), we just pause 245 * respawing and avoid exiting (-> making kernel oops). 246 * The user is responsible for the rest. */ 247 | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0) 248 , record_signo); 237 249 svdir = *argv++; 238 if (argv && *argv) { 250 251 #if ENABLE_FEATURE_RUNSVDIR_LOG 252 /* setup log */ 253 if (*argv) { 239 254 rplog = *argv; 240 if (setup_log() != 1) { 241 rplog = 0; 242 warnx("log service disabled"); 243 } 244 } 245 curdir = open_read("."); 255 rploglen = strlen(rplog); 256 if (rploglen < 7) { 257 warnx("log must have at least seven characters"); 258 } else if (piped_pair(logpipe)) { 259 warnx("can't create pipe for log"); 260 } else { 261 close_on_exec_on(logpipe.rd); 262 close_on_exec_on(logpipe.wr); 263 ndelay_on(logpipe.rd); 264 ndelay_on(logpipe.wr); 265 if (dup2(logpipe.wr, 2) == -1) { 266 warnx("can't set filedescriptor for log"); 267 } else { 268 pfd[0].fd = logpipe.rd; 269 pfd[0].events = POLLIN; 270 stamplog = monotonic_sec(); 271 goto run; 272 } 273 } 274 rplog = NULL; 275 warnx("log service disabled"); 276 } 277 run: 278 #endif 279 curdir = open(".", O_RDONLY|O_NDELAY); 246 280 if (curdir == -1) 247 281 fatal2_cannot("open current directory", ""); 248 c oe(curdir);282 close_on_exec_on(curdir); 249 283 250 284 stampcheck = monotonic_sec(); … … 253 287 /* collect children */ 254 288 for (;;) { 255 pid = wait_ nohang(&wstat);289 pid = wait_any_nohang(&wstat); 256 290 if (pid <= 0) 257 291 break; 258 292 for (i = 0; i < svnum; i++) { 259 293 if (pid == sv[i].pid) { 260 /* runsv has gone*/294 /* runsv has died */ 261 295 sv[i].pid = 0; 262 check = 1; 263 break; 296 need_rescan = 1; 264 297 } 265 298 } … … 272 305 273 306 if (stat(svdir, &s) != -1) { 274 if ( check|| s.st_mtime != last_mtime307 if (need_rescan || s.st_mtime != last_mtime 275 308 || s.st_ino != last_ino || s.st_dev != last_dev 276 309 ) { … … 280 313 last_dev = s.st_dev; 281 314 last_ino = s.st_ino; 282 check = 0; 283 //if (now <= mtime) 284 // sleep(1); 285 runsvdir(); 315 /* if the svdir changed this very second, wait until the 316 * next second, because we won't be able to detect more 317 * changes within this second */ 318 while (time(NULL) == last_mtime) 319 usleep(100000); 320 need_rescan = do_rescan(); 286 321 while (fchdir(curdir) == -1) { 287 322 warn2_cannot("change directory, pausing", ""); 288 323 sleep(5); 289 324 } 290 } else 325 } else { 291 326 warn2_cannot("change directory to ", svdir); 327 } 292 328 } 293 } else 329 } else { 294 330 warn2_cannot("stat ", svdir); 295 } 296 331 } 332 } 333 334 #if ENABLE_FEATURE_RUNSVDIR_LOG 297 335 if (rplog) { 298 336 if ((int)(now - stamplog) >= 0) { 299 write(logpipe [1], ".", 1);337 write(logpipe.wr, ".", 1); 300 338 stamplog = now + 900; 301 339 } 302 340 } 303 304 341 pfd[0].revents = 0; 342 #endif 343 deadline = (need_rescan ? 1 : 5); 305 344 sig_block(SIGCHLD); 306 deadline = (check ? 1 : 5); 345 #if ENABLE_FEATURE_RUNSVDIR_LOG 307 346 if (rplog) 308 347 poll(pfd, 1, deadline*1000); 309 348 else 349 #endif 310 350 sleep(deadline); 311 351 sig_unblock(SIGCHLD); 312 352 353 #if ENABLE_FEATURE_RUNSVDIR_LOG 313 354 if (pfd[0].revents & POLLIN) { 314 while (read(logpipe[0], &ch, 1) > 0) { 315 if (ch) { 316 for (i = 6; i < rploglen; i++) 317 rplog[i-1] = rplog[i]; 318 rplog[rploglen-1] = ch; 319 } 320 } 321 } 322 323 switch (exitsoon) { 324 case 1: 325 _exit(0); 326 case 2: 355 char ch; 356 while (read(logpipe.rd, &ch, 1) > 0) { 357 if (ch < ' ') 358 ch = ' '; 359 for (i = 6; i < rploglen; i++) 360 rplog[i-1] = rplog[i]; 361 rplog[rploglen-1] = ch; 362 } 363 } 364 #endif 365 if (!bb_got_signal) 366 continue; 367 368 /* -s SCRIPT: useful if we are init. 369 * In this case typically script never returns, 370 * it halts/powers off/reboots the system. */ 371 if (opt_s_argv[0]) { 372 /* Single parameter: signal# */ 373 opt_s_argv[1] = utoa(bb_got_signal); 374 pid = spawn(opt_s_argv); 375 if (pid > 0) { 376 /* Remembering to wait for _any_ children, 377 * not just pid */ 378 while (wait(NULL) != pid) 379 continue; 380 } 381 } 382 383 if (bb_got_signal == SIGHUP) { 327 384 for (i = 0; i < svnum; i++) 328 385 if (sv[i].pid) 329 386 kill(sv[i].pid, SIGTERM); 330 _exit(111); 331 } 332 } 333 /* not reached */ 334 return 0; 335 } 387 } 388 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */ 389 /* Exit unless we are init */ 390 if (getpid() != 1) 391 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS; 392 393 /* init continues to monitor services forever */ 394 bb_got_signal = 0; 395 } /* for (;;) */ 396 } -
branches/2.2.9/mindi-busybox/runit/sv.c
r1765 r2725 151 151 */ 152 152 153 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */153 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 154 154 /* TODO: depends on runit_lib.c - review and reduce/eliminate */ 155 155 … … 159 159 #include "runit_lib.h" 160 160 161 static const char *acts; 162 static char **service; 163 static unsigned rc; 161 struct globals { 162 const char *acts; 163 char **service; 164 unsigned rc; 164 165 /* "Bernstein" time format: unix + 0x400000000000000aULL */ 165 static uint64_t tstart, tnow; 166 svstatus_t svstatus; 167 168 169 static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN; 166 uint64_t tstart, tnow; 167 svstatus_t svstatus; 168 } FIX_ALIASING; 169 #define G (*(struct globals*)&bb_common_bufsiz1) 170 #define acts (G.acts ) 171 #define service (G.service ) 172 #define rc (G.rc ) 173 #define tstart (G.tstart ) 174 #define tnow (G.tnow ) 175 #define svstatus (G.svstatus ) 176 #define INIT_G() do { } while (0) 177 178 179 #define str_equal(s,t) (!strcmp((s), (t))) 180 181 182 static void fatal_cannot(const char *m1) NORETURN; 170 183 static void fatal_cannot(const char *m1) 171 184 { 172 bb_perror_msg("fatal: can not %s", m1);185 bb_perror_msg("fatal: can't %s", m1); 173 186 _exit(151); 174 187 } … … 180 193 printf(": %s", strerror(errno)); 181 194 } 182 puts(""); /* will also flush the output */195 bb_putchar('\n'); /* will also flush the output */ 183 196 } 184 197 … … 212 225 int fd, r; 213 226 214 fd = open _write("supervise/ok");227 fd = open("supervise/ok", O_WRONLY|O_NDELAY); 215 228 if (fd == -1) { 216 229 if (errno == ENODEV) { … … 219 232 return 0; 220 233 } 221 warn("can not open supervise/ok");234 warn("can't open supervise/ok"); 222 235 return -1; 223 236 } 224 237 close(fd); 225 fd = open _read("supervise/status");238 fd = open("supervise/status", O_RDONLY|O_NDELAY); 226 239 if (fd == -1) { 227 warn("can not open supervise/status");240 warn("can't open supervise/status"); 228 241 return -1; 229 242 } … … 234 247 break; 235 248 case -1: 236 warn("can not read supervise/status");249 warn("can't read supervise/status"); 237 250 return -1; 238 251 default: 239 252 errno = 0; 240 warn("can not read supervise/status: bad format");253 warn("can't read supervise/status: bad format"); 241 254 return -1; 242 255 } … … 254 267 if (stat("down", &s) == -1) { 255 268 if (errno != ENOENT) { 256 bb_perror_msg(WARN"can not stat %s/down", *service);269 bb_perror_msg(WARN"can't stat %s/down", *service); 257 270 return 0; 258 271 } … … 284 297 } 285 298 286 static int status(const char *unused )299 static int status(const char *unused UNUSED_PARAM) 287 300 { 288 301 int r; 289 302 290 r = svstatus_get();291 switch (r) { case -1: case 0: return 0; }303 if (svstatus_get() <= 0) 304 return 0; 292 305 293 306 r = svstatus_print(*service); 294 307 if (chdir("log") == -1) { 295 308 if (errno != ENOENT) { 296 printf("; log: "WARN"can not change to log service directory: %s",309 printf("; log: "WARN"can't change to log service directory: %s", 297 310 strerror(errno)); 298 311 } … … 301 314 svstatus_print("log"); 302 315 } 303 puts(""); /* will also flush the output */316 bb_putchar('\n'); /* will also flush the output */ 304 317 return r; 305 318 } … … 313 326 if (stat("check", &s) == -1) { 314 327 if (errno == ENOENT) return 1; 315 bb_perror_msg(WARN"can not stat %s/check", *service);328 bb_perror_msg(WARN"can't stat %s/check", *service); 316 329 return 0; 317 330 } … … 321 334 pid = spawn(prog); 322 335 if (pid <= 0) { 323 bb_perror_msg(WARN"can not %s child %s/check", "run", *service);336 bb_perror_msg(WARN"can't %s child %s/check", "run", *service); 324 337 return 0; 325 338 } 326 while (wait_pid(&w, pid) == -1) { 327 if (errno == EINTR) continue; 328 bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service); 339 while (safe_waitpid(pid, &w, 0) == -1) { 340 bb_perror_msg(WARN"can't %s child %s/check", "wait for", *service); 329 341 return 0; 330 342 } 331 return !wait_exitcode(w);343 return WEXITSTATUS(w) == 0; 332 344 } 333 345 … … 335 347 { 336 348 int r; 337 unsigned pid ;349 unsigned pid_le32; 338 350 uint64_t timestamp; 339 351 … … 346 358 return -1; 347 359 } 348 pid = SWAP_LE32(svstatus.pid_le32);360 pid_le32 = svstatus.pid_le32; 349 361 switch (*a) { 350 362 case 'x': 351 363 return 0; 352 364 case 'u': 353 if (!pid || svstatus.run_or_finish != 1) return 0;365 if (!pid_le32 || svstatus.run_or_finish != 1) return 0; 354 366 if (!checkscript()) return 0; 355 367 break; 356 368 case 'd': 357 if (pid ) return 0;369 if (pid_le32) return 0; 358 370 break; 359 371 case 'c': 360 if (pid && !checkscript()) return 0;372 if (pid_le32 && !checkscript()) return 0; 361 373 break; 362 374 case 't': 363 if (!pid && svstatus.want == 'd') break;375 if (!pid_le32 && svstatus.want == 'd') break; 364 376 timestamp = SWAP_BE64(svstatus.time_be64); 365 if ((tstart > timestamp) || !pid || svstatus.got_term || !checkscript())377 if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript()) 366 378 return 0; 367 379 break; 368 380 case 'o': 369 381 timestamp = SWAP_BE64(svstatus.time_be64); 370 if ((!pid && tstart > timestamp) || (pid&& svstatus.want != 'd'))382 if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd')) 371 383 return 0; 372 384 } 373 385 printf(OK); 374 386 svstatus_print(*service); 375 puts(""); /* will also flush the output */387 bb_putchar('\n'); /* will also flush the output */ 376 388 return 1; 377 389 } … … 379 391 static int control(const char *a) 380 392 { 381 int fd, r; 382 393 int fd, r, l; 394 395 /* Is it an optimization? 396 It causes problems with "sv o SRV; ...; sv d SRV" 397 ('d' is not passed to SRV because its .want == 'd'): 383 398 if (svstatus_get() <= 0) 384 399 return -1; 385 400 if (svstatus.want == *a) 386 401 return 0; 387 fd = open_write("supervise/control"); 402 */ 403 fd = open("supervise/control", O_WRONLY|O_NDELAY); 388 404 if (fd == -1) { 389 405 if (errno != ENODEV) 390 warn("can not open supervise/control");406 warn("can't open supervise/control"); 391 407 else 392 408 *a == 'x' ? ok("runsv not running") : failx("runsv not running"); 393 409 return -1; 394 410 } 395 r = write(fd, a, strlen(a)); 411 l = strlen(a); 412 r = write(fd, a, l); 396 413 close(fd); 397 if (r != strlen(a)) {398 warn("can not write to supervise/control");414 if (r != l) { 415 warn("can't write to supervise/control"); 399 416 return -1; 400 417 } … … 402 419 } 403 420 404 int sv_main(int argc, char **argv) ;405 int sv_main(int argc , char **argv)421 int sv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 422 int sv_main(int argc UNUSED_PARAM, char **argv) 406 423 { 407 424 unsigned opt; 408 unsigned i, want_exit;409 425 char *x; 410 426 char *action; 411 const char *varservice = "/var/service/"; 412 unsigned services; 413 char **servicex; 427 const char *varservice = CONFIG_SV_DEFAULT_SERVICE_DIR; 414 428 unsigned waitsec = 7; 415 429 smallint kll = 0; 416 smallint verbose = 0;430 int verbose = 0; 417 431 int (*act)(const char*); 418 432 int (*cbk)(const char*); 419 433 int curdir; 434 435 INIT_G(); 420 436 421 437 xfunc_error_retval = 100; … … 426 442 if (x) waitsec = xatou(x); 427 443 428 opt = getopt32(argv, "w:v", &x); 429 if (opt & 1) waitsec = xatou(x); // -w 430 if (opt & 2) verbose = 1; // -v 431 argc -= optind; 444 opt_complementary = "w+:vv"; /* -w N, -v is a counter */ 445 opt = getopt32(argv, "w:v", &waitsec, &verbose); 432 446 argv += optind; 433 447 action = *argv++; 434 448 if (!action || !*argv) bb_show_usage(); 435 service = argv; 436 services = argc - 1; 437 438 tnow = time(0) + 0x400000000000000aULL; 449 450 tnow = time(NULL) + 0x400000000000000aULL; 439 451 tstart = tnow; 440 curdir = open _read(".");452 curdir = open(".", O_RDONLY|O_NDELAY); 441 453 if (curdir == -1) 442 454 fatal_cannot("open current directory"); … … 525 537 } 526 538 527 service x = service;528 for (i = 0; i < services; ++i) {529 if ( (**service != '/') && (**service != '.')) {539 service = argv; 540 while ((x = *service) != NULL) { 541 if (x[0] != '/' && x[0] != '.') { 530 542 if (chdir(varservice) == -1) 531 543 goto chdir_failed_0; 532 544 } 533 if (chdir( *service) == -1) {545 if (chdir(x) == -1) { 534 546 chdir_failed_0: 535 fail("can not change to service directory");547 fail("can't change to service directory"); 536 548 goto nullify_service_0; 537 549 } 538 550 if (act && (act(acts) == -1)) { 539 551 nullify_service_0: 540 *service = NULL;552 *service = (char*) -1L; /* "dead" */ 541 553 } 542 554 if (fchdir(curdir) == -1) … … 546 558 547 559 if (cbk) while (1) { 560 int want_exit; 548 561 int diff; 549 562 550 563 diff = tnow - tstart; 551 service = servicex;564 service = argv; 552 565 want_exit = 1; 553 for (i = 0; i < services; ++i, ++service) {554 if ( !*service)555 continue;556 if ( (**service != '/') && (**service != '.')) {566 while ((x = *service) != NULL) { 567 if (x == (char*) -1L) /* "dead" */ 568 goto next; 569 if (x[0] != '/' && x[0] != '.') { 557 570 if (chdir(varservice) == -1) 558 571 goto chdir_failed; 559 572 } 560 if (chdir( *service) == -1) {573 if (chdir(x) == -1) { 561 574 chdir_failed: 562 fail("can not change to service directory");575 fail("can't change to service directory"); 563 576 goto nullify_service; 564 577 } … … 569 582 printf(kll ? "kill: " : "timeout: "); 570 583 if (svstatus_get() > 0) { 571 svstatus_print( *service);584 svstatus_print(x); 572 585 ++rc; 573 586 } 574 puts(""); /* will also flush the output */587 bb_putchar('\n'); /* will also flush the output */ 575 588 if (kll) 576 589 control("k"); 577 590 nullify_service: 578 *service = NULL;591 *service = (char*) -1L; /* "dead" */ 579 592 } 580 593 if (fchdir(curdir) == -1) 581 594 fatal_cannot("change to original directory"); 595 next: 596 service++; 582 597 } 583 598 if (want_exit) break; 584 599 usleep(420000); 585 tnow = time( 0) + 0x400000000000000aULL;600 tnow = time(NULL) + 0x400000000000000aULL; 586 601 } 587 602 return rc > 99 ? 99 : rc; -
branches/2.2.9/mindi-busybox/runit/svlogd.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* TODO: depends on runit_lib.c - review and reduce/eliminate */ 30 31 /* 32 Config files 33 34 On startup, and after receiving a HUP signal, svlogd checks for each 35 log directory log if the configuration file log/config exists, 36 and if so, reads the file line by line and adjusts configuration 37 for log as follows: 38 39 If the line is empty, or starts with a #, it is ignored. A line 40 of the form 41 42 ssize 43 sets the maximum file size of current when svlogd should rotate 44 the current log file to size bytes. Default is 1000000. 45 If size is zero, svlogd doesnt rotate log files 46 You should set size to at least (2 * len). 47 nnum 48 sets the number of old log files svlogd should maintain to num. 49 If svlogd sees more that num old log files in log after log file 50 rotation, it deletes the oldest one. Default is 10. 51 If num is zero, svlogd doesnt remove old log files. 52 Nmin 53 sets the minimum number of old log files svlogd should maintain 54 to min. min must be less than num. If min is set, and svlogd 55 cannot write to current because the filesystem is full, 56 and it sees more than min old log files, it deletes the oldest one. 57 ttimeout 58 sets the maximum age of the current log file when svlogd should 59 rotate the current log file to timeout seconds. If current 60 is timeout seconds old, and is not empty, svlogd forces log file rotation. 61 !processor 62 tells svlogd to feed each recent log file through processor 63 (see above) on log file rotation. By default log files are not processed. 64 ua.b.c.d[:port] 65 tells svlogd to transmit the first len characters of selected 66 log messages to the IP address a.b.c.d, port number port. 67 If port isnt set, the default port for syslog is used (514). 68 len can be set through the -l option, see below. If svlogd 69 has trouble sending udp packets, it writes error messages 70 to the log directory. Attention: logging through udp is unreliable, 71 and should be used in private networks only. 72 Ua.b.c.d[:port] 73 is the same as the u line above, but the log messages are no longer 74 written to the log directory, but transmitted through udp only. 75 Error messages from svlogd concerning sending udp packages still go 76 to the log directory. 77 pprefix 78 tells svlogd to prefix each line to be written to the log directory, 79 to standard error, or through UDP, with prefix. 80 81 If a line starts with a -, +, e, or E, svlogd matches the first len characters 82 of each log message against pattern and acts accordingly: 83 84 -pattern 85 the log message is deselected. 86 +pattern 87 the log message is selected. 88 epattern 89 the log message is selected to be printed to standard error. 90 Epattern 91 the log message is deselected to be printed to standard error. 92 93 Initially each line is selected to be written to log/current. Deselected 94 log messages are discarded from log. Initially each line is deselected 95 to be written to standard err. Log messages selected for standard error 96 are written to standard error. 97 98 Pattern Matching 99 100 svlogd matches a log message against the string pattern as follows: 101 102 pattern is applied to the log message one character by one, starting 103 with the first. A character not a star (*) and not a plus (+) matches itself. 104 A plus matches the next character in pattern in the log message one 105 or more times. A star before the end of pattern matches any string 106 in the log message that does not include the next character in pattern. 107 A star at the end of pattern matches any string. 108 109 Timestamps optionally added by svlogd are not considered part 110 of the log message. 111 112 An svlogd pattern is not a regular expression. For example consider 113 a log message like this 114 115 2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14 116 117 The following pattern doesnt match 118 119 -*pid* 120 121 because the first star matches up to the first p in tcpsvd, 122 and then the match fails because i is not s. To match this 123 log message, you can use a pattern like this instead 124 125 -*: *: pid * 126 */ 30 127 31 128 #include <sys/poll.h> … … 38 135 #define FMT_PTIME 30 39 136 40 static unsigned verbose; 41 static int linemax = 1000; 42 ////static int buflen = 1024; 43 static int linelen; 44 45 static char **fndir; 46 static int fdwdir; 47 static int wstat; 48 static unsigned nearest_rotate; 49 50 static char *line; 51 static smallint exitasap; 52 static smallint rotateasap; 53 static smallint reopenasap; 54 static smallint linecomplete = 1; 55 56 static smallint tmaxflag; 57 58 static char repl; 59 static const char *replace = ""; 60 61 static sigset_t *blocked_sigset; 62 static int fl_flag_0; 63 64 static struct logdir { 137 struct logdir { 65 138 ////char *btmp; 66 139 /* pattern list to match, in "aa\0bb\0\cc\0\0" form */ … … 82 155 char match; 83 156 char matcherr; 84 } *dir; 85 static unsigned dirn; 157 }; 158 159 160 struct globals { 161 struct logdir *dir; 162 unsigned verbose; 163 int linemax; 164 ////int buflen; 165 int linelen; 166 167 int fdwdir; 168 char **fndir; 169 int wstat; 170 unsigned nearest_rotate; 171 172 void* (*memRchr)(const void *, int, size_t); 173 174 smallint exitasap; 175 smallint rotateasap; 176 smallint reopenasap; 177 smallint linecomplete; 178 smallint tmaxflag; 179 180 char repl; 181 const char *replace; 182 int fl_flag_0; 183 unsigned dirn; 184 185 sigset_t blocked_sigset; 186 }; 187 #define G (*ptr_to_globals) 188 #define dir (G.dir ) 189 #define verbose (G.verbose ) 190 #define linemax (G.linemax ) 191 #define buflen (G.buflen ) 192 #define linelen (G.linelen ) 193 #define fndir (G.fndir ) 194 #define fdwdir (G.fdwdir ) 195 #define wstat (G.wstat ) 196 #define memRchr (G.memRchr ) 197 #define nearest_rotate (G.nearest_rotate) 198 #define exitasap (G.exitasap ) 199 #define rotateasap (G.rotateasap ) 200 #define reopenasap (G.reopenasap ) 201 #define linecomplete (G.linecomplete ) 202 #define tmaxflag (G.tmaxflag ) 203 #define repl (G.repl ) 204 #define replace (G.replace ) 205 #define blocked_sigset (G.blocked_sigset) 206 #define fl_flag_0 (G.fl_flag_0 ) 207 #define dirn (G.dirn ) 208 #define INIT_G() do { \ 209 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 210 linemax = 1000; \ 211 /*buflen = 1024;*/ \ 212 linecomplete = 1; \ 213 replace = ""; \ 214 } while (0) 215 216 #define line bb_common_bufsiz1 217 86 218 87 219 #define FATAL "fatal: " … … 90 222 #define INFO "info: " 91 223 92 #define usage() bb_show_usage()93 224 static void fatalx(const char *m0) 94 225 { … … 114 245 static void pause1cannot(const char *m0) 115 246 { 116 bb_perror_msg(PAUSE"can not %s", m0);247 bb_perror_msg(PAUSE"can't %s", m0); 117 248 sleep(3); 118 249 } 119 250 static void pause2cannot(const char *m0, const char *m1) 120 251 { 121 bb_perror_msg(PAUSE"can not %s %s", m0, m1);252 bb_perror_msg(PAUSE"can't %s %s", m0, m1); 122 253 sleep(3); 123 254 } … … 131 262 } 132 263 264 static unsigned pmatch(const char *p, const char *s, unsigned len) 265 { 266 for (;;) { 267 char c = *p++; 268 if (!c) return !len; 269 switch (c) { 270 case '*': 271 c = *p; 272 if (!c) return 1; 273 for (;;) { 274 if (!len) return 0; 275 if (*s == c) break; 276 ++s; 277 --len; 278 } 279 continue; 280 case '+': 281 c = *p++; 282 if (c != *s) return 0; 283 for (;;) { 284 if (!len) return 1; 285 if (*s != c) break; 286 ++s; 287 --len; 288 } 289 continue; 290 /* 291 case '?': 292 if (*p == '?') { 293 if (*s != '?') return 0; 294 ++p; 295 } 296 ++s; --len; 297 continue; 298 */ 299 default: 300 if (!len) return 0; 301 if (*s != c) return 0; 302 ++s; 303 --len; 304 continue; 305 } 306 } 307 return 0; 308 } 309 133 310 /*** ex fmt_ptime.[ch] ***/ 134 311 … … 136 313 static void fmt_time_human_30nul(char *s) 137 314 { 138 struct tm * t;315 struct tm *ptm; 139 316 struct timeval tv; 140 317 141 318 gettimeofday(&tv, NULL); 142 t = gmtime(&(tv.tv_sec));319 ptm = gmtime(&tv.tv_sec); 143 320 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000", 144 (unsigned)(1900 + t->tm_year),145 (unsigned)( t->tm_mon + 1),146 (unsigned)( t->tm_mday),147 (unsigned)( t->tm_hour),148 (unsigned)( t->tm_min),149 (unsigned)( t->tm_sec),321 (unsigned)(1900 + ptm->tm_year), 322 (unsigned)(ptm->tm_mon + 1), 323 (unsigned)(ptm->tm_mday), 324 (unsigned)(ptm->tm_hour), 325 (unsigned)(ptm->tm_min), 326 (unsigned)(ptm->tm_sec), 150 327 (unsigned)(tv.tv_usec) 151 328 ); … … 175 352 } 176 353 177 static unsigned processorstart(struct logdir *ld) 178 { 354 static void processorstart(struct logdir *ld) 355 { 356 char sv_ch; 179 357 int pid; 180 358 181 if (!ld->processor) return 0;359 if (!ld->processor) return; 182 360 if (ld->ppid) { 183 361 warnx("processor already running", ld->name); 184 return 0; 185 } 186 while ((pid = fork()) == -1) 187 pause2cannot("fork for processor", ld->name); 362 return; 363 } 364 365 /* vfork'ed child trashes this byte, save... */ 366 sv_ch = ld->fnsave[26]; 367 368 while ((pid = vfork()) == -1) 369 pause2cannot("vfork for processor", ld->name); 188 370 if (!pid) { 189 char *prog[4];190 371 int fd; 191 372 192 373 /* child */ 193 signal(SIGTERM, SIG_DFL); 194 signal(SIGALRM, SIG_DFL); 195 signal(SIGHUP, SIG_DFL); 374 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 375 /*bb_signals(0 376 + (1 << SIGTERM) 377 + (1 << SIGALRM) 378 + (1 << SIGHUP) 379 , SIG_DFL);*/ 196 380 sig_unblock(SIGTERM); 197 381 sig_unblock(SIGALRM); … … 202 386 fd = xopen(ld->fnsave, O_RDONLY|O_NDELAY); 203 387 xmove_fd(fd, 0); 204 ld->fnsave[26] = 't'; 388 ld->fnsave[26] = 't'; /* <- that's why we need sv_ch! */ 205 389 fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT); 206 390 xmove_fd(fd, 1); 207 fd = open _read("state");391 fd = open("state", O_RDONLY|O_NDELAY); 208 392 if (fd == -1) { 209 393 if (errno != ENOENT) 210 bb_perror_msg_and_die(FATAL"can not %s processor %s", "open state for", ld->name);394 bb_perror_msg_and_die(FATAL"can't %s processor %s", "open state for", ld->name); 211 395 close(xopen("state", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT)); 212 396 fd = xopen("state", O_RDONLY|O_NDELAY); … … 217 401 218 402 // getenv("SHELL")? 219 prog[0] = (char*)"sh"; 220 prog[1] = (char*)"-c"; 221 prog[2] = ld->processor; 222 prog[3] = NULL; 223 execve("/bin/sh", prog, environ); 224 bb_perror_msg_and_die(FATAL"cannot %s processor %s", "run", ld->name); 225 } 403 execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", ld->processor, (char*) NULL); 404 bb_perror_msg_and_die(FATAL"can't %s processor %s", "run", ld->name); 405 } 406 ld->fnsave[26] = sv_ch; /* ...restore */ 226 407 ld->ppid = pid; 227 return 1;228 408 } 229 409 … … 234 414 if (ld->ppid) { 235 415 sig_unblock(SIGHUP); 236 while ( wait_pid(&wstat, ld->ppid) == -1)416 while (safe_waitpid(ld->ppid, &wstat, 0) == -1) 237 417 pause2cannot("wait for processor", ld->name); 238 418 sig_block(SIGHUP); 239 419 ld->ppid = 0; 240 420 } 241 if (ld->fddir == -1) return 1; 421 if (ld->fddir == -1) 422 return 1; 242 423 while (fchdir(ld->fddir) == -1) 243 424 pause2cannot("change directory, want processor", ld->name); 244 if ( wait_exitcode(wstat) != 0) {425 if (WEXITSTATUS(wstat) != 0) { 245 426 warnx("processor failed, restart", ld->name); 246 427 ld->fnsave[26] = 't'; … … 262 443 ld->fnsave[26] = 'u'; 263 444 if (unlink(ld->fnsave) == -1) 264 bb_error_msg(WARNING"can not unlink: %s/%s", ld->name, ld->fnsave);445 bb_error_msg(WARNING"can't unlink: %s/%s", ld->name, ld->fnsave); 265 446 while (rename("newstate", "state") == -1) 266 447 pause2cannot("rename state", ld->name); … … 287 468 if (f->d_name[26] == 't') { 288 469 if (unlink(f->d_name) == -1) 289 warn2("can not unlink processor leftover", f->d_name);470 warn2("can't unlink processor leftover", f->d_name); 290 471 } else { 291 472 ++n; … … 297 478 } 298 479 if (errno) 299 warn2("can not read directory", ld->name);480 warn2("can't read directory", ld->name); 300 481 closedir(d); 301 482 … … 304 485 bb_error_msg(INFO"delete: %s/%s", ld->name, oldest); 305 486 if ((*oldest == '@') && (unlink(oldest) == -1)) 306 warn2("can not unlink oldest logfile", ld->name);487 warn2("can't unlink oldest logfile", ld->name); 307 488 } 308 489 } … … 359 540 while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1) 360 541 pause2cannot("create new current", ld->name); 361 /* we presume this cannot fail */362 ld->filecur = fdopen(ld->fdcur, "a"); ////542 while ((ld->filecur = fdopen(ld->fdcur, "a")) == NULL) //// 543 pause2cannot("create new current", ld->name); /* very unlikely */ 363 544 setvbuf(ld->filecur, NULL, _IOFBF, linelen); //// 364 c oe(ld->fdcur);545 close_on_exec_on(ld->fdcur); 365 546 ld->size = 0; 366 547 while (fchmod(ld->fdcur, 0644) == -1) 367 548 pause2cannot("set mode of current", ld->name); 549 368 550 rmoldest(ld); 369 551 processorstart(ld); … … 413 595 memcpy(oldest, f->d_name, 27); 414 596 } 415 if (errno) warn2("can not read directory, want remove old logfile",597 if (errno) warn2("can't read directory, want remove old logfile", 416 598 ld->name); 417 599 closedir(d); … … 423 605 errno = 0; 424 606 if (unlink(oldest) == -1) { 425 warn2("can not unlink oldest logfile", ld->name);607 warn2("can't unlink oldest logfile", ld->name); 426 608 errno = ENOSPC; 427 609 } … … 468 650 } 469 651 470 static unsigned logdir_open(struct logdir *ld, const char *fn)652 static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) 471 653 { 472 654 char buf[128]; … … 480 662 ld->fddir = open(fn, O_RDONLY|O_NDELAY); 481 663 if (ld->fddir == -1) { 482 warn2("can not open log directory", (char*)fn);664 warn2("can't open log directory", (char*)fn); 483 665 return 0; 484 666 } 485 c oe(ld->fddir);667 close_on_exec_on(ld->fddir); 486 668 if (fchdir(ld->fddir) == -1) { 487 669 logdir_close(ld); 488 warn2("can not change directory", (char*)fn);670 warn2("can't change directory", (char*)fn); 489 671 return 0; 490 672 } 491 673 ld->fdlock = open("lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 492 674 if ((ld->fdlock == -1) 493 || ( lock_exnb(ld->fdlock) == -1)675 || (flock(ld->fdlock, LOCK_EX | LOCK_NB) == -1) 494 676 ) { 495 677 logdir_close(ld); 496 warn2("can not lock directory", (char*)fn);678 warn2("can't lock directory", (char*)fn); 497 679 while (fchdir(fdwdir) == -1) 498 680 pause1cannot("change to initial working directory"); 499 681 return 0; 500 682 } 501 c oe(ld->fdlock);683 close_on_exec_on(ld->fdlock); 502 684 503 685 ld->size = 0; … … 512 694 513 695 /* read config */ 514 i = open_read_close("config", buf, sizeof(buf) );696 i = open_read_close("config", buf, sizeof(buf) - 1); 515 697 if (i < 0 && errno != ENOENT) 516 698 bb_perror_msg(WARNING"%s/config", ld->name); 517 699 if (i > 0) { 700 buf[i] = '\0'; 518 701 if (verbose) 519 702 bb_error_msg(INFO"read: %s/config", ld->name); … … 528 711 case 'e': 529 712 case 'E': 713 /* Filtering requires one-line buffering, 714 * resetting the "find newline" function 715 * accordingly */ 716 memRchr = memchr; 530 717 /* Add '\n'-terminated line to ld->inst */ 531 718 while (1) { 532 int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s);719 int l = asprintf(&new, "%s%s\n", ld->inst ? ld->inst : "", s); 533 720 if (l >= 0 && new) 534 721 break; … … 542 729 { "k", 1024 }, 543 730 { "m", 1024*1024 }, 544 { }731 { "", 0 } 545 732 }; 546 733 ld->sizemax = xatou_sfx(&s[1], km_suffixes); … … 548 735 } 549 736 case 'n': 550 ld->nmax = xatoi_ u(&s[1]);737 ld->nmax = xatoi_positive(&s[1]); 551 738 break; 552 739 case 'N': 553 ld->nmin = xatoi_ u(&s[1]);740 ld->nmin = xatoi_positive(&s[1]); 554 741 break; 555 742 case 't': { … … 558 745 { "h", 60*60 }, 559 746 /*{ "d", 24*60*60 },*/ 560 { }747 { "", 0 } 561 748 }; 562 749 ld->rotate_period = xatou_sfx(&s[1], mh_suffixes); … … 613 800 if (errno != ENOENT) { 614 801 logdir_close(ld); 615 warn2("can not stat current", ld->name);802 warn2("can't stat current", ld->name); 616 803 while (fchdir(fdwdir) == -1) 617 804 pause1cannot("change to initial working directory"); … … 621 808 while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1) 622 809 pause2cannot("open current", ld->name); 623 /* we presume this cannot fail */624 ld->filecur = fdopen(ld->fdcur, "a"); ////810 while ((ld->filecur = fdopen(ld->fdcur, "a")) == NULL) 811 pause2cannot("open current", ld->name); //// 625 812 setvbuf(ld->filecur, NULL, _IOFBF, linelen); //// 626 813 627 c oe(ld->fdcur);814 close_on_exec_on(ld->fdcur); 628 815 while (fchmod(ld->fdcur, 0644) == -1) 629 816 pause2cannot("set mode of current", ld->name); … … 666 853 667 854 /* Used for reading stdin */ 668 static int buffer_pread( int fd,char *s, unsigned len)855 static int buffer_pread(/*int fd, */char *s, unsigned len) 669 856 { 670 857 unsigned now; … … 672 859 int i; 673 860 674 input.fd = 0;861 input.fd = STDIN_FILENO; 675 862 input.events = POLLIN; 676 863 … … 701 888 } 702 889 703 sigprocmask(SIG_UNBLOCK, blocked_sigset, NULL);890 sigprocmask(SIG_UNBLOCK, &blocked_sigset, NULL); 704 891 i = nearest_rotate - now; 705 892 if (i > 1000000) … … 708 895 i = 1; 709 896 poll(&input, 1, i * 1000); 710 sigprocmask(SIG_BLOCK, blocked_sigset, NULL);711 712 i = ndelay_read( fd, s, len);897 sigprocmask(SIG_BLOCK, &blocked_sigset, NULL); 898 899 i = ndelay_read(STDIN_FILENO, s, len); 713 900 if (i >= 0) 714 901 break; … … 716 903 continue; 717 904 if (errno != EAGAIN) { 718 warn("can not read standard input");905 warn("can't read standard input"); 719 906 break; 720 907 } … … 750 937 } 751 938 752 static void sig_term_handler(int sig_no )939 static void sig_term_handler(int sig_no UNUSED_PARAM) 753 940 { 754 941 if (verbose) … … 757 944 } 758 945 759 static void sig_child_handler(int sig_no) 760 { 761 int pid, l; 946 static void sig_child_handler(int sig_no UNUSED_PARAM) 947 { 948 pid_t pid; 949 int l; 762 950 763 951 if (verbose) 764 952 bb_error_msg(INFO"sig%s received", "child"); 765 while ((pid = wait_ nohang(&wstat)) > 0) {953 while ((pid = wait_any_nohang(&wstat)) > 0) { 766 954 for (l = 0; l < dirn; ++l) { 767 955 if (dir[l].ppid == pid) { … … 774 962 } 775 963 776 static void sig_alarm_handler(int sig_no )964 static void sig_alarm_handler(int sig_no UNUSED_PARAM) 777 965 { 778 966 if (verbose) … … 781 969 } 782 970 783 static void sig_hangup_handler(int sig_no )971 static void sig_hangup_handler(int sig_no UNUSED_PARAM) 784 972 { 785 973 if (verbose) … … 812 1000 } 813 1001 814 int svlogd_main(int argc, char **argv) ;1002 int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 815 1003 int svlogd_main(int argc, char **argv) 816 1004 { 817 sigset_t ss; 818 char *r,*l,*b; 1005 char *r, *l, *b; 819 1006 ssize_t stdin_cnt = 0; 820 1007 int i; 821 1008 unsigned opt; 822 1009 unsigned timestamp = 0; 823 void* (*memRchr)(const void *, int, size_t) = memchr; 824 825 #define line bb_common_bufsiz1 1010 1011 INIT_G(); 826 1012 827 1013 opt_complementary = "tt:vv"; … … 830 1016 if (opt & 1) { // -r 831 1017 repl = r[0]; 832 if (!repl || r[1]) usage(); 1018 if (!repl || r[1]) 1019 bb_show_usage(); 833 1020 } 834 1021 if (opt & 2) if (!repl) repl = '_'; // -R 835 1022 if (opt & 4) { // -l 836 1023 linemax = xatou_range(l, 0, BUFSIZ-26); 837 if (linemax == 0) linemax = BUFSIZ-26; 838 if (linemax < 256) linemax = 256; 1024 if (linemax == 0) 1025 linemax = BUFSIZ-26; 1026 if (linemax < 256) 1027 linemax = 256; 839 1028 } 840 1029 ////if (opt & 8) { // -b 841 //// buflen = xatoi_ u(b);1030 //// buflen = xatoi_positive(b); 842 1031 //// if (buflen == 0) buflen = 1024; 843 1032 ////} … … 849 1038 850 1039 dirn = argc; 851 if (dirn <= 0) usage(); 852 ////if (buflen <= linemax) usage(); 1040 if (dirn <= 0) 1041 bb_show_usage(); 1042 ////if (buflen <= linemax) bb_show_usage(); 853 1043 fdwdir = xopen(".", O_RDONLY|O_NDELAY); 854 c oe(fdwdir);855 dir = xzalloc(dirn * sizeof( struct logdir));1044 close_on_exec_on(fdwdir); 1045 dir = xzalloc(dirn * sizeof(dir[0])); 856 1046 for (i = 0; i < dirn; ++i) { 857 1047 dir[i].fddir = -1; … … 867 1057 fl_flag_0 = fcntl(0, F_GETFL); 868 1058 869 blocked_sigset = &ss; 870 sigemptyset(&ss); 871 sigaddset(&ss, SIGTERM); 872 sigaddset(&ss, SIGCHLD); 873 sigaddset(&ss, SIGALRM); 874 sigaddset(&ss, SIGHUP); 875 sigprocmask(SIG_BLOCK, &ss, NULL); 876 sig_catch(SIGTERM, sig_term_handler); 877 sig_catch(SIGCHLD, sig_child_handler); 878 sig_catch(SIGALRM, sig_alarm_handler); 879 sig_catch(SIGHUP, sig_hangup_handler); 880 881 logdirs_reopen(); 1059 sigemptyset(&blocked_sigset); 1060 sigaddset(&blocked_sigset, SIGTERM); 1061 sigaddset(&blocked_sigset, SIGCHLD); 1062 sigaddset(&blocked_sigset, SIGALRM); 1063 sigaddset(&blocked_sigset, SIGHUP); 1064 sigprocmask(SIG_BLOCK, &blocked_sigset, NULL); 1065 bb_signals_recursive_norestart(1 << SIGTERM, sig_term_handler); 1066 bb_signals_recursive_norestart(1 << SIGCHLD, sig_child_handler); 1067 bb_signals_recursive_norestart(1 << SIGALRM, sig_alarm_handler); 1068 bb_signals_recursive_norestart(1 << SIGHUP, sig_hangup_handler); 882 1069 883 1070 /* Without timestamps, we don't have to print each line 884 1071 * separately, so we can look for _last_ newline, not first, 885 * thus batching writes */ 886 if (!timestamp) 887 memRchr = memrchr; 1072 * thus batching writes. If filtering is enabled in config, 1073 * logdirs_reopen resets it to memchr. 1074 */ 1075 memRchr = (timestamp ? memchr : memrchr); 1076 1077 logdirs_reopen(); 888 1078 889 1079 setvbuf(stderr, NULL, _IOFBF, linelen); … … 910 1100 i = linemax - stdin_cnt; /* avail. bytes at tail */ 911 1101 if (i >= 128) { 912 i = buffer_pread( 0,lineptr + stdin_cnt, i);1102 i = buffer_pread(/*0, */lineptr + stdin_cnt, i); 913 1103 if (i <= 0) /* EOF or error on stdin */ 914 1104 exitasap = 1; … … 925 1115 linelen = stdin_cnt; 926 1116 if (np) { 927 print_to_nl: /* NB: starting from here lineptr may point 1117 print_to_nl: 1118 /* NB: starting from here lineptr may point 928 1119 * farther out into line[] */ 929 1120 linelen = np - lineptr + 1; … … 953 1144 for (i = 0; i < dirn; ++i) { 954 1145 struct logdir *ld = &dir[i]; 955 if (ld->fddir == -1) continue; 1146 if (ld->fddir == -1) 1147 continue; 956 1148 if (ld->inst) 957 1149 logmatch(ld); 958 if (ld->matcherr == 'e') 959 ////full_write(2, printptr, printlen); 960 fwrite(lineptr, 1, linelen, stderr); 961 if (ld->match != '+') continue; 1150 if (ld->matcherr == 'e') { 1151 /* runit-1.8.0 compat: if timestamping, do it on stderr too */ 1152 ////full_write(STDERR_FILENO, printptr, printlen); 1153 fwrite(printptr, 1, printlen, stderr); 1154 } 1155 if (ld->match != '+') 1156 continue; 962 1157 buffer_pwrite(i, printptr, printlen); 963 1158 } … … 967 1162 while (ch != '\n') { 968 1163 /* lineptr is emptied now, safe to use as buffer */ 969 stdin_cnt = exitasap ? -1 : buffer_pread( 0,lineptr, linemax);1164 stdin_cnt = exitasap ? -1 : buffer_pread(/*0, */lineptr, linemax); 970 1165 if (stdin_cnt <= 0) { /* EOF or error on stdin */ 971 1166 exitasap = 1; … … 982 1177 /* linelen == no of chars incl. '\n' (or == stdin_cnt) */ 983 1178 for (i = 0; i < dirn; ++i) { 984 if (dir[i].fddir == -1) continue; 985 if (dir[i].matcherr == 'e') 986 ////full_write(2, lineptr, linelen); 1179 if (dir[i].fddir == -1) 1180 continue; 1181 if (dir[i].matcherr == 'e') { 1182 ////full_write(STDERR_FILENO, lineptr, linelen); 987 1183 fwrite(lineptr, 1, linelen, stderr); 988 if (dir[i].match != '+') continue; 1184 } 1185 if (dir[i].match != '+') 1186 continue; 989 1187 buffer_pwrite(i, lineptr, linelen); 990 1188 } … … 1002 1200 memmove((timestamp ? line+26 : line), lineptr, stdin_cnt); 1003 1201 } 1004 fflush (NULL);////1202 fflush_all();//// 1005 1203 } 1006 1204 … … 1008 1206 if (dir[i].ppid) 1009 1207 while (!processorstop(&dir[i])) 1010 /* repeat */;1208 continue; 1011 1209 logdir_close(&dir[i]); 1012 1210 }
Note:
See TracChangeset
for help on using the changeset viewer.