diff options
| author | Ron Yorston <rmy@pobox.com> | 2017-08-22 14:56:12 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2017-08-22 14:56:12 +0100 |
| commit | ce9af1cc5ea23f754587448cf35b5120c77bfeef (patch) | |
| tree | 69e5eaba5e75ab909ed92d5045393471b8ff3c13 /util-linux | |
| parent | c170026700eabb10147dd848c45c06995b43a32e (diff) | |
| parent | e837a0dbbebf4229306df98fe9ee3b9bb30630c4 (diff) | |
| download | busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.gz busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.bz2 busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.zip | |
Merge branch 'busybox' into merge
Diffstat (limited to 'util-linux')
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 | ||
| 98 | int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 97 | int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 99 | int ipcrm_main(int argc, char **argv) | 98 | int 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 | |||
| 588 | int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 588 | int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 589 | int ipcs_main(int argc UNUSED_PARAM, char **argv) | 589 | int 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 | }; |
| 106 | enum { | 84 | enum { |
| 107 | NS_USR_POS = 0, | 85 | NS_USR_POS = 0, |
| @@ -130,7 +108,7 @@ static const struct namespace_descr ns_list[] = { | |||
| 130 | */ | 108 | */ |
| 131 | static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F"; | 109 | static 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 |
| 134 | static const char nsenter_longopts[] ALIGN1 = | 112 | static 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 | ||
| 36 | extern int pivot_root(const char * new_root,const char * put_old); | 36 | extern int pivot_root(const char *new_root, const char *put_old); |
| 37 | 37 | ||
| 38 | int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 38 | int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 39 | int pivot_root_main(int argc, char **argv) | 39 | int 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 |
| 128 | struct caps { | 127 | DEFINE_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 | ||
| 135 | static 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 | ||
| 177 | static void getcaps(struct caps *caps) | 129 | static 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 | |||
| 214 | static 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 | ||
| 251 | static void set_inh_caps(char *capstring) | 145 | static 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 | ||
| 279 | static void set_ambient_caps(char *string) | 170 | static 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 |
| 302 | static 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 */ | ||
| 46 | extern int capset(cap_user_header_t header, cap_user_data_t data); | ||
| 47 | extern 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 | ||
| 104 | DEFINE_STRUCT_CAPS; | ||
| 105 | |||
| 106 | static 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 | |||
| 116 | static 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 | |||
| 131 | static 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 | |||
| 157 | static 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 | |||
| 92 | int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 176 | int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 93 | int switch_root_main(int argc UNUSED_PARAM, char **argv) | 177 | int 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) |
| 34 | enum { | 34 | enum { |
| 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 | */ |
| 140 | static const char opt_str[] ALIGN1 = "+muinpU""fr""\xfd::""\xfe:""\xff:"; | 140 | #define OPT_STR "+muinpU""fr""\xfd::""\xfe:""\xff:" |
| 141 | static const char unshare_longopts[] ALIGN1 = | 141 | static 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); |
