aboutsummaryrefslogtreecommitdiff
path: root/util-linux
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-08-22 14:56:12 +0100
committerRon Yorston <rmy@pobox.com>2017-08-22 14:56:12 +0100
commitce9af1cc5ea23f754587448cf35b5120c77bfeef (patch)
tree69e5eaba5e75ab909ed92d5045393471b8ff3c13 /util-linux
parentc170026700eabb10147dd848c45c06995b43a32e (diff)
parente837a0dbbebf4229306df98fe9ee3b9bb30630c4 (diff)
downloadbusybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.gz
busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.bz2
busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'util-linux')
-rw-r--r--util-linux/acpid.c8
-rw-r--r--util-linux/blkdiscard.c7
-rw-r--r--util-linux/blkid.c4
-rw-r--r--util-linux/blockdev.c2
-rw-r--r--util-linux/cal.c2
-rw-r--r--util-linux/chrt.c5
-rw-r--r--util-linux/eject.c5
-rw-r--r--util-linux/fallocate.c3
-rw-r--r--util-linux/fatattr.c2
-rw-r--r--util-linux/fdformat.c3
-rw-r--r--util-linux/fdisk.c4
-rw-r--r--util-linux/fdisk_osf.c2
-rw-r--r--util-linux/flock.c6
-rw-r--r--util-linux/freeramdisk.c14
-rw-r--r--util-linux/fsck_minix.c12
-rw-r--r--util-linux/fsfreeze.c14
-rw-r--r--util-linux/fstrim.c10
-rw-r--r--util-linux/getopt.c24
-rw-r--r--util-linux/hexdump_xxd.c5
-rw-r--r--util-linux/hwclock.c33
-rw-r--r--util-linux/ionice.c2
-rw-r--r--util-linux/ipcrm.c42
-rw-r--r--util-linux/ipcs.c42
-rw-r--r--util-linux/losetup.c7
-rw-r--r--util-linux/lspci.c2
-rw-r--r--util-linux/lsusb.c2
-rw-r--r--util-linux/mesg.c9
-rw-r--r--util-linux/mkfs_minix.c11
-rw-r--r--util-linux/mkfs_reiser.c3
-rw-r--r--util-linux/mkfs_vfat.c5
-rw-r--r--util-linux/mkswap.c3
-rw-r--r--util-linux/mount.c13
-rw-r--r--util-linux/mountpoint.c5
-rw-r--r--util-linux/nsenter.c35
-rw-r--r--util-linux/pivot_root.c6
-rw-r--r--util-linux/rdate.c3
-rw-r--r--util-linux/rdev.c2
-rw-r--r--util-linux/readprofile.c6
-rw-r--r--util-linux/renice.c2
-rw-r--r--util-linux/rtcwake.c8
-rw-r--r--util-linux/script.c54
-rw-r--r--util-linux/scriptreplay.c3
-rw-r--r--util-linux/setarch.c8
-rw-r--r--util-linux/setpriv.c152
-rw-r--r--util-linux/setsid.c4
-rw-r--r--util-linux/switch_root.c177
-rw-r--r--util-linux/taskset.c5
-rw-r--r--util-linux/uevent.c5
-rw-r--r--util-linux/umount.c15
-rw-r--r--util-linux/unshare.c22
50 files changed, 419 insertions, 399 deletions
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
index 3c3811752..4f491fa14 100644
--- a/util-linux/acpid.c
+++ b/util-linux/acpid.c
@@ -264,8 +264,12 @@ int acpid_main(int argc UNUSED_PARAM, char **argv)
264 264
265 INIT_G(); 265 INIT_G();
266 266
267 opt_complementary = "df:e--e"; 267 opts = getopt32(argv, "^"
268 opts = getopt32(argv, "c:de:fl:a:M:" IF_FEATURE_PIDFILE("p:") IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), 268 "c:de:fl:a:M:"
269 IF_FEATURE_PIDFILE("p:")
270 IF_FEATURE_ACPID_COMPAT("g:m:s:S:v")
271 "\0"
272 "df:e--e",
269 &opt_dir, &opt_input, &opt_logfile, &opt_action, &opt_map 273 &opt_dir, &opt_input, &opt_logfile, &opt_action, &opt_map
270 IF_FEATURE_PIDFILE(, &opt_pidfile) 274 IF_FEATURE_PIDFILE(, &opt_pidfile)
271 IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) 275 IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL)
diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c
index 8f6a4ab6c..5863f0aab 100644
--- a/util-linux/blkdiscard.c
+++ b/util-linux/blkdiscard.c
@@ -11,8 +11,9 @@
11//config: help 11//config: help
12//config: blkdiscard discards sectors on a given device. 12//config: blkdiscard discards sectors on a given device.
13 13
14//applet:IF_BLKDISCARD(APPLET_NOEXEC(blkdiscard, blkdiscard, BB_DIR_USR_BIN, BB_SUID_DROP, blkdiscard))
15
14//kbuild:lib-$(CONFIG_BLKDISCARD) += blkdiscard.o 16//kbuild:lib-$(CONFIG_BLKDISCARD) += blkdiscard.o
15//applet:IF_BLKDISCARD(APPLET(blkdiscard, BB_DIR_USR_BIN, BB_SUID_DROP))
16 17
17//usage:#define blkdiscard_trivial_usage 18//usage:#define blkdiscard_trivial_usage
18//usage: "[-o OFS] [-l LEN] [-s] DEVICE" 19//usage: "[-o OFS] [-l LEN] [-s] DEVICE"
@@ -44,7 +45,6 @@ int blkdiscard_main(int argc UNUSED_PARAM, char **argv)
44 uint64_t offset; /* Leaving these two variables out does not */ 45 uint64_t offset; /* Leaving these two variables out does not */
45 uint64_t length; /* shrink code size and hampers readability. */ 46 uint64_t length; /* shrink code size and hampers readability. */
46 uint64_t range[2]; 47 uint64_t range[2];
47// struct stat st;
48 int fd; 48 int fd;
49 49
50 enum { 50 enum {
@@ -53,8 +53,7 @@ int blkdiscard_main(int argc UNUSED_PARAM, char **argv)
53 OPT_SECURE = (1 << 2), 53 OPT_SECURE = (1 << 2),
54 }; 54 };
55 55
56 opt_complementary = "=1"; 56 opts = getopt32(argv, "^" "o:l:s" "\0" "=1", &offset_str, &length_str);
57 opts = getopt32(argv, "o:l:s", &offset_str, &length_str);
58 argv += optind; 57 argv += optind;
59 58
60 fd = xopen(argv[0], O_RDWR|O_EXCL); 59 fd = xopen(argv[0], O_RDWR|O_EXCL);
diff --git a/util-linux/blkid.c b/util-linux/blkid.c
index 0bd701aae..a56b69661 100644
--- a/util-linux/blkid.c
+++ b/util-linux/blkid.c
@@ -16,12 +16,12 @@
16//config: 16//config:
17//config:config FEATURE_BLKID_TYPE 17//config:config FEATURE_BLKID_TYPE
18//config: bool "Print filesystem type" 18//config: bool "Print filesystem type"
19//config: default n 19//config: default y
20//config: depends on BLKID 20//config: depends on BLKID
21//config: help 21//config: help
22//config: Show TYPE="filesystem type" 22//config: Show TYPE="filesystem type"
23 23
24//applet:IF_BLKID(APPLET(blkid, BB_DIR_SBIN, BB_SUID_DROP)) 24//applet:IF_BLKID(APPLET_NOEXEC(blkid, blkid, BB_DIR_SBIN, BB_SUID_DROP, blkid))
25 25
26//kbuild:lib-$(CONFIG_BLKID) += blkid.o 26//kbuild:lib-$(CONFIG_BLKID) += blkid.o
27 27
diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c
index 9e1fef206..e53ade995 100644
--- a/util-linux/blockdev.c
+++ b/util-linux/blockdev.c
@@ -11,7 +11,7 @@
11//config: help 11//config: help
12//config: Performs some ioctls with block devices. 12//config: Performs some ioctls with block devices.
13 13
14//applet:IF_BLOCKDEV(APPLET(blockdev, BB_DIR_SBIN, BB_SUID_DROP)) 14//applet:IF_BLOCKDEV(APPLET_NOEXEC(blockdev, blockdev, BB_DIR_SBIN, BB_SUID_DROP, blockdev))
15 15
16//kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o 16//kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o
17 17
diff --git a/util-linux/cal.c b/util-linux/cal.c
index 091fdbd2b..10df0ae8b 100644
--- a/util-linux/cal.c
+++ b/util-linux/cal.c
@@ -376,7 +376,7 @@ static char *build_row(char *p, unsigned *dp)
376 * may be used to endorse or promote products derived from this software 376 * may be used to endorse or promote products derived from this software
377 * without specific prior written permission. 377 * without specific prior written permission.
378 * 378 *
379 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 379 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
380 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 380 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
381 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 381 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
382 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 382 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
diff --git a/util-linux/chrt.c b/util-linux/chrt.c
index 4bc8b6cfa..2712ea3e3 100644
--- a/util-linux/chrt.c
+++ b/util-linux/chrt.c
@@ -12,7 +12,7 @@
12//config: manipulate real-time attributes of a process. 12//config: manipulate real-time attributes of a process.
13//config: This requires sched_{g,s}etparam support in your libc. 13//config: This requires sched_{g,s}etparam support in your libc.
14 14
15//applet:IF_CHRT(APPLET(chrt, BB_DIR_USR_BIN, BB_SUID_DROP)) 15//applet:IF_CHRT(APPLET_NOEXEC(chrt, chrt, BB_DIR_USR_BIN, BB_SUID_DROP, chrt))
16 16
17//kbuild:lib-$(CONFIG_CHRT) += chrt.o 17//kbuild:lib-$(CONFIG_CHRT) += chrt.o
18 18
@@ -77,8 +77,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv)
77 int policy = SCHED_RR; 77 int policy = SCHED_RR;
78 78
79 /* only one policy accepted */ 79 /* only one policy accepted */
80 opt_complementary = "r--fo:f--ro:o--rf"; 80 opt = getopt32(argv, "^+" "mprfo" "\0" "r--fo:f--ro:o--rf");
81 opt = getopt32(argv, "+mprfo");
82 if (opt & OPT_m) { /* print min/max and exit */ 81 if (opt & OPT_m) { /* print min/max and exit */
83 show_min_max(SCHED_FIFO); 82 show_min_max(SCHED_FIFO);
84 show_min_max(SCHED_RR); 83 show_min_max(SCHED_RR);
diff --git a/util-linux/eject.c b/util-linux/eject.c
index 8095cbef0..6c30facd2 100644
--- a/util-linux/eject.c
+++ b/util-linux/eject.c
@@ -124,8 +124,9 @@ int eject_main(int argc UNUSED_PARAM, char **argv)
124 unsigned flags; 124 unsigned flags;
125 const char *device; 125 const char *device;
126 126
127 opt_complementary = "?1:t--T:T--t"; 127 flags = getopt32(argv, "^" "tT"IF_FEATURE_EJECT_SCSI("s")
128 flags = getopt32(argv, "tT" IF_FEATURE_EJECT_SCSI("s")); 128 "\0" "?1:t--T:T--t"
129 );
129 device = argv[optind] ? argv[optind] : "/dev/cdrom"; 130 device = argv[optind] ? argv[optind] : "/dev/cdrom";
130 131
131 /* We used to do "umount <device>" here, but it was buggy 132 /* We used to do "umount <device>" here, but it was buggy
diff --git a/util-linux/fallocate.c b/util-linux/fallocate.c
index 70e7e178f..1a02a322f 100644
--- a/util-linux/fallocate.c
+++ b/util-linux/fallocate.c
@@ -82,8 +82,7 @@ int fallocate_main(int argc UNUSED_PARAM, char **argv)
82 int fd; 82 int fd;
83 83
84 /* exactly one non-option arg */ 84 /* exactly one non-option arg */
85 opt_complementary = "=1"; 85 opts = getopt32(argv, "^" "l:o:" "\0" "=1", &str_l, &str_o);
86 opts = getopt32(argv, "l:o:", &str_l, &str_o);
87 if (!(opts & 1)) 86 if (!(opts & 1))
88 bb_show_usage(); 87 bb_show_usage();
89 88
diff --git a/util-linux/fatattr.c b/util-linux/fatattr.c
index 9fb566d5a..770b1d2f9 100644
--- a/util-linux/fatattr.c
+++ b/util-linux/fatattr.c
@@ -15,7 +15,7 @@
15//config: help 15//config: help
16//config: fatattr lists or changes the file attributes on a fat file system. 16//config: fatattr lists or changes the file attributes on a fat file system.
17 17
18//applet:IF_FATATTR(APPLET(fatattr, BB_DIR_BIN, BB_SUID_DROP)) 18//applet:IF_FATATTR(APPLET_NOEXEC(fatattr, fatattr, BB_DIR_BIN, BB_SUID_DROP, fatattr))
19 19
20//kbuild:lib-$(CONFIG_FATATTR) += fatattr.o 20//kbuild:lib-$(CONFIG_FATATTR) += fatattr.o
21 21
diff --git a/util-linux/fdformat.c b/util-linux/fdformat.c
index 6faaf1b10..855269c30 100644
--- a/util-linux/fdformat.c
+++ b/util-linux/fdformat.c
@@ -66,8 +66,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
66 struct floppy_struct param; 66 struct floppy_struct param;
67 struct format_descr descr; 67 struct format_descr descr;
68 68
69 opt_complementary = "=1"; /* must have 1 param */ 69 verify = !getopt32(argv, "^" "n" "\0" "=1");
70 verify = !getopt32(argv, "n");
71 argv += optind; 70 argv += optind;
72 71
73 xstat(*argv, &st); 72 xstat(*argv, &st);
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index e00f85864..c4318b6c4 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -644,7 +644,7 @@ read_line(const char *prompt)
644{ 644{
645 int sz; 645 int sz;
646 646
647 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1); 647 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer));
648 if (sz <= 0) 648 if (sz <= 0)
649 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ 649 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
650 650
@@ -2848,7 +2848,7 @@ xselect(void)
2848 if (dos_compatible_flag) { 2848 if (dos_compatible_flag) {
2849 sector_offset = g_sectors; 2849 sector_offset = g_sectors;
2850 puts("Warning: setting sector offset for DOS " 2850 puts("Warning: setting sector offset for DOS "
2851 "compatiblity"); 2851 "compatibility");
2852 } 2852 }
2853 update_units(); 2853 update_units();
2854 break; 2854 break;
diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c
index 89f1f323c..1141b7801 100644
--- a/util-linux/fdisk_osf.c
+++ b/util-linux/fdisk_osf.c
@@ -18,7 +18,7 @@
18 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 19 * without specific prior written permission.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
diff --git a/util-linux/flock.c b/util-linux/flock.c
index ec35af18f..dd0bfd430 100644
--- a/util-linux/flock.c
+++ b/util-linux/flock.c
@@ -38,17 +38,15 @@ int flock_main(int argc UNUSED_PARAM, char **argv)
38 }; 38 };
39 39
40#if ENABLE_LONG_OPTS 40#if ENABLE_LONG_OPTS
41 static const char getopt_longopts[] ALIGN1 = 41 static const char flock_longopts[] ALIGN1 =
42 "shared\0" No_argument "s" 42 "shared\0" No_argument "s"
43 "exclusive\0" No_argument "x" 43 "exclusive\0" No_argument "x"
44 "unlock\0" No_argument "u" 44 "unlock\0" No_argument "u"
45 "nonblock\0" No_argument "n" 45 "nonblock\0" No_argument "n"
46 ; 46 ;
47 applet_long_options = getopt_longopts;
48#endif 47#endif
49 opt_complementary = "-1";
50 48
51 opt = getopt32(argv, "+sxnu"); 49 opt = getopt32long(argv, "^+" "sxnu" "\0" "-1", flock_longopts);
52 argv += optind; 50 argv += optind;
53 51
54 if (argv[1]) { 52 if (argv[1]) {
diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c
index 55187cb40..6752e49d8 100644
--- a/util-linux/freeramdisk.c
+++ b/util-linux/freeramdisk.c
@@ -33,9 +33,9 @@
33//config: ramdisk. If you have no use for freeing memory from a ramdisk, leave 33//config: ramdisk. If you have no use for freeing memory from a ramdisk, leave
34//config: this disabled. 34//config: this disabled.
35 35
36// APPLET_ODDNAME:name main location suid_type help 36// APPLET_ODDNAME:name main location suid_type help
37//applet:IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush)) 37//applet:IF_FDFLUSH( APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush ))
38//applet:IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP)) 38//applet:IF_FREERAMDISK(APPLET_NOEXEC(freeramdisk, freeramdisk, BB_DIR_SBIN, BB_SUID_DROP, freeramdisk))
39 39
40//kbuild:lib-$(CONFIG_FDFLUSH) += freeramdisk.o 40//kbuild:lib-$(CONFIG_FDFLUSH) += freeramdisk.o
41//kbuild:lib-$(CONFIG_FREERAMDISK) += freeramdisk.o 41//kbuild:lib-$(CONFIG_FREERAMDISK) += freeramdisk.o
@@ -67,8 +67,12 @@ int freeramdisk_main(int argc UNUSED_PARAM, char **argv)
67 fd = xopen(single_argv(argv), O_RDWR); 67 fd = xopen(single_argv(argv), O_RDWR);
68 68
69 // Act like freeramdisk, fdflush, or both depending on configuration. 69 // Act like freeramdisk, fdflush, or both depending on configuration.
70 ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1] == 'r') 70 ioctl_or_perror_and_die(fd,
71 || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH, NULL, "%s", argv[1]); 71 ((ENABLE_FREERAMDISK && applet_name[1] == 'r') || !ENABLE_FDFLUSH)
72 ? BLKFLSBUF
73 : FDFLUSH,
74 NULL, "%s", argv[1]
75 );
72 76
73 if (ENABLE_FEATURE_CLEAN_UP) close(fd); 77 if (ENABLE_FEATURE_CLEAN_UP) close(fd);
74 78
diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c
index 8c2b7d8de..c4612f251 100644
--- a/util-linux/fsck_minix.c
+++ b/util-linux/fsck_minix.c
@@ -173,7 +173,10 @@ struct globals {
173 173
174 /* Bigger stuff */ 174 /* Bigger stuff */
175 struct termios sv_termios; 175 struct termios sv_termios;
176 char superblock_buffer[BLOCK_SIZE]; 176 union {
177 char superblock_buffer[BLOCK_SIZE];
178 struct minix_superblock Super;
179 } u;
177 char add_zone_ind_blk[BLOCK_SIZE]; 180 char add_zone_ind_blk[BLOCK_SIZE];
178 char add_zone_dind_blk[BLOCK_SIZE]; 181 char add_zone_dind_blk[BLOCK_SIZE];
179 IF_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];) 182 IF_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
@@ -207,7 +210,7 @@ struct globals {
207#define name_depth (G.name_depth ) 210#define name_depth (G.name_depth )
208#define name_component (G.name_component ) 211#define name_component (G.name_component )
209#define sv_termios (G.sv_termios ) 212#define sv_termios (G.sv_termios )
210#define superblock_buffer (G.superblock_buffer ) 213#define superblock_buffer (G.u.superblock_buffer)
211#define add_zone_ind_blk (G.add_zone_ind_blk ) 214#define add_zone_ind_blk (G.add_zone_ind_blk )
212#define add_zone_dind_blk (G.add_zone_dind_blk ) 215#define add_zone_dind_blk (G.add_zone_dind_blk )
213#define add_zone_tind_blk (G.add_zone_tind_blk ) 216#define add_zone_tind_blk (G.add_zone_tind_blk )
@@ -247,7 +250,7 @@ enum {
247#define Inode1 (((struct minix1_inode *) inode_buffer)-1) 250#define Inode1 (((struct minix1_inode *) inode_buffer)-1)
248#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 251#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
249 252
250#define Super (*(struct minix_superblock *)(superblock_buffer)) 253#define Super (G.u.Super)
251 254
252#if ENABLE_FEATURE_MINIX2 255#if ENABLE_FEATURE_MINIX2
253# define ZONES ((unsigned)(version2 ? Super.s_zones : Super.s_nzones)) 256# define ZONES ((unsigned)(version2 ? Super.s_zones : Super.s_nzones))
@@ -1232,8 +1235,7 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
1232 1235
1233 INIT_G(); 1236 INIT_G();
1234 1237
1235 opt_complementary = "=1:ar"; /* one argument; -a assumes -r */ 1238 getopt32(argv, "^" OPTION_STR "\0" "=1:ar" /* one arg; -a assumes -r */);
1236 getopt32(argv, OPTION_STR);
1237 argv += optind; 1239 argv += optind;
1238 device_name = argv[0]; 1240 device_name = argv[0];
1239 1241
diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c
index 5c10c8044..2e2257337 100644
--- a/util-linux/fsfreeze.c
+++ b/util-linux/fsfreeze.c
@@ -13,7 +13,7 @@
13//config: help 13//config: help
14//config: Halt new accesses and flush writes on a mounted filesystem. 14//config: Halt new accesses and flush writes on a mounted filesystem.
15 15
16//applet:IF_FSFREEZE(APPLET(fsfreeze, BB_DIR_USR_SBIN, BB_SUID_DROP)) 16//applet:IF_FSFREEZE(APPLET_NOEXEC(fsfreeze, fsfreeze, BB_DIR_USR_SBIN, BB_SUID_DROP, fsfreeze))
17 17
18//kbuild:lib-$(CONFIG_FSFREEZE) += fsfreeze.o 18//kbuild:lib-$(CONFIG_FSFREEZE) += fsfreeze.o
19 19
@@ -36,15 +36,15 @@ int fsfreeze_main(int argc UNUSED_PARAM, char **argv)
36 unsigned opts; 36 unsigned opts;
37 int fd; 37 int fd;
38 38
39 applet_long_options =
40 "freeze\0" No_argument "\xff"
41 "unfreeze\0" No_argument "\xfe"
42 ;
43 /* exactly one non-option arg: the mountpoint */ 39 /* exactly one non-option arg: the mountpoint */
44 /* one of opts is required */ 40 /* one of opts is required */
45 /* opts are mutually exclusive */ 41 /* opts are mutually exclusive */
46 opt_complementary = "=1:""\xff:\xfe:""\xff--\xfe:\xfe--\xff"; 42 opts = getopt32long(argv, "^"
47 opts = getopt32(argv, ""); 43 "" /* no opts */
44 "\0" "=1:""\xff:\xfe:""\xff--\xfe:\xfe--\xff",
45 "freeze\0" No_argument "\xff"
46 "unfreeze\0" No_argument "\xfe"
47 );
48 48
49 fd = xopen(argv[optind], O_RDONLY); 49 fd = xopen(argv[optind], O_RDONLY);
50 /* Works with NULL arg on linux-4.8.0 */ 50 /* Works with NULL arg on linux-4.8.0 */
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
index 6d0d61d92..4acfa567a 100644
--- a/util-linux/fstrim.c
+++ b/util-linux/fstrim.c
@@ -15,7 +15,7 @@
15//config: help 15//config: help
16//config: Discard unused blocks on a mounted filesystem. 16//config: Discard unused blocks on a mounted filesystem.
17 17
18//applet:IF_FSTRIM(APPLET(fstrim, BB_DIR_SBIN, BB_SUID_DROP)) 18//applet:IF_FSTRIM(APPLET_NOEXEC(fstrim, fstrim, BB_DIR_SBIN, BB_SUID_DROP, fstrim))
19 19
20//kbuild:lib-$(CONFIG_FSTRIM) += fstrim.o 20//kbuild:lib-$(CONFIG_FSTRIM) += fstrim.o
21 21
@@ -63,17 +63,17 @@ int fstrim_main(int argc UNUSED_PARAM, char **argv)
63 }; 63 };
64 64
65#if ENABLE_LONG_OPTS 65#if ENABLE_LONG_OPTS
66 static const char getopt_longopts[] ALIGN1 = 66 static const char fstrim_longopts[] ALIGN1 =
67 "offset\0" Required_argument "o" 67 "offset\0" Required_argument "o"
68 "length\0" Required_argument "l" 68 "length\0" Required_argument "l"
69 "minimum\0" Required_argument "m" 69 "minimum\0" Required_argument "m"
70 "verbose\0" No_argument "v" 70 "verbose\0" No_argument "v"
71 ; 71 ;
72 applet_long_options = getopt_longopts;
73#endif 72#endif
74 73
75 opt_complementary = "=1"; /* exactly one non-option arg: the mountpoint */ 74 opts = getopt32long(argv, "^" "o:l:m:v" "\0" "=1", fstrim_longopts,
76 opts = getopt32(argv, "o:l:m:v", &arg_o, &arg_l, &arg_m); 75 &arg_o, &arg_l, &arg_m
76 );
77 77
78 memset(&range, 0, sizeof(range)); 78 memset(&range, 0, sizeof(range));
79 range.len = ULLONG_MAX; 79 range.len = ULLONG_MAX;
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index cf1bc592f..a151b7e56 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -42,32 +42,18 @@
42//config: 42//config:
43//config:config FEATURE_GETOPT_LONG 43//config:config FEATURE_GETOPT_LONG
44//config: bool "Support -l LONGOPTs" 44//config: bool "Support -l LONGOPTs"
45//config: default y if LONG_OPTS 45//config: default y
46//config: depends on GETOPT 46//config: depends on GETOPT && LONG_OPTS
47//config: help 47//config: help
48//config: Enable support for long options (option -l). 48//config: Enable support for long options (option -l).
49 49
50//applet:IF_GETOPT(APPLET(getopt, BB_DIR_BIN, BB_SUID_DROP)) 50//applet:IF_GETOPT(APPLET_NOEXEC(getopt, getopt, BB_DIR_BIN, BB_SUID_DROP, getopt))
51 51
52//kbuild:lib-$(CONFIG_GETOPT) += getopt.o 52//kbuild:lib-$(CONFIG_GETOPT) += getopt.o
53 53
54//usage:#define getopt_trivial_usage 54//usage:#define getopt_trivial_usage
55//usage: "[OPTIONS] [--] OPTSTRING PARAMS" 55//usage: "[OPTIONS] [--] OPTSTRING PARAMS"
56//usage:#define getopt_full_usage "\n\n" 56//usage:#define getopt_full_usage "\n\n"
57//usage: IF_LONG_OPTS(
58//usage: IF_FEATURE_GETOPT_LONG(
59//usage: " -a,--alternative Allow long options starting with single -\n"
60//usage: " -l,--longoptions LOPT[,...] Long options to recognize\n"
61//usage: )
62//usage: " -n,--name PROGNAME The name under which errors are reported"
63//usage: "\n -o,--options OPTSTRING Short options to recognize"
64//usage: "\n -q,--quiet No error messages on unrecognized options"
65//usage: "\n -Q,--quiet-output No normal output"
66//usage: "\n -s,--shell SHELL Set shell quoting conventions"
67//usage: "\n -T,--test Version test (exits with 4)"
68//usage: "\n -u,--unquoted Don't quote output"
69//usage: )
70//usage: IF_NOT_LONG_OPTS(
71//usage: IF_FEATURE_GETOPT_LONG( 57//usage: IF_FEATURE_GETOPT_LONG(
72//usage: " -a Allow long options starting with single -\n" 58//usage: " -a Allow long options starting with single -\n"
73//usage: " -l LOPT[,...] Long options to recognize\n" 59//usage: " -l LOPT[,...] Long options to recognize\n"
@@ -79,7 +65,6 @@
79//usage: "\n -s SHELL Set shell quoting conventions" 65//usage: "\n -s SHELL Set shell quoting conventions"
80//usage: "\n -T Version test (exits with 4)" 66//usage: "\n -T Version test (exits with 4)"
81//usage: "\n -u Don't quote output" 67//usage: "\n -u Don't quote output"
82//usage: )
83//usage: IF_FEATURE_GETOPT_LONG( /* example uses -l, needs FEATURE_GETOPT_LONG */ 68//usage: IF_FEATURE_GETOPT_LONG( /* example uses -l, needs FEATURE_GETOPT_LONG */
84//usage: "\n" 69//usage: "\n"
85//usage: "\nExample:" 70//usage: "\nExample:"
@@ -411,8 +396,7 @@ int getopt_main(int argc, char **argv)
411#if !ENABLE_FEATURE_GETOPT_LONG 396#if !ENABLE_FEATURE_GETOPT_LONG
412 opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg); 397 opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg);
413#else 398#else
414 applet_long_options = getopt_longopts; 399 opt = getopt32long(argv, "+o:n:qQs:Tual:*", getopt_longopts,
415 opt = getopt32(argv, "+o:n:qQs:Tual:*",
416 &optstr, &name, &s_arg, &l_arg); 400 &optstr, &name, &s_arg, &l_arg);
417 /* Effectuate the read options for the applet itself */ 401 /* Effectuate the read options for the applet itself */
418 while (l_arg) { 402 while (l_arg) {
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index 37e58f2d0..6cf6d0297 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -73,8 +73,9 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
73#define OPT_s (1 << 1) 73#define OPT_s (1 << 1)
74#define OPT_a (1 << 2) 74#define OPT_a (1 << 2)
75#define OPT_p (1 << 3) 75#define OPT_p (1 << 3)
76 opt_complementary = "?1"; /* 1 argument max */ 76 opt = getopt32(argv, "^" "l:s:apg:+c:+" "\0" "?1" /* 1 argument max */,
77 opt = getopt32(argv, "l:s:apg:+c:+", &opt_l, &opt_s, &bytes, &cols); 77 &opt_l, &opt_s, &bytes, &cols
78 );
78 argv += optind; 79 argv += optind;
79 80
80 dumper->dump_vflag = ALL; 81 dumper->dump_vflag = ALL;
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 5df56de15..29f51021e 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -16,11 +16,6 @@
16//config: shutdown in the hardware clock, so the hardware will keep the 16//config: shutdown in the hardware clock, so the hardware will keep the
17//config: correct time when Linux is _not_ running. 17//config: correct time when Linux is _not_ running.
18//config: 18//config:
19//config:config FEATURE_HWCLOCK_LONG_OPTIONS
20//config: bool "Support long options (--hctosys,...)"
21//config: default y
22//config: depends on HWCLOCK && LONG_OPTS
23//config:
24//config:config FEATURE_HWCLOCK_ADJTIME_FHS 19//config:config FEATURE_HWCLOCK_ADJTIME_FHS
25//config: bool "Use FHS /var/lib/hwclock/adjtime" 20//config: bool "Use FHS /var/lib/hwclock/adjtime"
26//config: default n # util-linux-ng in Fedora 13 still uses /etc/adjtime 21//config: default n # util-linux-ng in Fedora 13 still uses /etc/adjtime
@@ -293,12 +288,12 @@ static void set_system_clock_timezone(int utc)
293} 288}
294 289
295//usage:#define hwclock_trivial_usage 290//usage:#define hwclock_trivial_usage
296//usage: IF_FEATURE_HWCLOCK_LONG_OPTIONS( 291//usage: IF_LONG_OPTS(
297//usage: "[-r|--show] [-s|--hctosys] [-w|--systohc] [-t|--systz]" 292//usage: "[-r|--show] [-s|--hctosys] [-w|--systohc] [--systz]"
298//usage: " [-l|--localtime] [-u|--utc]" 293//usage: " [--localtime] [-u|--utc]"
299//usage: " [-f|--rtc FILE]" 294//usage: " [-f|--rtc FILE]"
300//usage: ) 295//usage: )
301//usage: IF_NOT_FEATURE_HWCLOCK_LONG_OPTIONS( 296//usage: IF_NOT_LONG_OPTS(
302//usage: "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]" 297//usage: "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]"
303//usage: ) 298//usage: )
304//usage:#define hwclock_full_usage "\n\n" 299//usage:#define hwclock_full_usage "\n\n"
@@ -306,12 +301,18 @@ static void set_system_clock_timezone(int utc)
306//usage: "\n -r Show hardware clock time" 301//usage: "\n -r Show hardware clock time"
307//usage: "\n -s Set system time from hardware clock" 302//usage: "\n -s Set system time from hardware clock"
308//usage: "\n -w Set hardware clock from system time" 303//usage: "\n -w Set hardware clock from system time"
309//usage: "\n -t Set in-kernel timezone, correct system time" 304//usage: IF_LONG_OPTS(
305//usage: "\n --systz Set in-kernel timezone, correct system time"
306//usage: )
310//usage: "\n if hardware clock is in local time" 307//usage: "\n if hardware clock is in local time"
311//usage: "\n -u Assume hardware clock is kept in UTC" 308//usage: "\n -u Assume hardware clock is kept in UTC"
312//usage: "\n -l Assume hardware clock is kept in local time" 309//usage: IF_LONG_OPTS(
310//usage: "\n --localtime Assume hardware clock is kept in local time"
311//usage: )
313//usage: "\n -f FILE Use specified device (e.g. /dev/rtc2)" 312//usage: "\n -f FILE Use specified device (e.g. /dev/rtc2)"
314 313
314//TODO: get rid of incompatible -t and -l aliases to --systz and --localtime
315
315#define HWCLOCK_OPT_LOCALTIME 0x01 316#define HWCLOCK_OPT_LOCALTIME 0x01
316#define HWCLOCK_OPT_UTC 0x02 317#define HWCLOCK_OPT_UTC 0x02
317#define HWCLOCK_OPT_SHOW 0x04 318#define HWCLOCK_OPT_SHOW 0x04
@@ -327,7 +328,7 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv)
327 unsigned opt; 328 unsigned opt;
328 int utc; 329 int utc;
329 330
330#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS 331#if ENABLE_LONG_OPTS
331 static const char hwclock_longopts[] ALIGN1 = 332 static const char hwclock_longopts[] ALIGN1 =
332 "localtime\0" No_argument "l" /* short opt is non-standard */ 333 "localtime\0" No_argument "l" /* short opt is non-standard */
333 "utc\0" No_argument "u" 334 "utc\0" No_argument "u"
@@ -337,14 +338,16 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv)
337 "systz\0" No_argument "t" /* short opt is non-standard */ 338 "systz\0" No_argument "t" /* short opt is non-standard */
338 "rtc\0" Required_argument "f" 339 "rtc\0" Required_argument "f"
339 ; 340 ;
340 applet_long_options = hwclock_longopts;
341#endif 341#endif
342 342
343 /* Initialize "timezone" (libc global variable) */ 343 /* Initialize "timezone" (libc global variable) */
344 tzset(); 344 tzset();
345 345
346 opt_complementary = "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l"; 346 opt = getopt32long(argv,
347 opt = getopt32(argv, "lurswtf:", &rtcname); 347 "^lurswtf:" "\0" "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l",
348 hwclock_longopts,
349 &rtcname
350 );
348 351
349 /* If -u or -l wasn't given check if we are using utc */ 352 /* If -u or -l wasn't given check if we are using utc */
350 if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) 353 if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
diff --git a/util-linux/ionice.c b/util-linux/ionice.c
index c7b7f0373..5b9664d25 100644
--- a/util-linux/ionice.c
+++ b/util-linux/ionice.c
@@ -14,7 +14,7 @@
14//config: Set/set program io scheduling class and priority 14//config: Set/set program io scheduling class and priority
15//config: Requires kernel >= 2.6.13 15//config: Requires kernel >= 2.6.13
16 16
17//applet:IF_IONICE(APPLET(ionice, BB_DIR_BIN, BB_SUID_DROP)) 17//applet:IF_IONICE(APPLET_NOEXEC(ionice, ionice, BB_DIR_BIN, BB_SUID_DROP, ionice))
18 18
19//kbuild:lib-$(CONFIG_IONICE) += ionice.o 19//kbuild:lib-$(CONFIG_IONICE) += ionice.o
20 20
diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c
index c51d33143..a93ceee11 100644
--- a/util-linux/ipcrm.c
+++ b/util-linux/ipcrm.c
@@ -15,19 +15,10 @@
15//config: communication (IPC) objects and the associated data structures 15//config: communication (IPC) objects and the associated data structures
16//config: from the system. 16//config: from the system.
17 17
18//applet:IF_IPCRM(APPLET(ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP)) 18//applet:IF_IPCRM(APPLET_NOEXEC(ipcrm, ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP, ipcrm))
19 19
20//kbuild:lib-$(CONFIG_IPCRM) += ipcrm.o 20//kbuild:lib-$(CONFIG_IPCRM) += ipcrm.o
21 21
22//usage:#define ipcrm_trivial_usage
23//usage: "[-MQS key] [-mqs id]"
24//usage:#define ipcrm_full_usage "\n\n"
25//usage: "Upper-case options MQS remove an object by shmkey value.\n"
26//usage: "Lower-case options remove an object by shmid value.\n"
27//usage: "\n -mM Remove memory segment after last detach"
28//usage: "\n -qQ Remove message queue"
29//usage: "\n -sS Remove semaphore"
30
31#include "libbb.h" 22#include "libbb.h"
32 23
33/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ 24/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
@@ -94,6 +85,14 @@ static int remove_ids(type_id type, char **argv)
94} 85}
95#endif /* IPCRM_LEGACY */ 86#endif /* IPCRM_LEGACY */
96 87
88//usage:#define ipcrm_trivial_usage
89//usage: "[-MQS key] [-mqs id]"
90//usage:#define ipcrm_full_usage "\n\n"
91//usage: "Upper-case options MQS remove an object by shmkey value.\n"
92//usage: "Lower-case options remove an object by shmid value.\n"
93//usage: "\n -mM Remove memory segment after last detach"
94//usage: "\n -qQ Remove message queue"
95//usage: "\n -sS Remove semaphore"
97 96
98int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 97int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
99int ipcrm_main(int argc, char **argv) 98int ipcrm_main(int argc, char **argv)
@@ -137,28 +136,20 @@ int ipcrm_main(int argc, char **argv)
137#endif /* IPCRM_LEGACY */ 136#endif /* IPCRM_LEGACY */
138 137
139 /* process new syntax to conform with SYSV ipcrm */ 138 /* process new syntax to conform with SYSV ipcrm */
140 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) { 139 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) {
141 int result; 140 int result;
142 int id = 0; 141 int id;
143 int iskey = isupper(c); 142 int iskey;
144
145 /* needed to delete semaphores */ 143 /* needed to delete semaphores */
146 union semun arg; 144 union semun arg;
147 145
148 arg.val = 0; 146 if (c == '?') /* option not in the string */
149
150 if ((c == '?') || (c == 'h')) {
151 bb_show_usage(); 147 bb_show_usage();
152 }
153
154 /* we don't need case information any more */
155 c = tolower(c);
156 148
157 /* make sure the option is in range: allowed are q, m, s */ 149 id = 0;
158 if (c != 'q' && c != 'm' && c != 's') { 150 arg.val = 0;
159 bb_show_usage();
160 }
161 151
152 iskey = !(c & 0x20); /* uppercase? */
162 if (iskey) { 153 if (iskey) {
163 /* keys are in hex or decimal */ 154 /* keys are in hex or decimal */
164 key_t key = xstrtoul(optarg, 0); 155 key_t key = xstrtoul(optarg, 0);
@@ -169,6 +160,7 @@ int ipcrm_main(int argc, char **argv)
169 continue; 160 continue;
170 } 161 }
171 162
163 c |= 0x20; /* lowercase. c is 'q', 'm' or 's' now */
172 /* convert key to id */ 164 /* convert key to id */
173 id = ((c == 'q') ? msgget(key, 0) : 165 id = ((c == 'q') ? msgget(key, 0) :
174 (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0)); 166 (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c
index 1404930d4..7092ecd92 100644
--- a/util-linux/ipcs.c
+++ b/util-linux/ipcs.c
@@ -15,26 +15,10 @@
15//config: The ipcs utility is used to provide information on the currently 15//config: The ipcs utility is used to provide information on the currently
16//config: allocated System V interprocess (IPC) objects in the system. 16//config: allocated System V interprocess (IPC) objects in the system.
17 17
18//applet:IF_IPCS(APPLET(ipcs, BB_DIR_USR_BIN, BB_SUID_DROP)) 18//applet:IF_IPCS(APPLET_NOEXEC(ipcs, ipcs, BB_DIR_USR_BIN, BB_SUID_DROP, ipcs))
19 19
20//kbuild:lib-$(CONFIG_IPCS) += ipcs.o 20//kbuild:lib-$(CONFIG_IPCS) += ipcs.o
21 21
22//usage:#define ipcs_trivial_usage
23//usage: "[[-smq] -i shmid] | [[-asmq] [-tcplu]]"
24//usage:#define ipcs_full_usage "\n\n"
25//usage: " -i Show specific resource"
26//usage: "\nResource specification:"
27//usage: "\n -m Shared memory segments"
28//usage: "\n -q Message queues"
29//usage: "\n -s Semaphore arrays"
30//usage: "\n -a All (default)"
31//usage: "\nOutput format:"
32//usage: "\n -t Time"
33//usage: "\n -c Creator"
34//usage: "\n -p Pid"
35//usage: "\n -l Limits"
36//usage: "\n -u Summary"
37
38/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ 22/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
39/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */ 23/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
40/* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */ 24/* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
@@ -585,6 +569,22 @@ static void print_sem(int semid)
585 bb_putchar('\n'); 569 bb_putchar('\n');
586} 570}
587 571
572//usage:#define ipcs_trivial_usage
573//usage: "[[-smq] -i shmid] | [[-asmq] [-tcplu]]"
574//usage:#define ipcs_full_usage "\n\n"
575//usage: " -i Show specific resource"
576//usage: "\nResource specification:"
577//usage: "\n -m Shared memory segments"
578//usage: "\n -q Message queues"
579//usage: "\n -s Semaphore arrays"
580//usage: "\n -a All (default)"
581//usage: "\nOutput format:"
582//usage: "\n -t Time"
583//usage: "\n -c Creator"
584//usage: "\n -p Pid"
585//usage: "\n -l Limits"
586//usage: "\n -u Summary"
587
588int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 588int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
589int ipcs_main(int argc UNUSED_PARAM, char **argv) 589int ipcs_main(int argc UNUSED_PARAM, char **argv)
590{ 590{
@@ -632,6 +632,10 @@ int ipcs_main(int argc UNUSED_PARAM, char **argv)
632 flags |= flag_msg | flag_shm | flag_sem; 632 flags |= flag_msg | flag_shm | flag_sem;
633 bb_putchar('\n'); 633 bb_putchar('\n');
634 634
635 if (flags & flag_msg) {
636 do_msg();
637 bb_putchar('\n');
638 }
635 if (flags & flag_shm) { 639 if (flags & flag_shm) {
636 do_shm(); 640 do_shm();
637 bb_putchar('\n'); 641 bb_putchar('\n');
@@ -640,9 +644,5 @@ int ipcs_main(int argc UNUSED_PARAM, char **argv)
640 do_sem(); 644 do_sem();
641 bb_putchar('\n'); 645 bb_putchar('\n');
642 } 646 }
643 if (flags & flag_msg) {
644 do_msg();
645 bb_putchar('\n');
646 }
647 fflush_stdout_and_exit(EXIT_SUCCESS); 647 fflush_stdout_and_exit(EXIT_SUCCESS);
648} 648}
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index c608de6cc..6b171d710 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -15,9 +15,9 @@
15//config: file or block device, and to query the status of a loop device. This 15//config: file or block device, and to query the status of a loop device. This
16//config: version does not currently support enabling data encryption. 16//config: version does not currently support enabling data encryption.
17 17
18//kbuild:lib-$(CONFIG_LOSETUP) += losetup.o 18//applet:IF_LOSETUP(APPLET_NOEXEC(losetup, losetup, BB_DIR_SBIN, BB_SUID_DROP, losetup))
19 19
20//applet:IF_LOSETUP(APPLET(losetup, BB_DIR_SBIN, BB_SUID_DROP)) 20//kbuild:lib-$(CONFIG_LOSETUP) += losetup.o
21 21
22//usage:#define losetup_trivial_usage 22//usage:#define losetup_trivial_usage
23//usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n" 23//usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n"
@@ -57,8 +57,7 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
57 OPT_r = (1 << 4), /* must be last */ 57 OPT_r = (1 << 4), /* must be last */
58 }; 58 };
59 59
60 opt_complementary = "?2:d--ofar:a--ofr"; 60 opt = getopt32(argv, "^" "do:far" "\0" "?2:d--ofar:a--ofr", &opt_o);
61 opt = getopt32(argv, "do:far", &opt_o);
62 argv += optind; 61 argv += optind;
63 62
64 /* LOOPDEV */ 63 /* LOOPDEV */
diff --git a/util-linux/lspci.c b/util-linux/lspci.c
index 3877deb67..0000fbfda 100644
--- a/util-linux/lspci.c
+++ b/util-linux/lspci.c
@@ -16,7 +16,7 @@
16//config: 16//config:
17//config: This version uses sysfs (/sys/bus/pci/devices) only. 17//config: This version uses sysfs (/sys/bus/pci/devices) only.
18 18
19//applet:IF_LSPCI(APPLET(lspci, BB_DIR_USR_BIN, BB_SUID_DROP)) 19//applet:IF_LSPCI(APPLET_NOEXEC(lspci, lspci, BB_DIR_USR_BIN, BB_SUID_DROP, lspci))
20 20
21//kbuild:lib-$(CONFIG_LSPCI) += lspci.o 21//kbuild:lib-$(CONFIG_LSPCI) += lspci.o
22 22
diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c
index cabf047cf..33639413a 100644
--- a/util-linux/lsusb.c
+++ b/util-linux/lsusb.c
@@ -16,7 +16,7 @@
16//config: 16//config:
17//config: This version uses sysfs (/sys/bus/usb/devices) only. 17//config: This version uses sysfs (/sys/bus/usb/devices) only.
18 18
19//applet:IF_LSUSB(APPLET(lsusb, BB_DIR_USR_BIN, BB_SUID_DROP)) 19//applet:IF_LSUSB(APPLET_NOEXEC(lsusb, lsusb, BB_DIR_USR_BIN, BB_SUID_DROP, lsusb))
20 20
21//kbuild:lib-$(CONFIG_LSUSB) += lsusb.o 21//kbuild:lib-$(CONFIG_LSUSB) += lsusb.o
22 22
diff --git a/util-linux/mesg.c b/util-linux/mesg.c
index c4371eb24..91c05317e 100644
--- a/util-linux/mesg.c
+++ b/util-linux/mesg.c
@@ -26,7 +26,7 @@
26//config: If you set this option to N, "mesg y" will enable writing 26//config: If you set this option to N, "mesg y" will enable writing
27//config: by anybody at all. This is not recommended. 27//config: by anybody at all. This is not recommended.
28 28
29//applet:IF_MESG(APPLET(mesg, BB_DIR_USR_BIN, BB_SUID_DROP)) 29//applet:IF_MESG(APPLET_NOFORK(mesg, mesg, BB_DIR_USR_BIN, BB_SUID_DROP, mesg))
30 30
31//kbuild:lib-$(CONFIG_MESG) += mesg.o 31//kbuild:lib-$(CONFIG_MESG) += mesg.o
32 32
@@ -60,10 +60,15 @@ int mesg_main(int argc UNUSED_PARAM, char **argv)
60 bb_show_usage(); 60 bb_show_usage();
61 } 61 }
62 62
63 /* We are a NOFORK applet.
64 * (Not that it's very useful, but code is trivially NOFORK-safe).
65 * Play nice. Do not leak anything.
66 */
67
63 if (!isatty(STDIN_FILENO)) 68 if (!isatty(STDIN_FILENO))
64 bb_error_msg_and_die("not a tty"); 69 bb_error_msg_and_die("not a tty");
65 70
66 xfstat(STDIN_FILENO, &sb, "stderr"); 71 xfstat(STDIN_FILENO, &sb, "stdin");
67 if (c == 0) { 72 if (c == 0) {
68 puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n"); 73 puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n");
69 return EXIT_SUCCESS; 74 return EXIT_SUCCESS;
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index 88647e9d8..69dfcd123 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -142,7 +142,10 @@ struct globals {
142 unsigned currently_testing; 142 unsigned currently_testing;
143 143
144 char root_block[BLOCK_SIZE]; 144 char root_block[BLOCK_SIZE];
145 char superblock_buffer[BLOCK_SIZE]; 145 union {
146 char superblock_buffer[BLOCK_SIZE];
147 struct minix_superblock SB;
148 } u;
146 char boot_block_buffer[512]; 149 char boot_block_buffer[512];
147 unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 150 unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
148 /* check_blocks(): buffer[] was the biggest static in entire bbox */ 151 /* check_blocks(): buffer[] was the biggest static in entire bbox */
@@ -166,7 +169,7 @@ static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
166#define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1) 169#define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1)
167#define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1) 170#define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1)
168 171
169#define SB (*(struct minix_superblock*)G.superblock_buffer) 172#define SB (G.u.SB)
170 173
171#define SB_INODES (SB.s_ninodes) 174#define SB_INODES (SB.s_ninodes)
172#define SB_IMAPS (SB.s_imap_blocks) 175#define SB_IMAPS (SB.s_imap_blocks)
@@ -234,7 +237,7 @@ static void write_tables(void)
234 xlseek(dev_fd, BLOCK_SIZE, SEEK_SET); 237 xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
235 238
236 msg_eol = "can't write superblock"; 239 msg_eol = "can't write superblock";
237 xwrite(dev_fd, G.superblock_buffer, BLOCK_SIZE); 240 xwrite(dev_fd, G.u.superblock_buffer, BLOCK_SIZE);
238 241
239 msg_eol = "can't write inode map"; 242 msg_eol = "can't write inode map";
240 xwrite(dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE); 243 xwrite(dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
@@ -541,7 +544,7 @@ static void setup_tables(void)
541 unsigned sb_zmaps; 544 unsigned sb_zmaps;
542 unsigned i; 545 unsigned i;
543 546
544 /* memset(G.superblock_buffer, 0, BLOCK_SIZE); */ 547 /* memset(G.u.superblock_buffer, 0, BLOCK_SIZE); */
545 /* memset(G.boot_block_buffer, 0, 512); */ 548 /* memset(G.boot_block_buffer, 0, 512); */
546 SB_MAGIC = G.magic; 549 SB_MAGIC = G.magic;
547 SB_ZONE_SIZE = 0; 550 SB_ZONE_SIZE = 0;
diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c
index c7d99b018..390aef86c 100644
--- a/util-linux/mkfs_reiser.c
+++ b/util-linux/mkfs_reiser.c
@@ -180,8 +180,7 @@ int mkfs_reiser_main(int argc UNUSED_PARAM, char **argv)
180 180
181 // using global "option_mask32" instead of local "opts": 181 // using global "option_mask32" instead of local "opts":
182 // we are register starved here 182 // we are register starved here
183 opt_complementary = "-1"; 183 /*opts =*/ getopt32(argv, "^" "b:+j:s:o:t:B:h:u:l:fqd" "\0" "-1",
184 /*opts =*/ getopt32(argv, "b:+j:s:o:t:B:h:u:l:fqd",
185 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &label); 184 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &label);
186 argv += optind; // argv[0] -- device 185 argv += optind; // argv[0] -- device
187 186
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c
index f9768ed56..426854b1e 100644
--- a/util-linux/mkfs_vfat.c
+++ b/util-linux/mkfs_vfat.c
@@ -269,8 +269,9 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
269 OPT_v = 1 << 16, // verbose 269 OPT_v = 1 << 16, // verbose
270 }; 270 };
271 271
272 opt_complementary = "-1";//:b+:f+:F+:h+:r+:R+:s+:S+:vv:c--l:l--c"; 272 opts = getopt32(argv, "^"
273 opts = getopt32(argv, "Ab:cCf:F:h:Ii:l:m:n:r:R:s:S:v", 273 "Ab:cCf:F:h:Ii:l:m:n:r:R:s:S:v"
274 "\0" "-1", //:b+:f+:F+:h+:r+:R+:s+:S+:vv:c--l:l--c
274 NULL, NULL, NULL, NULL, NULL, 275 NULL, NULL, NULL, NULL, NULL,
275 NULL, NULL, &volume_label, NULL, NULL, NULL, NULL); 276 NULL, NULL, &volume_label, NULL, NULL, NULL, NULL);
276 argv += optind; 277 argv += optind;
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index e44e13c0d..71449882d 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -119,9 +119,8 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv)
119 119
120 INIT_G(); 120 INIT_G();
121 121
122 opt_complementary = "-1"; /* at least one param */
123 /* TODO: -p PAGESZ, -U UUID */ 122 /* TODO: -p PAGESZ, -U UUID */
124 getopt32(argv, "L:", &label); 123 getopt32(argv, "^" "L:" "\0" "-1"/*at least one arg*/, &label);
125 argv += optind; 124 argv += optind;
126 125
127 fd = xopen(argv[0], O_WRONLY); 126 fd = xopen(argv[0], O_WRONLY);
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 4d5c2243a..4eade0869 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -69,7 +69,6 @@
69//config: bool "Support mounting NFS file systems on Linux < 2.6.23" 69//config: bool "Support mounting NFS file systems on Linux < 2.6.23"
70//config: default n 70//config: default n
71//config: depends on MOUNT 71//config: depends on MOUNT
72//config: select FEATURE_HAVE_RPC
73//config: select FEATURE_SYSLOG 72//config: select FEATURE_SYSLOG
74//config: help 73//config: help
75//config: Enable mounting of NFS file systems on Linux kernels prior 74//config: Enable mounting of NFS file systems on Linux kernels prior
@@ -2205,10 +2204,14 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2205 2204
2206 // Parse remaining options 2205 // Parse remaining options
2207 // Max 2 params; -o is a list, -v is a counter 2206 // Max 2 params; -o is a list, -v is a counter
2208 opt_complementary = "?2" IF_FEATURE_MOUNT_VERBOSE("vv"); 2207 opt = getopt32(argv, "^"
2209 opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch 2208 OPTION_STR
2210 IF_FEATURE_MOUNT_OTHERTAB(, &fstabname) 2209 "\0" "?2"IF_FEATURE_MOUNT_VERBOSE("vv"),
2211 IF_FEATURE_MOUNT_VERBOSE(, &verbose)); 2210 &lst_o, &fstype, &O_optmatch
2211 IF_FEATURE_MOUNT_OTHERTAB(, &fstabname)
2212 IF_FEATURE_MOUNT_VERBOSE(, &verbose)
2213 );
2214
2212 while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o 2215 while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o
2213 if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r 2216 if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r
2214 if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w 2217 if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w
diff --git a/util-linux/mountpoint.c b/util-linux/mountpoint.c
index b7f048196..6b21a5fb3 100644
--- a/util-linux/mountpoint.c
+++ b/util-linux/mountpoint.c
@@ -14,7 +14,7 @@
14//config: help 14//config: help
15//config: mountpoint checks if the directory is a mountpoint. 15//config: mountpoint checks if the directory is a mountpoint.
16 16
17//applet:IF_MOUNTPOINT(APPLET(mountpoint, BB_DIR_BIN, BB_SUID_DROP)) 17//applet:IF_MOUNTPOINT(APPLET_NOEXEC(mountpoint, mountpoint, BB_DIR_BIN, BB_SUID_DROP, mountpoint))
18 18
19//kbuild:lib-$(CONFIG_MOUNTPOINT) += mountpoint.o 19//kbuild:lib-$(CONFIG_MOUNTPOINT) += mountpoint.o
20 20
@@ -43,8 +43,7 @@ int mountpoint_main(int argc UNUSED_PARAM, char **argv)
43 char *arg; 43 char *arg;
44 int rc, opt; 44 int rc, opt;
45 45
46 opt_complementary = "=1"; /* must have one argument */ 46 opt = getopt32(argv, "^" "qdxn" "\0" "=1");
47 opt = getopt32(argv, "qdxn");
48#define OPT_q (1) 47#define OPT_q (1)
49#define OPT_d (2) 48#define OPT_d (2)
50#define OPT_x (4) 49#define OPT_x (4)
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 12c86b0ed..d91b0b509 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -13,14 +13,6 @@
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
15//config: Run program with namespaces of other processes. 15//config: Run program with namespaces of other processes.
16//config:
17//config:config FEATURE_NSENTER_LONG_OPTS
18//config: bool "Enable long options"
19//config: default y
20//config: depends on NSENTER && LONG_OPTS
21//config: help
22//config: Support long options for the nsenter applet. This makes
23//config: the busybox implementation more compatible with upstream.
24 16
25//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP)) 17//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
26 18
@@ -28,22 +20,6 @@
28 20
29//usage:#define nsenter_trivial_usage 21//usage:#define nsenter_trivial_usage
30//usage: "[OPTIONS] [PROG [ARGS]]" 22//usage: "[OPTIONS] [PROG [ARGS]]"
31//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
32//usage:#define nsenter_full_usage "\n"
33//usage: "\n -t,--target PID Target process to get namespaces from"
34//usage: "\n -m,--mount[=FILE] Enter mount namespace"
35//usage: "\n -u,--uts[=FILE] Enter UTS namespace (hostname etc)"
36//usage: "\n -i,--ipc[=FILE] Enter System V IPC namespace"
37//usage: "\n -n,--net[=FILE] Enter network namespace"
38//usage: "\n -p,--pid[=FILE] Enter pid namespace"
39//usage: "\n -U,--user[=FILE] Enter user namespace"
40//usage: "\n -S,--setuid UID Set uid in entered namespace"
41//usage: "\n -G,--setgid GID Set gid in entered namespace"
42//usage: "\n --preserve-credentials Don't touch uids or gids"
43//usage: "\n -r,--root[=DIR] Set root directory"
44//usage: "\n -w,--wd[=DIR] Set working directory"
45//usage: "\n -F,--no-fork Don't fork before exec'ing PROG"
46//usage:#else
47//usage:#define nsenter_full_usage "\n" 23//usage:#define nsenter_full_usage "\n"
48//usage: "\n -t PID Target process to get namespaces from" 24//usage: "\n -t PID Target process to get namespaces from"
49//usage: "\n -m[FILE] Enter mount namespace" 25//usage: "\n -m[FILE] Enter mount namespace"
@@ -54,10 +30,12 @@
54//usage: "\n -U[FILE] Enter user namespace" 30//usage: "\n -U[FILE] Enter user namespace"
55//usage: "\n -S UID Set uid in entered namespace" 31//usage: "\n -S UID Set uid in entered namespace"
56//usage: "\n -G GID Set gid in entered namespace" 32//usage: "\n -G GID Set gid in entered namespace"
33//usage: IF_LONG_OPTS(
34//usage: "\n --preserve-credentials Don't touch uids or gids"
35//usage: )
57//usage: "\n -r[DIR] Set root directory" 36//usage: "\n -r[DIR] Set root directory"
58//usage: "\n -w[DIR] Set working directory" 37//usage: "\n -w[DIR] Set working directory"
59//usage: "\n -F Don't fork before exec'ing PROG" 38//usage: "\n -F Don't fork before exec'ing PROG"
60//usage:#endif
61 39
62#include <sched.h> 40#include <sched.h>
63#ifndef CLONE_NEWUTS 41#ifndef CLONE_NEWUTS
@@ -101,7 +79,7 @@ enum {
101 OPT_root = 1 << 9, 79 OPT_root = 1 << 9,
102 OPT_wd = 1 << 10, 80 OPT_wd = 1 << 10,
103 OPT_nofork = 1 << 11, 81 OPT_nofork = 1 << 11,
104 OPT_prescred = (1 << 12) * ENABLE_FEATURE_NSENTER_LONG_OPTS, 82 OPT_prescred = (1 << 12) * ENABLE_LONG_OPTS,
105}; 83};
106enum { 84enum {
107 NS_USR_POS = 0, 85 NS_USR_POS = 0,
@@ -130,7 +108,7 @@ static const struct namespace_descr ns_list[] = {
130 */ 108 */
131static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F"; 109static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F";
132 110
133#if ENABLE_FEATURE_NSENTER_LONG_OPTS 111#if ENABLE_LONG_OPTS
134static const char nsenter_longopts[] ALIGN1 = 112static const char nsenter_longopts[] ALIGN1 =
135 "user\0" Optional_argument "U" 113 "user\0" Optional_argument "U"
136 "ipc\0" Optional_argument "i" 114 "ipc\0" Optional_argument "i"
@@ -190,8 +168,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
190 168
191 memset(ns_ctx_list, 0, sizeof(ns_ctx_list)); 169 memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
192 170
193 IF_FEATURE_NSENTER_LONG_OPTS(applet_long_options = nsenter_longopts); 171 opts = getopt32long(argv, opt_str, nsenter_longopts,
194 opts = getopt32(argv, opt_str,
195 &ns_ctx_list[NS_USR_POS].path, 172 &ns_ctx_list[NS_USR_POS].path,
196 &ns_ctx_list[NS_IPC_POS].path, 173 &ns_ctx_list[NS_IPC_POS].path,
197 &ns_ctx_list[NS_UTS_POS].path, 174 &ns_ctx_list[NS_UTS_POS].path,
diff --git a/util-linux/pivot_root.c b/util-linux/pivot_root.c
index 331038057..d6a26b912 100644
--- a/util-linux/pivot_root.c
+++ b/util-linux/pivot_root.c
@@ -21,7 +21,7 @@
21//config: Note: This is for initrd in linux 2.4. Under initramfs (introduced 21//config: Note: This is for initrd in linux 2.4. Under initramfs (introduced
22//config: in linux 2.6) use switch_root instead. 22//config: in linux 2.6) use switch_root instead.
23 23
24//applet:IF_PIVOT_ROOT(APPLET(pivot_root, BB_DIR_SBIN, BB_SUID_DROP)) 24//applet:IF_PIVOT_ROOT(APPLET_NOFORK(pivot_root, pivot_root, BB_DIR_SBIN, BB_SUID_DROP, pivot_root))
25 25
26//kbuild:lib-$(CONFIG_PIVOT_ROOT) += pivot_root.o 26//kbuild:lib-$(CONFIG_PIVOT_ROOT) += pivot_root.o
27 27
@@ -33,7 +33,7 @@
33 33
34#include "libbb.h" 34#include "libbb.h"
35 35
36extern int pivot_root(const char * new_root,const char * put_old); 36extern int pivot_root(const char *new_root, const char *put_old);
37 37
38int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 38int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
39int pivot_root_main(int argc, char **argv) 39int pivot_root_main(int argc, char **argv)
@@ -41,6 +41,8 @@ int pivot_root_main(int argc, char **argv)
41 if (argc != 3) 41 if (argc != 3)
42 bb_show_usage(); 42 bb_show_usage();
43 43
44 /* NOFORK applet. Hardly matters wrt performance, but code is trivial */
45
44 if (pivot_root(argv[1], argv[2]) < 0) { 46 if (pivot_root(argv[1], argv[2]) < 0) {
45 /* prints "pivot_root: <strerror text>" */ 47 /* prints "pivot_root: <strerror text>" */
46 bb_perror_nomsg_and_die(); 48 bb_perror_nomsg_and_die();
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 14ce591e9..f27294e25 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -81,8 +81,7 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
81 time_t remote_time; 81 time_t remote_time;
82 unsigned flags; 82 unsigned flags;
83 83
84 opt_complementary = "-1"; 84 flags = getopt32(argv, "^" "sp" "\0" "-1");
85 flags = getopt32(argv, "sp");
86 85
87 remote_time = askremotedate(argv[optind]); 86 remote_time = askremotedate(argv[optind]);
88 87
diff --git a/util-linux/rdev.c b/util-linux/rdev.c
index 2ffe07688..7eb7413a8 100644
--- a/util-linux/rdev.c
+++ b/util-linux/rdev.c
@@ -14,7 +14,7 @@
14//config: help 14//config: help
15//config: Print the device node associated with the filesystem mounted at '/'. 15//config: Print the device node associated with the filesystem mounted at '/'.
16 16
17//applet:IF_RDEV(APPLET(rdev, BB_DIR_USR_SBIN, BB_SUID_DROP)) 17//applet:IF_RDEV(APPLET_NOEXEC(rdev, rdev, BB_DIR_USR_SBIN, BB_SUID_DROP, rdev))
18 18
19//kbuild:lib-$(CONFIG_RDEV) += rdev.o 19//kbuild:lib-$(CONFIG_RDEV) += rdev.o
20 20
diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c
index b045657d8..394ece1dd 100644
--- a/util-linux/readprofile.c
+++ b/util-linux/readprofile.c
@@ -266,8 +266,10 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
266 printf("%6u %-40s %8.4f\n", 266 printf("%6u %-40s %8.4f\n",
267 total, "total", total/(double)(fn_add-add0)); 267 total, "total", total/(double)(fn_add-add0));
268 268
269 fclose(map); 269 if (ENABLE_FEATURE_CLEAN_UP) {
270 free(buf); 270 fclose(map);
271 free(buf);
272 }
271 273
272 return EXIT_SUCCESS; 274 return EXIT_SUCCESS;
273} 275}
diff --git a/util-linux/renice.c b/util-linux/renice.c
index 23cbca88d..70c494b3d 100644
--- a/util-linux/renice.c
+++ b/util-linux/renice.c
@@ -25,7 +25,7 @@
25//config: Renice alters the scheduling priority of one or more running 25//config: Renice alters the scheduling priority of one or more running
26//config: processes. 26//config: processes.
27 27
28//applet:IF_RENICE(APPLET(renice, BB_DIR_USR_BIN, BB_SUID_DROP)) 28//applet:IF_RENICE(APPLET_NOEXEC(renice, renice, BB_DIR_USR_BIN, BB_SUID_DROP, renice))
29 29
30//kbuild:lib-$(CONFIG_RENICE) += renice.o 30//kbuild:lib-$(CONFIG_RENICE) += renice.o
31 31
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c
index 4c47c5369..8ffa4f3a6 100644
--- a/util-linux/rtcwake.c
+++ b/util-linux/rtcwake.c
@@ -154,11 +154,11 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv)
154 "seconds\0" Required_argument "s" 154 "seconds\0" Required_argument "s"
155 "time\0" Required_argument "t" 155 "time\0" Required_argument "t"
156 ; 156 ;
157 applet_long_options = rtcwake_longopts;
158#endif 157#endif
159 /* Must have -s or -t, exclusive */ 158 opt = getopt32long(argv,
160 opt_complementary = "s:t:s--t:t--s"; 159 /* Must have -s or -t, exclusive */
161 opt = getopt32(argv, "alud:m:s:t:", &rtcname, &suspend, &opt_seconds, &opt_time); 160 "^alud:m:s:t:" "\0" "s:t:s--t:t--s", rtcwake_longopts,
161 &rtcname, &suspend, &opt_seconds, &opt_time);
162 162
163 /* this is the default 163 /* this is the default
164 if (opt & RTCWAKE_OPT_AUTO) 164 if (opt & RTCWAKE_OPT_AUTO)
diff --git a/util-linux/script.c b/util-linux/script.c
index 9eebb51a4..aac77c3ba 100644
--- a/util-linux/script.c
+++ b/util-linux/script.c
@@ -21,15 +21,25 @@
21//kbuild:lib-$(CONFIG_SCRIPT) += script.o 21//kbuild:lib-$(CONFIG_SCRIPT) += script.o
22 22
23//usage:#define script_trivial_usage 23//usage:#define script_trivial_usage
24//usage: "[-afq" IF_SCRIPTREPLAY("t") "] [-c PROG] [OUTFILE]" 24//usage: "[-afq] [-t[FILE]] [-c PROG] [OUTFILE]"
25//usage:#define script_full_usage "\n\n" 25//usage:#define script_full_usage "\n\n"
26//usage: " -a Append output" 26//usage: "Default OUTFILE is 'typescript'"
27//usage: "\n"
28//usage: "\n -a Append output"
27//usage: "\n -c PROG Run PROG, not shell" 29//usage: "\n -c PROG Run PROG, not shell"
28//usage: "\n -f Flush output after each write" 30/* Accepted but has no effect (we never buffer output) */
31/*//usage: "\n -f Flush output after each write"*/
29//usage: "\n -q Quiet" 32//usage: "\n -q Quiet"
30//usage: IF_SCRIPTREPLAY( 33//usage: "\n -t[FILE] Send timing to stderr or FILE"
31//usage: "\n -t Send timing to stderr" 34
32//usage: ) 35//util-linux-2.28:
36//-e: return exit code of the child
37
38//FYI (reported as bbox bug #2749):
39// > script -q -c 'echo -e -n "1\n2\n3\n"' /dev/null </dev/null >123.txt
40// > The output file on full-blown ubuntu system contains 6 bytes.
41// > Output on Busybox system (arm-linux) contains extra '\r' byte in each line.
42//however, in my test, "script" from util-linux-2.28 seems to also add '\r' bytes.
33 43
34#include "libbb.h" 44#include "libbb.h"
35#include "common_bufsiz.h" 45#include "common_bufsiz.h"
@@ -46,6 +56,8 @@ int script_main(int argc UNUSED_PARAM, char **argv)
46 char pty_line[GETPTY_BUFSIZE]; 56 char pty_line[GETPTY_BUFSIZE];
47 struct termios tt, rtt; 57 struct termios tt, rtt;
48 struct winsize win; 58 struct winsize win;
59 FILE *timing_fp;
60 const char *str_t = NULL;
49 const char *fname = "typescript"; 61 const char *fname = "typescript";
50 const char *shell; 62 const char *shell;
51 char shell_opt[] = "-i"; 63 char shell_opt[] = "-i";
@@ -59,19 +71,19 @@ int script_main(int argc UNUSED_PARAM, char **argv)
59 }; 71 };
60 72
61#if ENABLE_LONG_OPTS 73#if ENABLE_LONG_OPTS
62 static const char getopt_longopts[] ALIGN1 = 74 static const char script_longopts[] ALIGN1 =
63 "append\0" No_argument "a" 75 "append\0" No_argument "a"
64 "command\0" Required_argument "c" 76 "command\0" Required_argument "c"
65 "flush\0" No_argument "f" 77 "flush\0" No_argument "f"
66 "quiet\0" No_argument "q" 78 "quiet\0" No_argument "q"
67 IF_SCRIPTREPLAY("timing\0" No_argument "t") 79 "timing\0" Optional_argument "t"
68 ; 80 ;
69
70 applet_long_options = getopt_longopts;
71#endif 81#endif
72 82
73 opt_complementary = "?1"; /* max one arg */ 83 opt = getopt32long(argv, "^" "ac:fqt::" "\0" "?1"/* max one arg */,
74 opt = getopt32(argv, "ac:fq" IF_SCRIPTREPLAY("t") , &shell_arg); 84 script_longopts,
85 &shell_arg, &str_t
86 );
75 //argc -= optind; 87 //argc -= optind;
76 argv += optind; 88 argv += optind;
77 if (argv[0]) { 89 if (argv[0]) {
@@ -87,6 +99,10 @@ int script_main(int argc UNUSED_PARAM, char **argv)
87 if (!(opt & OPT_q)) { 99 if (!(opt & OPT_q)) {
88 printf("Script started, file is %s\n", fname); 100 printf("Script started, file is %s\n", fname);
89 } 101 }
102 timing_fp = stderr;
103 if (str_t) {
104 timing_fp = xfopen_for_write(str_t);
105 }
90 106
91 shell = get_shell_name(); 107 shell = get_shell_name();
92 108
@@ -120,8 +136,9 @@ int script_main(int argc UNUSED_PARAM, char **argv)
120 /* parent */ 136 /* parent */
121 struct pollfd pfd[2]; 137 struct pollfd pfd[2];
122 int outfd, count, loop; 138 int outfd, count, loop;
123 double oldtime = ENABLE_SCRIPTREPLAY ? time(NULL) : 0; 139 double oldtime = time(NULL);
124 smallint fd_count = 2; 140 smallint fd_count = 2;
141
125#define buf bb_common_bufsiz1 142#define buf bb_common_bufsiz1
126 setup_common_bufsiz(); 143 setup_common_bufsiz();
127 144
@@ -151,20 +168,21 @@ int script_main(int argc UNUSED_PARAM, char **argv)
151 goto restore; 168 goto restore;
152 } 169 }
153 if (count > 0) { 170 if (count > 0) {
154 if (ENABLE_SCRIPTREPLAY && (opt & OPT_t)) { 171 if (opt & OPT_t) {
155 struct timeval tv; 172 struct timeval tv;
156 double newtime; 173 double newtime;
157 174
158 gettimeofday(&tv, NULL); 175 gettimeofday(&tv, NULL);
159 newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; 176 newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
160 fprintf(stderr, "%f %u\n", newtime - oldtime, count); 177 fprintf(timing_fp, "%f %u\n", newtime - oldtime, count);
161 oldtime = newtime; 178 oldtime = newtime;
162 } 179 }
163 full_write(STDOUT_FILENO, buf, count); 180 full_write(STDOUT_FILENO, buf, count);
164 full_write(outfd, buf, count); 181 full_write(outfd, buf, count);
165 if (opt & OPT_f) { 182 // If we'd be using (buffered) FILE i/o, we'd need this:
166 fsync(outfd); 183 //if (opt & OPT_f) {
167 } 184 // fflush(outfd);
185 //}
168 } 186 }
169 } 187 }
170 if (pfd[1].revents) { 188 if (pfd[1].revents) {
diff --git a/util-linux/scriptreplay.c b/util-linux/scriptreplay.c
index 7e9850103..e3083ab93 100644
--- a/util-linux/scriptreplay.c
+++ b/util-linux/scriptreplay.c
@@ -5,7 +5,6 @@
5 * pascal.bellard@ads-lu.com 5 * pascal.bellard@ads-lu.com
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 *
9 */ 8 */
10//config:config SCRIPTREPLAY 9//config:config SCRIPTREPLAY
11//config: bool "scriptreplay (2.6 kb)" 10//config: bool "scriptreplay (2.6 kb)"
@@ -19,7 +18,7 @@
19//kbuild:lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o 18//kbuild:lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o
20 19
21//usage:#define scriptreplay_trivial_usage 20//usage:#define scriptreplay_trivial_usage
22//usage: "timingfile [typescript [divisor]]" 21//usage: "TIMINGFILE [TYPESCRIPT [DIVISOR]]"
23//usage:#define scriptreplay_full_usage "\n\n" 22//usage:#define scriptreplay_full_usage "\n\n"
24//usage: "Play back typescripts, using timing information" 23//usage: "Play back typescripts, using timing information"
25 24
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index d4b568832..520865318 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -30,10 +30,10 @@
30//config: help 30//config: help
31//config: Alias to "setarch linux64". 31//config: Alias to "setarch linux64".
32 32
33//applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP)) 33//applet:IF_SETARCH(APPLET_NOEXEC(setarch, setarch, BB_DIR_BIN, BB_SUID_DROP, setarch))
34// APPLET_ODDNAME:name main location suid_type help 34// APPLET_NOEXEC:name main location suid_type help
35//applet:IF_LINUX32(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32)) 35//applet:IF_LINUX32(APPLET_NOEXEC(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
36//applet:IF_LINUX64(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64)) 36//applet:IF_LINUX64(APPLET_NOEXEC(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
37 37
38//kbuild:lib-$(CONFIG_SETARCH) += setarch.o 38//kbuild:lib-$(CONFIG_SETARCH) += setarch.o
39//kbuild:lib-$(CONFIG_LINUX32) += setarch.o 39//kbuild:lib-$(CONFIG_LINUX32) += setarch.o
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index 0f85428ab..12ab1bd66 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -5,7 +5,6 @@
5 * Copyright (C) 2017 by <assafgordon@gmail.com> 5 * Copyright (C) 2017 by <assafgordon@gmail.com>
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 *
9 */ 8 */
10//config:config SETPRIV 9//config:config SETPRIV
11//config: bool "setpriv (3.4 kb)" 10//config: bool "setpriv (3.4 kb)"
@@ -125,96 +124,10 @@ enum {
125}; 124};
126 125
127#if ENABLE_FEATURE_SETPRIV_CAPABILITIES 126#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
128struct caps { 127DEFINE_STRUCT_CAPS;
129 struct __user_cap_header_struct header;
130 cap_user_data_t data;
131 int u32s;
132};
133
134# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
135static const char *const capabilities[] = {
136 "chown",
137 "dac_override",
138 "dac_read_search",
139 "fowner",
140 "fsetid",
141 "kill",
142 "setgid",
143 "setuid",
144 "setpcap",
145 "linux_immutable",
146 "net_bind_service",
147 "net_broadcast",
148 "net_admin",
149 "net_raw",
150 "ipc_lock",
151 "ipc_owner",
152 "sys_module",
153 "sys_rawio",
154 "sys_chroot",
155 "sys_ptrace",
156 "sys_pacct",
157 "sys_admin",
158 "sys_boot",
159 "sys_nice",
160 "sys_resource",
161 "sys_time",
162 "sys_tty_config",
163 "mknod",
164 "lease",
165 "audit_write",
166 "audit_control",
167 "setfcap",
168 "mac_override",
169 "mac_admin",
170 "syslog",
171 "wake_alarm",
172 "block_suspend",
173 "audit_read",
174};
175# endif /* FEATURE_SETPRIV_CAPABILITY_NAMES */
176 128
177static void getcaps(struct caps *caps) 129static unsigned parse_cap(const char *cap)
178{ 130{
179 static const uint8_t versions[] = {
180 _LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */
181 _LINUX_CAPABILITY_U32S_2, /* = 2 */
182 _LINUX_CAPABILITY_U32S_1, /* = 1 */
183 };
184 int i;
185
186 caps->header.pid = 0;
187 for (i = 0; i < ARRAY_SIZE(versions); i++) {
188 caps->header.version = versions[i];
189 if (capget(&caps->header, NULL) == 0)
190 goto got_it;
191 }
192 bb_simple_perror_msg_and_die("capget");
193 got_it:
194
195 switch (caps->header.version) {
196 case _LINUX_CAPABILITY_VERSION_1:
197 caps->u32s = _LINUX_CAPABILITY_U32S_1;
198 break;
199 case _LINUX_CAPABILITY_VERSION_2:
200 caps->u32s = _LINUX_CAPABILITY_U32S_2;
201 break;
202 case _LINUX_CAPABILITY_VERSION_3:
203 caps->u32s = _LINUX_CAPABILITY_U32S_3;
204 break;
205 default:
206 bb_error_msg_and_die("unsupported capability version");
207 }
208
209 caps->data = xmalloc(sizeof(caps->data[0]) * caps->u32s);
210 if (capget(&caps->header, caps->data) < 0)
211 bb_simple_perror_msg_and_die("capget");
212}
213
214static void parse_cap(unsigned long *index, const char *cap)
215{
216 unsigned long i;
217
218 switch (cap[0]) { 131 switch (cap[0]) {
219 case '-': 132 case '-':
220 break; 133 break;
@@ -226,26 +139,7 @@ static void parse_cap(unsigned long *index, const char *cap)
226 } 139 }
227 140
228 cap++; 141 cap++;
229 if ((sscanf(cap, "cap_%lu", &i)) == 1) { 142 return cap_name_to_number(cap);
230 if (!cap_valid(i))
231 bb_error_msg_and_die("unsupported capability '%s'", cap);
232 *index = i;
233 return;
234 }
235
236# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
237 for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
238 if (strcmp(capabilities[i], cap) != 0)
239 continue;
240
241 if (!cap_valid(i))
242 bb_error_msg_and_die("unsupported capability '%s'", cap);
243 *index = i;
244 return;
245 }
246# endif
247
248 bb_error_msg_and_die("unknown capability '%s'", cap);
249} 143}
250 144
251static void set_inh_caps(char *capstring) 145static void set_inh_caps(char *capstring)
@@ -256,11 +150,11 @@ static void set_inh_caps(char *capstring)
256 150
257 capstring = strtok(capstring, ","); 151 capstring = strtok(capstring, ",");
258 while (capstring) { 152 while (capstring) {
259 unsigned long cap; 153 unsigned cap;
260 154
261 parse_cap(&cap, capstring); 155 cap = parse_cap(capstring);
262 if (CAP_TO_INDEX(cap) >= caps.u32s) 156 if (CAP_TO_INDEX(cap) >= caps.u32s)
263 bb_error_msg_and_die("invalid capability cap"); 157 bb_error_msg_and_die("invalid capability '%s'", capstring);
264 158
265 if (capstring[0] == '+') 159 if (capstring[0] == '+')
266 caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap); 160 caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
@@ -269,11 +163,8 @@ static void set_inh_caps(char *capstring)
269 capstring = strtok(NULL, ","); 163 capstring = strtok(NULL, ",");
270 } 164 }
271 165
272 if ((capset(&caps.header, caps.data)) < 0) 166 if (capset(&caps.header, caps.data) != 0)
273 bb_perror_msg_and_die("capset"); 167 bb_perror_msg_and_die("capset");
274
275 if (ENABLE_FEATURE_CLEAN_UP)
276 free(caps.data);
277} 168}
278 169
279static void set_ambient_caps(char *string) 170static void set_ambient_caps(char *string)
@@ -282,9 +173,9 @@ static void set_ambient_caps(char *string)
282 173
283 cap = strtok(string, ","); 174 cap = strtok(string, ",");
284 while (cap) { 175 while (cap) {
285 unsigned long index; 176 unsigned index;
286 177
287 parse_cap(&index, cap); 178 index = parse_cap(cap);
288 if (cap[0] == '+') { 179 if (cap[0] == '+') {
289 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0) 180 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0)
290 bb_perror_msg("cap_ambient_raise"); 181 bb_perror_msg("cap_ambient_raise");
@@ -298,16 +189,7 @@ static void set_ambient_caps(char *string)
298#endif /* FEATURE_SETPRIV_CAPABILITIES */ 189#endif /* FEATURE_SETPRIV_CAPABILITIES */
299 190
300#if ENABLE_FEATURE_SETPRIV_DUMP 191#if ENABLE_FEATURE_SETPRIV_DUMP
301# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES 192# if !ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
302static void printf_cap(const char *pfx, unsigned cap_no)
303{
304 if (cap_no < ARRAY_SIZE(capabilities)) {
305 printf("%s%s", pfx, capabilities[cap_no]);
306 return;
307 }
308 printf("%scap_%u", pfx, cap_no);
309}
310# else
311# define printf_cap(pfx, cap_no) printf("%scap_%u", (pfx), (cap_no)) 193# define printf_cap(pfx, cap_no) printf("%scap_%u", (pfx), (cap_no))
312# endif 194# endif
313 195
@@ -396,10 +278,9 @@ static int dump(void)
396 bb_putchar('\n'); 278 bb_putchar('\n');
397# endif 279# endif
398 280
399 if (ENABLE_FEATURE_CLEAN_UP) { 281 if (ENABLE_FEATURE_CLEAN_UP)
400 IF_FEATURE_SETPRIV_CAPABILITIES(free(caps.data);)
401 free(gids); 282 free(gids);
402 } 283
403 return EXIT_SUCCESS; 284 return EXIT_SUCCESS;
404} 285}
405#endif /* FEATURE_SETPRIV_DUMP */ 286#endif /* FEATURE_SETPRIV_DUMP */
@@ -421,9 +302,12 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv)
421 int opts; 302 int opts;
422 IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps, *ambient_caps;) 303 IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps, *ambient_caps;)
423 304
424 applet_long_options = setpriv_longopts; 305 opts = getopt32long(argv, "+"
425 opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d") 306 IF_FEATURE_SETPRIV_DUMP("d")
426 IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:\xfd:", &inh_caps, &ambient_caps)); 307 IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:\xfd:"),
308 setpriv_longopts
309 IF_FEATURE_SETPRIV_CAPABILITIES(, &inh_caps, &ambient_caps)
310 );
427 argv += optind; 311 argv += optind;
428 312
429#if ENABLE_FEATURE_SETPRIV_DUMP 313#if ENABLE_FEATURE_SETPRIV_DUMP
diff --git a/util-linux/setsid.c b/util-linux/setsid.c
index 60cab2fcf..8385a9115 100644
--- a/util-linux/setsid.c
+++ b/util-linux/setsid.c
@@ -37,8 +37,8 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
37{ 37{
38 unsigned opt; 38 unsigned opt;
39 39
40 opt_complementary = "-1"; /* at least one arg */ 40 /* +: stop on first non-opt */
41 opt = getopt32(argv, "+c"); /* +: stop on first non-opt */ 41 opt = getopt32(argv, "^+" "c" "\0" "-1"/* at least one arg */);
42 argv += optind; 42 argv += optind;
43 43
44 /* setsid() is allowed only when we are not a process group leader. 44 /* setsid() is allowed only when we are not a process group leader.
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index 32708934e..080b05e45 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -24,22 +24,33 @@
24//config: * Because the Linux kernel uses rootfs internally as the starting 24//config: * Because the Linux kernel uses rootfs internally as the starting
25//config: and ending point for searching through the kernel's doubly linked 25//config: and ending point for searching through the kernel's doubly linked
26//config: list of active mount points. That's why. 26//config: list of active mount points. That's why.
27//config:
28// RUN_INIT config item is in klibc-utils
27 29
28//applet:IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP)) 30//applet:IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
31// APPLET_ODDNAME:name main location suid_type help
32//applet:IF_RUN_INIT( APPLET_ODDNAME(run-init, switch_root, BB_DIR_SBIN, BB_SUID_DROP, run_init))
29 33
30//kbuild:lib-$(CONFIG_SWITCH_ROOT) += switch_root.o 34//kbuild:lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
31 35//kbuild:lib-$(CONFIG_RUN_INIT) += switch_root.o
32//usage:#define switch_root_trivial_usage
33//usage: "[-c /dev/console] NEW_ROOT NEW_INIT [ARGS]"
34//usage:#define switch_root_full_usage "\n\n"
35//usage: "Free initramfs and switch to another root fs:\n"
36//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
37//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
38//usage: "\n -c DEV Reopen stdio to DEV after switch"
39 36
40#include <sys/vfs.h> 37#include <sys/vfs.h>
41#include <sys/mount.h> 38#include <sys/mount.h>
39#if ENABLE_RUN_INIT
40# include <sys/prctl.h>
41# include <linux/capability.h>
42// #include <sys/capability.h>
43// This header is in libcap, but the functions are in libc.
44// Comment in the header says this above capset/capget:
45/* system calls - look to libc for function to system call mapping */
46extern int capset(cap_user_header_t header, cap_user_data_t data);
47extern int capget(cap_user_header_t header, const cap_user_data_t data);
48// so for bbox, let's just repeat the declarations.
49// This way, libcap needs not be installed in build environment.
50#endif
51
42#include "libbb.h" 52#include "libbb.h"
53
43// Make up for header deficiencies 54// Make up for header deficiencies
44#ifndef RAMFS_MAGIC 55#ifndef RAMFS_MAGIC
45# define RAMFS_MAGIC ((unsigned)0x858458f6) 56# define RAMFS_MAGIC ((unsigned)0x858458f6)
@@ -89,17 +100,125 @@ static void delete_contents(const char *directory, dev_t rootdev)
89 } 100 }
90} 101}
91 102
103#if ENABLE_RUN_INIT
104DEFINE_STRUCT_CAPS;
105
106static void drop_capset(int cap_idx)
107{
108 struct caps caps;
109
110 getcaps(&caps);
111 caps.data[CAP_TO_INDEX(cap_idx)].inheritable &= ~CAP_TO_MASK(cap_idx);
112 if (capset(&caps.header, caps.data) != 0)
113 bb_perror_msg_and_die("capset");
114}
115
116static void drop_bounding_set(int cap_idx)
117{
118 int ret;
119
120 ret = prctl(PR_CAPBSET_READ, cap_idx, 0, 0, 0);
121 if (ret < 0)
122 bb_perror_msg_and_die("prctl: %s", "PR_CAPBSET_READ");
123
124 if (ret == 1) {
125 ret = prctl(PR_CAPBSET_DROP, cap_idx, 0, 0, 0);
126 if (ret != 0)
127 bb_perror_msg_and_die("prctl: %s", "PR_CAPBSET_DROP");
128 }
129}
130
131static void drop_usermodehelper(const char *filename, int cap_idx)
132{
133 unsigned lo, hi;
134 char buf[sizeof(int)*3 * 2 + 8];
135 int fd;
136 int ret;
137
138 ret = open_read_close(filename, buf, sizeof(buf) - 1);
139 if (ret < 0)
140 return; /* assuming files do not exist */
141
142 buf[ret] = '\0';
143 ret = sscanf(buf, "%u %u", &lo, &hi);
144 if (ret != 2)
145 bb_perror_msg_and_die("can't parse file '%s'", filename);
146
147 if (cap_idx < 32)
148 lo &= ~(1 << cap_idx);
149 else
150 hi &= ~(1 << (cap_idx - 32));
151
152 fd = xopen(filename, O_WRONLY);
153 fdprintf(fd, "%u %u", lo, hi);
154 close(fd);
155}
156
157static void drop_capabilities(char *string)
158{
159 char *cap;
160
161 cap = strtok(string, ",");
162 while (cap) {
163 unsigned cap_idx;
164
165 cap_idx = cap_name_to_number(cap);
166 drop_usermodehelper("/proc/sys/kernel/usermodehelper/bset", cap_idx);
167 drop_usermodehelper("/proc/sys/kernel/usermodehelper/inheritable", cap_idx);
168 drop_bounding_set(cap_idx);
169 drop_capset(cap_idx);
170 bb_error_msg("dropped capability: %s", cap);
171 cap = strtok(NULL, ",");
172 }
173}
174#endif
175
92int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 176int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
93int switch_root_main(int argc UNUSED_PARAM, char **argv) 177int switch_root_main(int argc UNUSED_PARAM, char **argv)
94{ 178{
95 char *newroot, *console = NULL; 179 char *newroot, *console = NULL;
96 struct stat st; 180 struct stat st;
97 struct statfs stfs; 181 struct statfs stfs;
182 unsigned dry_run = 0;
98 dev_t rootdev; 183 dev_t rootdev;
99 184
100 // Parse args (-c console) 185 // Parse args. '+': stop at first non-option
101 opt_complementary = "-2"; // minimum 2 params 186 if (ENABLE_SWITCH_ROOT && (!ENABLE_RUN_INIT || applet_name[0] == 's')) {
102 getopt32(argv, "+c:", &console); // '+': stop at first non-option 187//usage:#define switch_root_trivial_usage
188//usage: "[-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
189//usage:#define switch_root_full_usage "\n\n"
190//usage: "Free initramfs and switch to another root fs:\n"
191//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
192//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
193//usage: "\n -c DEV Reopen stdio to DEV after switch"
194 getopt32(argv, "^+"
195 "c:"
196 "\0" "-2" /* minimum 2 args */,
197 &console
198 );
199 } else {
200#if ENABLE_RUN_INIT
201//usage:#define run_init_trivial_usage
202//usage: "[-d CAP,CAP...] [-n] [-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]"
203//usage:#define run_init_full_usage "\n\n"
204//usage: "Free initramfs and switch to another root fs:\n"
205//usage: "chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,\n"
206//usage: "execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.\n"
207//usage: "\n -c DEV Reopen stdio to DEV after switch"
208//usage: "\n -d CAPS Drop capabilities"
209//usage: "\n -n Dry run"
210 char *cap_list = NULL;
211 dry_run = getopt32(argv, "^+"
212 "c:d:n"
213 "\0" "-2" /* minimum 2 args */,
214 &console,
215 &cap_list
216 );
217 dry_run >>= 2; // -n
218 if (cap_list)
219 drop_capabilities(cap_list);
220#endif
221 }
103 argv += optind; 222 argv += optind;
104 newroot = *argv++; 223 newroot = *argv++;
105 224
@@ -108,9 +227,12 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
108 xstat("/", &st); 227 xstat("/", &st);
109 rootdev = st.st_dev; 228 rootdev = st.st_dev;
110 xstat(".", &st); 229 xstat(".", &st);
111 if (st.st_dev == rootdev || getpid() != 1) { 230 if (st.st_dev == rootdev) {
112 // Show usage, it says new root must be a mountpoint 231 // Show usage, it says new root must be a mountpoint
113 // and we must be PID 1 232 bb_show_usage();
233 }
234 if (!dry_run && getpid() != 1) {
235 // Show usage, it says we must be PID 1
114 bb_show_usage(); 236 bb_show_usage();
115 } 237 }
116 238
@@ -118,7 +240,7 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
118 // we mean it. I could make this a CONFIG option, but I would get email 240 // we mean it. I could make this a CONFIG option, but I would get email
119 // from all the people who WILL destroy their filesystems. 241 // from all the people who WILL destroy their filesystems.
120 if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) { 242 if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
121 bb_error_msg_and_die("/init is not a regular file"); 243 bb_error_msg_and_die("'%s' is not a regular file", "/init");
122 } 244 }
123 statfs("/", &stfs); // this never fails 245 statfs("/", &stfs); // this never fails
124 if ((unsigned)stfs.f_type != RAMFS_MAGIC 246 if ((unsigned)stfs.f_type != RAMFS_MAGIC
@@ -127,13 +249,15 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
127 bb_error_msg_and_die("root filesystem is not ramfs/tmpfs"); 249 bb_error_msg_and_die("root filesystem is not ramfs/tmpfs");
128 } 250 }
129 251
130 // Zap everything out of rootdev 252 if (!dry_run) {
131 delete_contents("/", rootdev); 253 // Zap everything out of rootdev
254 delete_contents("/", rootdev);
132 255
133 // Overmount / with newdir and chroot into it 256 // Overmount / with newdir and chroot into it
134 if (mount(".", "/", NULL, MS_MOVE, NULL)) { 257 if (mount(".", "/", NULL, MS_MOVE, NULL)) {
135 // For example, fails when newroot is not a mountpoint 258 // For example, fails when newroot is not a mountpoint
136 bb_perror_msg_and_die("error moving root"); 259 bb_perror_msg_and_die("error moving root");
260 }
137 } 261 }
138 xchroot("."); 262 xchroot(".");
139 // The chdir is needed to recalculate "." and ".." links 263 // The chdir is needed to recalculate "." and ".." links
@@ -149,8 +273,17 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
149 } 273 }
150 } 274 }
151 275
152 // Exec real init 276 if (dry_run) {
153 execv(argv[0], argv); 277 // Does NEW_INIT look like it can be executed?
278 //xstat(argv[0], &st);
279 //if (!S_ISREG(st.st_mode))
280 // bb_perror_msg_and_die("'%s' is not a regular file", argv[0]);
281 if (access(argv[0], X_OK) == 0)
282 return 0;
283 } else {
284 // Exec NEW_INIT
285 execv(argv[0], argv);
286 }
154 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 287 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
155} 288}
156 289
diff --git a/util-linux/taskset.c b/util-linux/taskset.c
index 9957b1a71..401a1bcb7 100644
--- a/util-linux/taskset.c
+++ b/util-linux/taskset.c
@@ -22,7 +22,7 @@
22//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long 22//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long
23//config: in this case. Otherwise, it is limited to sizeof(long). 23//config: in this case. Otherwise, it is limited to sizeof(long).
24 24
25//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) 25//applet:IF_TASKSET(APPLET_NOEXEC(taskset, taskset, BB_DIR_USR_BIN, BB_SUID_DROP, taskset))
26//kbuild:lib-$(CONFIG_TASKSET) += taskset.o 26//kbuild:lib-$(CONFIG_TASKSET) += taskset.o
27 27
28//usage:#define taskset_trivial_usage 28//usage:#define taskset_trivial_usage
@@ -123,8 +123,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
123 * Indeed, util-linux-2.13-pre7 uses: 123 * Indeed, util-linux-2.13-pre7 uses:
124 * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */ 124 * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */
125 125
126 opt_complementary = "-1"; /* at least 1 arg */ 126 opt_p = getopt32(argv, "^+" "p" "\0" "-1" /* at least 1 arg */);
127 opt_p = getopt32(argv, "+p");
128 argv += optind; 127 argv += optind;
129 128
130 aff = *argv++; 129 aff = *argv++;
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 252e8fb64..7ff866cec 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -32,7 +32,10 @@
32#define env ((char **)bb_common_bufsiz1) 32#define env ((char **)bb_common_bufsiz1)
33#define INIT_G() do { setup_common_bufsiz(); } while (0) 33#define INIT_G() do { setup_common_bufsiz(); } while (0)
34enum { 34enum {
35 MAX_ENV = COMMON_BUFSIZE / sizeof(env[0]) - 1, 35 MAX_ENV = COMMON_BUFSIZE / sizeof(char*) - 1,
36 /* sizeof(env[0]) instead of sizeof(char*)
37 * makes gcc-6.3.0 emit "strict-aliasing" warning.
38 */
36}; 39};
37 40
38#ifndef SO_RCVBUFFORCE 41#ifndef SO_RCVBUFFORCE
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 122c0f579..a6405dfcc 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -24,7 +24,20 @@
24//config: help 24//config: help
25//config: Support -a option to unmount all currently mounted filesystems. 25//config: Support -a option to unmount all currently mounted filesystems.
26 26
27//applet:IF_UMOUNT(APPLET(umount, BB_DIR_BIN, BB_SUID_DROP)) 27//applet:IF_UMOUNT(APPLET_NOEXEC(umount, umount, BB_DIR_BIN, BB_SUID_DROP, umount))
28/*
29 * On one hand, in some weird situations you'd want umount
30 * to not do anything surprising, to behave as a usual fork+execed executable.
31 *
32 * OTOH, there can be situations where execing would not succeed, or even hang
33 * (say, if executable is on a filesystem which is in trouble and accesses to it
34 * block in kernel).
35 * In this case, you might be actually happy if your standalone bbox shell
36 * does not fork+exec, but only forks and calls umount_main() which it already has!
37 * Let's go with NOEXEC.
38 *
39 * bb_common_bufsiz1 usage here is safe wrt NOEXEC: not expecting it to be zeroed.
40 */
28 41
29//kbuild:lib-$(CONFIG_UMOUNT) += umount.o 42//kbuild:lib-$(CONFIG_UMOUNT) += umount.o
30 43
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index e7b95c72b..6a3da9f91 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -137,7 +137,7 @@ static const struct namespace_descr ns_list[] = {
137 * we are forced to use "fake" letters for them. 137 * we are forced to use "fake" letters for them.
138 * '+': stop at first non-option. 138 * '+': stop at first non-option.
139 */ 139 */
140static const char opt_str[] ALIGN1 = "+muinpU""fr""\xfd::""\xfe:""\xff:"; 140#define OPT_STR "+muinpU""fr""\xfd::""\xfe:""\xff:"
141static const char unshare_longopts[] ALIGN1 = 141static const char unshare_longopts[] ALIGN1 =
142 "mount\0" Optional_argument "\xf0" 142 "mount\0" Optional_argument "\xf0"
143 "uts\0" Optional_argument "\xf1" 143 "uts\0" Optional_argument "\xf1"
@@ -210,7 +210,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
210 prop_str = PRIVATE_STR; 210 prop_str = PRIVATE_STR;
211 setgrp_str = NULL; 211 setgrp_str = NULL;
212 212
213 opt_complementary = 213 opts = getopt32long(argv, "^" OPT_STR "\0"
214 "\xf0""m" /* long opts (via their "fake chars") imply short opts */ 214 "\xf0""m" /* long opts (via their "fake chars") imply short opts */
215 ":\xf1""u" 215 ":\xf1""u"
216 ":\xf2""i" 216 ":\xf2""i"
@@ -219,16 +219,14 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
219 ":\xf5""U" 219 ":\xf5""U"
220 ":ru" /* --map-root-user or -r implies -u */ 220 ":ru" /* --map-root-user or -r implies -u */
221 ":\xfd""m" /* --mount-proc implies -m */ 221 ":\xfd""m" /* --mount-proc implies -m */
222 ; 222 , unshare_longopts,
223 applet_long_options = unshare_longopts; 223 &proc_mnt_target, &prop_str, &setgrp_str,
224 opts = getopt32(argv, opt_str, 224 &ns_ctx_list[NS_MNT_POS].path,
225 &proc_mnt_target, &prop_str, &setgrp_str, 225 &ns_ctx_list[NS_UTS_POS].path,
226 &ns_ctx_list[NS_MNT_POS].path, 226 &ns_ctx_list[NS_IPC_POS].path,
227 &ns_ctx_list[NS_UTS_POS].path, 227 &ns_ctx_list[NS_NET_POS].path,
228 &ns_ctx_list[NS_IPC_POS].path, 228 &ns_ctx_list[NS_PID_POS].path,
229 &ns_ctx_list[NS_NET_POS].path, 229 &ns_ctx_list[NS_USR_POS].path
230 &ns_ctx_list[NS_PID_POS].path,
231 &ns_ctx_list[NS_USR_POS].path
232 ); 230 );
233 argv += optind; 231 argv += optind;
234 //bb_error_msg("opts:0x%x", opts); 232 //bb_error_msg("opts:0x%x", opts);