aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
committerRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
commitb680f05ad449505e3d914bebd4c8d83bf768c094 (patch)
treec08ded13d430b0e7e0104f2eb594fad190ce98a3 /miscutils
parent258200ff81d5a9da54dab35acf36213eff1e399b (diff)
parent513a2457b65894b10b9fd6aa8753fca59eced08c (diff)
downloadbusybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.gz
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.bz2
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/beep.c2
-rw-r--r--miscutils/crond.c140
-rw-r--r--miscutils/makedevs.c41
-rw-r--r--miscutils/ttysize.c7
-rw-r--r--miscutils/watchdog.c66
5 files changed, 194 insertions, 62 deletions
diff --git a/miscutils/beep.c b/miscutils/beep.c
index 14802b543..216f69400 100644
--- a/miscutils/beep.c
+++ b/miscutils/beep.c
@@ -16,7 +16,7 @@
16//config: 16//config:
17//config:config FEATURE_BEEP_FREQ 17//config:config FEATURE_BEEP_FREQ
18//config: int "default frequency" 18//config: int "default frequency"
19//config: range 0 2147483647 19//config: range 20 50000 # allowing 0 here breaks the build
20//config: default 4000 20//config: default 4000
21//config: depends on BEEP 21//config: depends on BEEP
22//config: help 22//config: help
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 88e7b47b3..c0c8bef11 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -35,6 +35,22 @@
35//config: help 35//config: help
36//config: Command output will be sent to corresponding user via email. 36//config: Command output will be sent to corresponding user via email.
37//config: 37//config:
38//config:config FEATURE_CROND_SPECIAL_TIMES
39//config: bool "Support special times (@reboot, @daily, etc) in crontabs"
40//config: default y
41//config: depends on CROND
42//config: help
43//config: string meaning
44//config: ------ -------
45//config: @reboot Run once, at startup
46//config: @yearly Run once a year: "0 0 1 1 *"
47//config: @annually Same as @yearly: "0 0 1 1 *"
48//config: @monthly Run once a month: "0 0 1 * *"
49//config: @weekly Run once a week: "0 0 * * 0"
50//config: @daily Run once a day: "0 0 * * *"
51//config: @midnight Same as @daily: "0 0 * * *"
52//config: @hourly Run once an hour: "0 * * * *"
53//config:
38//config:config FEATURE_CROND_DIR 54//config:config FEATURE_CROND_DIR
39//config: string "crond spool directory" 55//config: string "crond spool directory"
40//config: default "/var/spool/cron" 56//config: default "/var/spool/cron"
@@ -74,6 +90,7 @@
74 90
75#define CRON_DIR CONFIG_FEATURE_CROND_DIR 91#define CRON_DIR CONFIG_FEATURE_CROND_DIR
76#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" 92#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
93#define CRON_REBOOT CONFIG_PID_FILE_PATH "/crond.reboot"
77#ifndef SENDMAIL 94#ifndef SENDMAIL
78# define SENDMAIL "sendmail" 95# define SENDMAIL "sendmail"
79#endif 96#endif
@@ -101,6 +118,8 @@ typedef struct CronLine {
101 struct CronLine *cl_next; 118 struct CronLine *cl_next;
102 char *cl_cmd; /* shell command */ 119 char *cl_cmd; /* shell command */
103 pid_t cl_pid; /* >0:running, <0:needs to be started in this minute, 0:dormant */ 120 pid_t cl_pid; /* >0:running, <0:needs to be started in this minute, 0:dormant */
121#define START_ME_REBOOT -2
122#define START_ME_NORMAL -1
104#if ENABLE_FEATURE_CROND_CALL_SENDMAIL 123#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
105 int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */ 124 int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */
106 char *cl_mailto; /* whom to mail results, may be NULL */ 125 char *cl_mailto; /* whom to mail results, may be NULL */
@@ -465,21 +484,85 @@ static void load_crontab(const char *fileName)
465//line of the crontab's owner. HOME and SHELL may be overridden by settings 484//line of the crontab's owner. HOME and SHELL may be overridden by settings
466//in the crontab; LOGNAME may not. 485//in the crontab; LOGNAME may not.
467 486
487#if ENABLE_FEATURE_CROND_SPECIAL_TIMES
488 if (tokens[0][0] == '@') {
489 /*
490 * "@daily /a/script/to/run PARAM1 PARAM2..."
491 */
492 typedef struct SpecialEntry {
493 const char *name;
494 const char tokens[8];
495 } SpecialEntry;
496 static const SpecialEntry SpecAry[] = {
497 /* hour day month weekday */
498 { "yearly", "0\0" "1\0" "1\0" "*" },
499 { "annually", "0\0" "1\0" "1\0" "*" },
500 { "monthly", "0\0" "1\0" "*\0" "*" },
501 { "weekly", "0\0" "*\0" "*\0" "0" },
502 { "daily", "0\0" "*\0" "*\0" "*" },
503 { "midnight", "0\0" "*\0" "*\0" "*" },
504 { "hourly", "*\0" "*\0" "*\0" "*" },
505 { "reboot", "" },
506 };
507 const SpecialEntry *e = SpecAry;
508
509 if (n < 2)
510 continue;
511 for (;;) {
512 if (strcmp(e->name, tokens[0] + 1) == 0) {
513 /*
514 * tokens[1] is only the first word of command,
515 * can'r use it.
516 * find the entire command in unmodified string:
517 */
518 tokens[5] = skip_whitespace(
519 skip_non_whitespace(
520 skip_whitespace(parser->data)));
521 if (e->tokens[0]) {
522 char *et = (char*)e->tokens;
523 /* minute is "0" for all specials */
524 tokens[0] = (char*)"0";
525 tokens[1] = et;
526 tokens[2] = et + 2;
527 tokens[3] = et + 4;
528 tokens[4] = et + 6;
529 }
530 goto got_it;
531 }
532 if (!e->tokens[0])
533 break;
534 e++;
535 }
536 continue; /* bad line (unrecognized '@foo') */
537 }
538#endif
468 /* check if a minimum of tokens is specified */ 539 /* check if a minimum of tokens is specified */
469 if (n < 6) 540 if (n < 6)
470 continue; 541 continue;
542 IF_FEATURE_CROND_SPECIAL_TIMES(
543 got_it:
544 )
471 *pline = line = xzalloc(sizeof(*line)); 545 *pline = line = xzalloc(sizeof(*line));
472 /* parse date ranges */ 546#if ENABLE_FEATURE_CROND_SPECIAL_TIMES
473 ParseField(file->cf_username, line->cl_Mins, 60, 0, NULL, tokens[0]); 547 if (tokens[0][0] == '@') { /* "@reboot" line */
474 ParseField(file->cf_username, line->cl_Hrs, 24, 0, NULL, tokens[1]); 548 file->cf_wants_starting = 1;
475 ParseField(file->cf_username, line->cl_Days, 32, 0, NULL, tokens[2]); 549 line->cl_pid = START_ME_REBOOT; /* wants to start */
476 ParseField(file->cf_username, line->cl_Mons, 12, -1, MonAry, tokens[3]); 550 /* line->cl_Mins/Hrs/etc stay zero: never match any time */
477 ParseField(file->cf_username, line->cl_Dow, 7, 0, DowAry, tokens[4]); 551 } else
478 /* 552#endif
479 * fix days and dow - if one is not "*" and the other 553 {
480 * is "*", the other is set to 0, and vise-versa 554 /* parse date ranges */
481 */ 555 ParseField(file->cf_username, line->cl_Mins, 60, 0, NULL, tokens[0]);
482 FixDayDow(line); 556 ParseField(file->cf_username, line->cl_Hrs, 24, 0, NULL, tokens[1]);
557 ParseField(file->cf_username, line->cl_Days, 32, 0, NULL, tokens[2]);
558 ParseField(file->cf_username, line->cl_Mons, 12, -1, MonAry, tokens[3]);
559 ParseField(file->cf_username, line->cl_Dow, 7, 0, DowAry, tokens[4]);
560 /*
561 * fix days and dow - if one is not "*" and the other
562 * is "*", the other is set to 0, and vise-versa
563 */
564 FixDayDow(line);
565 }
483#if ENABLE_FEATURE_CROND_CALL_SENDMAIL 566#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
484 /* copy mailto (can be NULL) */ 567 /* copy mailto (can be NULL) */
485 line->cl_mailto = xstrdup(mailTo); 568 line->cl_mailto = xstrdup(mailTo);
@@ -664,7 +747,7 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
664 return pid; 747 return pid;
665} 748}
666 749
667static void start_one_job(const char *user, CronLine *line) 750static pid_t start_one_job(const char *user, CronLine *line)
668{ 751{
669 char mailFile[128]; 752 char mailFile[128];
670 int mailFd = -1; 753 int mailFd = -1;
@@ -698,6 +781,8 @@ static void start_one_job(const char *user, CronLine *line)
698 free(mailFile2); 781 free(mailFile2);
699 } 782 }
700 } 783 }
784
785 return line->cl_pid;
701} 786}
702 787
703/* 788/*
@@ -748,7 +833,7 @@ static void process_finished_job(const char *user, CronLine *line)
748 833
749#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ 834#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
750 835
751static void start_one_job(const char *user, CronLine *line) 836static pid_t start_one_job(const char *user, CronLine *line)
752{ 837{
753 const char *shell; 838 const char *shell;
754 struct passwd *pas; 839 struct passwd *pas;
@@ -782,6 +867,7 @@ static void start_one_job(const char *user, CronLine *line)
782 pid = 0; 867 pid = 0;
783 } 868 }
784 line->cl_pid = pid; 869 line->cl_pid = pid;
870 return pid;
785} 871}
786 872
787#define process_finished_job(user, line) ((line)->cl_pid = 0) 873#define process_finished_job(user, line) ((line)->cl_pid = 0)
@@ -825,7 +911,7 @@ static void flag_starting_jobs(time_t t1, time_t t2)
825 log8("user %s: process already running: %s", 911 log8("user %s: process already running: %s",
826 file->cf_username, line->cl_cmd); 912 file->cf_username, line->cl_cmd);
827 } else if (line->cl_pid == 0) { 913 } else if (line->cl_pid == 0) {
828 line->cl_pid = -1; 914 line->cl_pid = START_ME_NORMAL;
829 file->cf_wants_starting = 1; 915 file->cf_wants_starting = 1;
830 } 916 }
831 } 917 }
@@ -834,7 +920,20 @@ static void flag_starting_jobs(time_t t1, time_t t2)
834 } 920 }
835} 921}
836 922
837static void start_jobs(void) 923#if ENABLE_FEATURE_CROND_SPECIAL_TIMES
924static int touch_reboot_file(void)
925{
926 int fd = open(CRON_REBOOT, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0000);
927 if (fd >= 0) {
928 close(fd);
929 return 1;
930 }
931 /* File (presumably) exists - this is not the first run after reboot */
932 return 0;
933}
934#endif
935
936static void start_jobs(int wants_start)
838{ 937{
839 CronFile *file; 938 CronFile *file;
840 CronLine *line; 939 CronLine *line;
@@ -846,11 +945,10 @@ static void start_jobs(void)
846 file->cf_wants_starting = 0; 945 file->cf_wants_starting = 0;
847 for (line = file->cf_lines; line; line = line->cl_next) { 946 for (line = file->cf_lines; line; line = line->cl_next) {
848 pid_t pid; 947 pid_t pid;
849 if (line->cl_pid >= 0) 948 if (line->cl_pid != wants_start)
850 continue; 949 continue;
851 950
852 start_one_job(file->cf_username, line); 951 pid = start_one_job(file->cf_username, line);
853 pid = line->cl_pid;
854 log8("USER %s pid %3d cmd %s", 952 log8("USER %s pid %3d cmd %s",
855 file->cf_username, (int)pid, line->cl_cmd); 953 file->cf_username, (int)pid, line->cl_cmd);
856 if (pid < 0) { 954 if (pid < 0) {
@@ -950,6 +1048,10 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
950 log8("crond (busybox "BB_VER") started, log level %d", G.log_level); 1048 log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
951 rescan_crontab_dir(); 1049 rescan_crontab_dir();
952 write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid"); 1050 write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
1051#if ENABLE_FEATURE_CROND_SPECIAL_TIMES
1052 if (touch_reboot_file())
1053 start_jobs(START_ME_REBOOT); /* start @reboot entries, if any */
1054#endif
953 1055
954 /* Main loop */ 1056 /* Main loop */
955 t2 = time(NULL); 1057 t2 = time(NULL);
@@ -1002,7 +1104,7 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
1002 } else if (dt > 0) { 1104 } else if (dt > 0) {
1003 /* Usual case: time advances forward, as expected */ 1105 /* Usual case: time advances forward, as expected */
1004 flag_starting_jobs(t1, t2); 1106 flag_starting_jobs(t1, t2);
1005 start_jobs(); 1107 start_jobs(START_ME_NORMAL);
1006 sleep_time = 60; 1108 sleep_time = 60;
1007 if (check_completions() > 0) { 1109 if (check_completions() > 0) {
1008 /* some jobs are still running */ 1110 /* some jobs are still running */
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c
index 9e7ca340f..f436b08f8 100644
--- a/miscutils/makedevs.c
+++ b/miscutils/makedevs.c
@@ -208,17 +208,17 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
208 unsigned count = 0; 208 unsigned count = 0;
209 unsigned increment = 0; 209 unsigned increment = 0;
210 unsigned start = 0; 210 unsigned start = 0;
211 char name[41];
212 char user[41]; 211 char user[41];
213 char group[41]; 212 char group[41];
214 char *full_name = name; 213 char *full_name;
214 int name_len;
215 uid_t uid; 215 uid_t uid;
216 gid_t gid; 216 gid_t gid;
217 217
218 linenum = parser->lineno; 218 linenum = parser->lineno;
219 219
220 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", 220 if ((1 > sscanf(line, "%*s%n %c %o %40s %40s %u %u %u %u %u",
221 name, &type, &mode, user, group, 221 &name_len, &type, &mode, user, group,
222 &major, &minor, &start, &increment, &count)) 222 &major, &minor, &start, &increment, &count))
223 || ((unsigned)(major | minor | start | count | increment) > 255) 223 || ((unsigned)(major | minor | start | count | increment) > 255)
224 ) { 224 ) {
@@ -229,9 +229,11 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
229 229
230 gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid(); 230 gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
231 uid = (*user) ? get_ug_id(user, xuname2uid) : getuid(); 231 uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
232 line[name_len] = '\0';
233 full_name = line;
232 /* We are already in the right root dir, 234 /* We are already in the right root dir,
233 * so make absolute paths relative */ 235 * so make absolute paths relative */
234 if ('/' == *full_name) 236 if ('/' == full_name[0])
235 full_name++; 237 full_name++;
236 238
237 if (type == 'd') { 239 if (type == 'd') {
@@ -260,9 +262,7 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
260 if (chmod(full_name, mode) < 0) 262 if (chmod(full_name, mode) < 0)
261 goto chmod_fail; 263 goto chmod_fail;
262 } else { 264 } else {
263 dev_t rdev;
264 unsigned i; 265 unsigned i;
265 char *full_name_inc;
266 266
267 if (type == 'p') { 267 if (type == 'p') {
268 mode |= S_IFIFO; 268 mode |= S_IFIFO;
@@ -276,26 +276,29 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
276 continue; 276 continue;
277 } 277 }
278 278
279 full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2); 279 if (count != 0)
280 if (count)
281 count--; 280 count--;
282 for (i = start; i <= start + count; i++) { 281 for (i = 0; i <= count; i++) {
283 sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i); 282 dev_t rdev;
284 rdev = makedev(major, minor + (i - start) * increment); 283 char *nameN = full_name;
285 if (mknod(full_name_inc, mode, rdev) != 0 284 if (count != 0)
285 nameN = xasprintf("%s%u", full_name, start + i);
286 rdev = makedev(major, minor + i * increment);
287 if (mknod(nameN, mode, rdev) != 0
286 && errno != EEXIST 288 && errno != EEXIST
287 ) { 289 ) {
288 bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc); 290 bb_perror_msg("line %d: can't create node %s", linenum, nameN);
289 ret = EXIT_FAILURE; 291 ret = EXIT_FAILURE;
290 } else if (chown(full_name_inc, uid, gid) < 0) { 292 } else if (chown(nameN, uid, gid) < 0) {
291 bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc); 293 bb_perror_msg("line %d: can't chown %s", linenum, nameN);
292 ret = EXIT_FAILURE; 294 ret = EXIT_FAILURE;
293 } else if (chmod(full_name_inc, mode) < 0) { 295 } else if (chmod(nameN, mode) < 0) {
294 bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc); 296 bb_perror_msg("line %d: can't chmod %s", linenum, nameN);
295 ret = EXIT_FAILURE; 297 ret = EXIT_FAILURE;
296 } 298 }
299 if (count != 0)
300 free(nameN);
297 } 301 }
298 free(full_name_inc);
299 } 302 }
300 } 303 }
301 if (ENABLE_FEATURE_CLEAN_UP) 304 if (ENABLE_FEATURE_CLEAN_UP)
diff --git a/miscutils/ttysize.c b/miscutils/ttysize.c
index 135ce8535..cba65b148 100644
--- a/miscutils/ttysize.c
+++ b/miscutils/ttysize.c
@@ -25,7 +25,7 @@
25//usage:#define ttysize_trivial_usage 25//usage:#define ttysize_trivial_usage
26//usage: "[w] [h]" 26//usage: "[w] [h]"
27//usage:#define ttysize_full_usage "\n\n" 27//usage:#define ttysize_full_usage "\n\n"
28//usage: "Print dimension(s) of stdin's terminal, on error return 80x25" 28//usage: "Print dimensions of stdin tty, or 80x24"
29 29
30#include "libbb.h" 30#include "libbb.h"
31 31
@@ -37,7 +37,10 @@ int ttysize_main(int argc UNUSED_PARAM, char **argv)
37 37
38 w = 80; 38 w = 80;
39 h = 24; 39 h = 24;
40 if (!ioctl(0, TIOCGWINSZ, &wsz)) { 40 if (ioctl(0, TIOCGWINSZ, &wsz) == 0
41 || ioctl(1, TIOCGWINSZ, &wsz) == 0
42 || ioctl(2, TIOCGWINSZ, &wsz) == 0
43 ) {
41 w = wsz.ws_col; 44 w = wsz.ws_col;
42 h = wsz.ws_row; 45 h = wsz.ws_row;
43 } 46 }
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 07ae64e52..d379a97f4 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -35,27 +35,60 @@
35//usage: "\nUse 500ms to specify period in milliseconds" 35//usage: "\nUse 500ms to specify period in milliseconds"
36 36
37#include "libbb.h" 37#include "libbb.h"
38#include "linux/types.h" /* for __u32 */ 38#include <linux/types.h> /* for __u32 */
39#include "linux/watchdog.h" 39#include <linux/watchdog.h>
40
41#ifndef WDIOC_SETOPTIONS
42# define WDIOC_SETOPTIONS 0x5704
43#endif
44#ifndef WDIOC_SETTIMEOUT
45# define WDIOC_SETTIMEOUT 0x5706
46#endif
47#ifndef WDIOC_GETTIMEOUT
48# define WDIOC_GETTIMEOUT 0x5707
49#endif
50#ifndef WDIOS_ENABLECARD
51# define WDIOS_ENABLECARD 2
52#endif
40 53
41#define OPT_FOREGROUND (1 << 0) 54#define OPT_FOREGROUND (1 << 0)
42#define OPT_STIMER (1 << 1) 55#define OPT_STIMER (1 << 1)
43#define OPT_HTIMER (1 << 2) 56#define OPT_HTIMER (1 << 2)
44 57
45static void watchdog_shutdown(int sig UNUSED_PARAM) 58static void shutdown_watchdog(void)
46{ 59{
47 static const char V = 'V'; 60 static const char V = 'V';
61 write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */
62 close(3);
63}
48 64
65static void shutdown_on_signal(int sig UNUSED_PARAM)
66{
49 remove_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid"); 67 remove_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid");
50 write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ 68 shutdown_watchdog();
51 if (ENABLE_FEATURE_CLEAN_UP)
52 close(3);
53 _exit(EXIT_SUCCESS); 69 _exit(EXIT_SUCCESS);
54} 70}
55 71
72static void watchdog_open(const char* device)
73{
74 /* Use known fd # - avoid needing global 'int fd' */
75 xmove_fd(xopen(device, O_WRONLY), 3);
76
77 /* If the watchdog driver can do something other than cause a reboot
78 * on a timeout, then it's possible this program may be starting from
79 * a state when the watchdog hadn't been previously stopped with
80 * the magic write followed by a close. In this case the driver may
81 * not start properly, so always do the proper stop first just in case.
82 */
83 shutdown_watchdog();
84
85 xmove_fd(xopen(device, O_WRONLY), 3);
86}
87
56int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 88int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
57int watchdog_main(int argc, char **argv) 89int watchdog_main(int argc UNUSED_PARAM, char **argv)
58{ 90{
91 static const int enable = WDIOS_ENABLECARD;
59 static const struct suffix_mult suffixes[] = { 92 static const struct suffix_mult suffixes[] = {
60 { "ms", 1 }, 93 { "ms", 1 },
61 { "", 1000 }, 94 { "", 1000 },
@@ -80,31 +113,22 @@ int watchdog_main(int argc, char **argv)
80 if (!(opts & OPT_FOREGROUND)) 113 if (!(opts & OPT_FOREGROUND))
81 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 114 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
82 115
116 /* maybe bb_logenv_override(); here for LOGGING=syslog to work? */
117
83 if (opts & OPT_HTIMER) 118 if (opts & OPT_HTIMER)
84 htimer_duration = xatou_sfx(ht_arg, suffixes); 119 htimer_duration = xatou_sfx(ht_arg, suffixes);
85 stimer_duration = htimer_duration / 2; 120 stimer_duration = htimer_duration / 2;
86 if (opts & OPT_STIMER) 121 if (opts & OPT_STIMER)
87 stimer_duration = xatou_sfx(st_arg, suffixes); 122 stimer_duration = xatou_sfx(st_arg, suffixes);
88 123
89 bb_signals(BB_FATAL_SIGS, watchdog_shutdown); 124 bb_signals(BB_FATAL_SIGS, shutdown_on_signal);
90 125
91 /* Use known fd # - avoid needing global 'int fd' */ 126 watchdog_open(argv[optind]);
92 xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
93 127
94 /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */ 128 /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */
95 htimer_duration = htimer_duration / 1000; 129 htimer_duration = htimer_duration / 1000;
96#ifndef WDIOC_SETTIMEOUT 130 ioctl_or_warn(3, WDIOC_SETOPTIONS, (void*) &enable);
97# error WDIOC_SETTIMEOUT is not defined, cannot compile watchdog applet
98#else
99# if defined WDIOC_SETOPTIONS && defined WDIOS_ENABLECARD
100 {
101 static const int enable = WDIOS_ENABLECARD;
102 ioctl_or_warn(3, WDIOC_SETOPTIONS, (void*) &enable);
103 }
104# endif
105 ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration); 131 ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration);
106#endif
107
108#if 0 132#if 0
109 ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration); 133 ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration);
110 printf("watchdog: SW timer is %dms, HW timer is %ds\n", 134 printf("watchdog: SW timer is %dms, HW timer is %ds\n",