aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/chrt.c92
-rw-r--r--miscutils/crond.c4
-rw-r--r--miscutils/crontab.c11
-rw-r--r--miscutils/dc.c94
-rw-r--r--miscutils/eject.c95
-rw-r--r--miscutils/last.c2
-rw-r--r--miscutils/setsid.c10
-rw-r--r--miscutils/taskset.c88
-rw-r--r--miscutils/time.c118
-rw-r--r--miscutils/ttysize.c2
-rw-r--r--miscutils/watchdog.c16
11 files changed, 259 insertions, 273 deletions
diff --git a/miscutils/chrt.c b/miscutils/chrt.c
index 418e7ae79..0d55e3299 100644
--- a/miscutils/chrt.c
+++ b/miscutils/chrt.c
@@ -13,8 +13,8 @@
13#warning your system may be foobared 13#warning your system may be foobared
14#endif 14#endif
15static const struct { 15static const struct {
16 const int policy; 16 int policy;
17 const char const name[12]; 17 char name[12];
18} policies[] = { 18} policies[] = {
19 {SCHED_OTHER, "SCHED_OTHER"}, 19 {SCHED_OTHER, "SCHED_OTHER"},
20 {SCHED_FIFO, "SCHED_FIFO"}, 20 {SCHED_FIFO, "SCHED_FIFO"},
@@ -42,83 +42,83 @@ static void show_min_max(int pol)
42#define OPT_o (1<<4) 42#define OPT_o (1<<4)
43 43
44int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 44int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
45int chrt_main(int argc, char **argv) 45int chrt_main(int argc ATTRIBUTE_UNUSED, char **argv)
46{ 46{
47 pid_t pid = 0; 47 pid_t pid = 0;
48 unsigned opt; 48 unsigned opt;
49 struct sched_param sp; 49 struct sched_param sp;
50 char *p_opt = NULL, *priority = NULL; 50 char *pid_str;
51 const char *state = "current\0new"; 51 char *priority = priority; /* for compiler */
52 int prio = 0, policy = SCHED_RR; 52 const char *current_new;
53 int policy = SCHED_RR;
53 54
54 opt_complementary = "r--fo:f--ro:r--fo"; /* only one policy accepted */ 55 /* at least 1 arg; only one policy accepted */
55 opt = getopt32(argv, "+mp:rfo", &p_opt); 56 opt_complementary = "-1:r--fo:f--ro:r--fo";
57 opt = getopt32(argv, "+mprfo");
56 if (opt & OPT_r) 58 if (opt & OPT_r)
57 policy = SCHED_RR; 59 policy = SCHED_RR;
58 if (opt & OPT_f) 60 if (opt & OPT_f)
59 policy = SCHED_FIFO; 61 policy = SCHED_FIFO;
60 if (opt & OPT_o) 62 if (opt & OPT_o)
61 policy = SCHED_OTHER; 63 policy = SCHED_OTHER;
62
63 if (opt & OPT_m) { /* print min/max */ 64 if (opt & OPT_m) { /* print min/max */
64 show_min_max(SCHED_FIFO); 65 show_min_max(SCHED_FIFO);
65 show_min_max(SCHED_RR); 66 show_min_max(SCHED_RR);
66 show_min_max(SCHED_OTHER); 67 show_min_max(SCHED_OTHER);
67 fflush_stdout_and_exit(EXIT_SUCCESS); 68 fflush_stdout_and_exit(EXIT_SUCCESS);
68 } 69 }
70
71 argv += optind;
69 if (opt & OPT_p) { 72 if (opt & OPT_p) {
70 if (argc == optind+1) { /* -p <priority> <pid> */ 73 pid_str = *argv++;
71 priority = p_opt; 74 if (*argv) { /* "-p <priority> <pid> [...]" */
72 p_opt = argv[optind]; 75 priority = pid_str;
76 pid_str = *argv;
73 } 77 }
74 argv += optind; /* me -p <arg> */ 78 /* else "-p <pid>", and *argv == NULL */
75 pid = xatoul_range(p_opt, 1, ULONG_MAX); /* -p <pid> */ 79 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
76 } else { 80 } else {
77 argv += optind; /* me -p <arg> */ 81 priority = *argv++;
78 priority = *argv; 82 if (!*argv)
79 } 83 bb_show_usage();
80 if (priority) {
81 /* from the manpage of sched_getscheduler:
82 [...] sched_priority can have a value
83 in the range 0 to 99.
84 [...] SCHED_OTHER or SCHED_BATCH must be assigned
85 the static priority 0. [...] SCHED_FIFO or
86 SCHED_RR can have a static priority in the range 1 to 99.
87 */
88 prio = xstrtol_range(priority, 0, policy == SCHED_OTHER
89 ? 0 : 1, 99);
90 } 84 }
91 85
86 current_new = "current\0new";
92 if (opt & OPT_p) { 87 if (opt & OPT_p) {
93 int pol = 0; 88 int pol;
94print_rt_info: 89 print_rt_info:
95 pol = sched_getscheduler(pid); 90 pol = sched_getscheduler(pid);
96 if (pol < 0) 91 if (pol < 0)
97 bb_perror_msg_and_die("failed to %cet pid %d's policy", 'g', pid); 92 bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', pid);
98 printf("pid %d's %s scheduling policy: %s\n", 93 printf("pid %d's %s scheduling policy: %s\n",
99 pid, state, policies[pol].name); 94 pid, current_new, policies[pol].name);
100 if (sched_getparam(pid, &sp)) 95 if (sched_getparam(pid, &sp))
101 bb_perror_msg_and_die("failed to get pid %d's attributes", pid); 96 bb_perror_msg_and_die("can't get pid %d's attributes", pid);
102 printf("pid %d's %s scheduling priority: %d\n", 97 printf("pid %d's %s scheduling priority: %d\n",
103 pid, state, sp.sched_priority); 98 pid, current_new, sp.sched_priority);
104 if (!*argv) /* no new prio given or we did print already, done. */ 99 if (!*argv) {
100 /* Either it was just "-p <pid>",
101 * or it was "-p <priority> <pid>" and we came here
102 * for the second time (see goto below) */
105 return EXIT_SUCCESS; 103 return EXIT_SUCCESS;
104 }
105 *argv = NULL;
106 current_new += 8;
106 } 107 }
107 108
108 sp.sched_priority = prio; 109 /* from the manpage of sched_getscheduler:
110 [...] sched_priority can have a value in the range 0 to 99.
111 [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0.
112 [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range.
113 */
114 sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99);
115
109 if (sched_setscheduler(pid, policy, &sp) < 0) 116 if (sched_setscheduler(pid, policy, &sp) < 0)
110 bb_perror_msg_and_die("failed to %cet pid %d's policy", 's', pid); 117 bb_perror_msg_and_die("can't %cet pid %d's policy", 's', pid);
111 if (opt & OPT_p) { 118
112 state += 8; 119 if (!*argv) /* "-p <priority> <pid> [...]" */
113 ++argv;
114 goto print_rt_info; 120 goto print_rt_info;
115 } 121
116 ++argv;
117 BB_EXECVP(*argv, argv); 122 BB_EXECVP(*argv, argv);
118 bb_simple_perror_msg_and_die(*argv); 123 bb_simple_perror_msg_and_die(*argv);
119} 124}
120#undef OPT_p
121#undef OPT_r
122#undef OPT_f
123#undef OPT_o
124#undef OPT_m
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 75555c874..fcfc120f0 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -158,7 +158,7 @@ static void crondlog(const char *ctl, ...)
158} 158}
159 159
160int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 160int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
161int crond_main(int ac ATTRIBUTE_UNUSED, char **av) 161int crond_main(int argc ATTRIBUTE_UNUSED, char **argv)
162{ 162{
163 unsigned opt; 163 unsigned opt;
164 164
@@ -167,7 +167,7 @@ int crond_main(int ac ATTRIBUTE_UNUSED, char **av)
167 /* "-b after -f is ignored", and so on for every pair a-b */ 167 /* "-b after -f is ignored", and so on for every pair a-b */
168 opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l") 168 opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l")
169 ":l+:d+"; /* -l and -d have numeric param */ 169 ":l+:d+"; /* -l and -d have numeric param */
170 opt = getopt32(av, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"), 170 opt = getopt32(argv, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"),
171 &LogLevel, &LogFile, &CDir 171 &LogLevel, &LogFile, &CDir
172 USE_DEBUG_CROND_OPTION(,&LogLevel)); 172 USE_DEBUG_CROND_OPTION(,&LogLevel));
173 /* both -d N and -l N set the same variable: LogLevel */ 173 /* both -d N and -l N set the same variable: LogLevel */
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index 94d69f032..dc3179dac 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -18,9 +18,6 @@
18#ifndef CRONUPDATE 18#ifndef CRONUPDATE
19#define CRONUPDATE "cron.update" 19#define CRONUPDATE "cron.update"
20#endif 20#endif
21#ifndef PATH_VI
22#define PATH_VI "/bin/vi" /* location of vi */
23#endif
24 21
25static void change_user(const struct passwd *pas) 22static void change_user(const struct passwd *pas)
26{ 23{
@@ -56,7 +53,7 @@ static void edit_file(const struct passwd *pas, const char *file)
56 if (!ptr) { 53 if (!ptr) {
57 ptr = getenv("EDITOR"); 54 ptr = getenv("EDITOR");
58 if (!ptr) 55 if (!ptr)
59 ptr = PATH_VI; 56 ptr = "vi";
60 } 57 }
61 58
62 BB_EXECLP(ptr, ptr, file, NULL); 59 BB_EXECLP(ptr, ptr, file, NULL);
@@ -181,14 +178,16 @@ int crontab_main(int argc ATTRIBUTE_UNUSED, char **argv)
181 178
182 case OPT_e: /* Edit */ 179 case OPT_e: /* Edit */
183 tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid()); 180 tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid());
184 fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600); 181 /* No O_EXCL: we don't want to be stuck if earlier crontabs
182 * were killed, leaving stale temp file behind */
183 fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600);
185 xmove_fd(fd, STDIN_FILENO); 184 xmove_fd(fd, STDIN_FILENO);
185 fchown(STDIN_FILENO, pas->pw_uid, pas->pw_gid);
186 fd = open(pas->pw_name, O_RDONLY); 186 fd = open(pas->pw_name, O_RDONLY);
187 if (fd >= 0) { 187 if (fd >= 0) {
188 bb_copyfd_eof(fd, STDIN_FILENO); 188 bb_copyfd_eof(fd, STDIN_FILENO);
189 close(fd); 189 close(fd);
190 } 190 }
191 fchown(STDIN_FILENO, pas->pw_uid, pas->pw_gid);
192 edit_file(pas, tmp_fname); 191 edit_file(pas, tmp_fname);
193 xlseek(STDIN_FILENO, 0, SEEK_SET); 192 xlseek(STDIN_FILENO, 0, SEEK_SET);
194 /* fall through */ 193 /* fall through */
diff --git a/miscutils/dc.c b/miscutils/dc.c
index ffc3f8df4..68ecd8a3f 100644
--- a/miscutils/dc.c
+++ b/miscutils/dc.c
@@ -8,11 +8,18 @@
8 8
9/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ 9/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
10 10
11enum { STACK_SIZE = COMMON_BUFSIZE / sizeof(double) };
12 11
13#define stack ((double*)&bb_common_bufsiz1) 12struct globals {
14static unsigned int pointer; 13 unsigned pointer;
15static unsigned char base; 14 unsigned base;
15 double stack[1];
16};
17enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) };
18#define G (*(struct globals*)&bb_common_bufsiz1)
19#define pointer (G.pointer )
20#define base (G.base )
21#define stack (G.stack )
22
16 23
17static void push(double a) 24static void push(double a)
18{ 25{
@@ -61,34 +68,34 @@ static void divide(void)
61 68
62static void mod(void) 69static void mod(void)
63{ 70{
64 unsigned int d = pop(); 71 unsigned d = pop();
65 72
66 push((unsigned int) pop() % d); 73 push((unsigned) pop() % d);
67} 74}
68 75
69static void and(void) 76static void and(void)
70{ 77{
71 push((unsigned int) pop() & (unsigned int) pop()); 78 push((unsigned) pop() & (unsigned) pop());
72} 79}
73 80
74static void or(void) 81static void or(void)
75{ 82{
76 push((unsigned int) pop() | (unsigned int) pop()); 83 push((unsigned) pop() | (unsigned) pop());
77} 84}
78 85
79static void eor(void) 86static void eor(void)
80{ 87{
81 push((unsigned int) pop() ^ (unsigned int) pop()); 88 push((unsigned) pop() ^ (unsigned) pop());
82} 89}
83 90
84static void not(void) 91static void not(void)
85{ 92{
86 push(~(unsigned int) pop()); 93 push(~(unsigned) pop());
87} 94}
88 95
89static void set_output_base(void) 96static void set_output_base(void)
90{ 97{
91 base = (unsigned char)pop(); 98 base = (unsigned)pop();
92 if ((base != 10) && (base != 16)) { 99 if ((base != 10) && (base != 16)) {
93 bb_error_msg("error, base %d is not supported", base); 100 bb_error_msg("error, base %d is not supported", base);
94 base = 10; 101 base = 10;
@@ -98,14 +105,14 @@ static void set_output_base(void)
98static void print_base(double print) 105static void print_base(double print)
99{ 106{
100 if (base == 16) 107 if (base == 16)
101 printf("%x\n", (unsigned int)print); 108 printf("%x\n", (unsigned)print);
102 else 109 else
103 printf("%g\n", print); 110 printf("%g\n", print);
104} 111}
105 112
106static void print_stack_no_pop(void) 113static void print_stack_no_pop(void)
107{ 114{
108 unsigned int i = pointer; 115 unsigned i = pointer;
109 while (i) 116 while (i)
110 print_base(stack[--i]); 117 print_base(stack[--i]);
111} 118}
@@ -142,12 +149,12 @@ static const struct op operators[] = {
142 {"p", print_no_pop}, 149 {"p", print_no_pop},
143 {"f", print_stack_no_pop}, 150 {"f", print_stack_no_pop},
144 {"o", set_output_base}, 151 {"o", set_output_base},
145 {"", 0} 152 { /* zero filled */ }
146}; 153};
147 154
148static void stack_machine(const char *argument) 155static void stack_machine(const char *argument)
149{ 156{
150 char *endPointer = 0; 157 char *endPointer;
151 double d; 158 double d;
152 const struct op *o = operators; 159 const struct op *o = operators;
153 160
@@ -176,54 +183,39 @@ static void stack_machine(const char *argument)
176 */ 183 */
177static char *get_token(char **buffer) 184static char *get_token(char **buffer)
178{ 185{
179 char *start = NULL; 186 char *current = skip_whitespace(*buffer);
180 char *current; 187 if (*current != '\0') {
181 188 *buffer = skip_non_whitespace(current);
182 current = skip_whitespace(*buffer); 189 return current;
183 if (*current != 0) {
184 start = current;
185 current = skip_non_whitespace(current);
186 *buffer = current;
187 } 190 }
188 return start; 191 return NULL;
189}
190
191/* In Perl one might say, scalar m|\s*(\S+)\s*|g */
192static int number_of_tokens(char *buffer)
193{
194 int i = 0;
195 char *b = buffer;
196 while (get_token(&b)) { i++; }
197 return i;
198} 192}
199 193
200int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 194int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
201int dc_main(int argc, char **argv) 195int dc_main(int argc ATTRIBUTE_UNUSED, char **argv)
202{ 196{
203 /* take stuff from stdin if no args are given */ 197 argv++;
204 if (argc <= 1) { 198 if (!argv[0]) {
205 int i, len; 199 /* take stuff from stdin if no args are given */
206 char *line = NULL; 200 char *line;
207 char *cursor = NULL; 201 char *cursor;
208 char *token = NULL; 202 char *token;
209 while ((line = xmalloc_getline(stdin))) { 203 while ((line = xmalloc_getline(stdin)) != NULL) {
210 cursor = line; 204 cursor = line;
211 len = number_of_tokens(line); 205 while (1) {
212 for (i = 0; i < len; i++) {
213 token = get_token(&cursor); 206 token = get_token(&cursor);
214 *cursor++ = 0; 207 if (!token) break;
208 *cursor++ = '\0';
215 stack_machine(token); 209 stack_machine(token);
216 } 210 }
217 free(line); 211 free(line);
218 } 212 }
219 } else { 213 } else {
220 if (*argv[1] == '-') 214 if (argv[0][0] == '-')
221 bb_show_usage(); 215 bb_show_usage();
222 while (argc >= 2) { 216 do {
223 stack_machine(argv[1]); 217 stack_machine(*argv);
224 argv++; 218 } while (*++argv);
225 argc--;
226 }
227 } 219 }
228 return EXIT_SUCCESS; 220 return EXIT_SUCCESS;
229} 221}
diff --git a/miscutils/eject.c b/miscutils/eject.c
index 3d27ce545..42e071941 100644
--- a/miscutils/eject.c
+++ b/miscutils/eject.c
@@ -22,68 +22,71 @@
22/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */ 22/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
23#define CDS_TRAY_OPEN 2 23#define CDS_TRAY_OPEN 2
24 24
25#define FLAG_CLOSE 1 25#define dev_fd 3
26#define FLAG_SMART 2
27
28 26
29/* Code taken from the original eject (http://eject.sourceforge.net/), 27/* Code taken from the original eject (http://eject.sourceforge.net/),
30 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */ 28 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */
31#define FLAG_SCSI 4
32 29
33#include <scsi/sg.h> 30#include <scsi/sg.h>
34#include <scsi/scsi.h> 31#include <scsi/scsi.h>
35static void eject_scsi(const int fd, const char * const dev) 32
33static void eject_scsi(const char *dev)
36{ 34{
37 int i; 35 static const char sg_commands[3][6] = {
38 unsigned char sense_buffer[32]; 36 { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
39 unsigned char inqBuff[2]; 37 { START_STOP, 0, 0, 0, 1, 0 },
40 sg_io_hdr_t io_hdr; 38 { START_STOP, 0, 0, 0, 2, 0 }
41 char sg_commands[3][6] = { 39 };
42 {ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0}, 40
43 {START_STOP, 0, 0, 0, 1, 0}, 41 int i;
44 {START_STOP, 0, 0, 0, 2, 0} 42 unsigned char sense_buffer[32];
45 }; 43 unsigned char inqBuff[2];
46 44 sg_io_hdr_t io_hdr;
47 if ((ioctl(fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000)) 45
48 bb_error_msg_and_die("not an sg device or old sg driver"); 46 if ((ioctl(dev_fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000))
49 47 bb_error_msg_and_die("not a sg device or old sg driver");
50 memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 48
51 io_hdr.interface_id = 'S'; 49 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
52 io_hdr.cmd_len = 6; 50 io_hdr.interface_id = 'S';
53 io_hdr.mx_sb_len = sizeof(sense_buffer); 51 io_hdr.cmd_len = 6;
54 io_hdr.dxfer_direction = SG_DXFER_NONE; 52 io_hdr.mx_sb_len = sizeof(sense_buffer);
55 /* io_hdr.dxfer_len = 0; */ 53 io_hdr.dxfer_direction = SG_DXFER_NONE;
56 io_hdr.dxferp = inqBuff; 54 /* io_hdr.dxfer_len = 0; */
57 io_hdr.sbp = sense_buffer; 55 io_hdr.dxferp = inqBuff;
58 io_hdr.timeout = 2000; 56 io_hdr.sbp = sense_buffer;
59 57 io_hdr.timeout = 2000;
60 for (i=0; i < 3; i++) { 58
61 io_hdr.cmdp = sg_commands[i]; 59 for (i = 0; i < 3; i++) {
62 ioctl_or_perror_and_die(fd, SG_IO, (void *)&io_hdr, "%s", dev); 60 io_hdr.cmdp = (char*)sg_commands[i];
63 } 61 ioctl_or_perror_and_die(dev_fd, SG_IO, (void *)&io_hdr, "%s", dev);
64 62 }
65 /* force kernel to reread partition table when new disc inserted */ 63
66 ioctl(fd, BLKRRPART); 64 /* force kernel to reread partition table when new disc is inserted */
65 ioctl(dev_fd, BLKRRPART);
67} 66}
68 67
69static void eject_cdrom(const int fd, const unsigned long flags, 68#define FLAG_CLOSE 1
70 const char * const dev) 69#define FLAG_SMART 2
70#define FLAG_SCSI 4
71
72static void eject_cdrom(unsigned flags, const char *dev)
71{ 73{
72 int cmd = CDROMEJECT; 74 int cmd = CDROMEJECT;
73 75
74 if (flags & FLAG_CLOSE 76 if (flags & FLAG_CLOSE
75 || (flags & FLAG_SMART && ioctl(fd, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN)) 77 || (flags & FLAG_SMART && ioctl(dev_fd, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN)
78 ) {
76 cmd = CDROMCLOSETRAY; 79 cmd = CDROMCLOSETRAY;
80 }
77 81
78 return ioctl_or_perror_and_die(fd, cmd, NULL, "%s", dev); 82 ioctl_or_perror_and_die(dev_fd, cmd, NULL, "%s", dev);
79} 83}
80 84
81int eject_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 85int eject_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
82int eject_main(int argc ATTRIBUTE_UNUSED, char **argv) 86int eject_main(int argc ATTRIBUTE_UNUSED, char **argv)
83{ 87{
84 unsigned long flags; 88 unsigned flags;
85 const char *device; 89 const char *device;
86 int dev;
87 90
88 opt_complementary = "?1:t--T:T--t"; 91 opt_complementary = "?1:t--T:T--t";
89 flags = getopt32(argv, "tT" USE_FEATURE_EJECT_SCSI("s")); 92 flags = getopt32(argv, "tT" USE_FEATURE_EJECT_SCSI("s"));
@@ -96,18 +99,18 @@ int eject_main(int argc ATTRIBUTE_UNUSED, char **argv)
96 This works equally well (or better): 99 This works equally well (or better):
97 #!/bin/sh 100 #!/bin/sh
98 umount /dev/cdrom 101 umount /dev/cdrom
99 eject 102 eject /dev/cdrom
100 */ 103 */
101 104
102 dev = xopen(device, O_RDONLY|O_NONBLOCK); 105 xmove_fd(xopen(device, O_RDONLY|O_NONBLOCK), dev_fd);
103 106
104 if (ENABLE_FEATURE_EJECT_SCSI && (flags & FLAG_SCSI)) 107 if (ENABLE_FEATURE_EJECT_SCSI && (flags & FLAG_SCSI))
105 eject_scsi(dev, device); 108 eject_scsi(device);
106 else 109 else
107 eject_cdrom(dev, flags, device); 110 eject_cdrom(flags, device);
108 111
109 if (ENABLE_FEATURE_CLEAN_UP) 112 if (ENABLE_FEATURE_CLEAN_UP)
110 close(dev); 113 close(dev_fd);
111 114
112 return EXIT_SUCCESS; 115 return EXIT_SUCCESS;
113} 116}
diff --git a/miscutils/last.c b/miscutils/last.c
index f4d9a812e..f46d4ca0c 100644
--- a/miscutils/last.c
+++ b/miscutils/last.c
@@ -14,7 +14,7 @@
14# define SHUTDOWN_TIME 254 14# define SHUTDOWN_TIME 254
15#endif 15#endif
16 16
17/* Grr... utmp char[] members do not have to be nul-terminated. 17/* Grr... utmp char[] members do not have to be nul-terminated.
18 * Do what we can while still keeping this reasonably small. 18 * Do what we can while still keeping this reasonably small.
19 * Note: We are assuming the ut_id[] size is fixed at 4. */ 19 * Note: We are assuming the ut_id[] size is fixed at 4. */
20 20
diff --git a/miscutils/setsid.c b/miscutils/setsid.c
index 110bb6bb6..014de51e5 100644
--- a/miscutils/setsid.c
+++ b/miscutils/setsid.c
@@ -4,7 +4,7 @@
4 * Rick Sladkey <jrs@world.std.com> 4 * Rick Sladkey <jrs@world.std.com>
5 * In the public domain. 5 * In the public domain.
6 * 6 *
7 * 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL> 7 * 1999-02-22 Arkadiusz Mickiewicz <misiek@pld.ORG.PL>
8 * - added Native Language Support 8 * - added Native Language Support
9 * 9 *
10 * 2001-01-18 John Fremlin <vii@penguinpowered.com> 10 * 2001-01-18 John Fremlin <vii@penguinpowered.com>
@@ -17,12 +17,14 @@
17#include "libbb.h" 17#include "libbb.h"
18 18
19int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 19int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
20int setsid_main(int argc, char **argv) 20int setsid_main(int argc ATTRIBUTE_UNUSED, char **argv)
21{ 21{
22 if (argc < 2) 22 if (!argv[1])
23 bb_show_usage(); 23 bb_show_usage();
24 24
25 /* Comment why is this necessary? */ 25 /* setsid() is allowed only when we are not a process group leader.
26 * Otherwise our PID serves as PGID of some existing process group
27 * and cannot be used as PGID of a new process group. */
26 if (getpgrp() == getpid()) 28 if (getpgrp() == getpid())
27 forkexit_or_rexec(argv); 29 forkexit_or_rexec(argv);
28 30
diff --git a/miscutils/taskset.c b/miscutils/taskset.c
index e64fd655b..6247aa869 100644
--- a/miscutils/taskset.c
+++ b/miscutils/taskset.c
@@ -39,61 +39,71 @@ static char *__from_cpuset(cpu_set_t *mask)
39#define from_cpuset(mask) (*(unsigned*)(void*)&(mask)) 39#define from_cpuset(mask) (*(unsigned*)(void*)&(mask))
40#endif 40#endif
41 41
42#define OPT_p 1
43 42
44int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 43int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
45int taskset_main(int argc, char **argv) 44int taskset_main(int argc ATTRIBUTE_UNUSED, char **argv)
46{ 45{
47 cpu_set_t mask, new_mask; 46 cpu_set_t mask;
48 pid_t pid = 0; 47 pid_t pid = 0;
49 unsigned opt; 48 unsigned opt_p;
50 const char *state = "current\0new"; 49 const char *current_new;
51 char *p_opt = NULL, *aff = NULL; 50 char *pid_str;
51 char *aff = aff; /* for compiler */
52 52
53 opt = getopt32(argv, "+p:", &p_opt); 53 opt_complementary = "-1"; /* at least 1 arg */
54 opt_p = getopt32(argv, "+p");
55 argv += optind;
54 56
55 if (opt & OPT_p) { 57 if (opt_p) {
56 if (argc == optind+1) { /* -p <aff> <pid> */ 58 pid_str = *argv++;
57 aff = p_opt; 59 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */
58 p_opt = argv[optind]; 60 aff = pid_str;
59 } 61 pid_str = *argv; /* NB: *argv != NULL in this case */
60 argv += optind; /* me -p <arg> */
61 pid = xatoul_range(p_opt, 1, ULONG_MAX); /* -p <pid> */
62 } else
63 aff = *++argv; /* <aff> <cmd...> */
64 if (aff) {
65 unsigned i = 0;
66 unsigned long l = xstrtol_range(aff, 0, 1, LONG_MAX);
67
68 CPU_ZERO(&new_mask);
69 while (i < CPU_SETSIZE && l >= (1<<i)) {
70 if ((1<<i) & l)
71 CPU_SET(i, &new_mask);
72 ++i;
73 } 62 }
63 /* else it was just "-p <pid>", and *argv == NULL */
64 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
65 } else {
66 aff = *argv++; /* <aff> <cmd...> */
67 if (!*argv)
68 bb_show_usage();
74 } 69 }
75 70
76 if (opt & OPT_p) { 71 current_new = "current\0new";
72 if (opt_p) {
77 print_aff: 73 print_aff:
78 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) 74 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0)
79 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 'g', pid); 75 bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid);
80 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 76 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n",
81 pid, state, from_cpuset(mask)); 77 pid, current_new, from_cpuset(mask));
82 if (!*argv) /* no new affinity given or we did print already, done. */ 78 if (!*argv) {
79 /* Either it was just "-p <pid>",
80 * or it was "-p <aff> <pid>" and we came here
81 * for the second time (see goto below) */
83 return EXIT_SUCCESS; 82 return EXIT_SUCCESS;
83 }
84 *argv = NULL;
85 current_new += 8; /* "new" */
84 } 86 }
85 87
86 if (sched_setaffinity(pid, sizeof(new_mask), &new_mask)) 88 { /* Affinity was specified, translate it into cpu_set_t */
87 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 's', pid); 89 unsigned i;
88 if (opt & OPT_p) { 90 /* Do not allow zero mask: */
89 state += 8; 91 unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
90 ++argv; 92 CPU_ZERO(&mask);
91 goto print_aff; 93 for (i = 0; i < CPU_SETSIZE; i++) {
94 unsigned long long bit = (1ULL << i);
95 if (bit & m)
96 CPU_SET(i, &mask);
97 }
92 } 98 }
93 ++argv; 99
100 /* Set pid's or our own (pid==0) affinity */
101 if (sched_setaffinity(pid, sizeof(mask), &mask))
102 bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid);
103
104 if (!*argv) /* "-p <aff> <pid> [...ignored...]" */
105 goto print_aff; /* print new affinity and exit */
106
94 BB_EXECVP(*argv, argv); 107 BB_EXECVP(*argv, argv);
95 bb_simple_perror_msg_and_die(*argv); 108 bb_simple_perror_msg_and_die(*argv);
96} 109}
97#undef OPT_p
98#undef TASKSET_PRINTF_MASK
99#undef from_cpuset
diff --git a/miscutils/time.c b/miscutils/time.c
index 677ca6d8b..ed4385948 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -1,5 +1,5 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* `time' utility to display resource usage of processes. 2/* 'time' utility to display resource usage of processes.
3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc. 3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
4 4
5 Licensed under GPL version 2, see file LICENSE in this tarball for details. 5 Licensed under GPL version 2, see file LICENSE in this tarball for details.
@@ -28,7 +28,6 @@ static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T";
28/* The output format for the -p option .*/ 28/* The output format for the -p option .*/
29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; 29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S";
30 30
31
32/* Format string for printing all statistics verbosely. 31/* Format string for printing all statistics verbosely.
33 Keep this output to 24 lines so users on terminals can see it all.*/ 32 Keep this output to 24 lines so users on terminals can see it all.*/
34static const char long_format[] ALIGN1 = 33static const char long_format[] ALIGN1 =
@@ -56,35 +55,31 @@ static const char long_format[] ALIGN1 =
56 "\tPage size (bytes): %Z\n" 55 "\tPage size (bytes): %Z\n"
57 "\tExit status: %x"; 56 "\tExit status: %x";
58 57
59
60/* Wait for and fill in data on child process PID. 58/* Wait for and fill in data on child process PID.
61 Return 0 on error, 1 if ok. */ 59 Return 0 on error, 1 if ok. */
62
63/* pid_t is short on BSDI, so don't try to promote it. */ 60/* pid_t is short on BSDI, so don't try to promote it. */
64static int resuse_end(pid_t pid, resource_t *resp) 61static void resuse_end(pid_t pid, resource_t *resp)
65{ 62{
66 int status;
67 pid_t caught; 63 pid_t caught;
68 64
69 /* Ignore signals, but don't ignore the children. When wait3 65 /* Ignore signals, but don't ignore the children. When wait3
70 returns the child process, set the time the command finished. */ 66 returns the child process, set the time the command finished. */
71 while ((caught = wait3(&status, 0, &resp->ru)) != pid) { 67 while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) {
72 if (caught == -1 && errno != EINTR) 68 if (caught == -1 && errno != EINTR) {
73 return 0; 69 bb_perror_msg("wait");
70 return;
71 }
74 } 72 }
75 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms; 73 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
76 resp->waitstatus = status;
77 return 1;
78} 74}
79 75
80/* Print ARGV, with each entry in ARGV separated by FILLER. */ 76static void printargv(char *const *argv)
81static void printargv(char *const *argv, const char *filler)
82{ 77{
83 fputs(*argv, stdout); 78 const char *fmt = " %s" + 1;
84 while (*++argv) { 79 do {
85 fputs(filler, stdout); 80 printf(fmt, *argv);
86 fputs(*argv, stdout); 81 fmt = " %s";
87 } 82 } while (*++argv);
88} 83}
89 84
90/* Return the number of kilobytes corresponding to a number of pages PAGES. 85/* Return the number of kilobytes corresponding to a number of pages PAGES.
@@ -94,24 +89,18 @@ static void printargv(char *const *argv, const char *filler)
94 This is funky since the pagesize could be less than 1K. 89 This is funky since the pagesize could be less than 1K.
95 Note: Some machines express getrusage statistics in terms of K, 90 Note: Some machines express getrusage statistics in terms of K,
96 others in terms of pages. */ 91 others in terms of pages. */
97 92static unsigned long ptok(unsigned pagesize, unsigned long pages)
98static unsigned long ptok(unsigned long pages)
99{ 93{
100 static unsigned long ps;
101 unsigned long tmp; 94 unsigned long tmp;
102 95
103 /* Initialization. */
104 if (ps == 0)
105 ps = getpagesize();
106
107 /* Conversion. */ 96 /* Conversion. */
108 if (pages > (LONG_MAX / ps)) { /* Could overflow. */ 97 if (pages > (LONG_MAX / pagesize)) { /* Could overflow. */
109 tmp = pages / 1024; /* Smaller first, */ 98 tmp = pages / 1024; /* Smaller first, */
110 return tmp * ps; /* then larger. */ 99 return tmp * pagesize; /* then larger. */
111 } 100 }
112 /* Could underflow. */ 101 /* Could underflow. */
113 tmp = pages * ps; /* Larger first, */ 102 tmp = pages * pagesize; /* Larger first, */
114 return tmp / 1024; /* then smaller. */ 103 return tmp / 1024; /* then smaller. */
115} 104}
116 105
117/* summarize: Report on the system use of a command. 106/* summarize: Report on the system use of a command.
@@ -162,15 +151,18 @@ static unsigned long ptok(unsigned long pages)
162#define TICKS_PER_SEC 100 151#define TICKS_PER_SEC 100
163#endif 152#endif
164 153
165static void summarize(const char *fmt, char **command, resource_t * resp) 154static void summarize(const char *fmt, char **command, resource_t *resp)
166{ 155{
167 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ 156 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */
168 unsigned cpu_ticks; /* Same, in "CPU ticks" */ 157 unsigned cpu_ticks; /* Same, in "CPU ticks" */
158 unsigned pagesize = getpagesize();
169 159
160 /* Impossible: we do not use WUNTRACED flag in wait()...
170 if (WIFSTOPPED(resp->waitstatus)) 161 if (WIFSTOPPED(resp->waitstatus))
171 printf("Command stopped by signal %u\n", 162 printf("Command stopped by signal %u\n",
172 WSTOPSIG(resp->waitstatus)); 163 WSTOPSIG(resp->waitstatus));
173 else if (WIFSIGNALED(resp->waitstatus)) 164 else */
165 if (WIFSIGNALED(resp->waitstatus))
174 printf("Command terminated by signal %u\n", 166 printf("Command terminated by signal %u\n",
175 WTERMSIG(resp->waitstatus)); 167 WTERMSIG(resp->waitstatus));
176 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) 168 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
@@ -181,7 +173,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
181 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; 173 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
182 174
183#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 175#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
184 /* 1000 is exactly divisible by TICKS_PER_SEC */ 176 /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */
185 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); 177 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
186#else 178#else
187 cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; 179 cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000;
@@ -221,12 +213,12 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
221 break; 213 break;
222#endif 214#endif
223 case 'C': /* The command that got timed. */ 215 case 'C': /* The command that got timed. */
224 printargv(command, " "); 216 printargv(command);
225 break; 217 break;
226 case 'D': /* Average unshared data size. */ 218 case 'D': /* Average unshared data size. */
227 printf("%lu", 219 printf("%lu",
228 ptok((UL) resp->ru.ru_idrss) / cpu_ticks + 220 (ptok(pagesize, (UL) resp->ru.ru_idrss) +
229 ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 221 ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks);
230 break; 222 break;
231 case 'E': { /* Elapsed real (wall clock) time. */ 223 case 'E': { /* Elapsed real (wall clock) time. */
232 unsigned seconds = resp->elapsed_ms / 1000; 224 unsigned seconds = resp->elapsed_ms / 1000;
@@ -250,12 +242,12 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
250 break; 242 break;
251 case 'K': /* Average mem usage == data+stack+text. */ 243 case 'K': /* Average mem usage == data+stack+text. */
252 printf("%lu", 244 printf("%lu",
253 ptok((UL) resp->ru.ru_idrss) / cpu_ticks + 245 (ptok(pagesize, (UL) resp->ru.ru_idrss) +
254 ptok((UL) resp->ru.ru_isrss) / cpu_ticks + 246 ptok(pagesize, (UL) resp->ru.ru_isrss) +
255 ptok((UL) resp->ru.ru_ixrss) / cpu_ticks); 247 ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks);
256 break; 248 break;
257 case 'M': /* Maximum resident set size. */ 249 case 'M': /* Maximum resident set size. */
258 printf("%lu", ptok((UL) resp->ru.ru_maxrss)); 250 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss));
259 break; 251 break;
260 case 'O': /* Outputs. */ 252 case 'O': /* Outputs. */
261 printf("%lu", resp->ru.ru_oublock); 253 printf("%lu", resp->ru.ru_oublock);
@@ -308,7 +300,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
308 printf("%lu", resp->ru.ru_nswap); 300 printf("%lu", resp->ru.ru_nswap);
309 break; 301 break;
310 case 'X': /* Average shared text size. */ 302 case 'X': /* Average shared text size. */
311 printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks); 303 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks);
312 break; 304 break;
313 case 'Z': /* Page size. */ 305 case 'Z': /* Page size. */
314 printf("%u", getpagesize()); 306 printf("%u", getpagesize());
@@ -325,7 +317,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
325 printf("%lu", resp->ru.ru_nsignals); 317 printf("%lu", resp->ru.ru_nsignals);
326 break; 318 break;
327 case 'p': /* Average stack segment. */ 319 case 'p': /* Average stack segment. */
328 printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 320 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks);
329 break; 321 break;
330 case 'r': /* Incoming socket messages received. */ 322 case 'r': /* Incoming socket messages received. */
331 printf("%lu", resp->ru.ru_msgrcv); 323 printf("%lu", resp->ru.ru_msgrcv);
@@ -334,7 +326,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
334 printf("%lu", resp->ru.ru_msgsnd); 326 printf("%lu", resp->ru.ru_msgsnd);
335 break; 327 break;
336 case 't': /* Average resident set size. */ 328 case 't': /* Average resident set size. */
337 printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks); 329 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks);
338 break; 330 break;
339 case 'w': /* Voluntary context switches. */ 331 case 'w': /* Voluntary context switches. */
340 printf("%lu", resp->ru.ru_nvcsw); 332 printf("%lu", resp->ru.ru_nvcsw);
@@ -396,8 +388,7 @@ static void run_command(char *const *cmd, resource_t *resp)
396 interrupt_signal = signal(SIGINT, SIG_IGN); 388 interrupt_signal = signal(SIGINT, SIG_IGN);
397 quit_signal = signal(SIGQUIT, SIG_IGN); 389 quit_signal = signal(SIGQUIT, SIG_IGN);
398 390
399 if (resuse_end(pid, resp) == 0) 391 resuse_end(pid, resp);
400 bb_error_msg("error waiting for child process");
401 392
402 /* Re-enable signals. */ 393 /* Re-enable signals. */
403 signal(SIGINT, interrupt_signal); 394 signal(SIGINT, interrupt_signal);
@@ -405,41 +396,26 @@ static void run_command(char *const *cmd, resource_t *resp)
405} 396}
406 397
407int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 398int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
408int time_main(int argc, char **argv) 399int time_main(int argc ATTRIBUTE_UNUSED, char **argv)
409{ 400{
410 resource_t res; 401 resource_t res;
411 const char *output_format = default_format; 402 const char *output_format = default_format;
412 char c; 403 int opt;
413 404
414 goto next; 405 /* "+": stop on first non-option */
415 /* Parse any options -- don't use getopt() here so we don't 406 opt = getopt32(argv, "+vp");
416 * consume the args of our client application... */ 407 argv += optind;
417 while (argc > 0 && argv[0][0] == '-') { 408 if (opt & 1)
418 while ((c = *++*argv)) { 409 output_format = long_format;
419 switch (c) { 410 if (opt & 2)
420 case 'v': 411 output_format = posix_format;
421 output_format = long_format;
422 break;
423 case 'p':
424 output_format = posix_format;
425 break;
426 default:
427 bb_show_usage();
428 }
429 }
430 next:
431 argv++;
432 argc--;
433 if (!argc)
434 bb_show_usage();
435 }
436 412
437 run_command(argv, &res); 413 run_command(argv, &res);
438 414
439 /* Cheat. printf's are shorter :) */ 415 /* Cheat. printf's are shorter :) */
440 /* (but see bb_putchar() body for additional wrinkle!) */ 416 /* (but see bb_putchar() body for additional wrinkle!) */
417 xdup2(2, 1); /* just in case libc does something silly :( */
441 stdout = stderr; 418 stdout = stderr;
442 dup2(2, 1); /* just in case libc does something silly :( */
443 summarize(output_format, argv, &res); 419 summarize(output_format, argv, &res);
444 420
445 if (WIFSTOPPED(res.waitstatus)) 421 if (WIFSTOPPED(res.waitstatus))
diff --git a/miscutils/ttysize.c b/miscutils/ttysize.c
index f51b328ea..05455543d 100644
--- a/miscutils/ttysize.c
+++ b/miscutils/ttysize.c
@@ -14,7 +14,7 @@
14int ttysize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 14int ttysize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
15int ttysize_main(int argc, char **argv) 15int ttysize_main(int argc, char **argv)
16{ 16{
17 unsigned w,h; 17 unsigned w, h;
18 struct winsize wsz; 18 struct winsize wsz;
19 19
20 w = 80; 20 w = 80;
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 28bd35813..7fb16b861 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -13,8 +13,7 @@
13#define OPT_FOREGROUND 0x01 13#define OPT_FOREGROUND 0x01
14#define OPT_TIMER 0x02 14#define OPT_TIMER 0x02
15 15
16static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) ATTRIBUTE_NORETURN; 16static void watchdog_shutdown(int sig ATTRIBUTE_UNUSED)
17static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig)
18{ 17{
19 static const char V = 'V'; 18 static const char V = 'V';
20 19
@@ -47,14 +46,19 @@ int watchdog_main(int argc, char **argv)
47 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 46 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
48 } 47 }
49 48
50 bb_signals(0 49 bb_signals(BB_SIGS_FATAL, watchdog_shutdown);
51 + (1 << SIGHUP)
52 + (1 << SIGINT)
53 , watchdog_shutdown);
54 50
55 /* Use known fd # - avoid needing global 'int fd' */ 51 /* Use known fd # - avoid needing global 'int fd' */
56 xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3); 52 xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
57 53
54// TODO?
55// if (!(opts & OPT_TIMER)) {
56// if (ioctl(fd, WDIOC_GETTIMEOUT, &timer_duration) == 0)
57// timer_duration *= 500;
58// else
59// timer_duration = 30000;
60// }
61
58 while (1) { 62 while (1) {
59 /* 63 /*
60 * Make sure we clear the counter before sleeping, as the counter value 64 * Make sure we clear the counter before sleeping, as the counter value