Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/miscutils
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (14 years ago)
- Location:
- branches/2.2.9/mindi-busybox/miscutils
- Files:
-
- 22 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/miscutils/Config.in
r1765 r2725 1 # DO NOT EDIT. This file is generated from Config.src 1 2 # 2 3 # For a description of the syntax of this configuration file, … … 6 7 menu "Miscellaneous Utilities" 7 8 9 config CONSPY 10 bool "conspy" 11 default n 12 depends on PLATFORM_LINUX 13 help 14 A text-mode VNC like program for Linux virtual terminals. 15 example: conspy NUM shared access to console num 16 or conspy -nd NUM screenshot of console num 17 or conspy -cs NUM poor man's GNU screen like 18 config NANDWRITE 19 bool "nandwrite" 20 default n 21 depends on PLATFORM_LINUX 22 help 23 Write to the specified MTD device, with bad blocks awareness 24 25 config NANDDUMP 26 bool "nanddump" 27 default n 28 depends on PLATFORM_LINUX 29 help 30 Dump the content of raw NAND chip 31 config UBIATTACH 32 bool "ubiattach" 33 default n 34 depends on PLATFORM_LINUX 35 help 36 Attach MTD device to an UBI device. 37 38 config UBIDETACH 39 bool "ubidetach" 40 default n 41 depends on PLATFORM_LINUX 42 help 43 Detach MTD device from an UBI device. 44 8 45 config ADJTIMEX 9 46 bool "adjtimex" 10 default n 47 default y 48 depends on PLATFORM_LINUX 11 49 help 12 50 Adjtimex reads and optionally sets adjustment parameters for … … 20 58 busybox was built. 21 59 60 config FEATURE_COMPRESS_BBCONFIG 61 bool "Compress bbconfig data" 62 default y 63 depends on BBCONFIG 64 help 65 Store bbconfig data in compressed form, uncompress them on-the-fly 66 before output. 67 68 If you have a really tiny busybox with few applets enabled (and 69 bunzip2 isn't one of them), the overhead of the decompressor might 70 be noticeable. Also, if you run executables directly from ROM 71 and have very little memory, this might not be a win. Otherwise, 72 you probably want this. 73 74 config BEEP 75 bool "beep" 76 default y 77 depends on PLATFORM_LINUX 78 help 79 The beep applets beeps in a given freq/Hz. 80 81 config FEATURE_BEEP_FREQ 82 int "default frequency" 83 range 0 2147483647 84 default 4000 85 depends on BEEP 86 help 87 Frequency for default beep. 88 89 config FEATURE_BEEP_LENGTH_MS 90 int "default length" 91 range 0 2147483647 92 default 30 93 depends on BEEP 94 help 95 Length in ms for default beep. 96 97 config CHAT 98 bool "chat" 99 default y 100 help 101 Simple chat utility. 102 103 config FEATURE_CHAT_NOFAIL 104 bool "Enable NOFAIL expect strings" 105 depends on CHAT 106 default y 107 help 108 When enabled expect strings which are started with a dash trigger 109 no-fail mode. That is when expectation is not met within timeout 110 the script is not terminated but sends next SEND string and waits 111 for next EXPECT string. This allows to compose far more flexible 112 scripts. 113 114 config FEATURE_CHAT_TTY_HIFI 115 bool "Force STDIN to be a TTY" 116 depends on CHAT 117 default n 118 help 119 Original chat always treats STDIN as a TTY device and sets for it 120 so-called raw mode. This option turns on such behaviour. 121 122 config FEATURE_CHAT_IMPLICIT_CR 123 bool "Enable implicit Carriage Return" 124 depends on CHAT 125 default y 126 help 127 When enabled make chat to terminate all SEND strings with a "\r" 128 unless "\c" is met anywhere in the string. 129 130 config FEATURE_CHAT_SWALLOW_OPTS 131 bool "Swallow options" 132 depends on CHAT 133 default y 134 help 135 Busybox chat require no options. To make it not fail when used 136 in place of original chat (which has a bunch of options) turn 137 this on. 138 139 config FEATURE_CHAT_SEND_ESCAPES 140 bool "Support weird SEND escapes" 141 depends on CHAT 142 default y 143 help 144 Original chat uses some escape sequences in SEND arguments which 145 are not sent to device but rather performs special actions. 146 E.g. "\K" means to send a break sequence to device. 147 "\d" delays execution for a second, "\p" -- for a 1/100 of second. 148 Before turning this option on think twice: do you really need them? 149 150 config FEATURE_CHAT_VAR_ABORT_LEN 151 bool "Support variable-length ABORT conditions" 152 depends on CHAT 153 default y 154 help 155 Original chat uses fixed 50-bytes length ABORT conditions. Say N here. 156 157 config FEATURE_CHAT_CLR_ABORT 158 bool "Support revoking of ABORT conditions" 159 depends on CHAT 160 default y 161 help 162 Support CLR_ABORT directive. 163 22 164 config CHRT 23 165 bool "chrt" 24 default n166 default y 25 167 help 26 168 manipulate real-time attributes of a process. … … 29 171 config CROND 30 172 bool "crond" 31 default n 32 select FEATURE_SUID 173 default y 33 174 select FEATURE_SYSLOG 34 175 help 35 176 Crond is a background daemon that parses individual crontab 36 177 files and executes commands on behalf of the users in question. 37 This is a port of dcron from slackware. 178 This is a port of dcron from slackware. It uses files of the 38 179 format /var/spool/cron/crontabs/<username> files, for example: 39 180 $ cat /var/spool/cron/crontabs/root 40 181 # Run daily cron jobs at 4:40 every day: 41 182 40 4 * * * /etc/cron/daily > /dev/null 2>&1 183 184 config FEATURE_CROND_D 185 bool "Support option -d to redirect output to stderr" 186 depends on CROND 187 default y 188 help 189 -d sets loglevel to 0 (most verbose) and directs all output to stderr. 190 191 config FEATURE_CROND_CALL_SENDMAIL 192 bool "Report command output via email (using sendmail)" 193 default y 194 depends on CROND 195 help 196 Command output will be sent to corresponding user via email. 197 198 config FEATURE_CROND_DIR 199 string "crond spool directory" 200 default "/var/spool/cron" 201 depends on CROND || CRONTAB 202 help 203 Location of crond spool. 204 205 config CRONTAB 206 bool "crontab" 207 default y 208 help 209 Crontab manipulates the crontab for a particular user. Only 210 the superuser may specify a different user and/or crontab directory. 42 211 Note that Busybox binary must be setuid root for this applet to 43 212 work properly. 44 213 45 config DEBUG_CROND_OPTION46 bool "Support debug option -d"47 depends on CROND48 default n49 help50 Support option -d to enter debug mode.51 52 config FEATURE_CROND_CALL_SENDMAIL53 bool "Using /usr/sbin/sendmail?"54 default n55 depends on CROND56 help57 Support calling /usr/sbin/sendmail for send cmd outputs.58 59 config CRONTAB60 bool "crontab"61 default n62 select FEATURE_SUID63 help64 Crontab manipulates the crontab for a particular user. Only65 the superuser may specify a different user and/or crontab directory.66 67 214 config DC 68 215 bool "dc" 69 default n216 default y 70 217 help 71 218 Dc is a reverse-polish desk calculator which supports unlimited 72 219 precision arithmetic. 73 220 221 config FEATURE_DC_LIBM 222 bool "Enable power and exp functions (requires libm)" 223 default y 224 depends on DC 225 help 226 Enable power and exp functions. 227 NOTE: This will require libm to be present for linking. 228 74 229 config DEVFSD 75 230 bool "devfsd (obsolete)" 76 231 default n 232 depends on PLATFORM_LINUX 77 233 select FEATURE_SYSLOG 78 234 help 79 This is deprecated, and will be removed at the end of 2008. 235 This is deprecated and should NOT be used anymore. 236 Use linux >= 2.6 (optionally with hotplug) and mdev instead! 237 See docs/mdev.txt for detailed instructions on how to use mdev 238 instead. 80 239 81 240 Provides compatibility with old device names on a devfs systems. … … 86 245 "MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT". 87 246 88 247 But only if they are written UPPERCASE!!!!!!!! 89 248 90 249 config DEVFSD_MODLOAD 91 250 bool "Adds support for MODLOAD keyword in devsfd.conf" 92 default n251 default y 93 252 depends on DEVFSD 94 253 help … … 98 257 config DEVFSD_FG_NP 99 258 bool "Enables the -fg and -np options" 100 default n259 default y 101 260 depends on DEVFSD 102 261 help 103 -fg Run the daemon in the foreground. 104 -np Exit after parsing the configuration file. Do not poll for events. 262 -fg Run the daemon in the foreground. 263 -np Exit after parsing the configuration file. 264 Do not poll for events. 105 265 106 266 config DEVFSD_VERBOSE 107 267 bool "Increases logging (and size)" 108 default n268 default y 109 269 depends on DEVFSD 110 270 help … … 112 272 113 273 config FEATURE_DEVFS 114 bool " Use devfs names for all devices (obsolete)" 115 default n 116 help 117 This is obsolete and will be going away at the end of 2008.. 118 119 This tells busybox to look for names like /dev/loop/0 instead of 120 /dev/loop0. If your /dev directory has normal names instead of 274 bool "Use devfs names for all devices (obsolete)" 275 default n 276 depends on PLATFORM_LINUX 277 help 278 This is obsolete and should NOT be used anymore. 279 Use linux >= 2.6 (optionally with hotplug) and mdev instead! 280 281 For legacy systems -- if there is no way around devfsd -- this 282 tells busybox to look for names like /dev/loop/0 instead of 283 /dev/loop0. If your /dev directory has normal names instead of 121 284 devfs names, you don't want this. 285 286 config DEVMEM 287 bool "devmem" 288 default y 289 help 290 devmem is a small program that reads and writes from physical 291 memory using /dev/mem. 122 292 123 293 config EJECT 124 294 bool "eject" 125 default n 126 help 127 Used to eject cdroms. (defaults to /dev/cdrom) 295 default y 296 depends on PLATFORM_LINUX 297 help 298 Used to eject cdroms. (defaults to /dev/cdrom) 299 300 config FEATURE_EJECT_SCSI 301 bool "SCSI support" 302 default y 303 depends on EJECT 304 help 305 Add the -s option to eject, this allows to eject SCSI-Devices and 306 usb-storage devices. 307 308 config FBSPLASH 309 bool "fbsplash" 310 default y 311 depends on PLATFORM_LINUX 312 help 313 Shows splash image and progress bar on framebuffer device. 314 Can be used during boot phase of an embedded device. ~2kb. 315 Usage: 316 - use kernel option 'vga=xxx' or otherwise enable fb device. 317 - put somewhere fbsplash.cfg file and an image in .ppm format. 318 - $ setsid fbsplash [params] & 319 -c: hide cursor 320 -d /dev/fbN: framebuffer device (if not /dev/fb0) 321 -s path_to_image_file (can be "-" for stdin) 322 -i path_to_cfg_file (can be "-" for stdin) 323 -f path_to_fifo (can be "-" for stdin) 324 - if you want to run it only in presence of kernel parameter: 325 grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params] & 326 - commands for fifo: 327 "NN" (ASCII decimal number) - percentage to show on progress bar 328 "exit" - well you guessed it 329 330 config FLASHCP 331 bool "flashcp" 332 default n # doesn't build on Ubuntu 8.04 333 help 334 The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7. 335 This utility is used to copy images into a MTD device. 336 337 config FLASH_LOCK 338 bool "flash_lock" 339 default n # doesn't build on Ubuntu 8.04 340 help 341 The flash_lock binary from mtd-utils as of git head 5ec0c10d0. This 342 utility locks part or all of the flash device. 343 344 config FLASH_UNLOCK 345 bool "flash_unlock" 346 default n # doesn't build on Ubuntu 8.04 347 help 348 The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This 349 utility unlocks part or all of the flash device. 350 351 config FLASH_ERASEALL 352 bool "flash_eraseall" 353 default n # doesn't build on Ubuntu 8.04 354 help 355 The flash_eraseall binary from mtd-utils as of git head c4c6a59eb. 356 This utility is used to erase the whole MTD device. 357 358 config IONICE 359 bool "ionice" 360 default y 361 depends on PLATFORM_LINUX 362 help 363 Set/set program io scheduling class and priority 364 Requires kernel >= 2.6.13 365 366 config INOTIFYD 367 bool "inotifyd" 368 default n # doesn't build on Knoppix 5 369 help 370 Simple inotify daemon. Reports filesystem changes. Requires 371 kernel >= 2.6.13 128 372 129 373 config LAST 130 374 bool "last" 131 default n132 selectFEATURE_WTMP375 default y 376 depends on FEATURE_WTMP 133 377 help 134 378 'last' displays a list of the last users that logged into the system. 379 380 choice 381 prompt "Choose last implementation" 382 depends on LAST 383 default FEATURE_LAST_FANCY 384 385 config FEATURE_LAST_SMALL 386 bool "small" 387 help 388 This is a small version of last with just the basic set of 389 features. 390 391 config FEATURE_LAST_FANCY 392 bool "huge" 393 help 394 'last' displays detailed information about the last users that 395 logged into the system (mimics sysvinit last). +900 bytes. 396 endchoice 135 397 136 398 config LESS 137 399 bool "less" 138 default n400 default y 139 401 help 140 402 'less' is a pager, meaning that it displays text files. It possesses … … 164 426 The -m flag enables a simpler status line with a percentage. 165 427 166 config FEATURE_LESS_FLAGCS167 bool "Enable flag changes"168 default n169 depends on LESS170 help171 This enables the ability to change command-line flags within172 less itself.173 174 428 config FEATURE_LESS_MARKS 175 429 bool "Enable marks" 176 default n430 default y 177 431 depends on LESS 178 432 help … … 181 435 config FEATURE_LESS_REGEXP 182 436 bool "Enable regular expressions" 183 default n437 default y 184 438 depends on LESS 185 439 help 186 440 Enable regular expressions, allowing complex file searches. 441 442 config FEATURE_LESS_WINCH 443 bool "Enable automatic resizing on window size changes" 444 default y 445 depends on LESS 446 help 447 Makes less track window size changes. 448 449 config FEATURE_LESS_DASHCMD 450 bool "Enable flag changes ('-' command)" 451 default y 452 depends on LESS 453 help 454 This enables the ability to change command-line flags within 455 less itself ('-' keyboard command). 456 457 config FEATURE_LESS_LINENUMS 458 bool "Enable dynamic switching of line numbers" 459 default y 460 depends on FEATURE_LESS_DASHCMD 461 help 462 Enables "-N" command. 187 463 188 464 config HDPARM 189 465 bool "hdparm" 190 default n 191 help 192 Get/Set hard drive parameters. Primarily intended for ATA 193 drives. Adds about 13k (or around 30k if you enable the 466 default y 467 depends on PLATFORM_LINUX 468 help 469 Get/Set hard drive parameters. Primarily intended for ATA 470 drives. Adds about 13k (or around 30k if you enable the 194 471 FEATURE_HDPARM_GET_IDENTITY option).... 195 472 … … 206 483 config FEATURE_HDPARM_HDIO_SCAN_HWIF 207 484 bool "Register an IDE interface (DANGEROUS)" 208 default n485 default y 209 486 depends on HDPARM 210 487 help … … 214 491 config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 215 492 bool "Un-register an IDE interface (DANGEROUS)" 216 default n493 default y 217 494 depends on HDPARM 218 495 help … … 221 498 222 499 config FEATURE_HDPARM_HDIO_DRIVE_RESET 223 bool " perform device reset (DANGEROUS)"224 default n500 bool "Perform device reset (DANGEROUS)" 501 default y 225 502 depends on HDPARM 226 503 help … … 229 506 230 507 config FEATURE_HDPARM_HDIO_TRISTATE_HWIF 231 bool " tristate device for hotswap (DANGEROUS)"232 default n508 bool "Tristate device for hotswap (DANGEROUS)" 509 default y 233 510 depends on HDPARM 234 511 help 235 512 Enables the 'hdparm -x' option to tristate device for hotswap, 236 and the '-b' option to get/set bus state. 513 and the '-b' option to get/set bus state. This is dangerous 237 514 stuff, so you should probably say N. 238 515 239 516 config FEATURE_HDPARM_HDIO_GETSET_DMA 240 bool " get/set using_dma flag (DANGEROUS)"241 default n517 bool "Get/set using_dma flag" 518 default y 242 519 depends on HDPARM 243 520 help 244 521 Enables the 'hdparm -d' option to get/set using_dma flag. 245 This is dangerous stuff, so you should probably say N.246 522 247 523 config MAKEDEVS 248 524 bool "makedevs" 249 default n525 default y 250 526 help 251 527 'makedevs' is a utility used to create a batch of devices with 252 528 one command. 253 . 529 254 530 There are two choices for command line behaviour, the interface 255 531 as used by LEAF/Linux Router Project, or a device table file. 256 . 532 257 533 'leaf' is traditionally what busybox follows, it allows multiple 258 534 devices of a particluar type to be created per command. 259 535 e.g. /dev/hda[0-9] 260 536 Device properties are passed as command line arguments. 261 . 537 262 538 'table' reads device properties from a file or stdin, allowing 263 539 a batch of unrelated devices to be made with one command. … … 277 553 endchoice 278 554 555 config MAN 556 bool "man" 557 default y 558 help 559 Format and display manual pages. 560 561 config MICROCOM 562 bool "microcom" 563 default y 564 help 565 The poor man's minicom utility for chatting with serial port devices. 566 279 567 config MOUNTPOINT 280 568 bool "mountpoint" 281 default n569 default y 282 570 help 283 571 mountpoint checks if the directory is a mountpoint. … … 285 573 config MT 286 574 bool "mt" 287 default n288 help 289 mt is used to control tape devices. 575 default y 576 help 577 mt is used to control tape devices. You can use the mt utility 290 578 to advance or rewind a tape past a specified number of archive 291 579 files on the tape. … … 293 581 config RAIDAUTORUN 294 582 bool "raidautorun" 295 default n 583 default y 584 depends on PLATFORM_LINUX 296 585 help 297 586 raidautorun tells the kernel md driver to … … 300 589 config READAHEAD 301 590 bool "readahead" 302 default n303 depends on LFS 591 default y 592 depends on LFS && PLATFORM_LINUX 304 593 help 305 594 Preload the files listed on the command line into RAM cache so that … … 308 597 This applet just calls the readahead(2) system call on each file. 309 598 It is mainly useful in system startup scripts to preload files 310 or executables before they are used. 311 (in particular when a CPU bound process is running) it can599 or executables before they are used. When used at the right time 600 (in particular when a CPU bound process is running) it can 312 601 significantly speed up system startup. 313 602 … … 315 604 run this applet as a background job. 316 605 606 config RFKILL 607 bool "rfkill" 608 default n # doesn't build on Ubuntu 9.04 609 depends on PLATFORM_LINUX 610 help 611 Enable/disable wireless devices. 612 613 rfkill list : list all wireless devices 614 rfkill list bluetooth : list all bluetooth devices 615 rfkill list 1 : list device corresponding to the given index 616 rfkill block|unblock wlan : block/unblock all wlan(wifi) devices 617 317 618 config RUNLEVEL 318 619 bool "runlevel" 319 default n620 default y 320 621 help 321 622 find the current and previous system runlevel. … … 326 627 config RX 327 628 bool "rx" 328 default n 629 default y 630 depends on PLATFORM_LINUX 329 631 help 330 632 Receive files using the Xmodem protocol. 633 634 config SETSID 635 bool "setsid" 636 default y 637 help 638 setsid runs a program in a new session 331 639 332 640 config STRINGS 333 641 bool "strings" 334 default n642 default y 335 643 help 336 644 strings prints the printable character sequences for each file 337 645 specified. 338 646 339 config SETSID340 bool "setsid"341 default n342 help343 setsid runs a program in a new session344 345 647 config TASKSET 346 648 bool "taskset" 347 default n 649 default n # doesn't build on some non-x86 targets (m68k) 348 650 help 349 651 Retrieve or set a processes's CPU affinity. … … 351 653 352 654 config FEATURE_TASKSET_FANCY 353 bool " fancy output"655 bool "Fancy output" 354 656 default y 355 657 depends on TASKSET … … 361 663 config TIME 362 664 bool "time" 363 default n665 default y 364 666 help 365 667 The time command runs the specified program with the given arguments. … … 367 669 giving timing statistics about this program run. 368 670 671 config TIMEOUT 672 bool "timeout" 673 default y 674 help 675 Runs a program and watches it. If it does not terminate in 676 specified number of seconds, it is sent a signal. 677 369 678 config TTYSIZE 370 679 bool "ttysize" 371 default n680 default y 372 681 help 373 682 A replacement for "stty size". Unlike stty, can report only width, 374 only height, or both, in any order. It also does not complain on error, 375 but returns default 80x24. Usage in shell scripts: width=`ttysize w`. 683 only height, or both, in any order. It also does not complain on 684 error, but returns default 80x24. 685 Usage in shell scripts: width=`ttysize w`. 686 687 config VOLNAME 688 bool "volname" 689 default y 690 help 691 Prints a CD-ROM volume name. 692 693 config WALL 694 bool "wall" 695 default y 696 help 697 Write a message to all users that are logged in. 376 698 377 699 config WATCHDOG 378 700 bool "watchdog" 379 default n 701 default y 702 depends on PLATFORM_LINUX 380 703 help 381 704 The watchdog utility is used with hardware or software watchdog 382 device drivers. 383 and periodically writes a magic character to the device. 705 device drivers. It opens the specified watchdog device special file 706 and periodically writes a magic character to the device. If the 384 707 watchdog applet ever fails to write the magic character within a 385 708 certain amount of time, the watchdog device assumes the system has … … 387 710 388 711 endmenu 389 -
branches/2.2.9/mindi-busybox/miscutils/Kbuild
r1765 r2725 1 # DO NOT EDIT. This file is generated from Kbuild.src 1 2 # Makefile for busybox 2 3 # 3 4 # Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> 4 5 # 5 # Licensed under the GPL v2, see the file LICENSE in this tarball.6 # Licensed under GPLv2, see file LICENSE in this source tree. 6 7 7 8 lib-y:= 9 10 lib-$(CONFIG_CONSPY) += conspy.o 11 lib-$(CONFIG_NANDWRITE) += nandwrite.o 12 lib-$(CONFIG_NANDDUMP) += nandwrite.o 13 lib-$(CONFIG_UBIATTACH) += ubi_attach_detach.o 14 lib-$(CONFIG_UBIDETACH) += ubi_attach_detach.o 8 15 lib-$(CONFIG_ADJTIMEX) += adjtimex.o 9 16 lib-$(CONFIG_BBCONFIG) += bbconfig.o 17 lib-$(CONFIG_BEEP) += beep.o 18 lib-$(CONFIG_CHAT) += chat.o 10 19 lib-$(CONFIG_CHRT) += chrt.o 11 20 lib-$(CONFIG_CROND) += crond.o … … 13 22 lib-$(CONFIG_DC) += dc.o 14 23 lib-$(CONFIG_DEVFSD) += devfsd.o 24 lib-$(CONFIG_DEVMEM) += devmem.o 15 25 lib-$(CONFIG_EJECT) += eject.o 26 lib-$(CONFIG_FBSPLASH) += fbsplash.o 27 lib-$(CONFIG_FLASHCP) += flashcp.o 28 lib-$(CONFIG_FLASH_ERASEALL) += flash_eraseall.o 29 lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o 30 lib-$(CONFIG_FLASH_UNLOCK) += flash_lock_unlock.o 31 lib-$(CONFIG_IONICE) += ionice.o 16 32 lib-$(CONFIG_HDPARM) += hdparm.o 17 lib-$(CONFIG_LAST) += last.o 33 lib-$(CONFIG_INOTIFYD) += inotifyd.o 34 lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o 35 lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o 18 36 lib-$(CONFIG_LESS) += less.o 19 37 lib-$(CONFIG_MAKEDEVS) += makedevs.o 38 lib-$(CONFIG_MAN) += man.o 39 lib-$(CONFIG_MICROCOM) += microcom.o 20 40 lib-$(CONFIG_MOUNTPOINT) += mountpoint.o 21 41 lib-$(CONFIG_MT) += mt.o 22 42 lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o 23 43 lib-$(CONFIG_READAHEAD) += readahead.o 44 lib-$(CONFIG_RFKILL) += rfkill.o 24 45 lib-$(CONFIG_RUNLEVEL) += runlevel.o 25 46 lib-$(CONFIG_RX) += rx.o … … 28 49 lib-$(CONFIG_TASKSET) += taskset.o 29 50 lib-$(CONFIG_TIME) += time.o 51 lib-$(CONFIG_TIMEOUT) += timeout.o 30 52 lib-$(CONFIG_TTYSIZE) += ttysize.o 53 lib-$(CONFIG_VOLNAME) += volname.o 54 lib-$(CONFIG_WALL) += wall.o 31 55 lib-$(CONFIG_WATCHDOG) += watchdog.o -
branches/2.2.9/mindi-busybox/miscutils/adjtimex.c
r1765 r2725 9 9 * busyboxed 20 March 2001, Larry Doolittle <ldoolitt@recycle.lbl.gov> 10 10 * 11 * Licensed under GPLv2 or later, see file L icense in this tarball for details.11 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 12 12 */ 13 13 … … 15 15 #include <sys/timex.h> 16 16 17 static const struct { 18 int bit; 19 const char *name; 20 } statlist[] = { 21 { STA_PLL, "PLL" }, 22 { STA_PPSFREQ, "PPSFREQ" }, 23 { STA_PPSTIME, "PPSTIME" }, 24 { STA_FLL, "FFL" }, 25 { STA_INS, "INS" }, 26 { STA_DEL, "DEL" }, 27 { STA_UNSYNC, "UNSYNC" }, 28 { STA_FREQHOLD, "FREQHOLD" }, 29 { STA_PPSSIGNAL, "PPSSIGNAL" }, 30 { STA_PPSJITTER, "PPSJITTER" }, 31 { STA_PPSWANDER, "PPSWANDER" }, 32 { STA_PPSERROR, "PPSERROR" }, 33 { STA_CLOCKERR, "CLOCKERR" }, 34 { 0, NULL } 17 static const uint16_t statlist_bit[] = { 18 STA_PLL, 19 STA_PPSFREQ, 20 STA_PPSTIME, 21 STA_FLL, 22 STA_INS, 23 STA_DEL, 24 STA_UNSYNC, 25 STA_FREQHOLD, 26 STA_PPSSIGNAL, 27 STA_PPSJITTER, 28 STA_PPSWANDER, 29 STA_PPSERROR, 30 STA_CLOCKERR, 31 0 35 32 }; 33 static const char statlist_name[] = 34 "PLL" "\0" 35 "PPSFREQ" "\0" 36 "PPSTIME" "\0" 37 "FFL" "\0" 38 "INS" "\0" 39 "DEL" "\0" 40 "UNSYNC" "\0" 41 "FREQHOLD" "\0" 42 "PPSSIGNAL" "\0" 43 "PPSJITTER" "\0" 44 "PPSWANDER" "\0" 45 "PPSERROR" "\0" 46 "CLOCKERR" 47 ; 36 48 37 static const char *const ret_code_descript[] = {38 "clock synchronized" ,39 "insert leap second" ,40 "delete leap second" ,41 "leap second in progress" ,42 "leap second has occurred" ,49 static const char ret_code_descript[] = 50 "clock synchronized" "\0" 51 "insert leap second" "\0" 52 "delete leap second" "\0" 53 "leap second in progress" "\0" 54 "leap second has occurred" "\0" 43 55 "clock not synchronized" 44 };56 ; 45 57 46 int adjtimex_main(int argc, char **argv) ;47 int adjtimex_main(int argc , char **argv)58 int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 59 int adjtimex_main(int argc UNUSED_PARAM, char **argv) 48 60 { 49 61 enum { … … 53 65 char *opt_o, *opt_f, *opt_p, *opt_t; 54 66 struct timex txc; 55 int i, ret , sep;67 int i, ret; 56 68 const char *descript; 57 txc.modes=0;58 69 70 opt_complementary = "=0"; /* no valid non-option parameters */ 59 71 opt = getopt32(argv, "qo:f:p:t:", 60 72 &opt_o, &opt_f, &opt_p, &opt_t); 73 txc.modes = 0; 61 74 //if (opt & 0x1) // -q 62 75 if (opt & 0x2) { // -o … … 76 89 txc.modes |= ADJ_TICK; 77 90 } 78 if (argc != optind) { /* no valid non-option parameters */79 bb_show_usage();80 }81 91 82 92 ret = adjtimex(&txc); 83 93 84 if (ret < 0) perror("adjtimex"); 94 if (ret < 0) { 95 bb_perror_nomsg_and_die(); 96 } 85 97 86 if (!(opt & OPT_quiet) && ret>=0) { 98 if (!(opt & OPT_quiet)) { 99 int sep; 100 const char *name; 101 87 102 printf( 88 103 " mode: %d\n" … … 91 106 " maxerror: %ld\n" 92 107 " esterror: %ld\n" 93 " status: %d ( 108 " status: %d (", 94 109 txc.modes, txc.offset, txc.freq, txc.maxerror, 95 110 txc.esterror, txc.status); … … 97 112 /* representative output of next code fragment: 98 113 "PLL | PPSTIME" */ 99 sep=0; 100 for (i=0; statlist[i].name; i++) { 101 if (txc.status & statlist[i].bit) { 102 if (sep) fputs(" | ",stdout); 103 fputs(statlist[i].name,stdout); 104 sep=1; 114 name = statlist_name; 115 sep = 0; 116 for (i = 0; statlist_bit[i]; i++) { 117 if (txc.status & statlist_bit[i]) { 118 if (sep) 119 fputs(" | ", stdout); 120 fputs(name, stdout); 121 sep = 1; 105 122 } 123 name += strlen(name) + 1; 106 124 } 107 125 108 126 descript = "error"; 109 if (ret >= 0 && ret <= 5) descript = ret_code_descript[ret]; 110 printf(" )\n" 127 if (ret <= 5) 128 descript = nth_string(ret_code_descript, ret); 129 printf(")\n" 111 130 "-p timeconstant: %ld\n" 112 131 " precision: %ld\n" … … 120 139 (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript); 121 140 } 122 return (ret<0); 141 142 return 0; 123 143 } -
branches/2.2.9/mindi-busybox/miscutils/bbconfig.c
r1765 r2725 4 4 #include "libbb.h" 5 5 #include "bbconfigopts.h" 6 #if ENABLE_FEATURE_COMPRESS_BBCONFIG 7 # include "archive.h" 8 # include "bbconfigopts_bz2.h" 9 #endif 6 10 7 int bbconfig_main(int argc, char **argv) ;8 int bbconfig_main(int argc , char **argv)11 int bbconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 12 int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 9 13 { 10 printf(bbconfig_config); 14 #if ENABLE_FEATURE_COMPRESS_BBCONFIG 15 bunzip_data *bd; 16 int i = start_bunzip(&bd, 17 /* src_fd: */ -1, 18 /* inbuf: */ bbconfig_config_bz2, 19 /* len: */ sizeof(bbconfig_config_bz2)); 20 /* read_bunzip can longjmp to start_bunzip, and ultimately 21 * end up here with i != 0 on read data errors! Not trivial */ 22 if (!i) { 23 /* Cannot use xmalloc: will leak bd in NOFORK case! */ 24 char *outbuf = malloc_or_warn(sizeof(bbconfig_config)); 25 if (outbuf) { 26 read_bunzip(bd, outbuf, sizeof(bbconfig_config)); 27 full_write1_str(outbuf); 28 } 29 } 30 #else 31 full_write1_str(bbconfig_config); 32 #endif 11 33 return 0; 12 34 } -
branches/2.2.9/mindi-busybox/miscutils/chrt.c
r1765 r2725 2 2 /* 3 3 * chrt - manipulate real-time attributes of a process 4 * Copyright (c) 2006-2007 Bernhard Fischer4 * Copyright (c) 2006-2007 Bernhard Reutner-Fischer 5 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 7 */ 8 9 8 #include <sched.h> 10 #include <getopt.h> /* optind */11 9 #include "libbb.h" 12 10 #ifndef _POSIX_PRIORITY_SCHEDULING 13 11 #warning your system may be foobared 14 12 #endif 13 15 14 static const struct { 16 constint policy;17 c onst char const name[12];15 int policy; 16 char name[sizeof("SCHED_OTHER")]; 18 17 } policies[] = { 19 18 {SCHED_OTHER, "SCHED_OTHER"}, … … 22 21 }; 23 22 23 //TODO: add 24 // -b, SCHED_BATCH 25 // -i, SCHED_IDLE 26 24 27 static void show_min_max(int pol) 25 28 { 26 const char *fmt = "%s min/max priority\t: % d/%d\n\0%s not supported?\n";29 const char *fmt = "%s min/max priority\t: %u/%u\n"; 27 30 int max, min; 31 28 32 max = sched_get_priority_max(pol); 29 33 min = sched_get_priority_min(pol); 30 if (max >= 0 && min >= 0) 31 printf(fmt, policies[pol].name, min, max); 32 else { 33 fmt += 29; 34 printf(fmt, policies[pol].name); 35 } 34 if ((max|min) < 0) 35 fmt = "%s not supported\n"; 36 printf(fmt, policies[pol].name, min, max); 36 37 } 37 38 … … 42 43 #define OPT_o (1<<4) 43 44 44 int chrt_main(int argc, char ** argv);45 int chrt_main(int argc , char**argv)45 int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 46 int chrt_main(int argc UNUSED_PARAM, char **argv) 46 47 { 47 48 pid_t pid = 0; 48 49 unsigned opt; 49 50 struct sched_param sp; 50 char *p_opt = NULL, *priority = NULL; 51 const char *state = "current\0new"; 52 int prio = 0, policy = SCHED_RR; 51 char *pid_str; 52 char *priority = priority; /* for compiler */ 53 const char *current_new; 54 int policy = SCHED_RR; 53 55 54 opt_complementary = "r--fo:f--ro:r--fo"; /* only one policy accepted */ 55 opt = getopt32(argv, "+mp:rfo", &p_opt); 56 /* at least 1 arg; only one policy accepted */ 57 opt_complementary = "-1:r--fo:f--ro:r--fo"; 58 opt = getopt32(argv, "+mprfo"); 56 59 if (opt & OPT_r) 57 60 policy = SCHED_RR; … … 60 63 if (opt & OPT_o) 61 64 policy = SCHED_OTHER; 62 63 65 if (opt & OPT_m) { /* print min/max */ 64 66 show_min_max(SCHED_FIFO); … … 67 69 fflush_stdout_and_exit(EXIT_SUCCESS); 68 70 } 71 72 argv += optind; 69 73 if (opt & OPT_p) { 70 if (argc == optind+1) { /* -p <priority> <pid> */ 71 priority = p_opt; 72 p_opt = argv[optind]; 74 pid_str = *argv++; 75 if (*argv) { /* "-p <priority> <pid> [...]" */ 76 priority = pid_str; 77 pid_str = *argv; 73 78 } 74 argv += optind; /* me -p <arg>*/75 pid = xatoul_range(p _opt, 1, ULONG_MAX); /* -p <pid> */79 /* else "-p <pid>", and *argv == NULL */ 80 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); 76 81 } else { 77 argv += optind; /* me -p <arg> */ 78 priority = *argv; 79 } 80 if (priority) { 81 /* from the manpage of sched_getscheduler: 82 [...] sched_priority can have a value 83 in the range 0 to 99. 84 [...] SCHED_OTHER or SCHED_BATCH must be assigned 85 the static priority 0. [...] SCHED_FIFO or 86 SCHED_RR can have a static priority in the range 1 to 99. 87 */ 88 prio = xstrtol_range(priority, 0, policy == SCHED_OTHER 89 ? 0 : 1, 99); 82 priority = *argv++; 83 if (!*argv) 84 bb_show_usage(); 90 85 } 91 86 87 current_new = "current\0new"; 92 88 if (opt & OPT_p) { 93 int pol = 0;94 print_rt_info:89 int pol; 90 print_rt_info: 95 91 pol = sched_getscheduler(pid); 96 92 if (pol < 0) 97 bb_perror_msg_and_die(" failed to%cet pid %d's policy", 'g', pid);93 bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', pid); 98 94 printf("pid %d's %s scheduling policy: %s\n", 99 pid, state, policies[pol].name);95 pid, current_new, policies[pol].name); 100 96 if (sched_getparam(pid, &sp)) 101 bb_perror_msg_and_die(" failed toget pid %d's attributes", pid);97 bb_perror_msg_and_die("can't get pid %d's attributes", pid); 102 98 printf("pid %d's %s scheduling priority: %d\n", 103 pid, state, sp.sched_priority); 104 if (!*argv) /* no new prio given or we did print already, done. */ 99 pid, current_new, sp.sched_priority); 100 if (!*argv) { 101 /* Either it was just "-p <pid>", 102 * or it was "-p <priority> <pid>" and we came here 103 * for the second time (see goto below) */ 105 104 return EXIT_SUCCESS; 105 } 106 *argv = NULL; 107 current_new += 8; 106 108 } 107 109 108 sp.sched_priority = prio; 110 /* from the manpage of sched_getscheduler: 111 [...] sched_priority can have a value in the range 0 to 99. 112 [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0. 113 [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range. 114 */ 115 sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99); 116 109 117 if (sched_setscheduler(pid, policy, &sp) < 0) 110 bb_perror_msg_and_die("failed to %cet pid %d's policy", 's', pid); 111 if (opt & OPT_p) { 112 state += 8; 113 ++argv; 118 bb_perror_msg_and_die("can't %cet pid %d's policy", 's', pid); 119 120 if (!argv[0]) /* "-p <priority> <pid> [...]" */ 114 121 goto print_rt_info; 115 } 116 ++argv; 117 BB_EXECVP(*argv, argv); 118 bb_perror_msg_and_die("%s", *argv); 122 123 BB_EXECVP_or_die(argv); 119 124 } 120 #undef OPT_p121 #undef OPT_r122 #undef OPT_f123 #undef OPT_o124 #undef OPT_m -
branches/2.2.9/mindi-busybox/miscutils/crond.c
r1765 r2725 9 9 * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002 10 10 * 11 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.11 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 12 12 */ 13 13 14 #include <sys/syslog.h>15 14 #include "libbb.h" 16 17 #ifndef CRONTABS 18 #define CRONTABS "/var/spool/cron/crontabs" 19 #endif 20 #ifndef TMPDIR 21 #define TMPDIR "/var/spool/cron" 22 #endif 15 #include <syslog.h> 16 17 /* glibc frees previous setenv'ed value when we do next setenv() 18 * of the same variable. uclibc does not do this! */ 19 #if (defined(__GLIBC__) && !defined(__UCLIBC__)) /* || OTHER_SAFE_LIBC... */ 20 # define SETENV_LEAKS 0 21 #else 22 # define SETENV_LEAKS 1 23 #endif 24 25 26 #define TMPDIR CONFIG_FEATURE_CROND_DIR 27 #define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" 23 28 #ifndef SENDMAIL 24 # define SENDMAIL"sendmail"29 # define SENDMAIL "sendmail" 25 30 #endif 26 31 #ifndef SENDMAIL_ARGS 27 # define SENDMAIL_ARGS "-ti", "oem"32 # define SENDMAIL_ARGS "-ti" 28 33 #endif 29 34 #ifndef CRONUPDATE 30 # define CRONUPDATE"cron.update"35 # define CRONUPDATE "cron.update" 31 36 #endif 32 37 #ifndef MAXLINES 33 #define MAXLINES 256 /* max lines in non-root crontabs */ 34 #endif 38 # define MAXLINES 256 /* max lines in non-root crontabs */ 39 #endif 40 35 41 36 42 typedef struct CronFile { 37 struct CronFile *cf_ Next;38 struct CronLine *cf_ LineBase;39 char *cf_ User; /* username */40 int cf_Ready;/* bool: one or more jobs ready */41 int cf_Running;/* bool: one or more jobs running */42 int cf_Deleted; /* marked for deletion, ignore*/43 struct CronFile *cf_next; 44 struct CronLine *cf_lines; 45 char *cf_username; 46 smallint cf_wants_starting; /* bool: one or more jobs ready */ 47 smallint cf_has_running; /* bool: one or more jobs running */ 48 smallint cf_deleted; /* marked for deletion (but still has running jobs) */ 43 49 } CronFile; 44 50 45 51 typedef struct CronLine { 46 struct CronLine *cl_Next; 47 char *cl_Shell; /* shell command */ 48 pid_t cl_Pid; /* running pid, 0, or armed (-1) */ 49 int cl_MailFlag; /* running pid is for mail */ 50 int cl_MailPos; /* 'empty file' size */ 51 char cl_Mins[60]; /* 0-59 */ 52 char cl_Hrs[24]; /* 0-23 */ 53 char cl_Days[32]; /* 1-31 */ 54 char cl_Mons[12]; /* 0-11 */ 55 char cl_Dow[7]; /* 0-6, beginning sunday */ 52 struct CronLine *cl_next; 53 char *cl_cmd; /* shell command */ 54 pid_t cl_pid; /* >0:running, <0:needs to be started in this minute, 0:dormant */ 55 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 56 int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */ 57 char *cl_mailto; /* whom to mail results, may be NULL */ 58 #endif 59 /* ordered by size, not in natural order. makes code smaller: */ 60 char cl_Dow[7]; /* 0-6, beginning sunday */ 61 char cl_Mons[12]; /* 0-11 */ 62 char cl_Hrs[24]; /* 0-23 */ 63 char cl_Days[32]; /* 1-31 */ 64 char cl_Mins[60]; /* 0-59 */ 56 65 } CronLine; 57 66 58 #define RUN_RANOUT 1 59 #define RUN_RUNNING 2 60 #define RUN_FAILED 3 61 62 #define DaemonUid 0 63 64 #if ENABLE_DEBUG_CROND_OPTION 65 static unsigned DebugOpt; 66 #endif 67 68 static unsigned LogLevel = 8; 69 static const char *LogFile; 70 static const char *CDir = CRONTABS; 71 72 static void startlogger(void); 73 74 static void CheckUpdates(void); 75 static void SynchronizeDir(void); 76 static int TestJobs(time_t t1, time_t t2); 77 static void RunJobs(void); 78 static int CheckJobs(void); 79 80 static void RunJob(const char *user, CronLine * line); 81 82 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 83 static void EndJob(const char *user, CronLine * line); 67 68 #define DAEMON_UID 0 69 70 71 enum { 72 OPT_l = (1 << 0), 73 OPT_L = (1 << 1), 74 OPT_f = (1 << 2), 75 OPT_b = (1 << 3), 76 OPT_S = (1 << 4), 77 OPT_c = (1 << 5), 78 OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D, 79 }; 80 #if ENABLE_FEATURE_CROND_D 81 # define DebugOpt (option_mask32 & OPT_d) 84 82 #else 85 #define EndJob(user, line) line->cl_Pid = 0 86 #endif 87 88 static void DeleteFile(const char *userName); 89 90 static CronFile *FileBase; 91 92 83 # define DebugOpt 0 84 #endif 85 86 87 struct globals { 88 unsigned log_level; /* = 8; */ 89 time_t crontab_dir_mtime; 90 const char *log_filename; 91 const char *crontab_dir_name; /* = CRONTABS; */ 92 CronFile *cron_files; 93 #if SETENV_LEAKS 94 char *env_var_user; 95 char *env_var_home; 96 #endif 97 } FIX_ALIASING; 98 #define G (*(struct globals*)&bb_common_bufsiz1) 99 #define INIT_G() do { \ 100 G.log_level = 8; \ 101 G.crontab_dir_name = CRONTABS; \ 102 } while (0) 103 104 105 /* 0 is the most verbose, default 8 */ 106 #define LVL5 "\x05" 107 #define LVL7 "\x07" 108 #define LVL8 "\x08" 109 #define WARN9 "\x49" 110 #define DIE9 "\xc9" 111 /* level >= 20 is "error" */ 112 #define ERR20 "\x14" 113 114 static void crondlog(const char *ctl, ...) __attribute__ ((format (printf, 1, 2))); 93 115 static void crondlog(const char *ctl, ...) 94 116 { 95 117 va_list va; 96 const char *fmt; 97 int level = (int) (ctl[0] & 0xf); 98 int type = level == 20 ? 99 LOG_ERR : ((ctl[0] & 0100) ? LOG_WARNING : LOG_NOTICE); 100 118 int level = (ctl[0] & 0x1f); 101 119 102 120 va_start(va, ctl); 103 fmt = ctl + 1; 104 if (level >= LogLevel) { 105 106 #if ENABLE_DEBUG_CROND_OPTION 107 if (DebugOpt) { 108 vfprintf(stderr, fmt, va); 109 } else 110 #endif 111 if (LogFile == 0) { 112 vsyslog(type, fmt, va); 121 if (level >= (int)G.log_level) { 122 /* Debug mode: all to (non-redirected) stderr, */ 123 /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */ 124 if (!DebugOpt && G.log_filename) { 125 /* Otherwise (log to file): we reopen log file at every write: */ 126 int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND); 127 if (logfd >= 0) 128 xmove_fd(logfd, STDERR_FILENO); 129 } 130 /* When we log to syslog, level > 8 is logged at LOG_ERR 131 * syslog level, level <= 8 is logged at LOG_INFO. */ 132 if (level > 8) { 133 bb_verror_msg(ctl + 1, va, /* strerr: */ NULL); 113 134 } else { 114 #if !ENABLE_DEBUG_CROND_OPTION 115 int logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600); 116 #else 117 int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600); 118 #endif 119 if (logfd >= 0) { 120 vdprintf(logfd, fmt, va); 121 close(logfd); 122 } 135 char *msg = NULL; 136 vasprintf(&msg, ctl + 1, va); 137 bb_info_msg("%s: %s", applet_name, msg); 138 free(msg); 123 139 } 124 140 } 125 141 va_end(va); 126 if (ctl[0] & 0 200) {142 if (ctl[0] & 0x80) 127 143 exit(20); 128 } 129 } 130 131 int crond_main(int ac, char **av); 132 int crond_main(int ac, char **av) 133 { 134 unsigned opt; 135 char *lopt, *Lopt, *copt; 136 USE_DEBUG_CROND_OPTION(char *dopt;) 137 138 opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l"); 139 opterr = 0; /* disable getopt 'errors' message. */ 140 opt = getopt32(av, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"), 141 &lopt, &Lopt, &copt USE_DEBUG_CROND_OPTION(, &dopt)); 142 if (opt & 1) /* -l */ 143 LogLevel = xatou(lopt); 144 if (opt & 2) /* -L */ 145 if (*Lopt) 146 LogFile = Lopt; 147 if (opt & 32) /* -c */ 148 if (*copt) 149 CDir = copt; 150 #if ENABLE_DEBUG_CROND_OPTION 151 if (opt & 64) { /* -d */ 152 DebugOpt = xatou(dopt); 153 LogLevel = 0; 154 } 155 #endif 156 157 /* close stdin and stdout, stderr. 158 * close unused descriptors - don't need. 159 * optional detach from controlling terminal 160 */ 161 if (!(opt & 4)) 162 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, av); 163 164 xchdir(CDir); 165 signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ 166 167 startlogger(); /* need if syslog mode selected */ 168 169 /* 170 * main loop - synchronize to 1 second after the minute, minimum sleep 171 * of 1 second. 172 */ 173 crondlog("\011%s " BB_VER " started, log level %d\n", 174 applet_name, LogLevel); 175 176 SynchronizeDir(); 177 178 { 179 time_t t1 = time(NULL); 180 time_t t2; 181 long dt; 182 int rescan = 60; 183 short sleep_time = 60; 184 185 write_pidfile("/var/run/crond.pid"); 186 for (;;) { 187 sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time)); 188 189 t2 = time(NULL); 190 dt = t2 - t1; 191 192 /* 193 * The file 'cron.update' is checked to determine new cron 194 * jobs. The directory is rescanned once an hour to deal 195 * with any screwups. 196 * 197 * check for disparity. Disparities over an hour either way 198 * result in resynchronization. A reverse-indexed disparity 199 * less then an hour causes us to effectively sleep until we 200 * match the original time (i.e. no re-execution of jobs that 201 * have just been run). A forward-indexed disparity less then 202 * an hour causes intermediate jobs to be run, but only once 203 * in the worst case. 204 * 205 * when running jobs, the inequality used is greater but not 206 * equal to t1, and less then or equal to t2. 207 */ 208 209 if (--rescan == 0) { 210 rescan = 60; 211 SynchronizeDir(); 212 } 213 CheckUpdates(); 214 #if ENABLE_DEBUG_CROND_OPTION 215 if (DebugOpt) 216 crondlog("\005Wakeup dt=%d\n", dt); 217 #endif 218 if (dt < -60 * 60 || dt > 60 * 60) { 219 t1 = t2; 220 crondlog("\111time disparity of %d minutes detected\n", dt / 60); 221 } else if (dt > 0) { 222 TestJobs(t1, t2); 223 RunJobs(); 224 sleep(5); 225 if (CheckJobs() > 0) { 226 sleep_time = 10; 227 } else { 228 sleep_time = 60; 229 } 230 t1 = t2; 231 } 232 } 233 } 234 return 0; /* not reached */ 235 } 236 237 static int ChangeUser(const char *user) 238 { 239 struct passwd *pas; 240 const char *err_msg; 241 242 /* 243 * Obtain password entry and change privileges 244 */ 245 pas = getpwnam(user); 246 if (pas == 0) { 247 crondlog("\011failed to get uid for %s", user); 248 return -1; 249 } 250 setenv("USER", pas->pw_name, 1); 251 setenv("HOME", pas->pw_dir, 1); 252 setenv("SHELL", DEFAULT_SHELL, 1); 253 254 /* 255 * Change running state to the user in question 256 */ 257 err_msg = change_identity_e2str(pas); 258 if (err_msg) { 259 crondlog("\011%s for user %s", err_msg, user); 260 return -1; 261 } 262 if (chdir(pas->pw_dir) < 0) { 263 crondlog("\011chdir failed: %s: %m", pas->pw_dir); 264 if (chdir(TMPDIR) < 0) { 265 crondlog("\011chdir failed: %s: %m", TMPDIR); 266 return -1; 267 } 268 } 269 return pas->pw_uid; 270 } 271 272 static void startlogger(void) 273 { 274 if (LogFile == 0) { 275 openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); 276 } 277 #if ENABLE_DEBUG_CROND_OPTION 278 else { /* test logfile */ 279 int logfd; 280 281 logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600); 282 if (logfd >= 0) { 283 close(logfd); 284 } 285 } 286 #endif 287 } 288 144 } 289 145 290 146 static const char DowAry[] ALIGN1 = … … 298 154 ; 299 155 300 static char *ParseField(char *user, char *ary, int modvalue, int off,156 static void ParseField(char *user, char *ary, int modvalue, int off, 301 157 const char *names, char *ptr) 302 158 /* 'names' is a pointer to a set of 3-char abbreviations */ … … 306 162 int n2 = -1; 307 163 308 if (base == NULL) {309 return NULL;310 }311 312 while ( *ptr != ' ' && *ptr != '\t' && *ptr != '\n') {164 // this can't happen due to config_read() 165 /*if (base == NULL) 166 return;*/ 167 168 while (1) { 313 169 int skip = 0; 314 170 315 171 /* Handle numeric digit or symbol or '*' */ 316 317 172 if (*ptr == '*') { 318 n1 = 0; 173 n1 = 0; /* everything will be filled */ 319 174 n2 = modvalue - 1; 320 175 skip = 1; 321 176 ++ptr; 322 } else if (*ptr >= '0' && *ptr <= '9') { 177 } else if (isdigit(*ptr)) { 178 char *endp; 323 179 if (n1 < 0) { 324 n1 = strtol(ptr, & ptr, 10) + off;180 n1 = strtol(ptr, &endp, 10) + off; 325 181 } else { 326 n2 = strtol(ptr, &ptr, 10) + off; 327 } 182 n2 = strtol(ptr, &endp, 10) + off; 183 } 184 ptr = endp; /* gcc likes temp var for &endp */ 328 185 skip = 1; 329 186 } else if (names) { … … 346 203 347 204 /* handle optional range '-' */ 348 349 205 if (skip == 0) { 350 crondlog("\111failed user %s parsing %s\n", user, base); 351 return NULL; 206 goto err; 352 207 } 353 208 if (*ptr == '-' && n2 < 0) { … … 360 215 * in the character array appropriately. 361 216 */ 362 363 217 if (n2 < 0) { 364 218 n2 = n1; 365 219 } 366 220 if (*ptr == '/') { 367 skip = strtol(ptr + 1, &ptr, 10); 368 } 221 char *endp; 222 skip = strtol(ptr + 1, &endp, 10); 223 ptr = endp; /* gcc likes temp var for &endp */ 224 } 225 369 226 /* 370 227 * fill array, using a failsafe is the easiest way to prevent 371 228 * an endless loop 372 229 */ 373 374 230 { 375 231 int s0 = 1; … … 384 240 s0 = skip; 385 241 } 386 } 387 while (n1 != n2 && --failsafe); 388 389 if (failsafe == 0) { 390 crondlog("\111failed user %s parsing %s\n", user, base); 391 return NULL; 392 } 242 if (--failsafe == 0) { 243 goto err; 244 } 245 } while (n1 != n2); 393 246 } 394 247 if (*ptr != ',') { … … 400 253 } 401 254 402 if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') { 403 crondlog("\111failed user %s parsing %s\n", user, base); 404 return NULL; 405 } 406 407 while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') { 408 ++ptr; 409 } 410 #if ENABLE_DEBUG_CROND_OPTION 411 if (DebugOpt) { 255 if (*ptr) { 256 err: 257 crondlog(WARN9 "user %s: parse error at %s", user, base); 258 return; 259 } 260 261 if (DebugOpt && (G.log_level <= 5)) { /* like LVL5 */ 262 /* can't use crondlog, it inserts '\n' */ 412 263 int i; 413 414 for (i = 0; i < modvalue; ++i) { 415 crondlog("\005%d", ary[i]); 416 } 417 crondlog("\005\n"); 418 } 419 #endif 420 421 return ptr; 422 } 423 424 static void FixDayDow(CronLine * line) 425 { 426 int i; 264 for (i = 0; i < modvalue; ++i) 265 fprintf(stderr, "%d", (unsigned char)ary[i]); 266 bb_putchar_stderr('\n'); 267 } 268 } 269 270 static void FixDayDow(CronLine *line) 271 { 272 unsigned i; 427 273 int weekUsed = 0; 428 274 int daysUsed = 0; 429 275 430 for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Dow)); ++i) {276 for (i = 0; i < ARRAY_SIZE(line->cl_Dow); ++i) { 431 277 if (line->cl_Dow[i] == 0) { 432 278 weekUsed = 1; … … 434 280 } 435 281 } 436 for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Days)); ++i) {282 for (i = 0; i < ARRAY_SIZE(line->cl_Days); ++i) { 437 283 if (line->cl_Days[i] == 0) { 438 284 daysUsed = 1; … … 440 286 } 441 287 } 442 if (weekUsed && !daysUsed) { 443 memset(line->cl_Days, 0, sizeof(line->cl_Days)); 444 } 445 if (daysUsed && !weekUsed) { 446 memset(line->cl_Dow, 0, sizeof(line->cl_Dow)); 447 } 448 } 449 450 451 452 static void SynchronizeFile(const char *fileName) 453 { 454 int maxEntries = MAXLINES; 288 if (weekUsed != daysUsed) { 289 if (weekUsed) 290 memset(line->cl_Days, 0, sizeof(line->cl_Days)); 291 else /* daysUsed */ 292 memset(line->cl_Dow, 0, sizeof(line->cl_Dow)); 293 } 294 } 295 296 /* 297 * delete_cronfile() - delete user database 298 * 299 * Note: multiple entries for same user may exist if we were unable to 300 * completely delete a database due to running processes. 301 */ 302 //FIXME: we will start a new job even if the old job is running 303 //if crontab was reloaded: crond thinks that "new" job is different from "old" 304 //even if they are in fact completely the same. Example 305 //Crontab was: 306 // 0-59 * * * * job1 307 // 0-59 * * * * long_running_job2 308 //User edits crontab to: 309 // 0-59 * * * * job1_updated 310 // 0-59 * * * * long_running_job2 311 //Bug: crond can now start another long_running_job2 even if old one 312 //is still running. 313 //OTOH most other versions of cron do not wait for job termination anyway, 314 //they end up with multiple copies of jobs if they don't terminate soon enough. 315 static void delete_cronfile(const char *userName) 316 { 317 CronFile **pfile = &G.cron_files; 318 CronFile *file; 319 320 while ((file = *pfile) != NULL) { 321 if (strcmp(userName, file->cf_username) == 0) { 322 CronLine **pline = &file->cf_lines; 323 CronLine *line; 324 325 file->cf_has_running = 0; 326 file->cf_deleted = 1; 327 328 while ((line = *pline) != NULL) { 329 if (line->cl_pid > 0) { 330 file->cf_has_running = 1; 331 pline = &line->cl_next; 332 } else { 333 *pline = line->cl_next; 334 free(line->cl_cmd); 335 free(line); 336 } 337 } 338 if (file->cf_has_running == 0) { 339 *pfile = file->cf_next; 340 free(file->cf_username); 341 free(file); 342 continue; 343 } 344 } 345 pfile = &file->cf_next; 346 } 347 } 348 349 static void load_crontab(const char *fileName) 350 { 351 struct parser_t *parser; 352 struct stat sbuf; 455 353 int maxLines; 456 char buf[1024]; 457 458 if (strcmp(fileName, "root") == 0) { 459 maxEntries = 65535; 460 } 461 maxLines = maxEntries * 10; 462 463 if (fileName) { 464 FILE *fi; 465 466 DeleteFile(fileName); 467 468 fi = fopen(fileName, "r"); 469 if (fi != NULL) { 470 struct stat sbuf; 471 472 if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { 473 CronFile *file = xzalloc(sizeof(CronFile)); 474 CronLine **pline; 475 476 file->cf_User = strdup(fileName); 477 pline = &file->cf_LineBase; 478 479 while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) { 480 CronLine line; 481 char *ptr; 482 483 trim(buf); 484 if (buf[0] == 0 || buf[0] == '#') { 485 continue; 486 } 487 if (--maxEntries == 0) { 488 break; 489 } 490 memset(&line, 0, sizeof(line)); 491 492 #if ENABLE_DEBUG_CROND_OPTION 493 if (DebugOpt) { 494 crondlog("\111User %s Entry %s\n", fileName, buf); 495 } 496 #endif 497 498 /* parse date ranges */ 499 ptr = ParseField(file->cf_User, line.cl_Mins, 60, 0, NULL, buf); 500 ptr = ParseField(file->cf_User, line.cl_Hrs, 24, 0, NULL, ptr); 501 ptr = ParseField(file->cf_User, line.cl_Days, 32, 0, NULL, ptr); 502 ptr = ParseField(file->cf_User, line.cl_Mons, 12, -1, MonAry, ptr); 503 ptr = ParseField(file->cf_User, line.cl_Dow, 7, 0, DowAry, ptr); 504 505 /* check failure */ 506 if (ptr == NULL) { 507 continue; 508 } 509 510 /* 511 * fix days and dow - if one is not * and the other 512 * is *, the other is set to 0, and vise-versa 513 */ 514 515 FixDayDow(&line); 516 517 *pline = xzalloc(sizeof(CronLine)); 518 **pline = line; 519 520 /* copy command */ 521 (*pline)->cl_Shell = strdup(ptr); 522 523 #if ENABLE_DEBUG_CROND_OPTION 524 if (DebugOpt) { 525 crondlog("\111 Command %s\n", ptr); 526 } 527 #endif 528 529 pline = &((*pline)->cl_Next); 530 } 531 *pline = NULL; 532 533 file->cf_Next = FileBase; 534 FileBase = file; 535 536 if (maxLines == 0 || maxEntries == 0) { 537 crondlog("\111Maximum number of lines reached for user %s\n", fileName); 538 } 539 } 540 fclose(fi); 541 } 542 } 543 } 544 545 static void CheckUpdates(void) 354 char *tokens[6]; 355 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 356 char *mailTo = NULL; 357 #endif 358 359 delete_cronfile(fileName); 360 361 if (!getpwnam(fileName)) { 362 crondlog(LVL7 "ignoring file '%s' (no such user)", fileName); 363 return; 364 } 365 366 parser = config_open(fileName); 367 if (!parser) 368 return; 369 370 maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; 371 372 if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DAEMON_UID) { 373 CronFile *file = xzalloc(sizeof(CronFile)); 374 CronLine **pline; 375 int n; 376 377 file->cf_username = xstrdup(fileName); 378 pline = &file->cf_lines; 379 380 while (1) { 381 CronLine *line; 382 383 if (!--maxLines) 384 break; 385 n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY); 386 if (!n) 387 break; 388 389 if (DebugOpt) 390 crondlog(LVL5 "user:%s entry:%s", fileName, parser->data); 391 392 /* check if line is setting MAILTO= */ 393 if (0 == strncmp(tokens[0], "MAILTO=", 7)) { 394 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 395 free(mailTo); 396 mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; 397 #endif /* otherwise just ignore such lines */ 398 continue; 399 } 400 /* check if a minimum of tokens is specified */ 401 if (n < 6) 402 continue; 403 *pline = line = xzalloc(sizeof(*line)); 404 /* parse date ranges */ 405 ParseField(file->cf_username, line->cl_Mins, 60, 0, NULL, tokens[0]); 406 ParseField(file->cf_username, line->cl_Hrs, 24, 0, NULL, tokens[1]); 407 ParseField(file->cf_username, line->cl_Days, 32, 0, NULL, tokens[2]); 408 ParseField(file->cf_username, line->cl_Mons, 12, -1, MonAry, tokens[3]); 409 ParseField(file->cf_username, line->cl_Dow, 7, 0, DowAry, tokens[4]); 410 /* 411 * fix days and dow - if one is not "*" and the other 412 * is "*", the other is set to 0, and vise-versa 413 */ 414 FixDayDow(line); 415 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 416 /* copy mailto (can be NULL) */ 417 line->cl_mailto = xstrdup(mailTo); 418 #endif 419 /* copy command */ 420 line->cl_cmd = xstrdup(tokens[5]); 421 if (DebugOpt) { 422 crondlog(LVL5 " command:%s", tokens[5]); 423 } 424 pline = &line->cl_next; 425 //bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]); 426 } 427 *pline = NULL; 428 429 file->cf_next = G.cron_files; 430 G.cron_files = file; 431 432 if (maxLines == 0) { 433 crondlog(WARN9 "user %s: too many lines", fileName); 434 } 435 } 436 config_close(parser); 437 } 438 439 static void process_cron_update_file(void) 546 440 { 547 441 FILE *fi; 548 442 char buf[256]; 549 443 550 fi = fopen (CRONUPDATE, "r");444 fi = fopen_for_read(CRONUPDATE); 551 445 if (fi != NULL) { 552 remove(CRONUPDATE);446 unlink(CRONUPDATE); 553 447 while (fgets(buf, sizeof(buf), fi) != NULL) { 554 SynchronizeFile(strtok(buf, " \t\r\n")); 448 /* use first word only */ 449 skip_non_whitespace(buf)[0] = '\0'; 450 load_crontab(buf); 555 451 } 556 452 fclose(fi); … … 558 454 } 559 455 560 static void SynchronizeDir(void) 561 { 562 /* Attempt to delete the database. */ 563 564 for (;;) { 565 CronFile *file; 566 567 for (file = FileBase; file && file->cf_Deleted; file = file->cf_Next); 568 if (file == NULL) { 569 break; 570 } 571 DeleteFile(file->cf_User); 572 } 573 574 /* 575 * Remove cron update file 576 * 577 * Re-chdir, in case directory was renamed & deleted, or otherwise 578 * screwed up. 579 * 580 * scan directory and add associated users 581 */ 582 583 remove(CRONUPDATE); 584 if (chdir(CDir) < 0) { 585 crondlog("\311cannot find %s\n", CDir); 586 } 456 static void rescan_crontab_dir(void) 457 { 458 CronFile *file; 459 460 /* Delete all files until we only have ones with running jobs (or none) */ 461 again: 462 for (file = G.cron_files; file; file = file->cf_next) { 463 if (!file->cf_deleted) { 464 delete_cronfile(file->cf_username); 465 goto again; 466 } 467 } 468 469 /* Remove cron update file */ 470 unlink(CRONUPDATE); 471 /* Re-chdir, in case directory was renamed & deleted */ 472 if (chdir(G.crontab_dir_name) < 0) { 473 crondlog(DIE9 "chdir(%s)", G.crontab_dir_name); 474 } 475 476 /* Scan directory and add associated users */ 587 477 { 588 478 DIR *dir = opendir("."); 589 479 struct dirent *den; 590 480 591 if (dir) { 592 while ((den = readdir(dir))) { 593 if (strchr(den->d_name, '.') != NULL) { 594 continue; 595 } 596 if (getpwnam(den->d_name)) { 597 SynchronizeFile(den->d_name); 598 } else { 599 crondlog("\007ignoring %s\n", den->d_name); 600 } 601 } 602 closedir(dir); 603 } else { 604 crondlog("\311cannot open current dir!\n"); 605 } 606 } 607 } 608 609 610 /* 611 * DeleteFile() - delete user database 612 * 613 * Note: multiple entries for same user may exist if we were unable to 614 * completely delete a database due to running processes. 615 */ 616 617 static void DeleteFile(const char *userName) 618 { 619 CronFile **pfile = &FileBase; 620 CronFile *file; 621 622 while ((file = *pfile) != NULL) { 623 if (strcmp(userName, file->cf_User) == 0) { 624 CronLine **pline = &file->cf_LineBase; 625 CronLine *line; 626 627 file->cf_Running = 0; 628 file->cf_Deleted = 1; 629 630 while ((line = *pline) != NULL) { 631 if (line->cl_Pid > 0) { 632 file->cf_Running = 1; 633 pline = &line->cl_Next; 634 } else { 635 *pline = line->cl_Next; 636 free(line->cl_Shell); 637 free(line); 638 } 639 } 640 if (file->cf_Running == 0) { 641 *pfile = file->cf_Next; 642 free(file->cf_User); 643 free(file); 644 } else { 645 pfile = &file->cf_Next; 646 } 647 } else { 648 pfile = &file->cf_Next; 649 } 650 } 651 } 652 653 /* 654 * TestJobs() 655 * 656 * determine which jobs need to be run. Under normal conditions, the 657 * period is about a minute (one scan). Worst case it will be one 658 * hour (60 scans). 659 */ 660 661 static int TestJobs(time_t t1, time_t t2) 662 { 663 int nJobs = 0; 664 time_t t; 665 666 /* Find jobs > t1 and <= t2 */ 667 668 for (t = t1 - t1 % 60; t <= t2; t += 60) { 669 if (t > t1) { 670 struct tm *tp = localtime(&t); 671 CronFile *file; 672 CronLine *line; 673 674 for (file = FileBase; file; file = file->cf_Next) { 675 #if ENABLE_DEBUG_CROND_OPTION 676 if (DebugOpt) 677 crondlog("\005FILE %s:\n", file->cf_User); 678 #endif 679 if (file->cf_Deleted) 680 continue; 681 for (line = file->cf_LineBase; line; line = line->cl_Next) { 682 #if ENABLE_DEBUG_CROND_OPTION 683 if (DebugOpt) 684 crondlog("\005 LINE %s\n", line->cl_Shell); 685 #endif 686 if (line->cl_Mins[tp->tm_min] && line->cl_Hrs[tp->tm_hour] && 687 (line->cl_Days[tp->tm_mday] || line->cl_Dow[tp->tm_wday]) 688 && line->cl_Mons[tp->tm_mon]) { 689 #if ENABLE_DEBUG_CROND_OPTION 690 if (DebugOpt) { 691 crondlog("\005 JobToDo: %d %s\n", 692 line->cl_Pid, line->cl_Shell); 693 } 694 #endif 695 if (line->cl_Pid > 0) { 696 crondlog("\010 process already running: %s %s\n", 697 file->cf_User, line->cl_Shell); 698 } else if (line->cl_Pid == 0) { 699 line->cl_Pid = -1; 700 file->cf_Ready = 1; 701 ++nJobs; 702 } 703 } 704 } 705 } 706 } 707 } 708 return nJobs; 709 } 710 711 static void RunJobs(void) 712 { 713 CronFile *file; 714 CronLine *line; 715 716 for (file = FileBase; file; file = file->cf_Next) { 717 if (file->cf_Ready) { 718 file->cf_Ready = 0; 719 720 for (line = file->cf_LineBase; line; line = line->cl_Next) { 721 if (line->cl_Pid < 0) { 722 723 RunJob(file->cf_User, line); 724 725 crondlog("\010USER %s pid %3d cmd %s\n", 726 file->cf_User, line->cl_Pid, line->cl_Shell); 727 if (line->cl_Pid < 0) { 728 file->cf_Ready = 1; 729 } 730 else if (line->cl_Pid > 0) { 731 file->cf_Running = 1; 732 } 733 } 734 } 735 } 736 } 737 } 738 739 /* 740 * CheckJobs() - check for job completion 741 * 742 * Check for job completion, return number of jobs still running after 743 * all done. 744 */ 745 746 static int CheckJobs(void) 747 { 748 CronFile *file; 749 CronLine *line; 750 int nStillRunning = 0; 751 752 for (file = FileBase; file; file = file->cf_Next) { 753 if (file->cf_Running) { 754 file->cf_Running = 0; 755 756 for (line = file->cf_LineBase; line; line = line->cl_Next) { 757 if (line->cl_Pid > 0) { 758 int status; 759 int r = wait4(line->cl_Pid, &status, WNOHANG, NULL); 760 761 if (r < 0 || r == line->cl_Pid) { 762 EndJob(file->cf_User, line); 763 if (line->cl_Pid) { 764 file->cf_Running = 1; 765 } 766 } else if (r == 0) { 767 file->cf_Running = 1; 768 } 769 } 770 } 771 } 772 nStillRunning += file->cf_Running; 773 } 774 return nStillRunning; 775 } 776 777 481 if (!dir) 482 crondlog(DIE9 "chdir(%s)", "."); /* exits */ 483 while ((den = readdir(dir)) != NULL) { 484 if (strchr(den->d_name, '.') != NULL) { 485 continue; 486 } 487 load_crontab(den->d_name); 488 } 489 closedir(dir); 490 } 491 } 492 493 #if SETENV_LEAKS 494 /* We set environment *before* vfork (because we want to use vfork), 495 * so we cannot use setenv() - repeated calls to setenv() may leak memory! 496 * Using putenv(), and freeing memory after unsetenv() won't leak */ 497 static void safe_setenv(char **pvar_val, const char *var, const char *val) 498 { 499 char *var_val = *pvar_val; 500 501 if (var_val) { 502 bb_unsetenv_and_free(var_val); 503 } 504 *pvar_val = xasprintf("%s=%s", var, val); 505 putenv(*pvar_val); 506 } 507 #endif 508 509 static void set_env_vars(struct passwd *pas) 510 { 511 #if SETENV_LEAKS 512 safe_setenv(&G.env_var_user, "USER", pas->pw_name); 513 safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); 514 /* if we want to set user's shell instead: */ 515 /*safe_setenv(G.env_var_shell, "SHELL", pas->pw_shell);*/ 516 #else 517 xsetenv("USER", pas->pw_name); 518 xsetenv("HOME", pas->pw_dir); 519 #endif 520 /* currently, we use constant one: */ 521 /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */ 522 } 523 524 static void change_user(struct passwd *pas) 525 { 526 /* careful: we're after vfork! */ 527 change_identity(pas); /* - initgroups, setgid, setuid */ 528 if (chdir(pas->pw_dir) < 0) { 529 crondlog(WARN9 "chdir(%s)", pas->pw_dir); 530 if (chdir(TMPDIR) < 0) { 531 crondlog(DIE9 "chdir(%s)", TMPDIR); /* exits */ 532 } 533 } 534 } 535 536 // TODO: sendmail should be _run-time_ option, not compile-time! 778 537 #if ENABLE_FEATURE_CROND_CALL_SENDMAIL 779 static void 780 ForkJob(const char *user, CronLine * line, int mailFd, 781 const char *prog, const char *cmd, const char *arg, const char *mailf) 782 { 783 /* Fork as the user in question and run program */ 784 pid_t pid = fork(); 785 786 line->cl_Pid = pid; 538 539 static pid_t 540 fork_job(const char *user, int mailFd, 541 const char *prog, 542 const char *shell_cmd /* if NULL, we run sendmail */ 543 ) { 544 struct passwd *pas; 545 pid_t pid; 546 547 /* prepare things before vfork */ 548 pas = getpwnam(user); 549 if (!pas) { 550 crondlog(WARN9 "can't get uid for %s", user); 551 goto err; 552 } 553 set_env_vars(pas); 554 555 pid = vfork(); 787 556 if (pid == 0) { 788 557 /* CHILD */ 789 790 /* Change running state to the user in question */ 791 792 if (ChangeUser(user) < 0) { 793 exit(0); 794 } 795 #if ENABLE_DEBUG_CROND_OPTION 558 /* initgroups, setgid, setuid, and chdir to home or TMPDIR */ 559 change_user(pas); 796 560 if (DebugOpt) { 797 crondlog("\005Child Running %s\n", prog); 798 } 799 #endif 800 561 crondlog(LVL5 "child running %s", prog); 562 } 801 563 if (mailFd >= 0) { 802 dup2(mailFd, mailf != NULL); 803 dup2((mailf ? mailFd : 1), 2); 804 close(mailFd); 805 } 806 execl(prog, prog, cmd, arg, NULL); 807 crondlog("\024cannot exec, user %s cmd %s %s %s\n", user, prog, cmd, arg); 808 if (mailf) { 809 fdprintf(1, "Exec failed: %s -c %s\n", prog, arg); 810 } 811 exit(0); 812 } else if (pid < 0) { 564 xmove_fd(mailFd, shell_cmd ? 1 : 0); 565 dup2(1, 2); 566 } 567 /* crond 3.0pl1-100 puts tasks in separate process groups */ 568 bb_setpgrp(); 569 execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL); 570 crondlog(ERR20 "can't execute '%s' for user %s", prog, user); 571 if (shell_cmd) { 572 fdprintf(1, "Exec failed: %s -c %s\n", prog, shell_cmd); 573 } 574 _exit(EXIT_SUCCESS); 575 } 576 577 if (pid < 0) { 813 578 /* FORK FAILED */ 814 crondlog("\024cannot fork, user %s\n", user); 815 line->cl_Pid = 0; 816 if (mailf) { 817 remove(mailf); 818 } 819 } else if (mailf) { 820 /* PARENT, FORK SUCCESS 821 * rename mail-file based on pid of process 822 */ 823 char mailFile2[128]; 824 825 snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", user, pid); 826 rename(mailf, mailFile2); 827 } 579 crondlog(ERR20 "can't vfork"); 580 err: 581 pid = 0; 582 } /* else: PARENT, FORK SUCCESS */ 583 828 584 /* 829 585 * Close the mail file descriptor.. we can't just leave it open in 830 586 * a structure, closing it later, because we might run out of descriptors 831 587 */ 832 833 588 if (mailFd >= 0) { 834 589 close(mailFd); 835 590 } 836 } 837 838 static void RunJob(const char *user, CronLine * line) 591 return pid; 592 } 593 594 static void start_one_job(const char *user, CronLine *line) 839 595 { 840 596 char mailFile[128]; 841 int mailFd; 842 843 line->cl_Pid = 0; 844 line->cl_MailFlag = 0; 845 846 /* open mail file - owner root so nobody can screw with it. */ 847 848 snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", user, getpid()); 849 mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); 850 597 int mailFd = -1; 598 599 line->cl_pid = 0; 600 line->cl_empty_mail_size = 0; 601 602 if (line->cl_mailto) { 603 /* Open mail file (owner is root so nobody can screw with it) */ 604 snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid()); 605 mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); 606 607 if (mailFd >= 0) { 608 fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", line->cl_mailto, 609 line->cl_cmd); 610 line->cl_empty_mail_size = lseek(mailFd, 0, SEEK_CUR); 611 } else { 612 crondlog(ERR20 "can't create mail file %s for user %s, " 613 "discarding output", mailFile, user); 614 } 615 } 616 617 line->cl_pid = fork_job(user, mailFd, DEFAULT_SHELL, line->cl_cmd); 851 618 if (mailFd >= 0) { 852 line->cl_MailFlag = 1;853 fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user,854 line->cl_Shell);855 line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR);856 } else {857 crondlog("\024cannot create mail file user %s file %s, output to /dev/null\n", user, mailFile);858 }859 860 ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);619 if (line->cl_pid <= 0) { 620 unlink(mailFile); 621 } else { 622 /* rename mail-file based on pid of process */ 623 char *mailFile2 = xasprintf("%s/cron.%s.%d", TMPDIR, user, (int)line->cl_pid); 624 rename(mailFile, mailFile2); // TODO: xrename? 625 free(mailFile2); 626 } 627 } 861 628 } 862 629 863 630 /* 864 * EndJob - called when job terminates and when mail terminates631 * process_finished_job - called when job terminates and when mail terminates 865 632 */ 866 867 static void EndJob(const char *user, CronLine * line) 868 { 633 static void process_finished_job(const char *user, CronLine *line) 634 { 635 pid_t pid; 869 636 int mailFd; 870 637 char mailFile[128]; 871 638 struct stat sbuf; 872 639 873 /* No job */874 875 if ( line->cl_Pid <= 0) {876 line->cl_Pid = 0;640 pid = line->cl_pid; 641 line->cl_pid = 0; 642 if (pid <= 0) { 643 /* No job */ 877 644 return; 878 645 } 646 if (line->cl_empty_mail_size <= 0) { 647 /* End of job and no mail file, or end of sendmail job */ 648 return; 649 } 879 650 880 651 /* 881 * End of job and no mail file882 * End of sendmail job652 * End of primary job - check for mail file. 653 * If size has changed and the file is still valid, we send it. 883 654 */ 884 885 snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", user, line->cl_Pid); 886 line->cl_Pid = 0; 887 888 if (line->cl_MailFlag != 1) { 889 return; 890 } 891 line->cl_MailFlag = 0; 892 893 /* 894 * End of primary job - check for mail file. If size has increased and 895 * the file is still valid, we sendmail it. 896 */ 897 655 snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, (int)pid); 898 656 mailFd = open(mailFile, O_RDONLY); 899 remove(mailFile);657 unlink(mailFile); 900 658 if (mailFd < 0) { 901 659 return; 902 660 } 903 661 904 if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid 905 || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos 662 if (fstat(mailFd, &sbuf) < 0 663 || sbuf.st_uid != DAEMON_UID 664 || sbuf.st_nlink != 0 665 || sbuf.st_size == line->cl_empty_mail_size 906 666 || !S_ISREG(sbuf.st_mode) 907 667 ) { … … 909 669 return; 910 670 } 911 ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); 912 } 913 #else 914 /* crond without sendmail */ 915 916 static void RunJob(const char *user, CronLine * line) 917 { 671 line->cl_empty_mail_size = 0; 672 /* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */ 673 line->cl_pid = fork_job(user, mailFd, SENDMAIL, NULL); 674 } 675 676 #else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ 677 678 static void start_one_job(const char *user, CronLine *line) 679 { 680 struct passwd *pas; 681 pid_t pid; 682 683 pas = getpwnam(user); 684 if (!pas) { 685 crondlog(WARN9 "can't get uid for %s", user); 686 goto err; 687 } 688 689 /* Prepare things before vfork */ 690 set_env_vars(pas); 691 918 692 /* Fork as the user in question and run program */ 919 pid_t pid = fork(); 920 693 pid = vfork(); 921 694 if (pid == 0) { 922 695 /* CHILD */ 923 924 /* Change running state to the user in question */ 925 926 if (ChangeUser(user) < 0) { 927 exit(0); 928 } 929 #if ENABLE_DEBUG_CROND_OPTION 696 /* initgroups, setgid, setuid, and chdir to home or TMPDIR */ 697 change_user(pas); 930 698 if (DebugOpt) { 931 crondlog( "\005Child Running %s\n", DEFAULT_SHELL);932 } 933 #endif 934 935 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_ Shell,NULL);936 crondlog( "\024cannot exec, user %s cmd %s -c %s\n", user,937 DEFAULT_SHELL, line->cl_Shell);938 exit(0);939 } elseif (pid < 0) {699 crondlog(LVL5 "child running %s", DEFAULT_SHELL); 700 } 701 /* crond 3.0pl1-100 puts tasks in separate process groups */ 702 bb_setpgrp(); 703 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL); 704 crondlog(ERR20 "can't execute '%s' for user %s", DEFAULT_SHELL, user); 705 _exit(EXIT_SUCCESS); 706 } 707 if (pid < 0) { 940 708 /* FORK FAILED */ 941 crondlog("\024cannot, user %s\n", user); 709 crondlog(ERR20 "can't vfork"); 710 err: 942 711 pid = 0; 943 712 } 944 line->cl_Pid = pid; 945 } 946 #endif /* ENABLE_FEATURE_CROND_CALL_SENDMAIL */ 713 line->cl_pid = pid; 714 } 715 716 #define process_finished_job(user, line) ((line)->cl_pid = 0) 717 718 #endif /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ 719 720 /* 721 * Determine which jobs need to be run. Under normal conditions, the 722 * period is about a minute (one scan). Worst case it will be one 723 * hour (60 scans). 724 */ 725 static void flag_starting_jobs(time_t t1, time_t t2) 726 { 727 time_t t; 728 729 /* Find jobs > t1 and <= t2 */ 730 731 for (t = t1 - t1 % 60; t <= t2; t += 60) { 732 struct tm *ptm; 733 CronFile *file; 734 CronLine *line; 735 736 if (t <= t1) 737 continue; 738 739 ptm = localtime(&t); 740 for (file = G.cron_files; file; file = file->cf_next) { 741 if (DebugOpt) 742 crondlog(LVL5 "file %s:", file->cf_username); 743 if (file->cf_deleted) 744 continue; 745 for (line = file->cf_lines; line; line = line->cl_next) { 746 if (DebugOpt) 747 crondlog(LVL5 " line %s", line->cl_cmd); 748 if (line->cl_Mins[ptm->tm_min] 749 && line->cl_Hrs[ptm->tm_hour] 750 && (line->cl_Days[ptm->tm_mday] || line->cl_Dow[ptm->tm_wday]) 751 && line->cl_Mons[ptm->tm_mon] 752 ) { 753 if (DebugOpt) { 754 crondlog(LVL5 " job: %d %s", 755 (int)line->cl_pid, line->cl_cmd); 756 } 757 if (line->cl_pid > 0) { 758 crondlog(LVL8 "user %s: process already running: %s", 759 file->cf_username, line->cl_cmd); 760 } else if (line->cl_pid == 0) { 761 line->cl_pid = -1; 762 file->cf_wants_starting = 1; 763 } 764 } 765 } 766 } 767 } 768 } 769 770 static void start_jobs(void) 771 { 772 CronFile *file; 773 CronLine *line; 774 775 for (file = G.cron_files; file; file = file->cf_next) { 776 if (!file->cf_wants_starting) 777 continue; 778 779 file->cf_wants_starting = 0; 780 for (line = file->cf_lines; line; line = line->cl_next) { 781 pid_t pid; 782 if (line->cl_pid >= 0) 783 continue; 784 785 start_one_job(file->cf_username, line); 786 pid = line->cl_pid; 787 crondlog(LVL8 "USER %s pid %3d cmd %s", 788 file->cf_username, (int)pid, line->cl_cmd); 789 if (pid < 0) { 790 file->cf_wants_starting = 1; 791 } 792 if (pid > 0) { 793 file->cf_has_running = 1; 794 } 795 } 796 } 797 } 798 799 /* 800 * Check for job completion, return number of jobs still running after 801 * all done. 802 */ 803 static int check_completions(void) 804 { 805 CronFile *file; 806 CronLine *line; 807 int num_still_running = 0; 808 809 for (file = G.cron_files; file; file = file->cf_next) { 810 if (!file->cf_has_running) 811 continue; 812 813 file->cf_has_running = 0; 814 for (line = file->cf_lines; line; line = line->cl_next) { 815 int r; 816 817 if (line->cl_pid <= 0) 818 continue; 819 820 r = waitpid(line->cl_pid, NULL, WNOHANG); 821 if (r < 0 || r == line->cl_pid) { 822 process_finished_job(file->cf_username, line); 823 if (line->cl_pid == 0) { 824 /* sendmail was not started for it */ 825 continue; 826 } 827 /* else: sendmail was started, job is still running, fall thru */ 828 } 829 /* else: r == 0: "process is still running" */ 830 file->cf_has_running = 1; 831 } 832 //FIXME: if !file->cf_has_running && file->deleted: delete it! 833 //otherwise deleted entries will stay forever, right? 834 num_still_running += file->cf_has_running; 835 } 836 return num_still_running; 837 } 838 839 int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 840 int crond_main(int argc UNUSED_PARAM, char **argv) 841 { 842 time_t t2; 843 int rescan; 844 int sleep_time; 845 unsigned opts; 846 847 INIT_G(); 848 849 /* "-b after -f is ignored", and so on for every pair a-b */ 850 opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l") 851 ":l+:d+"; /* -l and -d have numeric param */ 852 opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"), 853 &G.log_level, &G.log_filename, &G.crontab_dir_name 854 IF_FEATURE_CROND_D(,&G.log_level)); 855 /* both -d N and -l N set the same variable: G.log_level */ 856 857 if (!(opts & OPT_f)) { 858 /* close stdin, stdout, stderr. 859 * close unused descriptors - don't need them. */ 860 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); 861 } 862 863 if (!(opts & OPT_d) && G.log_filename == NULL) { 864 /* logging to syslog */ 865 openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); 866 logmode = LOGMODE_SYSLOG; 867 } 868 869 xchdir(G.crontab_dir_name); 870 //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ 871 xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ 872 crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", G.log_level); 873 rescan_crontab_dir(); 874 write_pidfile("/var/run/crond.pid"); 875 876 /* Main loop */ 877 t2 = time(NULL); 878 rescan = 60; 879 sleep_time = 60; 880 for (;;) { 881 struct stat sbuf; 882 time_t t1; 883 long dt; 884 885 t1 = t2; 886 887 /* Synchronize to 1 minute, minimum 1 second */ 888 sleep(sleep_time - (time(NULL) % sleep_time) + 1); 889 890 t2 = time(NULL); 891 dt = (long)t2 - (long)t1; 892 893 /* 894 * The file 'cron.update' is checked to determine new cron 895 * jobs. The directory is rescanned once an hour to deal 896 * with any screwups. 897 * 898 * Check for time jump. Disparities over an hour either way 899 * result in resynchronization. A negative disparity 900 * less than an hour causes us to effectively sleep until we 901 * match the original time (i.e. no re-execution of jobs that 902 * have just been run). A positive disparity less than 903 * an hour causes intermediate jobs to be run, but only once 904 * in the worst case. 905 * 906 * When running jobs, the inequality used is greater but not 907 * equal to t1, and less then or equal to t2. 908 */ 909 if (stat(G.crontab_dir_name, &sbuf) != 0) 910 sbuf.st_mtime = 0; /* force update (once) if dir was deleted */ 911 if (G.crontab_dir_mtime != sbuf.st_mtime) { 912 G.crontab_dir_mtime = sbuf.st_mtime; 913 rescan = 1; 914 } 915 if (--rescan == 0) { 916 rescan = 60; 917 rescan_crontab_dir(); 918 } 919 process_cron_update_file(); 920 if (DebugOpt) 921 crondlog(LVL5 "wakeup dt=%ld", dt); 922 if (dt < -60 * 60 || dt > 60 * 60) { 923 crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); 924 /* and we do not run any jobs in this case */ 925 } else if (dt > 0) { 926 /* Usual case: time advances forward, as expected */ 927 flag_starting_jobs(t1, t2); 928 start_jobs(); 929 if (check_completions() > 0) { 930 /* some jobs are still running */ 931 sleep_time = 10; 932 } else { 933 sleep_time = 60; 934 } 935 } 936 /* else: time jumped back, do not run any jobs */ 937 } /* for (;;) */ 938 939 return 0; /* not reached */ 940 } -
branches/2.2.9/mindi-busybox/miscutils/crontab.c
r1765 r2725 8 8 * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002 9 9 * 10 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 11 */ 12 12 13 13 #include "libbb.h" 14 14 15 #ifndef CRONTABS 16 #define CRONTABS "/var/spool/cron/crontabs" 17 #endif 18 #ifndef TMPDIR 19 #define TMPDIR "/var/spool/cron" 20 #endif 15 #define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" 21 16 #ifndef CRONUPDATE 22 17 #define CRONUPDATE "cron.update" 23 18 #endif 24 #ifndef PATH_VI 25 #define PATH_VI "/bin/vi" /* location of vi */ 26 #endif 27 28 static const char *CDir = CRONTABS; 29 30 static void EditFile(const char *user, const char *file); 31 static int GetReplaceStream(const char *user, const char *file); 32 static int ChangeUser(const char *user, short dochdir); 33 34 int crontab_main(int ac, char **av); 35 int crontab_main(int ac, char **av) 19 20 static void edit_file(const struct passwd *pas, const char *file) 36 21 { 37 enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE; 22 const char *ptr; 23 int pid = xvfork(); 24 25 if (pid) { /* parent */ 26 wait4pid(pid); 27 return; 28 } 29 30 /* CHILD - change user and run editor */ 31 /* initgroups, setgid, setuid */ 32 change_identity(pas); 33 setup_environment(DEFAULT_SHELL, 34 SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP, 35 pas); 36 ptr = getenv("VISUAL"); 37 if (!ptr) { 38 ptr = getenv("EDITOR"); 39 if (!ptr) 40 ptr = "vi"; 41 } 42 43 BB_EXECLP(ptr, ptr, file, NULL); 44 bb_perror_msg_and_die("exec %s", ptr); 45 } 46 47 static int open_as_user(const struct passwd *pas, const char *file) 48 { 49 pid_t pid; 50 char c; 51 52 pid = xvfork(); 53 if (pid) { /* PARENT */ 54 if (wait4pid(pid) == 0) { 55 /* exitcode 0: child says it can read */ 56 return open(file, O_RDONLY); 57 } 58 return -1; 59 } 60 61 /* CHILD */ 62 /* initgroups, setgid, setuid */ 63 change_identity(pas); 64 /* We just try to read one byte. If it works, file is readable 65 * under this user. We signal that by exiting with 0. */ 66 _exit(safe_read(xopen(file, O_RDONLY), &c, 1) < 0); 67 } 68 69 int crontab_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 70 int crontab_main(int argc UNUSED_PARAM, char **argv) 71 { 38 72 const struct passwd *pas; 39 const char *repFile = NULL; 40 int repFd = 0; 41 int i; 42 char caller[256]; /* user that ran program */ 43 char buf[1024]; 44 int UserId; 45 46 UserId = getuid(); 47 pas = getpwuid(UserId); 48 if (pas == NULL) 49 bb_perror_msg_and_die("getpwuid"); 50 51 safe_strncpy(caller, pas->pw_name, sizeof(caller)); 52 53 i = 1; 54 if (ac > 1) { 55 if (LONE_DASH(av[1])) { 56 option = REPLACE; 57 ++i; 58 } else if (av[1][0] != '-') { 59 option = REPLACE; 60 ++i; 61 repFile = av[1]; 62 } 63 } 64 65 for (; i < ac; ++i) { 66 char *ptr = av[i]; 67 68 if (*ptr != '-') 73 const char *crontab_dir = CRONTABS; 74 char *tmp_fname; 75 char *new_fname; 76 char *user_name; /* -u USER */ 77 int fd; 78 int src_fd; 79 int opt_ler; 80 81 /* file [opts] Replace crontab from file 82 * - [opts] Replace crontab from stdin 83 * -u user User 84 * -c dir Crontab directory 85 * -l List crontab for user 86 * -e Edit crontab for user 87 * -r Delete crontab for user 88 * bbox also supports -d == -r, but most other crontab 89 * implementations do not. Deprecated. 90 */ 91 enum { 92 OPT_u = (1 << 0), 93 OPT_c = (1 << 1), 94 OPT_l = (1 << 2), 95 OPT_e = (1 << 3), 96 OPT_r = (1 << 4), 97 OPT_ler = OPT_l + OPT_e + OPT_r, 98 }; 99 100 opt_complementary = "?1:dr"; /* max one argument; -d implies -r */ 101 opt_ler = getopt32(argv, "u:c:lerd", &user_name, &crontab_dir); 102 argv += optind; 103 104 if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */ 105 /* Run by non-root */ 106 if (opt_ler & (OPT_u|OPT_c)) 107 bb_error_msg_and_die(bb_msg_you_must_be_root); 108 } 109 110 if (opt_ler & OPT_u) { 111 pas = xgetpwnam(user_name); 112 } else { 113 pas = xgetpwuid(getuid()); 114 } 115 116 #define user_name DONT_USE_ME_BEYOND_THIS_POINT 117 118 /* From now on, keep only -l, -e, -r bits */ 119 opt_ler &= OPT_ler; 120 if ((opt_ler - 1) & opt_ler) /* more than one bit set? */ 121 bb_show_usage(); 122 123 /* Read replacement file under user's UID/GID/group vector */ 124 src_fd = STDIN_FILENO; 125 if (!opt_ler) { /* Replace? */ 126 if (!argv[0]) 127 bb_show_usage(); 128 if (NOT_LONE_DASH(argv[0])) { 129 src_fd = open_as_user(pas, argv[0]); 130 if (src_fd < 0) 131 bb_error_msg_and_die("user %s cannot read %s", 132 pas->pw_name, argv[0]); 133 } 134 } 135 136 /* cd to our crontab directory */ 137 xchdir(crontab_dir); 138 139 tmp_fname = NULL; 140 141 /* Handle requested operation */ 142 switch (opt_ler) { 143 144 default: /* case OPT_r: Delete */ 145 unlink(pas->pw_name); 146 break; 147 148 case OPT_l: /* List */ 149 { 150 char *args[2] = { pas->pw_name, NULL }; 151 return bb_cat(args); 152 /* list exits, 153 * the rest go play with cron update file */ 154 } 155 156 case OPT_e: /* Edit */ 157 tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid()); 158 /* No O_EXCL: we don't want to be stuck if earlier crontabs 159 * were killed, leaving stale temp file behind */ 160 src_fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600); 161 fchown(src_fd, pas->pw_uid, pas->pw_gid); 162 fd = open(pas->pw_name, O_RDONLY); 163 if (fd >= 0) { 164 bb_copyfd_eof(fd, src_fd); 165 close(fd); 166 xlseek(src_fd, 0, SEEK_SET); 167 } 168 close_on_exec_on(src_fd); /* don't want editor to see this fd */ 169 edit_file(pas, tmp_fname); 170 /* fall through */ 171 172 case 0: /* Replace (no -l, -e, or -r were given) */ 173 new_fname = xasprintf("%s.new", pas->pw_name); 174 fd = open(new_fname, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600); 175 if (fd >= 0) { 176 bb_copyfd_eof(src_fd, fd); 177 close(fd); 178 xrename(new_fname, pas->pw_name); 179 } else { 180 bb_error_msg("can't create %s/%s", 181 crontab_dir, new_fname); 182 } 183 if (tmp_fname) 184 unlink(tmp_fname); 185 /*free(tmp_fname);*/ 186 /*free(new_fname);*/ 187 188 } /* switch */ 189 190 /* Bump notification file. Handle window where crond picks file up 191 * before we can write our entry out. 192 */ 193 while ((fd = open(CRONUPDATE, O_WRONLY|O_CREAT|O_APPEND, 0600)) >= 0) { 194 struct stat st; 195 196 fdprintf(fd, "%s\n", pas->pw_name); 197 if (fstat(fd, &st) != 0 || st.st_nlink != 0) { 198 /*close(fd);*/ 69 199 break; 70 ptr += 2; 71 72 switch (ptr[-1]) { 73 case 'l': 74 if (ptr[-1] == 'l') 75 option = LIST; 76 /* fall through */ 77 case 'e': 78 if (ptr[-1] == 'e') 79 option = EDIT; 80 /* fall through */ 81 case 'd': 82 if (ptr[-1] == 'd') 83 option = DELETE; 84 /* fall through */ 85 case 'u': 86 if (i + 1 < ac && av[i+1][0] != '-') { 87 ++i; 88 if (getuid() == geteuid()) { 89 pas = getpwnam(av[i]); 90 if (pas) { 91 UserId = pas->pw_uid; 92 } else { 93 bb_error_msg_and_die("user %s unknown", av[i]); 94 } 95 } else { 96 bb_error_msg_and_die("only the superuser may specify a user"); 97 } 98 } 99 break; 100 case 'c': 101 if (getuid() == geteuid()) { 102 CDir = (*ptr) ? ptr : av[++i]; 103 } else { 104 bb_error_msg_and_die("-c option: superuser only"); 105 } 106 break; 107 default: 108 i = ac; 109 break; 110 } 111 } 112 if (i != ac || option == NONE) 113 bb_show_usage(); 114 115 /* 116 * Get password entry 117 */ 118 119 pas = getpwuid(UserId); 120 if (pas == NULL) 121 bb_perror_msg_and_die("getpwuid"); 122 123 /* 124 * If there is a replacement file, obtain a secure descriptor to it. 125 */ 126 127 if (repFile) { 128 repFd = GetReplaceStream(caller, repFile); 129 if (repFd < 0) 130 bb_error_msg_and_die("cannot read replacement file"); 131 } 132 133 /* 134 * Change directory to our crontab directory 135 */ 136 137 xchdir(CDir); 138 139 /* 140 * Handle options as appropriate 141 */ 142 143 switch (option) { 144 case LIST: 145 { 146 FILE *fi; 147 148 fi = fopen(pas->pw_name, "r"); 149 if (fi) { 150 while (fgets(buf, sizeof(buf), fi) != NULL) 151 fputs(buf, stdout); 152 fclose(fi); 153 } else { 154 bb_error_msg("no crontab for %s", pas->pw_name); 155 } 156 } 157 break; 158 case EDIT: 159 { 160 /* FIXME: messy code here! we have file copying helpers for this! */ 161 FILE *fi; 162 int fd; 163 int n; 164 char tmp[128]; 165 166 snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid()); 167 fd = xopen3(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600); 168 /* race, use fchown */ 169 chown(tmp, getuid(), getgid()); 170 fi = fopen(pas->pw_name, "r"); 171 if (fi) { 172 while ((n = fread(buf, 1, sizeof(buf), fi)) > 0) 173 full_write(fd, buf, n); 174 } 175 EditFile(caller, tmp); 176 remove(tmp); 177 lseek(fd, 0L, SEEK_SET); 178 repFd = fd; 179 } 180 option = REPLACE; 181 /* fall through */ 182 case REPLACE: 183 { 184 /* same here */ 185 char path[1024]; 186 int fd; 187 int n; 188 189 snprintf(path, sizeof(path), "%s.new", pas->pw_name); 190 fd = open(path, O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0600); 191 if (fd >= 0) { 192 while ((n = read(repFd, buf, sizeof(buf))) > 0) { 193 full_write(fd, buf, n); 194 } 195 close(fd); 196 rename(path, pas->pw_name); 197 } else { 198 bb_error_msg("cannot create %s/%s", CDir, path); 199 } 200 close(repFd); 201 } 202 break; 203 case DELETE: 204 remove(pas->pw_name); 205 break; 206 case NONE: 207 default: 208 break; 209 } 210 211 /* 212 * Bump notification file. Handle window where crond picks file up 213 * before we can write our entry out. 214 */ 215 216 if (option == REPLACE || option == DELETE) { 217 FILE *fo; 218 struct stat st; 219 220 while ((fo = fopen(CRONUPDATE, "a"))) { 221 fprintf(fo, "%s\n", pas->pw_name); 222 fflush(fo); 223 if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) { 224 fclose(fo); 225 break; 226 } 227 fclose(fo); 228 /* loop */ 229 } 230 if (fo == NULL) { 231 bb_error_msg("cannot append to %s/%s", CDir, CRONUPDATE); 232 } 200 } 201 /* st.st_nlink == 0: 202 * file was deleted, maybe crond missed our notification */ 203 close(fd); 204 /* loop */ 205 } 206 if (fd < 0) { 207 bb_error_msg("can't append to %s/%s", 208 crontab_dir, CRONUPDATE); 233 209 } 234 210 return 0; 235 211 } 236 237 static int GetReplaceStream(const char *user, const char *file)238 {239 int filedes[2];240 int pid;241 int fd;242 int n;243 char buf[1024];244 245 if (pipe(filedes) < 0) {246 perror("pipe");247 return -1;248 }249 pid = fork();250 if (pid < 0) {251 perror("fork");252 return -1;253 }254 if (pid > 0) {255 /*256 * PARENT257 */258 259 close(filedes[1]);260 if (read(filedes[0], buf, 1) != 1) {261 close(filedes[0]);262 filedes[0] = -1;263 }264 return filedes[0];265 }266 267 /*268 * CHILD269 */270 271 close(filedes[0]);272 273 if (ChangeUser(user, 0) < 0)274 exit(0);275 276 xfunc_error_retval = 0;277 fd = xopen(file, O_RDONLY);278 buf[0] = 0;279 write(filedes[1], buf, 1);280 while ((n = read(fd, buf, sizeof(buf))) > 0) {281 write(filedes[1], buf, n);282 }283 exit(0);284 }285 286 static void EditFile(const char *user, const char *file)287 {288 int pid = fork();289 290 if (pid == 0) {291 /*292 * CHILD - change user and run editor293 */294 const char *ptr;295 296 if (ChangeUser(user, 1) < 0)297 exit(0);298 ptr = getenv("VISUAL");299 if (ptr == NULL)300 ptr = getenv("EDITOR");301 if (ptr == NULL)302 ptr = PATH_VI;303 304 ptr = xasprintf("%s %s", ptr, file);305 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", ptr, NULL);306 bb_perror_msg_and_die("exec");307 }308 if (pid < 0) {309 /*310 * PARENT - failure311 */312 bb_perror_msg_and_die("fork");313 }314 wait4(pid, NULL, 0, NULL);315 }316 317 static int ChangeUser(const char *user, short dochdir)318 {319 struct passwd *pas;320 321 /*322 * Obtain password entry and change privileges323 */324 325 pas = getpwnam(user);326 if (pas == NULL) {327 bb_perror_msg_and_die("failed to get uid for %s", user);328 }329 setenv("USER", pas->pw_name, 1);330 setenv("HOME", pas->pw_dir, 1);331 setenv("SHELL", DEFAULT_SHELL, 1);332 333 /*334 * Change running state to the user in question335 */336 change_identity(pas);337 338 if (dochdir) {339 if (chdir(pas->pw_dir) < 0) {340 bb_perror_msg("chdir(%s) by %s failed", pas->pw_dir, user);341 xchdir(TMPDIR);342 }343 }344 return pas->pw_uid;345 } -
branches/2.2.9/mindi-busybox/miscutils/dc.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 5 … … 7 7 #include <math.h> 8 8 9 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ 10 11 enum { STACK_SIZE = COMMON_BUFSIZE / sizeof(double) }; 12 13 #define stack ((double*)&bb_common_bufsiz1) 14 static unsigned int pointer; 15 static unsigned char base; 9 //usage:#define dc_trivial_usage 10 //usage: "EXPRESSION..." 11 //usage: 12 //usage:#define dc_full_usage "\n\n" 13 //usage: "Tiny RPN calculator. Operations:\n" 14 //usage: "+, add, -, sub, *, mul, /, div, %, mod, **, exp, and, or, not, eor,\n" 15 //usage: "p - print top of the stack (without popping),\n" 16 //usage: "f - print entire stack,\n" 17 //usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" 18 //usage: "Examples: 'dc 2 2 add' -> 4, 'dc 8 8 * 2 2 + /' -> 16" 19 //usage: 20 //usage:#define dc_example_usage 21 //usage: "$ dc 2 2 + p\n" 22 //usage: "4\n" 23 //usage: "$ dc 8 8 \\* 2 2 + / p\n" 24 //usage: "16\n" 25 //usage: "$ dc 0 1 and p\n" 26 //usage: "0\n" 27 //usage: "$ dc 0 1 or p\n" 28 //usage: "1\n" 29 //usage: "$ echo 72 9 div 8 mul p | dc\n" 30 //usage: "64\n" 31 32 #if 0 33 typedef unsigned data_t; 34 #define DATA_FMT "" 35 #elif 0 36 typedef unsigned long data_t; 37 #define DATA_FMT "l" 38 #else 39 typedef unsigned long long data_t; 40 #define DATA_FMT "ll" 41 #endif 42 43 44 struct globals { 45 unsigned pointer; 46 unsigned base; 47 double stack[1]; 48 } FIX_ALIASING; 49 enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) }; 50 #define G (*(struct globals*)&bb_common_bufsiz1) 51 #define pointer (G.pointer ) 52 #define base (G.base ) 53 #define stack (G.stack ) 54 #define INIT_G() do { \ 55 base = 10; \ 56 } while (0) 57 16 58 17 59 static void push(double a) … … 46 88 } 47 89 90 #if ENABLE_FEATURE_DC_LIBM 48 91 static void power(void) 49 92 { … … 52 95 push(pow(pop(), topower)); 53 96 } 97 #endif 54 98 55 99 static void divide(void) … … 62 106 static void mod(void) 63 107 { 64 unsigned int d = pop();65 66 push(( unsigned int) pop() % d);108 data_t d = pop(); 109 110 push((data_t) pop() % d); 67 111 } 68 112 69 113 static void and(void) 70 114 { 71 push(( unsigned int) pop() & (unsigned int) pop());115 push((data_t) pop() & (data_t) pop()); 72 116 } 73 117 74 118 static void or(void) 75 119 { 76 push(( unsigned int) pop() | (unsigned int) pop());120 push((data_t) pop() | (data_t) pop()); 77 121 } 78 122 79 123 static void eor(void) 80 124 { 81 push(( unsigned int) pop() ^ (unsigned int) pop());125 push((data_t) pop() ^ (data_t) pop()); 82 126 } 83 127 84 128 static void not(void) 85 129 { 86 push(~( unsigned int) pop());130 push(~(data_t) pop()); 87 131 } 88 132 89 133 static void set_output_base(void) 90 134 { 91 base = (unsigned char)pop(); 92 if ((base != 10) && (base != 16)) { 93 bb_error_msg("error, base %d is not supported", base); 135 static const char bases[] ALIGN1 = { 2, 8, 10, 16, 0 }; 136 unsigned b = (unsigned)pop(); 137 138 base = *strchrnul(bases, b); 139 if (base == 0) { 140 bb_error_msg("error, base %u is not supported", b); 94 141 base = 10; 95 142 } … … 98 145 static void print_base(double print) 99 146 { 100 if (base == 16) 101 printf("%x\n", (unsigned int)print); 102 else 103 printf("%g\n", print); 147 data_t x, i; 148 149 x = (data_t) print; 150 if (base == 10) { 151 if (x == print) /* exactly representable as unsigned integer */ 152 printf("%"DATA_FMT"u\n", x); 153 else 154 printf("%g\n", print); 155 return; 156 } 157 158 switch (base) { 159 case 16: 160 printf("%"DATA_FMT"x\n", x); 161 break; 162 case 8: 163 printf("%"DATA_FMT"o\n", x); 164 break; 165 default: /* base 2 */ 166 i = MAXINT(data_t) - (MAXINT(data_t) >> 1); 167 /* i is 100000...00000 */ 168 do { 169 if (x & i) 170 break; 171 i >>= 1; 172 } while (i > 1); 173 do { 174 bb_putchar('1' - !(x & i)); 175 i >>= 1; 176 } while (i); 177 bb_putchar('\n'); 178 } 104 179 } 105 180 106 181 static void print_stack_no_pop(void) 107 182 { 108 unsigned i nt i= pointer;183 unsigned i = pointer; 109 184 while (i) 110 185 print_base(stack[--i]); … … 130 205 {"/", divide}, 131 206 {"div", divide}, 207 #if ENABLE_FEATURE_DC_LIBM 132 208 {"**", power}, 133 209 {"exp", power}, 134 210 {"pow", power}, 211 #endif 135 212 {"%", mod}, 136 213 {"mod", mod}, … … 143 220 {"f", print_stack_no_pop}, 144 221 {"o", set_output_base}, 145 { "", 0}222 { "", NULL } 146 223 }; 147 224 148 225 static void stack_machine(const char *argument) 149 226 { 150 char *endPointer = 0;227 char *endPointer; 151 228 double d; 152 229 const struct op *o = operators; 153 230 154 if (argument == 0)155 return;156 157 231 d = strtod(argument, &endPointer); 158 232 159 if (endPointer != argument ) {233 if (endPointer != argument && *endPointer == '\0') { 160 234 push(d); 161 235 return; 162 236 } 163 237 164 while (o-> name[0]) {238 while (o->function) { 165 239 if (strcmp(o->name, argument) == 0) { 166 240 o->function(); … … 169 243 o++; 170 244 } 171 bb_error_msg_and_die(" %s: syntax error", argument);245 bb_error_msg_and_die("syntax error at '%s'", argument); 172 246 } 173 247 … … 177 251 static char *get_token(char **buffer) 178 252 { 179 char *start = NULL; 180 char *current; 181 182 current = skip_whitespace(*buffer); 183 if (*current != 0) { 184 start = current; 185 current = skip_non_whitespace(current); 186 *buffer = current; 187 } 188 return start; 189 } 190 191 /* In Perl one might say, scalar m|\s*(\S+)\s*|g */ 192 static int number_of_tokens(char *buffer) 193 { 194 int i = 0; 195 char *b = buffer; 196 while (get_token(&b)) { i++; } 197 return i; 198 } 199 200 int dc_main(int argc, char **argv); 201 int dc_main(int argc, char **argv) 202 { 203 /* take stuff from stdin if no args are given */ 204 if (argc <= 1) { 205 int i, len; 206 char *line = NULL; 207 char *cursor = NULL; 208 char *token = NULL; 209 while ((line = xmalloc_getline(stdin))) { 253 char *current = skip_whitespace(*buffer); 254 if (*current != '\0') { 255 *buffer = skip_non_whitespace(current); 256 return current; 257 } 258 return NULL; 259 } 260 261 int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 262 int dc_main(int argc UNUSED_PARAM, char **argv) 263 { 264 INIT_G(); 265 266 argv++; 267 if (!argv[0]) { 268 /* take stuff from stdin if no args are given */ 269 char *line; 270 char *cursor; 271 char *token; 272 while ((line = xmalloc_fgetline(stdin)) != NULL) { 210 273 cursor = line; 211 len = number_of_tokens(line); 212 for (i = 0; i < len; i++) { 274 while (1) { 213 275 token = get_token(&cursor); 214 *cursor++ = 0; 276 if (!token) 277 break; 278 *cursor++ = '\0'; 215 279 stack_machine(token); 216 280 } … … 218 282 } 219 283 } else { 220 if (*argv[1] == '-') 221 bb_show_usage(); 222 while (argc >= 2) { 223 stack_machine(argv[1]); 224 argv++; 225 argc--; 226 } 284 // why? it breaks "dc -2 2 * p" 285 //if (argv[0][0] == '-') 286 // bb_show_usage(); 287 do { 288 stack_machine(*argv); 289 } while (*++argv); 227 290 } 228 291 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/miscutils/devfsd.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 5 … … 54 54 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. 55 55 */ 56 57 //#include <sys/wait.h>58 //#include <sys/ioctl.h>59 //#include <sys/socket.h>60 #include <sys/un.h>61 #include <dirent.h>62 #include <syslog.h>63 #include <sys/sysmacros.h>64 56 #include "libbb.h" 65 57 #include "xregex.h" 66 58 #include <syslog.h> 59 60 #include <sys/un.h> 61 #include <sys/sysmacros.h> 67 62 68 63 /* Various defines taken from linux/major.h */ … … 81 76 /* Various defines taken from linux/devfs_fs.h */ 82 77 #define DEVFSD_PROTOCOL_REVISION_KERNEL 5 83 #define 78 #define DEVFSD_IOCTL_BASE 'd' 84 79 /* These are the various ioctls */ 85 80 #define DEVFSDIOC_GET_PROTO_REV _IOR(DEVFSD_IOCTL_BASE, 0, int) … … 98 93 /* Never change this otherwise the binary interface will change */ 99 94 100 struct devfsd_notify_struct 101 {/* Use native C types to ensure same types in kernel and user space */102 103 104 105 106 107 108 109 110 111 95 struct devfsd_notify_struct { 96 /* Use native C types to ensure same types in kernel and user space */ 97 unsigned int type; /* DEVFSD_NOTIFY_* value */ 98 unsigned int mode; /* Mode of the inode or device entry */ 99 unsigned int major; /* Major number of device entry */ 100 unsigned int minor; /* Minor number of device entry */ 101 unsigned int uid; /* Uid of process, inode or device entry */ 102 unsigned int gid; /* Gid of process, inode or device entry */ 103 unsigned int overrun_count; /* Number of lost events */ 104 unsigned int namelen; /* Number of characters not including '\0' */ 105 /* The device name MUST come last */ 106 char devname[DEVFS_PATHLEN]; /* This will be '\0' terminated */ 112 107 }; 113 108 … … 157 152 #define AC_RESTORE 11 158 153 159 struct permissions_type 160 { 154 struct permissions_type { 161 155 mode_t mode; 162 156 uid_t uid; … … 164 158 }; 165 159 166 struct execute_type 167 { 160 struct execute_type { 168 161 char *argv[MAX_ARGS + 1]; /* argv[0] must always be the programme */ 169 162 }; 170 163 171 struct copy_type 172 { 164 struct copy_type { 173 165 const char *source; 174 166 const char *destination; 175 167 }; 176 168 177 struct action_type 178 { 169 struct action_type { 179 170 unsigned int what; 180 171 unsigned int when; 181 172 }; 182 173 183 struct config_entry_struct 184 { 174 struct config_entry_struct { 185 175 struct action_type action; 186 176 regex_t preg; … … 195 185 }; 196 186 197 struct get_variable_info 198 { 187 struct get_variable_info { 199 188 const struct devfsd_notify_struct *info; 200 189 const char *devname; … … 289 278 #define info_logger(p, fmt, args...) 290 279 #define msg_logger(p, fmt, args...) 291 #define msg_logger_and_die(p, fmt, args...) exit( 1)280 #define msg_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) 292 281 #define error_logger(p, fmt, args...) 293 #define error_logger_and_die(p, fmt, args...) exit( 1)282 #define error_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) 294 283 #endif 295 284 … … 337 326 /* Public functions follow */ 338 327 339 int devfsd_main(int argc, char **argv) ;328 int devfsd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 340 329 int devfsd_main(int argc, char **argv) 341 330 { … … 372 361 373 362 fd = xopen(".devfsd", O_RDONLY); 374 375 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) 376 bb_perror_msg_and_die("FD_CLOEXEC"); 377 363 close_on_exec_on(fd); 378 364 xioctl(fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev); 379 365 … … 395 381 xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); 396 382 383 /* Set up SIGHUP and SIGUSR1 handlers */ 397 384 sigemptyset(&new_action.sa_mask); 398 385 new_action.sa_flags = 0; 399 400 /* Set up SIGHUP and SIGUSR1 handlers */401 386 new_action.sa_handler = signal_handler; 402 if (sigaction(SIGHUP, &new_action, NULL) != 0 || sigaction(SIGUSR1, &new_action, NULL) != 0)403 bb_error_msg_and_die("sigaction");404 405 printf("%s v%s started for %s\n",applet_name, DEVFSD_VERSION, mount_point);387 sigaction_set(SIGHUP, &new_action); 388 sigaction_set(SIGUSR1, &new_action); 389 390 printf("%s v%s started for %s\n", applet_name, DEVFSD_VERSION, mount_point); 406 391 407 392 /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ … … 412 397 413 398 if (ENABLE_DEVFSD_FG_NP && no_polling) 414 exit( 0);399 exit(EXIT_SUCCESS); 415 400 416 401 if (ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG) … … 469 454 return; 470 455 } 471 if ((fp = fopen(path, "r")) != NULL) { 456 fp = fopen_for_read(path); 457 if (fp != NULL) { 472 458 while (fgets(buf, STRING_LENGTH, fp) != NULL) { 473 459 /* Skip whitespace */ … … 564 550 new->action.what = AC_PERMISSIONS; 565 551 /* Get user and group */ 566 if ((ptr = strchr(p[0], '.')) == NULL) { 552 ptr = strchr(p[0], '.'); 553 if (ptr == NULL) { 567 554 msg = "UID.GID"; 568 555 goto process_config_line_err; /*"missing '.' in UID.GID"*/ … … 651 638 while (!caught_signal) { 652 639 errno = 0; 653 bytes = read(fd, (char *) &info, sizeof info);640 bytes = read(fd, (char *) &info, sizeof info); 654 641 if (caught_signal) 655 642 break; /* Must test for this first */ … … 749 736 750 737 static void action_modload(const struct devfsd_notify_struct *info, 751 const struct config_entry_struct *entry ATTRIBUTE_UNUSED)738 const struct config_entry_struct *entry UNUSED_PARAM) 752 739 /* [SUMMARY] Load a module. 753 740 <info> The devfs change. … … 765 752 argv[5] = NULL; 766 753 767 wait4pid(xspawn(argv));754 spawn_and_wait(argv); 768 755 free(argv[4]); 769 756 } /* End Function action_modload */ … … 797 784 } 798 785 argv[count] = NULL; 799 wait4pid(spawn(argv));786 spawn_and_wait(argv); 800 787 } /* End Function action_execute */ 801 788 … … 955 942 free(dpath); 956 943 if (S_ISLNK(source_stat.st_mode) || (source_stat.st_mode & S_ISVTX)) 957 copy_inode(dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX), spath, &source_stat);944 copy_inode(dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX), spath, &source_stat); 958 945 959 946 if (S_ISDIR(source_stat.st_mode)) 960 dir_operation(RESTORE, spath, rootlen, NULL);947 dir_operation(RESTORE, spath, rootlen, NULL); 961 948 } 962 949 … … 983 970 /* Same type */ 984 971 if (S_ISLNK(source_stat->st_mode)) { 985 if ((source_len = readlink(sourcepath, source_link, STRING_LENGTH - 1)) < 0 986 || (dest_len = readlink(destpath , dest_link , STRING_LENGTH - 1)) < 0 972 source_len = readlink(sourcepath, source_link, STRING_LENGTH - 1); 973 if ((source_len < 0) 974 || (dest_len = readlink(destpath, dest_link, STRING_LENGTH - 1)) < 0 987 975 ) 988 976 return FALSE; … … 1003 991 switch (source_stat->st_mode & S_IFMT) { 1004 992 case S_IFSOCK: 1005 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 993 fd = socket(AF_UNIX, SOCK_STREAM, 0); 994 if (fd < 0) 1006 995 break; 1007 996 un_addr.sun_family = AF_UNIX; 1008 997 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s", destpath); 1009 val = bind(fd, (struct sockaddr *) &un_addr,(int) sizeof un_addr);998 val = bind(fd, (struct sockaddr *) &un_addr, (int) sizeof un_addr); 1010 999 close(fd); 1011 1000 if (val != 0 || chmod(destpath, new_mode & ~S_IFMT) != 0) … … 1013 1002 goto do_chown; 1014 1003 case S_IFLNK: 1015 if ((val = readlink(sourcepath, symlink_val, STRING_LENGTH - 1)) < 0) 1004 val = readlink(sourcepath, symlink_val, STRING_LENGTH - 1); 1005 if (val < 0) 1016 1006 break; 1017 1007 symlink_val[val] = '\0'; … … 1020 1010 break; 1021 1011 case S_IFREG: 1022 if ((fd = open(destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT)) < 0) 1012 fd = open(destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT); 1013 if (fd < 0) 1023 1014 break; 1024 1015 close(fd); … … 1086 1077 return atoi(string); 1087 1078 1088 if (flag == UID && (pw_ent 1079 if (flag == UID && (pw_ent = getpwnam(string)) != NULL) 1089 1080 return pw_ent->pw_uid; 1090 1081 … … 1095 1086 1096 1087 if (ENABLE_DEVFSD_VERBOSE) 1097 msg_logger(LOG_ERR, "unknown %s: %s, defaulting to %cid=0", msg, string, msg[0]);1088 msg_logger(LOG_ERR, "unknown %s: %s, defaulting to %cid=0", msg, string, msg[0]); 1098 1089 return 0; 1099 1090 }/* End Function get_uid_gid */ … … 1136 1127 { 1137 1128 static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */ 1138 1139 char hostname[STRING_LENGTH]; 1129 static char *hostname; 1130 1140 1131 struct get_variable_info *gv_info = info; 1141 1132 const char *field_names[] = { … … 1146 1137 int i; 1147 1138 1148 if (gethostname(hostname, STRING_LENGTH - 1) != 0) 1149 /* Here on error we should do exit(RV_SYS_ERROR), instead we do exit(EXIT_FAILURE) */ 1150 error_logger_and_die(LOG_ERR, "gethostname"); 1151 1152 hostname[STRING_LENGTH - 1] = '\0'; 1153 1139 if (!hostname) 1140 hostname = safe_gethostname(); 1154 1141 /* index_in_str_array returns i>=0 */ 1155 1142 i = index_in_str_array(field_names, variable); … … 1201 1188 char *path; 1202 1189 1203 if ((dp = warn_opendir(dir_name)) == NULL) 1190 dp = warn_opendir(dir_name); 1191 if (dp == NULL) 1204 1192 return; 1205 1193 … … 1343 1331 /* from compat_name.c */ 1344 1332 1345 struct translate_struct 1346 { 1333 struct translate_struct { 1347 1334 const char *match; /* The string to match to(up to length) */ 1348 1335 const char *format; /* Format of output, "%s" takes data past match string, … … 1446 1433 /* 2 ==scsi/disc, 4 == scsi/part */ 1447 1434 if (i == 2 || i == 4) 1448 compat_name = write_old_sd_name(buffer, major, minor, ((i == 2) ? "" : (ptr + 4)));1435 compat_name = write_old_sd_name(buffer, major, minor, ((i == 2) ? "" : (ptr + 4))); 1449 1436 1450 1437 /* 5 == scsi/mt */ … … 1585 1572 if (isspace(ch) ||(ch == '/') ||(ch == '\0')) { 1586 1573 /* User's own home directory: leave separator for next time */ 1587 if ((env = getenv("HOME")) == NULL) { 1574 env = getenv("HOME"); 1575 if (env == NULL) { 1588 1576 info_logger(LOG_INFO, bb_msg_variable_not_found, "HOME"); 1589 1577 return FALSE; … … 1604 1592 safe_memcpy(tmp, input, len); 1605 1593 input = ptr - 1; 1606 if ((pwent = getpwnam(tmp)) == NULL) { 1594 pwent = getpwnam(tmp); 1595 if (pwent == NULL) { 1607 1596 info_logger(LOG_INFO, "no pwent for: %s", tmp); 1608 1597 return FALSE; … … 1664 1653 if (ch == '$') { 1665 1654 /* Special case for "$$": PID */ 1666 sprintf(tmp, "%d", (int) getpid());1655 sprintf(tmp, "%d", (int) getpid()); 1667 1656 len = strlen(tmp); 1668 1657 if (len + *out_pos >= length) … … 1684 1673 safe_memcpy(tmp, input, len); 1685 1674 input = ptr - 1; 1686 if ((env = get_variable_v2(tmp, func, info)) == NULL) { 1675 env = get_variable_v2(tmp, func, info); 1676 if (env == NULL) { 1687 1677 info_logger(LOG_INFO, bb_msg_variable_not_found, tmp); 1688 1678 return NULL; … … 1736 1726 break; 1737 1727 case '\0': 1738 info_logger(LOG_INFO, "\"}\" not found in: %s", input);1728 info_logger(LOG_INFO, "\"}\" not found in: %s", input); 1739 1729 return NULL; 1740 1730 default: … … 1744 1734 --ptr; 1745 1735 /* At this point ptr should point to closing brace of "${var:-word}" */ 1746 if ((env = get_variable_v2(tmp, func, info)) != NULL) { 1736 env = get_variable_v2(tmp, func, info); 1737 if (env != NULL) { 1747 1738 /* Found environment variable, so skip the input to the closing brace 1748 1739 and return the variable */ -
branches/2.2.9/mindi-busybox/miscutils/eject.c
r1765 r2725 6 6 * Copyright (C) 2005 Tito Ragusa <farmatito@tiscali.it> 7 7 * 8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 9 */ 10 10 … … 14 14 */ 15 15 16 #include <sys/mount.h> 16 17 #include "libbb.h" 18 /* Must be after libbb.h: they need size_t */ 19 #include "fix_u32.h" 20 #include <scsi/sg.h> 21 #include <scsi/scsi.h> 17 22 18 23 /* various defines swiped from linux/cdrom.h */ … … 23 28 #define CDS_TRAY_OPEN 2 24 29 30 #define dev_fd 3 31 32 /* Code taken from the original eject (http://eject.sourceforge.net/), 33 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */ 34 35 static void eject_scsi(const char *dev) 36 { 37 static const char sg_commands[3][6] = { 38 { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 }, 39 { START_STOP, 0, 0, 0, 1, 0 }, 40 { START_STOP, 0, 0, 0, 2, 0 } 41 }; 42 43 unsigned i; 44 unsigned char sense_buffer[32]; 45 unsigned char inqBuff[2]; 46 sg_io_hdr_t io_hdr; 47 48 if ((ioctl(dev_fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000)) 49 bb_error_msg_and_die("not a sg device or old sg driver"); 50 51 memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 52 io_hdr.interface_id = 'S'; 53 io_hdr.cmd_len = 6; 54 io_hdr.mx_sb_len = sizeof(sense_buffer); 55 io_hdr.dxfer_direction = SG_DXFER_NONE; 56 /* io_hdr.dxfer_len = 0; */ 57 io_hdr.dxferp = inqBuff; 58 io_hdr.sbp = sense_buffer; 59 io_hdr.timeout = 2000; 60 61 for (i = 0; i < 3; i++) { 62 io_hdr.cmdp = (void *)sg_commands[i]; 63 ioctl_or_perror_and_die(dev_fd, SG_IO, (void *)&io_hdr, "%s", dev); 64 } 65 66 /* force kernel to reread partition table when new disc is inserted */ 67 ioctl(dev_fd, BLKRRPART); 68 } 69 25 70 #define FLAG_CLOSE 1 26 71 #define FLAG_SMART 2 72 #define FLAG_SCSI 4 27 73 28 int eject_main(int argc, char **argv); 29 int eject_main(int argc, char **argv) 74 static void eject_cdrom(unsigned flags, const char *dev) 30 75 { 31 unsigned long flags; 76 int cmd = CDROMEJECT; 77 78 if (flags & FLAG_CLOSE 79 || ((flags & FLAG_SMART) && ioctl(dev_fd, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) 80 ) { 81 cmd = CDROMCLOSETRAY; 82 } 83 84 ioctl_or_perror_and_die(dev_fd, cmd, NULL, "%s", dev); 85 } 86 87 int eject_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 88 int eject_main(int argc UNUSED_PARAM, char **argv) 89 { 90 unsigned flags; 32 91 const char *device; 33 int dev, cmd;34 92 35 93 opt_complementary = "?1:t--T:T--t"; 36 flags = getopt32(argv, "tT" );37 device = argv[optind] ? : "/dev/cdrom";94 flags = getopt32(argv, "tT" IF_FEATURE_EJECT_SCSI("s")); 95 device = argv[optind] ? argv[optind] : "/dev/cdrom"; 38 96 39 // We used to do "umount <device>" here, but it was buggy 40 // if something was mounted OVER cdrom and 41 // if cdrom is mounted many times. 42 // 43 // This works equally well (or better): 44 // #!/bin/sh 45 // umount /dev/cdrom 46 // eject 97 /* We used to do "umount <device>" here, but it was buggy 98 if something was mounted OVER cdrom and 99 if cdrom is mounted many times. 47 100 48 dev = xopen(device, O_RDONLY|O_NONBLOCK);49 cmd = CDROMEJECT;50 if (flags & FLAG_CLOSE51 || (flags & FLAG_SMART && ioctl(dev, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN))52 cmd = CDROMCLOSETRAY;101 This works equally well (or better): 102 #!/bin/sh 103 umount /dev/cdrom 104 eject /dev/cdrom 105 */ 53 106 54 ioctl_or_perror_and_die(dev, cmd, NULL, "%s", device); 107 xmove_fd(xopen_nonblocking(device), dev_fd); 108 109 if (ENABLE_FEATURE_EJECT_SCSI && (flags & FLAG_SCSI)) 110 eject_scsi(device); 111 else 112 eject_cdrom(flags, device); 55 113 56 114 if (ENABLE_FEATURE_CLEAN_UP) 57 close(dev );115 close(dev_fd); 58 116 59 117 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/miscutils/hdparm.c
r1765 r2725 6 6 * Hacked by Tito <farmatito@tiscali.it> for size optimization. 7 7 * 8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 9 * 10 10 * This program is based on the source code of hdparm: see below... … … 12 12 * - by Mark Lord (C) 1994-2002 -- freely distributable 13 13 */ 14 15 14 #include "libbb.h" 15 /* must be _after_ libbb.h: */ 16 16 #include <linux/hdreg.h> 17 #include <sys/mount.h> 18 #if !defined(BLKGETSIZE64) 19 # define BLKGETSIZE64 _IOR(0x12,114,size_t) 20 #endif 17 21 18 22 /* device types */ … … 60 64 /* multiword DMA xfer cycle time: */ 61 65 #define DMA_TIME_MIN 65 /* - minimum */ 62 #define DMA_TIME_NORM 66 /* - manufacturer's recommended 66 #define DMA_TIME_NORM 66 /* - manufacturer's recommended */ 63 67 /* minimum PIO xfer cycle time: */ 64 68 #define PIO_NO_FLOW 67 /* - without flow control */ … … 83 87 #define ADV_PWR 91 /* current advanced power management level 84 88 in low byte, 0x40 in high byte. */ 85 #define PSWD_CODE 92 /* master password revision code 89 #define PSWD_CODE 92 /* master password revision code */ 86 90 #define HWRST_RSLT 93 /* hardware reset result */ 87 91 #define ACOUSTIC 94 /* acoustic mgmt values ( >= ATA-6) */ … … 128 132 #define CDROM 0x0005 129 133 130 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY131 static const char *const pkt_str[] = {132 "Direct-access device", /* word 0, bits 12-8 = 00 */133 "Sequential-access device", /* word 0, bits 12-8 = 01 */134 "Printer", /* word 0, bits 12-8 = 02 */135 "Processor", /* word 0, bits 12-8 = 03 */136 "Write-once device", /* word 0, bits 12-8 = 04 */137 "CD-ROM", /* word 0, bits 12-8 = 05 */138 "Scanner", /* word 0, bits 12-8 = 06 */139 "Optical memory", /* word 0, bits 12-8 = 07 */140 "Medium changer", /* word 0, bits 12-8 = 08 */141 "Communications device", /* word 0, bits 12-8 = 09 */142 "ACS-IT8 device", /* word 0, bits 12-8 = 0a */143 "ACS-IT8 device", /* word 0, bits 12-8 = 0b */144 "Array controller", /* word 0, bits 12-8 = 0c */145 "Enclosure services", /* word 0, bits 12-8 = 0d */146 "Reduced block command device", /* word 0, bits 12-8 = 0e */147 "Optical card reader/writer", /* word 0, bits 12-8 = 0f */148 "", /* word 0, bits 12-8 = 10 */149 "", /* word 0, bits 12-8 = 11 */150 "", /* word 0, bits 12-8 = 12 */151 "", /* word 0, bits 12-8 = 13 */152 "", /* word 0, bits 12-8 = 14 */153 "", /* word 0, bits 12-8 = 15 */154 "", /* word 0, bits 12-8 = 16 */155 "", /* word 0, bits 12-8 = 17 */156 "", /* word 0, bits 12-8 = 18 */157 "", /* word 0, bits 12-8 = 19 */158 "", /* word 0, bits 12-8 = 1a */159 "", /* word 0, bits 12-8 = 1b */160 "", /* word 0, bits 12-8 = 1c */161 "", /* word 0, bits 12-8 = 1d */162 "", /* word 0, bits 12-8 = 1e */163 "Unknown", /* word 0, bits 12-8 = 1f */164 };165 166 static const char *const ata1_cfg_str[] = { /* word 0 in ATA-1 mode */167 "Reserved", /* bit 0 */168 "hard sectored", /* bit 1 */169 "soft sectored", /* bit 2 */170 "not MFM encoded ", /* bit 3 */171 "head switch time > 15us", /* bit 4 */172 "spindle motor control option", /* bit 5 */173 "fixed drive", /* bit 6 */174 "removable drive", /* bit 7 */175 "disk xfer rate <= 5Mbs", /* bit 8 */176 "disk xfer rate > 5Mbs, <= 10Mbs", /* bit 9 */177 "disk xfer rate > 5Mbs", /* bit 10 */178 "rotational speed tol.", /* bit 11 */179 "data strobe offset option", /* bit 12 */180 "track offset option", /* bit 13 */181 "format speed tolerance gap reqd", /* bit 14 */182 "ATAPI" /* bit 14 */183 };184 #endif185 186 134 /* word 1: number of logical cylinders */ 187 135 #define LCYLS_MAX 0x3fff /* maximum allowable value */ … … 239 187 /* word 81: minor version number */ 240 188 #define MINOR_MAX 0x22 189 /* words 82-84: cmds/feats supported */ 190 #define CMDS_W82 0x77ff /* word 82: defined command locations*/ 191 #define CMDS_W83 0x3fff /* word 83: defined command locations*/ 192 #define CMDS_W84 0x002f /* word 83: defined command locations*/ 193 #define SUPPORT_48_BIT 0x0400 194 #define NUM_CMD_FEAT_STR 48 195 196 /* words 85-87: cmds/feats enabled */ 197 /* use cmd_feat_str[] to display what commands and features have 198 * been enabled with words 85-87 199 */ 200 201 /* words 89, 90, SECU ERASE TIME */ 202 #define ERASE_BITS 0x00ff 203 204 /* word 92: master password revision */ 205 /* NOVAL_0 or NOVAL_1 means no support for master password revision */ 206 207 /* word 93: hw reset result */ 208 #define CBLID 0x2000 /* CBLID status */ 209 #define RST0 0x0001 /* 1=reset to device #0 */ 210 #define DEV_DET 0x0006 /* how device num determined */ 211 #define JUMPER_VAL 0x0002 /* device num determined by jumper */ 212 #define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ 213 214 /* word 127: removable media status notification feature set support */ 215 #define RM_STAT_BITS 0x0003 216 #define RM_STAT_SUP 0x0001 217 218 /* word 128: security */ 219 #define SECU_ENABLED 0x0002 220 #define SECU_LEVEL 0x0010 221 #define NUM_SECU_STR 6 222 223 /* word 160: CFA power mode */ 224 #define VALID_W160 0x8000 /* 1=word valid */ 225 #define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ 226 #define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ 227 #define MAX_AMPS 0x0fff /* value = max current in ma */ 228 229 /* word 255: integrity */ 230 #define SIG 0x00ff /* signature location */ 231 #define SIG_VAL 0x00a5 /* signature value */ 232 233 #define TIMING_BUF_MB 1 234 #define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) 235 236 #undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ 237 238 239 #define IS_GET 1 240 #define IS_SET 2 241 242 243 enum { fd = 3 }; 244 245 246 struct globals { 247 smallint get_identity, get_geom; 248 smallint do_flush; 249 smallint do_ctimings, do_timings; 250 smallint reread_partn; 251 smallint set_piomode, noisy_piomode; 252 smallint getset_readahead; 253 smallint getset_readonly; 254 smallint getset_unmask; 255 smallint getset_mult; 256 #ifdef HDIO_GET_QDMA 257 smallint getset_dma_q; 258 #endif 259 smallint getset_nowerr; 260 smallint getset_keep; 261 smallint getset_io32bit; 262 int piomode; 263 unsigned long Xreadahead; 264 unsigned long readonly; 265 unsigned long unmask; 266 unsigned long mult; 267 #ifdef HDIO_SET_QDMA 268 unsigned long dma_q; 269 #endif 270 unsigned long nowerr; 271 unsigned long keep; 272 unsigned long io32bit; 273 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 274 unsigned long dma; 275 smallint getset_dma; 276 #endif 277 #ifdef HDIO_DRIVE_CMD 278 smallint set_xfermode, get_xfermode; 279 smallint getset_dkeep; 280 smallint getset_standby; 281 smallint getset_lookahead; 282 smallint getset_prefetch; 283 smallint getset_defects; 284 smallint getset_wcache; 285 smallint getset_doorlock; 286 smallint set_seagate; 287 smallint set_standbynow; 288 smallint set_sleepnow; 289 smallint get_powermode; 290 smallint getset_apmmode; 291 int xfermode_requested; 292 unsigned long dkeep; 293 unsigned long standby_requested; /* 0..255 */ 294 unsigned long lookahead; 295 unsigned long prefetch; 296 unsigned long defects; 297 unsigned long wcache; 298 unsigned long doorlock; 299 unsigned long apmmode; 300 #endif 301 IF_FEATURE_HDPARM_GET_IDENTITY( smallint get_IDentity;) 302 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint getset_busstate;) 303 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET( smallint perform_reset;) 304 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint perform_tristate;) 305 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;) 306 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF( smallint scan_hwif;) 307 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long busstate;) 308 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long tristate;) 309 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;) 310 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 311 unsigned long hwif_data; 312 unsigned long hwif_ctrl; 313 unsigned long hwif_irq; 314 #endif 315 #ifdef DO_FLUSHCACHE 316 unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 }; 317 #endif 318 } FIX_ALIASING; 319 #define G (*(struct globals*)&bb_common_bufsiz1) 320 struct BUG_G_too_big { 321 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; 322 }; 323 #define get_identity (G.get_identity ) 324 #define get_geom (G.get_geom ) 325 #define do_flush (G.do_flush ) 326 #define do_ctimings (G.do_ctimings ) 327 #define do_timings (G.do_timings ) 328 #define reread_partn (G.reread_partn ) 329 #define set_piomode (G.set_piomode ) 330 #define noisy_piomode (G.noisy_piomode ) 331 #define getset_readahead (G.getset_readahead ) 332 #define getset_readonly (G.getset_readonly ) 333 #define getset_unmask (G.getset_unmask ) 334 #define getset_mult (G.getset_mult ) 335 #define getset_dma_q (G.getset_dma_q ) 336 #define getset_nowerr (G.getset_nowerr ) 337 #define getset_keep (G.getset_keep ) 338 #define getset_io32bit (G.getset_io32bit ) 339 #define piomode (G.piomode ) 340 #define Xreadahead (G.Xreadahead ) 341 #define readonly (G.readonly ) 342 #define unmask (G.unmask ) 343 #define mult (G.mult ) 344 #define dma_q (G.dma_q ) 345 #define nowerr (G.nowerr ) 346 #define keep (G.keep ) 347 #define io32bit (G.io32bit ) 348 #define dma (G.dma ) 349 #define getset_dma (G.getset_dma ) 350 #define set_xfermode (G.set_xfermode ) 351 #define get_xfermode (G.get_xfermode ) 352 #define getset_dkeep (G.getset_dkeep ) 353 #define getset_standby (G.getset_standby ) 354 #define getset_lookahead (G.getset_lookahead ) 355 #define getset_prefetch (G.getset_prefetch ) 356 #define getset_defects (G.getset_defects ) 357 #define getset_wcache (G.getset_wcache ) 358 #define getset_doorlock (G.getset_doorlock ) 359 #define set_seagate (G.set_seagate ) 360 #define set_standbynow (G.set_standbynow ) 361 #define set_sleepnow (G.set_sleepnow ) 362 #define get_powermode (G.get_powermode ) 363 #define getset_apmmode (G.getset_apmmode ) 364 #define xfermode_requested (G.xfermode_requested ) 365 #define dkeep (G.dkeep ) 366 #define standby_requested (G.standby_requested ) 367 #define lookahead (G.lookahead ) 368 #define prefetch (G.prefetch ) 369 #define defects (G.defects ) 370 #define wcache (G.wcache ) 371 #define doorlock (G.doorlock ) 372 #define apmmode (G.apmmode ) 373 #define get_IDentity (G.get_IDentity ) 374 #define getset_busstate (G.getset_busstate ) 375 #define perform_reset (G.perform_reset ) 376 #define perform_tristate (G.perform_tristate ) 377 #define unregister_hwif (G.unregister_hwif ) 378 #define scan_hwif (G.scan_hwif ) 379 #define busstate (G.busstate ) 380 #define tristate (G.tristate ) 381 #define hwif (G.hwif ) 382 #define hwif_data (G.hwif_data ) 383 #define hwif_ctrl (G.hwif_ctrl ) 384 #define hwif_irq (G.hwif_irq ) 385 386 387 /* Busybox messages and functions */ 388 #if ENABLE_IOCTL_HEX2STR_ERROR 389 static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string) 390 { 391 if (!ioctl(fd, cmd, args)) 392 return 0; 393 args[0] = alt; 394 return bb_ioctl_or_warn(fd, cmd, args, string); 395 } 396 #define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd) 397 #else 398 static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt) 399 { 400 if (!ioctl(fd, cmd, args)) 401 return 0; 402 args[0] = alt; 403 return bb_ioctl_or_warn(fd, cmd, args); 404 } 405 #define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt) 406 #endif 407 408 static void on_off(int value) 409 { 410 puts(value ? " (on)" : " (off)"); 411 } 412 413 static void print_flag_on_off(int get_arg, const char *s, unsigned long arg) 414 { 415 if (get_arg) { 416 printf(" setting %s to %ld", s, arg); 417 on_off(arg); 418 } 419 } 420 421 static void print_value_on_off(const char *str, unsigned long argp) 422 { 423 printf(" %s\t= %2ld", str, argp); 424 on_off(argp != 0); 425 } 426 241 427 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 242 static const char *const minor_str[MINOR_MAX + 2] = { 428 static void print_ascii(const char *p, int length) 429 { 430 #if BB_BIG_ENDIAN 431 #define LE_ONLY(x) 432 enum { ofs = 0 }; 433 #else 434 #define LE_ONLY(x) x 435 /* every 16bit word is big-endian (i.e. inverted) */ 436 /* accessing bytes in 1,0, 3,2, 5,4... sequence */ 437 int ofs = 1; 438 #endif 439 440 length *= 2; 441 /* find first non-space & print it */ 442 while (length && p[ofs] != ' ') { 443 p++; 444 LE_ONLY(ofs = -ofs;) 445 length--; 446 } 447 while (length && p[ofs]) { 448 bb_putchar(p[ofs]); 449 p++; 450 LE_ONLY(ofs = -ofs;) 451 length--; 452 } 453 bb_putchar('\n'); 454 #undef LE_ONLY 455 } 456 457 static void xprint_ascii(uint16_t *val, int i, const char *string, int n) 458 { 459 if (val[i]) { 460 printf("\t%-20s", string); 461 print_ascii((void*)&val[i], n); 462 } 463 } 464 465 static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode) 466 { 467 uint16_t ii; 468 uint8_t err_dma = 0; 469 470 for (ii = 0; ii <= MODE_MAX; ii++) { 471 if (mode_sel & 0x0001) { 472 printf("*%cdma%u ", cc, ii); 473 if (*have_mode) 474 err_dma = 1; 475 *have_mode = 1; 476 } else if (mode_sup & 0x0001) 477 printf("%cdma%u ", cc, ii); 478 479 mode_sup >>= 1; 480 mode_sel >>= 1; 481 } 482 return err_dma; 483 } 484 485 static const char pkt_str[] ALIGN1 = 486 "Direct-access device" "\0" /* word 0, bits 12-8 = 00 */ 487 "Sequential-access device" "\0" /* word 0, bits 12-8 = 01 */ 488 "Printer" "\0" /* word 0, bits 12-8 = 02 */ 489 "Processor" "\0" /* word 0, bits 12-8 = 03 */ 490 "Write-once device" "\0" /* word 0, bits 12-8 = 04 */ 491 "CD-ROM" "\0" /* word 0, bits 12-8 = 05 */ 492 "Scanner" "\0" /* word 0, bits 12-8 = 06 */ 493 "Optical memory" "\0" /* word 0, bits 12-8 = 07 */ 494 "Medium changer" "\0" /* word 0, bits 12-8 = 08 */ 495 "Communications device" "\0" /* word 0, bits 12-8 = 09 */ 496 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0a */ 497 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0b */ 498 "Array controller" "\0" /* word 0, bits 12-8 = 0c */ 499 "Enclosure services" "\0" /* word 0, bits 12-8 = 0d */ 500 "Reduced block command device" "\0" /* word 0, bits 12-8 = 0e */ 501 "Optical card reader/writer" "\0" /* word 0, bits 12-8 = 0f */ 502 ; 503 504 static const char ata1_cfg_str[] ALIGN1 = /* word 0 in ATA-1 mode */ 505 "reserved" "\0" /* bit 0 */ 506 "hard sectored" "\0" /* bit 1 */ 507 "soft sectored" "\0" /* bit 2 */ 508 "not MFM encoded " "\0" /* bit 3 */ 509 "head switch time > 15us" "\0" /* bit 4 */ 510 "spindle motor control option" "\0" /* bit 5 */ 511 "fixed drive" "\0" /* bit 6 */ 512 "removable drive" "\0" /* bit 7 */ 513 "disk xfer rate <= 5Mbs" "\0" /* bit 8 */ 514 "disk xfer rate > 5Mbs, <= 10Mbs" "\0" /* bit 9 */ 515 "disk xfer rate > 5Mbs" "\0" /* bit 10 */ 516 "rotational speed tol." "\0" /* bit 11 */ 517 "data strobe offset option" "\0" /* bit 12 */ 518 "track offset option" "\0" /* bit 13 */ 519 "format speed tolerance gap reqd" "\0" /* bit 14 */ 520 "ATAPI" /* bit 14 */ 521 ; 522 523 static const char minor_str[] ALIGN1 = 243 524 /* word 81 value: */ 244 "Unspecified", /* 0x0000 */ 245 "ATA-1 X3T9.2 781D prior to rev.4", /* 0x0001 */ 246 "ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ 247 "ATA-1 X3T9.2 781D rev.4", /* 0x0003 */ 248 "ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ 249 "ATA-2 X3T10 948D prior to rev.2k", /* 0x0005 */ 250 "ATA-3 X3T10 2008D rev.1", /* 0x0006 */ 251 "ATA-2 X3T10 948D rev.2k", /* 0x0007 */ 252 "ATA-3 X3T10 2008D rev.0", /* 0x0008 */ 253 "ATA-2 X3T10 948D rev.3", /* 0x0009 */ 254 "ATA-3 published, ANSI X3.298-199x", /* 0x000a */ 255 "ATA-3 X3T10 2008D rev.6", /* 0x000b */ 256 "ATA-3 X3T13 2008D rev.7 and 7a", /* 0x000c */ 257 "ATA/ATAPI-4 X3T13 1153D rev.6", /* 0x000d */ 258 "ATA/ATAPI-4 T13 1153D rev.13", /* 0x000e */ 259 "ATA/ATAPI-4 X3T13 1153D rev.7", /* 0x000f */ 260 "ATA/ATAPI-4 T13 1153D rev.18", /* 0x0010 */ 261 "ATA/ATAPI-4 T13 1153D rev.15", /* 0x0011 */ 262 "ATA/ATAPI-4 published, ANSI INCITS 317-1998", /* 0x0012 */ 263 "ATA/ATAPI-5 T13 1321D rev.3", /* 0x0013 */ 264 "ATA/ATAPI-4 T13 1153D rev.14", /* 0x0014 */ 265 "ATA/ATAPI-5 T13 1321D rev.1", /* 0x0015 */ 266 "ATA/ATAPI-5 published, ANSI INCITS 340-2000", /* 0x0016 */ 267 "ATA/ATAPI-4 T13 1153D rev.17", /* 0x0017 */ 268 "ATA/ATAPI-6 T13 1410D rev.0", /* 0x0018 */ 269 "ATA/ATAPI-6 T13 1410D rev.3a", /* 0x0019 */ 270 "ATA/ATAPI-7 T13 1532D rev.1", /* 0x001a */ 271 "ATA/ATAPI-6 T13 1410D rev.2", /* 0x001b */ 272 "ATA/ATAPI-6 T13 1410D rev.1", /* 0x001c */ 273 "ATA/ATAPI-7 published, ANSI INCITS 397-2005", /* 0x001d */ 274 "ATA/ATAPI-7 T13 1532D rev.0", /* 0x001e */ 275 "Reserved" /* 0x001f */ 276 "Reserved" /* 0x0020 */ 277 "ATA/ATAPI-7 T13 1532D rev.4a", /* 0x0021 */ 278 "ATA/ATAPI-6 published, ANSI INCITS 361-2002", /* 0x0022 */ 279 "Reserved" /* 0x0023-0xfffe */ 280 }; 281 #endif 525 "Unspecified" "\0" /* 0x0000 */ 526 "ATA-1 X3T9.2 781D prior to rev.4" "\0" /* 0x0001 */ 527 "ATA-1 published, ANSI X3.221-1994" "\0" /* 0x0002 */ 528 "ATA-1 X3T9.2 781D rev.4" "\0" /* 0x0003 */ 529 "ATA-2 published, ANSI X3.279-1996" "\0" /* 0x0004 */ 530 "ATA-2 X3T10 948D prior to rev.2k" "\0" /* 0x0005 */ 531 "ATA-3 X3T10 2008D rev.1" "\0" /* 0x0006 */ 532 "ATA-2 X3T10 948D rev.2k" "\0" /* 0x0007 */ 533 "ATA-3 X3T10 2008D rev.0" "\0" /* 0x0008 */ 534 "ATA-2 X3T10 948D rev.3" "\0" /* 0x0009 */ 535 "ATA-3 published, ANSI X3.298-199x" "\0" /* 0x000a */ 536 "ATA-3 X3T10 2008D rev.6" "\0" /* 0x000b */ 537 "ATA-3 X3T13 2008D rev.7 and 7a" "\0" /* 0x000c */ 538 "ATA/ATAPI-4 X3T13 1153D rev.6" "\0" /* 0x000d */ 539 "ATA/ATAPI-4 T13 1153D rev.13" "\0" /* 0x000e */ 540 "ATA/ATAPI-4 X3T13 1153D rev.7" "\0" /* 0x000f */ 541 "ATA/ATAPI-4 T13 1153D rev.18" "\0" /* 0x0010 */ 542 "ATA/ATAPI-4 T13 1153D rev.15" "\0" /* 0x0011 */ 543 "ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0" /* 0x0012 */ 544 "ATA/ATAPI-5 T13 1321D rev.3" "\0" /* 0x0013 */ 545 "ATA/ATAPI-4 T13 1153D rev.14" "\0" /* 0x0014 */ 546 "ATA/ATAPI-5 T13 1321D rev.1" "\0" /* 0x0015 */ 547 "ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0" /* 0x0016 */ 548 "ATA/ATAPI-4 T13 1153D rev.17" "\0" /* 0x0017 */ 549 "ATA/ATAPI-6 T13 1410D rev.0" "\0" /* 0x0018 */ 550 "ATA/ATAPI-6 T13 1410D rev.3a" "\0" /* 0x0019 */ 551 "ATA/ATAPI-7 T13 1532D rev.1" "\0" /* 0x001a */ 552 "ATA/ATAPI-6 T13 1410D rev.2" "\0" /* 0x001b */ 553 "ATA/ATAPI-6 T13 1410D rev.1" "\0" /* 0x001c */ 554 "ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0" /* 0x001d */ 555 "ATA/ATAPI-7 T13 1532D rev.0" "\0" /* 0x001e */ 556 "reserved" "\0" /* 0x001f */ 557 "reserved" "\0" /* 0x0020 */ 558 "ATA/ATAPI-7 T13 1532D rev.4a" "\0" /* 0x0021 */ 559 "ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0" /* 0x0022 */ 560 "reserved" /* 0x0023-0xfffe */ 561 ; 282 562 static const char actual_ver[MINOR_MAX + 2] ALIGN1 = { 283 563 /* word 81 value: */ … … 320 600 }; 321 601 322 /* words 82-84: cmds/feats supported */ 323 #define CMDS_W82 0x77ff /* word 82: defined command locations*/ 324 #define CMDS_W83 0x3fff /* word 83: defined command locations*/ 325 #define CMDS_W84 0x002f /* word 83: defined command locations*/ 326 #define SUPPORT_48_BIT 0x0400 327 #define NUM_CMD_FEAT_STR 48 328 329 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 330 static const char *const cmd_feat_str[] = { 331 "", /* word 82 bit 15: obsolete */ 332 "NOP cmd", /* word 82 bit 14 */ 333 "READ BUFFER cmd", /* word 82 bit 13 */ 334 "WRITE BUFFER cmd", /* word 82 bit 12 */ 335 "", /* word 82 bit 11: obsolete */ 336 "Host Protected Area feature set", /* word 82 bit 10 */ 337 "DEVICE RESET cmd", /* word 82 bit 9 */ 338 "SERVICE interrupt", /* word 82 bit 8 */ 339 "Release interrupt", /* word 82 bit 7 */ 340 "Look-ahead", /* word 82 bit 6 */ 341 "Write cache", /* word 82 bit 5 */ 342 "PACKET command feature set", /* word 82 bit 4 */ 343 "Power Management feature set", /* word 82 bit 3 */ 344 "Removable Media feature set", /* word 82 bit 2 */ 345 "Security Mode feature set", /* word 82 bit 1 */ 346 "SMART feature set", /* word 82 bit 0 */ 347 /* -------------- */ 348 "", /* word 83 bit 15: !valid bit */ 349 "", /* word 83 bit 14: valid bit */ 350 "FLUSH CACHE EXT cmd", /* word 83 bit 13 */ 351 "Mandatory FLUSH CACHE cmd ", /* word 83 bit 12 */ 352 "Device Configuration Overlay feature set ", 353 "48-bit Address feature set ", /* word 83 bit 10 */ 354 "", 355 "SET MAX security extension", /* word 83 bit 8 */ 356 "Address Offset Reserved Area Boot", /* word 83 bit 7 */ 357 "SET FEATURES subcommand required to spinup after power up", 358 "Power-Up In Standby feature set", /* word 83 bit 5 */ 359 "Removable Media Status Notification feature set", 360 "Adv. Power Management feature set", /* word 83 bit 3 */ 361 "CFA feature set", /* word 83 bit 2 */ 362 "READ/WRITE DMA QUEUED", /* word 83 bit 1 */ 363 "DOWNLOAD MICROCODE cmd", /* word 83 bit 0 */ 364 /* -------------- */ 365 "", /* word 84 bit 15: !valid bit */ 366 "", /* word 84 bit 14: valid bit */ 367 "", /* word 84 bit 13: reserved */ 368 "", /* word 84 bit 12: reserved */ 369 "", /* word 84 bit 11: reserved */ 370 "", /* word 84 bit 10: reserved */ 371 "", /* word 84 bit 9: reserved */ 372 "", /* word 84 bit 8: reserved */ 373 "", /* word 84 bit 7: reserved */ 374 "", /* word 84 bit 6: reserved */ 375 "General Purpose Logging feature set", /* word 84 bit 5 */ 376 "", /* word 84 bit 4: reserved */ 377 "Media Card Pass Through Command feature set ", 378 "Media serial number ", /* word 84 bit 2 */ 379 "SMART self-test ", /* word 84 bit 1 */ 380 "SMART error logging " /* word 84 bit 0 */ 381 }; 382 383 static void identify(uint16_t *id_supplied) ATTRIBUTE_NORETURN; 384 static void identify_from_stdin(void) ATTRIBUTE_NORETURN; 385 #else 386 void identify_from_stdin(void); 387 #endif 388 389 390 /* words 85-87: cmds/feats enabled */ 391 /* use cmd_feat_str[] to display what commands and features have 392 * been enabled with words 85-87 393 */ 394 395 /* words 89, 90, SECU ERASE TIME */ 396 #define ERASE_BITS 0x00ff 397 398 /* word 92: master password revision */ 399 /* NOVAL_0 or NOVAL_1 means no support for master password revision */ 400 401 /* word 93: hw reset result */ 402 #define CBLID 0x2000 /* CBLID status */ 403 #define RST0 0x0001 /* 1=reset to device #0 */ 404 #define DEV_DET 0x0006 /* how device num determined */ 405 #define JUMPER_VAL 0x0002 /* device num determined by jumper */ 406 #define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ 407 408 /* word 127: removable media status notification feature set support */ 409 #define RM_STAT_BITS 0x0003 410 #define RM_STAT_SUP 0x0001 411 412 /* word 128: security */ 413 #define SECU_ENABLED 0x0002 414 #define SECU_LEVEL 0x0010 415 #define NUM_SECU_STR 6 416 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 417 static const char *const secu_str[] = { 418 "supported", /* word 128, bit 0 */ 419 "enabled", /* word 128, bit 1 */ 420 "locked", /* word 128, bit 2 */ 421 "frozen", /* word 128, bit 3 */ 422 "expired: security count", /* word 128, bit 4 */ 423 "supported: enhanced erase" /* word 128, bit 5 */ 424 }; 425 #endif 426 427 /* word 160: CFA power mode */ 428 #define VALID_W160 0x8000 /* 1=word valid */ 429 #define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ 430 #define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ 431 #define MAX_AMPS 0x0fff /* value = max current in ma */ 432 433 /* word 255: integrity */ 434 #define SIG 0x00ff /* signature location */ 435 #define SIG_VAL 0x00a5 /* signature value */ 436 437 #define TIMING_MB 64 438 #define TIMING_BUF_MB 1 439 #define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) 440 #define BUFCACHE_FACTOR 2 441 442 #undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ 443 444 /* Busybox messages and functions */ 445 #if ENABLE_IOCTL_HEX2STR_ERROR 446 static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt, const char *string) 447 { 448 if (!ioctl(fd, cmd, args)) 449 return 0; 450 args[0] = alt; 451 return bb_ioctl_or_warn(fd, cmd, args, string); 452 } 453 #define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt,#cmd) 454 #else 455 static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt) 456 { 457 if (!ioctl(fd, cmd, args)) 458 return 0; 459 args[0] = alt; 460 return bb_ioctl_or_warn(fd, cmd, args); 461 } 462 #define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt) 463 #endif 464 465 static void on_off(int value) 466 { 467 puts(value ? " (on)" : " (off)"); 468 } 469 470 static void print_flag_on_off(int get_arg, const char *s, unsigned long arg) 471 { 472 if (get_arg) { 473 printf(" setting %s to %ld", s, arg); 474 on_off(arg); 475 } 476 } 477 478 static void print_value_on_off(const char *str, unsigned long argp) 479 { 480 printf(" %s\t= %2ld", str, argp); 481 on_off(argp != 0); 482 } 483 484 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 485 static void print_ascii(uint16_t *p, uint8_t length); 486 487 static void xprint_ascii(uint16_t *val, int i, const char *string, int n) 488 { 489 if (val[i]) { 490 printf("\t%-20s", string); 491 print_ascii(&val[i], n); 492 } 493 } 494 #endif 495 /* end of busybox specific stuff */ 496 497 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 498 static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode) 499 { 500 uint16_t ii; 501 uint8_t err_dma = 0; 502 503 for (ii = 0; ii <= MODE_MAX; ii++) { 504 if (mode_sel & 0x0001) { 505 printf("*%cdma%u ", cc, ii); 506 if (*have_mode) 507 err_dma = 1; 508 *have_mode = 1; 509 } else if (mode_sup & 0x0001) 510 printf("%cdma%u ", cc, ii); 511 512 mode_sup >>= 1; 513 mode_sel >>= 1; 514 } 515 return err_dma; 516 } 517 518 static void print_ascii(uint16_t *p, uint8_t length) 519 { 520 uint8_t ii; 521 char cl; 522 523 /* find first non-space & print it */ 524 for (ii = 0; ii < length; ii++) { 525 if ((char)((*p)>>8) != ' ') 526 break; 527 cl = (char)(*p); 528 if (cl != ' ') { 529 if (cl != '\0') 530 printf("%c", cl); 531 p++; 532 ii++; 533 break; 534 } 535 p++; 536 } 537 /* print the rest */ 538 for (; ii< length; ii++) { 539 if (!(*p)) 540 break; /* some older devices have NULLs */ 541 printf("%c%c", (char)((*p)>>8), (char)(*p)); 542 p++; 543 } 544 puts(""); 545 } 602 static const char cmd_feat_str[] ALIGN1 = 603 "" "\0" /* word 82 bit 15: obsolete */ 604 "NOP cmd" "\0" /* word 82 bit 14 */ 605 "READ BUFFER cmd" "\0" /* word 82 bit 13 */ 606 "WRITE BUFFER cmd" "\0" /* word 82 bit 12 */ 607 "" "\0" /* word 82 bit 11: obsolete */ 608 "Host Protected Area feature set" "\0" /* word 82 bit 10 */ 609 "DEVICE RESET cmd" "\0" /* word 82 bit 9 */ 610 "SERVICE interrupt" "\0" /* word 82 bit 8 */ 611 "Release interrupt" "\0" /* word 82 bit 7 */ 612 "Look-ahead" "\0" /* word 82 bit 6 */ 613 "Write cache" "\0" /* word 82 bit 5 */ 614 "PACKET command feature set" "\0" /* word 82 bit 4 */ 615 "Power Management feature set" "\0" /* word 82 bit 3 */ 616 "Removable Media feature set" "\0" /* word 82 bit 2 */ 617 "Security Mode feature set" "\0" /* word 82 bit 1 */ 618 "SMART feature set" "\0" /* word 82 bit 0 */ 619 /* -------------- */ 620 "" "\0" /* word 83 bit 15: !valid bit */ 621 "" "\0" /* word 83 bit 14: valid bit */ 622 "FLUSH CACHE EXT cmd" "\0" /* word 83 bit 13 */ 623 "Mandatory FLUSH CACHE cmd " "\0" /* word 83 bit 12 */ 624 "Device Configuration Overlay feature set " "\0" 625 "48-bit Address feature set " "\0" /* word 83 bit 10 */ 626 "" "\0" 627 "SET MAX security extension" "\0" /* word 83 bit 8 */ 628 "Address Offset Reserved Area Boot" "\0" /* word 83 bit 7 */ 629 "SET FEATURES subcommand required to spinup after power up" "\0" 630 "Power-Up In Standby feature set" "\0" /* word 83 bit 5 */ 631 "Removable Media Status Notification feature set" "\0" 632 "Adv. Power Management feature set" "\0" /* word 83 bit 3 */ 633 "CFA feature set" "\0" /* word 83 bit 2 */ 634 "READ/WRITE DMA QUEUED" "\0" /* word 83 bit 1 */ 635 "DOWNLOAD MICROCODE cmd" "\0" /* word 83 bit 0 */ 636 /* -------------- */ 637 "" "\0" /* word 84 bit 15: !valid bit */ 638 "" "\0" /* word 84 bit 14: valid bit */ 639 "" "\0" /* word 84 bit 13: reserved */ 640 "" "\0" /* word 84 bit 12: reserved */ 641 "" "\0" /* word 84 bit 11: reserved */ 642 "" "\0" /* word 84 bit 10: reserved */ 643 "" "\0" /* word 84 bit 9: reserved */ 644 "" "\0" /* word 84 bit 8: reserved */ 645 "" "\0" /* word 84 bit 7: reserved */ 646 "" "\0" /* word 84 bit 6: reserved */ 647 "General Purpose Logging feature set" "\0" /* word 84 bit 5 */ 648 "" "\0" /* word 84 bit 4: reserved */ 649 "Media Card Pass Through Command feature set " "\0" 650 "Media serial number " "\0" /* word 84 bit 2 */ 651 "SMART self-test " "\0" /* word 84 bit 1 */ 652 "SMART error logging " /* word 84 bit 0 */ 653 ; 654 655 static const char secu_str[] ALIGN1 = 656 "supported" "\0" /* word 128, bit 0 */ 657 "enabled" "\0" /* word 128, bit 1 */ 658 "locked" "\0" /* word 128, bit 2 */ 659 "frozen" "\0" /* word 128, bit 3 */ 660 "expired: security count" "\0" /* word 128, bit 4 */ 661 "supported: enhanced erase" /* word 128, bit 5 */ 662 ; 546 663 547 664 // Parse 512 byte disk identification block and print much crap. 548 549 static void identify(uint16_t *id_supplied) 550 { 551 uint16_t buf[256]; 552 uint16_t *val, ii, jj, kk; 665 static void identify(uint16_t *val) NORETURN; 666 static void identify(uint16_t *val) 667 { 668 uint16_t ii, jj, kk; 553 669 uint16_t like_std = 1, std = 0, min_std = 0xffff; 554 670 uint16_t dev = NO_DEV, eqpt = NO_DEV; … … 558 674 uint64_t bbbig; /* (:) */ 559 675 const char *strng; 560 561 // Adjust for endianness if necessary. 562 563 if (BB_BIG_ENDIAN) { 564 swab(id_supplied, buf, sizeof(buf)); 565 val = buf; 566 } else 567 val = id_supplied; 568 569 chksum &= 0xff; 570 571 /* check if we recognise the device type */ 572 puts(""); 676 #if BB_BIG_ENDIAN 677 uint16_t buf[256]; 678 679 // Adjust for endianness 680 swab(val, buf, sizeof(buf)); 681 val = buf; 682 #endif 683 /* check if we recognize the device type */ 684 bb_putchar('\n'); 573 685 if (!(val[GEN_CONFIG] & NOT_ATA)) { 574 686 dev = ATA_DEV; … … 581 693 dev = ATAPI_DEV; 582 694 eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT; 583 printf("ATAPI %s, with ", pkt_str[eqpt]);695 printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown"); 584 696 like_std = 3; 585 697 } else 586 /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/698 /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */ 587 699 bb_error_msg_and_die("unknown device type"); 588 700 … … 619 731 if (like_std < 3) like_std = 3; 620 732 std = actual_ver[val[MINOR]]; 621 if (std) printf("\n\tUsed: %s ", minor_str[val[MINOR]]);622 733 if (std) 734 printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR])); 623 735 } 624 736 /* looks like when they up-issue the std, they obsolete one; … … 687 799 printf("& some of %u\n", like_std); 688 800 else 689 puts("");801 bb_putchar('\n'); 690 802 } else { 691 803 /* TBD: do CDROM stuff more thoroughly. For now... */ … … 704 816 } 705 817 } 706 p rintf("%s\n",kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");818 puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1"); 707 819 /* the cdrom stuff is more like ATA-2 than anything else, so: */ 708 820 like_std = 2; … … 718 830 for (ii = 1; ii < 15; ii++) { 719 831 if (jj & 0x0001) 720 printf("\t%s\n", ata1_cfg_str[ii]);832 printf("\t%s\n", nth_string(ata1_cfg_str, ii)); 721 833 jj >>=1; 722 834 } … … 730 842 strng ="50us"; 731 843 else 732 strng = " Unknown";844 strng = "unknown"; 733 845 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ 734 846 … … 738 850 strng = "16 bytes"; 739 851 else 740 strng = " Unknown";852 strng = "unknown"; 741 853 puts(strng); 742 854 } else { 743 855 /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */ 744 856 ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB]; 745 mm = 0; bbbig = 0; 857 mm = 0; 858 bbbig = 0; 746 859 if ((ll > 0x00FBFC10) && (!val[LCYLS])) 747 860 printf("\tCHS addressing not supported\n"); 748 861 else { 749 862 jj = val[WHATS_VALID] & OK_W54_58; 750 printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n", 751 val[LCYLS],jj?val[LCYLS_CUR]:0, val[LHEADS],jj?val[LHEADS_CUR]:0, val[LSECTS],jj?val[LSECTS_CUR]:0); 863 printf("\tLogical\t\tmax\tcurrent\n" 864 "\tcylinders\t%u\t%u\n" 865 "\theads\t\t%u\t%u\n" 866 "\tsectors/track\t%u\t%u\n" 867 "\t--\n", 868 val[LCYLS], 869 jj ? val[LCYLS_CUR] : 0, 870 val[LHEADS], 871 jj ? val[LHEADS_CUR] : 0, 872 val[LSECTS], 873 jj ? val[LSECTS_CUR] : 0); 752 874 753 875 if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES])) 754 printf("\tbytes/track: %u\tbytes/sector: %u\n", val[TRACK_BYTES], val[SECT_BYTES]); 876 printf("\tbytes/track: %u\tbytes/sector: %u\n", 877 val[TRACK_BYTES], val[SECT_BYTES]); 755 878 756 879 if (jj) { … … 787 910 printf("(%"PRIu64" GB)\n", bbbig/1000); 788 911 else 789 puts("");912 bb_putchar('\n'); 790 913 } 791 914 … … 794 917 795 918 if (dev == ATAPI_DEV) { 796 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, "); 797 if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, "); 919 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) 920 printf("Cmd queuing, "); 921 if (val[CAPAB_0] & OVLP_SUP) 922 printf("Cmd overlap, "); 798 923 } 799 924 if (val[CAPAB_0] & LBA_SUP) printf("LBA, "); … … 801 926 if (like_std != 1) { 802 927 printf("IORDY%s(can%s be disabled)\n", 803 804 928 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", 929 (val[CAPAB_0] & IORDY_OFF) ? "" :"not"); 805 930 } else 806 931 printf("no IORDY\n"); … … 808 933 if ((like_std == 1) && val[BUF_TYPE]) { 809 934 printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE], 810 811 935 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", 936 (val[BUF_TYPE] > 2) ? " with read caching ability" : ""); 812 937 } 813 938 … … 826 951 printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : ""); 827 952 else { 828 printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor"); 953 printf("\tStandby timer values: spec'd by %s", 954 (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor"); 829 955 if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL)) 830 printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no"); 956 printf(", %s device specific minimum\n", 957 (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no"); 831 958 else 832 puts("");959 bb_putchar('\n'); 833 960 } 834 961 printf("\tR/W multiple sector transfer: "); … … 856 983 if (like_std > 5 && val[ACOUSTIC]) { 857 984 printf("\tRecommended acoustic management value: %u, current value: %u\n", 858 (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff); 985 (val[ACOUSTIC] >> 8) & 0x00ff, 986 val[ACOUSTIC] & 0x00ff); 859 987 } 860 988 } else { … … 865 993 if (val[PKT_REL] || val[SVC_NBSY]) { 866 994 printf("\tOverlap support:"); 867 if (val[PKT_REL]) printf(" %uus to release bus.", val[PKT_REL]); 868 if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.", val[SVC_NBSY]); 869 puts(""); 995 if (val[PKT_REL]) 996 printf(" %uus to release bus.", val[PKT_REL]); 997 if (val[SVC_NBSY]) 998 printf(" %uus to clear BSY after SERVICE cmd.", 999 val[SVC_NBSY]); 1000 bb_putchar('\n'); 870 1001 } 871 1002 } … … 894 1025 } 895 1026 if (err_dma || !have_mode) printf("(?)"); 896 puts("");1027 bb_putchar('\n'); 897 1028 898 1029 if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP)) … … 905 1036 if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]); 906 1037 if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]); 907 puts("");1038 bb_putchar('\n'); 908 1039 } 909 1040 } … … 919 1050 jj >>=1; 920 1051 } 921 puts("");1052 bb_putchar('\n'); 922 1053 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { 923 1054 for (ii = 0; ii <= val[PIO_MODE]>>8; ii++) 924 1055 printf("pio%d ", ii); 925 puts("");1056 bb_putchar('\n'); 926 1057 } else 927 p rintf("unknown\n");1058 puts("unknown"); 928 1059 929 1060 if (val[WHATS_VALID] & OK_W64_70) { 930 1061 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) { 931 1062 printf("\t\tCycle time:"); 932 if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]); 933 if (val[PIO_FLOW]) printf(" IORDY flow control=%uns", val[PIO_FLOW]); 934 puts(""); 1063 if (val[PIO_NO_FLOW]) 1064 printf(" no flow control=%uns", val[PIO_NO_FLOW]); 1065 if (val[PIO_FLOW]) 1066 printf(" IORDY flow control=%uns", val[PIO_FLOW]); 1067 bb_putchar('\n'); 935 1068 } 936 1069 } 937 1070 938 1071 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) { 939 printf("Commands/features:\n\tEnabled\tSupported:\n"); 1072 printf("Commands/features:\n" 1073 "\tEnabled\tSupported:\n"); 940 1074 jj = val[CMDS_SUPP_0]; 941 1075 kk = val[CMDS_EN_0]; 942 1076 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) { 943 if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) { 944 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", cmd_feat_str[ii]); 1077 const char *feat_str = nth_string(cmd_feat_str, ii); 1078 if ((jj & 0x8000) && (*feat_str != '\0')) { 1079 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", feat_str); 945 1080 } 946 1081 jj <<= 1; … … 958 1093 /* Removable Media Status Notification feature set */ 959 1094 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) 960 printf("\t%s supported\n", cmd_feat_str[27]);1095 printf("\t%s supported\n", nth_string(cmd_feat_str, 27)); 961 1096 962 1097 /* security */ … … 970 1105 if (jj) { 971 1106 for (ii = 0; ii < NUM_SECU_STR; ii++) { 972 printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", secu_str[ii]); 1107 printf("\t%s\t%s\n", 1108 (!(jj & 0x0001)) ? "not" : "", 1109 nth_string(secu_str, ii)); 973 1110 jj >>=1; 974 1111 } 975 1112 if (val[SECU_STATUS] & SECU_ENABLED) { 976 printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high"); 1113 printf("\tSecurity level %s\n", 1114 (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high"); 977 1115 } 978 1116 } … … 980 1118 kk = val[ENH_ERASE_TIME] & ERASE_BITS; 981 1119 if (jj || kk) { 982 printf("\t");1120 bb_putchar('\t'); 983 1121 if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, ""); 984 1122 if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED "); 985 puts("");1123 bb_putchar('\n'); 986 1124 } 987 1125 } … … 990 1128 jj = val[HWRST_RSLT]; 991 1129 if ((jj & VALID) == VALID_VAL) { 992 if (!(oo = (jj & RST0))) 1130 oo = (jj & RST0); 1131 if (!oo) 993 1132 jj >>= 8; 994 1133 if ((jj & DEV_DET) == JUMPER_VAL) … … 998 1137 else 999 1138 strng = ""; 1000 printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n", 1001 (val[HWRST_RSLT] & CBLID) ? "above" : "below", !(oo), strng); 1139 printf("HW reset results:\n" 1140 "\tCBLID- %s Vih\n" 1141 "\tDevice num = %i%s\n", 1142 (val[HWRST_RSLT] & CBLID) ? "above" : "below", 1143 !(oo), strng); 1002 1144 } 1003 1145 … … 1005 1147 if ((like_std > 4) && (eqpt != CDROM)) { 1006 1148 if (val[CFA_PWR_MODE] & VALID_W160) { 1007 printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled", 1008 (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : ""); 1009 1149 printf("CFA power mode 1:\n" 1150 "\t%s%s\n", 1151 (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled", 1152 (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : ""); 1010 1153 if (val[CFA_PWR_MODE] & MAX_AMPS) 1011 1154 printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS); … … 1018 1161 exit(EXIT_SUCCESS); 1019 1162 } 1020 #endif1021 1022 static smallint get_identity, get_geom;1023 static smallint do_flush;1024 static smallint do_ctimings, do_timings;1025 static smallint reread_partn;1026 1027 static smallint set_piomode, noisy_piomode;1028 static smallint set_readahead, get_readahead;1029 static smallint set_readonly, get_readonly;1030 static smallint set_unmask, get_unmask;1031 static smallint set_mult, get_mult;1032 static smallint set_dma_q, get_dma_q;1033 static smallint set_nowerr, get_nowerr;1034 static smallint set_keep, get_keep;1035 static smallint set_io32bit, get_io32bit;1036 static int piomode;1037 static unsigned long Xreadahead;1038 static unsigned long readonly;1039 static unsigned long unmask;1040 static unsigned long mult;1041 static unsigned long dma_q;1042 static unsigned long nowerr;1043 static unsigned long keep;1044 static unsigned long io32bit;1045 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA1046 static unsigned long dma;1047 static smallint set_dma, get_dma;1048 #endif1049 #ifdef HDIO_DRIVE_CMD1050 static smallint set_xfermode, get_xfermode;1051 static smallint set_dkeep, get_dkeep;1052 static smallint set_standby, get_standby;1053 static smallint set_lookahead, get_lookahead;1054 static smallint set_prefetch, get_prefetch;1055 static smallint set_defects, get_defects;1056 static smallint set_wcache, get_wcache;1057 static smallint set_doorlock, get_doorlock;1058 static smallint set_seagate, get_seagate;1059 static smallint set_standbynow, get_standbynow;1060 static smallint set_sleepnow, get_sleepnow;1061 static smallint get_powermode;1062 static smallint set_apmmode, get_apmmode;1063 static int xfermode_requested;1064 static unsigned long dkeep;1065 static unsigned long standby_requested;1066 static unsigned long lookahead;1067 static unsigned long prefetch;1068 static unsigned long defects;1069 static unsigned long wcache;1070 static unsigned long doorlock;1071 static unsigned long apmmode;1072 #endif1073 USE_FEATURE_HDPARM_GET_IDENTITY( static smallint get_IDentity;)1074 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( static smallint set_busstate, get_busstate;)1075 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET( static smallint perform_reset;)1076 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( static smallint perform_tristate;)1077 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static smallint unregister_hwif;)1078 USE_FEATURE_HDPARM_HDIO_SCAN_HWIF( static smallint scan_hwif;)1079 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( static unsigned long busstate;)1080 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( static unsigned long tristate;)1081 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static unsigned long hwif;)1082 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF1083 static unsigned long hwif_data;1084 static unsigned long hwif_ctrl;1085 static unsigned long hwif_irq;1086 1163 #endif 1087 1164 … … 1098 1175 1099 1176 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 1100 static const char *const cfg_str[] = {1101 "" , "HardSect", "SoftSect", "NotMFM",1102 "HdSw>15uSec" , "SpinMotCtl", "Fixed", "Removeable",1103 "DTR<=5Mbs" , "DTR>5Mbs", "DTR>10Mbs", "RotSpdTol>.5%",1104 "dStbOff" , "TrkOff", "FmtGapReq","nonMagnetic"1105 };1106 1107 static const char *const BuffType[] = {1108 " Unknown", "1Sect", "DualPort","DualPortCache"1109 };1110 1111 static void dump_identity(const struct hd_driveid *id)1177 static const char cfg_str[] ALIGN1 = 1178 """\0" "HardSect""\0" "SoftSect""\0" "NotMFM""\0" 1179 "HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0" "Removeable""\0" 1180 "DTR<=5Mbs""\0" "DTR>5Mbs""\0" "DTR>10Mbs""\0" "RotSpdTol>.5%""\0" 1181 "dStbOff""\0" "TrkOff""\0" "FmtGapReq""\0" "nonMagnetic" 1182 ; 1183 1184 static const char BuffType[] ALIGN1 = 1185 "unknown""\0" "1Sect""\0" "DualPort""\0" "DualPortCache" 1186 ; 1187 1188 static NOINLINE void dump_identity(const struct hd_driveid *id) 1112 1189 { 1113 1190 int i; 1114 const unsigned short int*id_regs = (const void*) id;1191 const unsigned short *id_regs = (const void*) id; 1115 1192 1116 1193 printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={", … … 1118 1195 for (i = 0; i <= 15; i++) { 1119 1196 if (id->config & (1<<i)) 1120 printf(" %s", cfg_str[i]);1197 printf(" %s", nth_string(cfg_str, i)); 1121 1198 } 1122 1199 printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n" 1123 " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u", 1124 id->cyls, id->heads, id->sectors, id->track_bytes, 1125 id->sector_bytes, id->ecc_bytes, 1126 id->buf_type, BuffType[(id->buf_type > 3) ? 0 : id->buf_type], 1127 id->buf_size/2, id->max_multsect); 1200 " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u", 1201 id->cyls, id->heads, id->sectors, id->track_bytes, 1202 id->sector_bytes, id->ecc_bytes, 1203 id->buf_type, 1204 nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type), 1205 id->buf_size/2, id->max_multsect); 1128 1206 if (id->max_multsect) { 1129 1207 printf(", MultSect="); … … 1135 1213 printf("off"); 1136 1214 } 1137 puts("");1215 bb_putchar('\n'); 1138 1216 1139 1217 if (!(id->field_valid & 1)) … … 1150 1228 printf(", LBAsects=%u", id->lba_capacity); 1151 1229 1152 printf("\n IORDY=%s", (id->capability & 8) ? (id->capability & 4) ? "on/off" : "yes" : "no"); 1230 printf("\n IORDY=%s", 1231 (id->capability & 8) 1232 ? ((id->capability & 4) ? "on/off" : "yes") 1233 : "no"); 1153 1234 1154 1235 if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2)) … … 1165 1246 } 1166 1247 if (id->field_valid & 2) { 1167 if (id->eide_pio_modes & 1) printf("pio3 "); 1168 if (id->eide_pio_modes & 2) printf("pio4 "); 1169 if (id->eide_pio_modes &~3) printf("pio? "); 1248 static const masks_labels_t pio_modes = { 1249 .masks = { 1, 2, ~3 }, 1250 .labels = "pio3 \0""pio4 \0""pio? \0", 1251 }; 1252 print_flags(&pio_modes, id->eide_pio_modes); 1170 1253 } 1171 1254 if (id->capability & 1) { 1172 1255 if (id->dma_1word | id->dma_mword) { 1256 static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; 1173 1257 printf("\n DMA modes: "); 1174 if (id->dma_1word & 0x100) printf("*"); 1175 if (id->dma_1word & 1) printf("sdma0 "); 1176 if (id->dma_1word & 0x200) printf("*"); 1177 if (id->dma_1word & 2) printf("sdma1 "); 1178 if (id->dma_1word & 0x400) printf("*"); 1179 if (id->dma_1word & 4) printf("sdma2 "); 1180 if (id->dma_1word & 0xf800) printf("*"); 1181 if (id->dma_1word & 0xf8) printf("sdma? "); 1182 if (id->dma_mword & 0x100) printf("*"); 1183 if (id->dma_mword & 1) printf("mdma0 "); 1184 if (id->dma_mword & 0x200) printf("*"); 1185 if (id->dma_mword & 2) printf("mdma1 "); 1186 if (id->dma_mword & 0x400) printf("*"); 1187 if (id->dma_mword & 4) printf("mdma2 "); 1188 if (id->dma_mword & 0xf800) printf("*"); 1189 if (id->dma_mword & 0xf8) printf("mdma? "); 1258 print_flags_separated(dma_wmode_masks, 1259 "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0", 1260 id->dma_1word, NULL); 1261 print_flags_separated(dma_wmode_masks, 1262 "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0", 1263 id->dma_mword, NULL); 1190 1264 } 1191 1265 } 1192 1266 if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) { 1267 static const masks_labels_t ultra_modes1 = { 1268 .masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 }, 1269 .labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0", 1270 }; 1271 1193 1272 printf("\n UDMA modes: "); 1194 if (id->dma_ultra & 0x100) printf("*"); 1195 if (id->dma_ultra & 0x001) printf("udma0 "); 1196 if (id->dma_ultra & 0x200) printf("*"); 1197 if (id->dma_ultra & 0x002) printf("udma1 "); 1198 if (id->dma_ultra & 0x400) printf("*"); 1199 if (id->dma_ultra & 0x004) printf("udma2 "); 1273 print_flags(&ultra_modes1, id->dma_ultra); 1200 1274 #ifdef __NEW_HD_DRIVE_ID 1201 1275 if (id->hw_config & 0x2000) { … … 1203 1277 if (id->word93 & 0x2000) { 1204 1278 #endif /* __NEW_HD_DRIVE_ID */ 1205 if (id->dma_ultra & 0x0800) printf("*"); 1206 if (id->dma_ultra & 0x0008) printf("udma3 "); 1207 if (id->dma_ultra & 0x1000) printf("*"); 1208 if (id->dma_ultra & 0x0010) printf("udma4 "); 1209 if (id->dma_ultra & 0x2000) printf("*"); 1210 if (id->dma_ultra & 0x0020) printf("udma5 "); 1211 if (id->dma_ultra & 0x4000) printf("*"); 1212 if (id->dma_ultra & 0x0040) printf("udma6 "); 1213 if (id->dma_ultra & 0x8000) printf("*"); 1214 if (id->dma_ultra & 0x0080) printf("udma7 "); 1279 static const masks_labels_t ultra_modes2 = { 1280 .masks = { 0x0800, 0x0008, 0x1000, 0x0010, 1281 0x2000, 0x0020, 0x4000, 0x0040, 1282 0x8000, 0x0080 }, 1283 .labels = "*\0""udma3 \0""*\0""udma4 \0" 1284 "*\0""udma5 \0""*\0""udma6 \0" 1285 "*\0""udma7 \0" 1286 }; 1287 print_flags(&ultra_modes2, id->dma_ultra); 1215 1288 } 1216 1289 } … … 1230 1303 || (id->major_rev_num && id->minor_rev_num <= 31) 1231 1304 ) { 1232 printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown"); 1233 if (id->major_rev_num != 0x0000 && /* NOVAL_0 */ 1234 id->major_rev_num != 0xFFFF) { /* NOVAL_1 */ 1305 printf("\n Drive conforms to: %s: ", 1306 (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown"); 1307 if (id->major_rev_num != 0x0000 /* NOVAL_0 */ 1308 && id->major_rev_num != 0xFFFF /* NOVAL_1 */ 1309 ) { 1235 1310 for (i = 0; i <= 15; i++) { 1236 1311 if (id->major_rev_num & (1<<i)) 1237 1312 printf(" ATA/ATAPI-%u", i); 1238 1313 } 1239 1314 } … … 1244 1319 #endif 1245 1320 1246 static void flush_buffer_cache( int fd)1321 static void flush_buffer_cache(/*int fd*/ void) 1247 1322 { 1248 1323 fsync(fd); /* flush buffers */ … … 1259 1334 } 1260 1335 1261 static int seek_to_zero(int fd) 1262 { 1263 if (lseek(fd, (off_t) 0, SEEK_SET)) 1264 return 1; 1265 return 0; 1266 } 1267 1268 static int read_big_block(int fd, char *buf) 1336 static void seek_to_zero(/*int fd*/ void) 1337 { 1338 xlseek(fd, (off_t) 0, SEEK_SET); 1339 } 1340 1341 static void read_big_block(/*int fd,*/ char *buf) 1269 1342 { 1270 1343 int i; 1271 1344 1272 i = read(fd, buf, TIMING_BUF_BYTES); 1273 if (i != TIMING_BUF_BYTES) { 1274 bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i); 1275 return 1; 1276 } 1345 xread(fd, buf, TIMING_BUF_BYTES); 1277 1346 /* access all sectors of buf to ensure the read fully completed */ 1278 1347 for (i = 0; i < TIMING_BUF_BYTES; i += 512) 1279 1348 buf[i] &= 1; 1280 return 0; 1281 } 1282 1283 static int do_blkgetsize(int fd, unsigned long long *blksize64) 1284 { 1285 int rc; 1286 unsigned blksize32 = 0; 1287 1288 if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) { // returns bytes 1289 *blksize64 /= 512; 1290 return 0; 1291 } 1292 rc = ioctl_or_warn(fd, BLKGETSIZE, &blksize32); // returns sectors 1293 *blksize64 = blksize32; 1294 return rc; 1295 } 1296 1297 static void print_timing(unsigned t, double e) 1298 { 1299 if (t >= e) /* more than 1MB/s */ 1300 printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M'); 1301 else 1302 printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k'); 1303 } 1304 1305 static void do_time(int flag, int fd) 1306 /* flag = 0 time_cache, 1 time_device */ 1307 { 1308 static const struct itimerval thousand = {{1000, 0}, {1000, 0}}; 1309 1310 struct itimerval itv; 1349 } 1350 1351 static unsigned dev_size_mb(/*int fd*/ void) 1352 { 1353 union { 1354 unsigned long long blksize64; 1355 unsigned blksize32; 1356 } u; 1357 1358 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes 1359 u.blksize64 /= (1024 * 1024); 1360 } else { 1361 xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors 1362 u.blksize64 = u.blksize32 / (2 * 1024); 1363 } 1364 if (u.blksize64 > UINT_MAX) 1365 return UINT_MAX; 1366 return u.blksize64; 1367 } 1368 1369 static void print_timing(unsigned m, unsigned elapsed_us) 1370 { 1371 unsigned sec = elapsed_us / 1000000; 1372 unsigned hs = (elapsed_us % 1000000) / 10000; 1373 1374 printf("%5u MB in %u.%02u seconds = %u kB/s\n", 1375 m, sec, hs, 1376 /* "| 1" prevents div-by-0 */ 1377 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1)) 1378 // ~= (m * 1024) / (elapsed_us / 1000000) 1379 // = kb / elapsed_sec 1380 ); 1381 } 1382 1383 static void do_time(int cache /*,int fd*/) 1384 /* cache=1: time cache: repeatedly read N MB at offset 0 1385 * cache=0: time device: linear read, starting at offset 0 1386 */ 1387 { 1388 unsigned max_iterations, iterations; 1389 unsigned start; /* doesn't need to be long long */ 1311 1390 unsigned elapsed, elapsed2; 1312 unsigned max_iterations, total_MB, iterations; 1313 unsigned long long blksize; 1314 RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES); 1315 1316 if (mlock(buf, TIMING_BUF_BYTES)) { 1317 bb_perror_msg("mlock"); 1318 goto quit2; 1319 } 1320 1321 max_iterations = 1024; 1322 if (0 == do_blkgetsize(fd, &blksize)) { 1323 max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB; 1324 } 1325 1326 /* Clear out the device request queues & give them time to complete */ 1391 unsigned total_MB; 1392 char *buf = xmalloc(TIMING_BUF_BYTES); 1393 1394 if (mlock(buf, TIMING_BUF_BYTES)) 1395 bb_perror_msg_and_die("mlock"); 1396 1397 /* Clear out the device request queues & give them time to complete. 1398 * NB: *small* delay. User is expected to have a clue and to not run 1399 * heavy io in parallel with measurements. */ 1327 1400 sync(); 1328 sleep(2); 1329 if (flag == 0) { /* Time cache */ 1330 if (seek_to_zero(fd)) 1331 goto quit; 1332 if (read_big_block(fd, buf)) 1333 goto quit; 1334 printf(" Timing buffer-cache reads: "); 1401 sleep(1); 1402 if (cache) { /* Time cache */ 1403 seek_to_zero(); 1404 read_big_block(buf); 1405 printf("Timing buffer-cache reads: "); 1335 1406 } else { /* Time device */ 1336 printf(" Timing buffered disk reads: "); 1337 } 1338 fflush(stdout); 1407 printf("Timing buffered disk reads:"); 1408 } 1409 fflush_all(); 1410 1411 /* Now do the timing */ 1339 1412 iterations = 0; 1340 /* 1341 * getitimer() is used rather than gettimeofday() because 1342 * it is much more consistent (on my machine, at least). 1343 */ 1344 setitimer(ITIMER_REAL, &thousand, NULL); 1345 /* Now do the timing */ 1413 /* Max time to run (small for cache, avoids getting 1414 * huge total_MB which can overlow unsigned type) */ 1415 elapsed2 = 510000; /* cache */ 1416 max_iterations = UINT_MAX; 1417 if (!cache) { 1418 elapsed2 = 3000000; /* not cache */ 1419 /* Don't want to read past the end! */ 1420 max_iterations = dev_size_mb() / TIMING_BUF_MB; 1421 } 1422 start = monotonic_us(); 1346 1423 do { 1424 if (cache) 1425 seek_to_zero(); 1426 read_big_block(buf); 1427 elapsed = (unsigned)monotonic_us() - start; 1347 1428 ++iterations; 1348 if ((flag == 0) && seek_to_zero(fd)) 1349 goto quit; 1350 if (read_big_block(fd, buf)) 1351 goto quit; 1352 getitimer(ITIMER_REAL, &itv); 1353 elapsed = (1000 - itv.it_value.tv_sec) * 1000000 1354 - itv.it_value.tv_usec; 1355 } while (elapsed < 3000000 && iterations < max_iterations); 1429 } while (elapsed < elapsed2 && iterations < max_iterations); 1356 1430 total_MB = iterations * TIMING_BUF_MB; 1357 if (flag == 0) { 1358 /* Now remove the lseek() and getitimer() overheads from the elapsed time */ 1359 setitimer(ITIMER_REAL, &thousand, NULL); 1431 //printf(" elapsed:%u iterations:%u ", elapsed, iterations); 1432 if (cache) { 1433 /* Cache: remove lseek() and monotonic_us() overheads 1434 * from elapsed */ 1435 start = monotonic_us(); 1360 1436 do { 1361 if (seek_to_zero(fd)) 1362 goto quit; 1363 getitimer(ITIMER_REAL, &itv); 1364 elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000 1365 - itv.it_value.tv_usec; 1437 seek_to_zero(); 1438 elapsed2 = (unsigned)monotonic_us() - start; 1366 1439 } while (--iterations); 1440 //printf(" elapsed2:%u ", elapsed2); 1367 1441 elapsed -= elapsed2; 1368 total_MB *= BUFCACHE_FACTOR; 1369 flush_buffer_cache(fd); 1370 } 1371 print_timing(total_MB, elapsed / 1000000.0); 1372 quit: 1442 total_MB *= 2; // BUFCACHE_FACTOR (why?) 1443 flush_buffer_cache(); 1444 } 1445 print_timing(total_MB, elapsed); 1373 1446 munlock(buf, TIMING_BUF_BYTES); 1374 quit2: 1375 RELEASE_CONFIG_BUFFER(buf); 1447 free(buf); 1376 1448 } 1377 1449 … … 1391 1463 1392 1464 #ifdef HDIO_DRIVE_CMD 1393 static void interpret_standby(unsigned standby) 1394 { 1395 unsigned t; 1396 1465 static void interpret_standby(uint8_t standby) 1466 { 1397 1467 printf(" ("); 1398 if (standby == 0) 1468 if (standby == 0) { 1399 1469 printf("off"); 1400 else if (standby == 252) 1401 printf("21 minutes"); 1402 else if (standby == 253) 1470 } else if (standby <= 240 || standby == 252 || standby == 255) { 1471 /* standby is in 5 sec units */ 1472 unsigned t = standby * 5; 1473 printf("%u minutes %u seconds", t / 60, t % 60); 1474 } else if (standby <= 251) { 1475 unsigned t = (standby - 240); /* t is in 30 min units */; 1476 printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0'); 1477 } 1478 if (standby == 253) 1403 1479 printf("vendor-specific"); 1404 else if (standby == 254) 1405 printf("Reserved"); 1406 else if (standby == 255) 1407 printf("21 minutes + 15 seconds"); 1408 else if (standby <= 240) { 1409 t = standby * 5; 1410 printf("%u minutes + %u seconds", t / 60, t % 60); 1411 } else if (standby <= 251) { 1412 t = (standby - 240) * 30; 1413 printf("%u hours + %u minutes", t / 60, t % 60); 1414 } else 1415 printf("illegal value"); 1480 if (standby == 254) 1481 printf("reserved"); 1416 1482 printf(")\n"); 1417 1483 } … … 1433 1499 static int translate_xfermode(const char *name) 1434 1500 { 1435 int val, i; 1501 int val; 1502 unsigned i; 1436 1503 1437 1504 for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) { … … 1463 1530 printf("UltraDMA mode%u", xfermode - 64); 1464 1531 else 1465 printf(" Unknown");1532 printf("unknown"); 1466 1533 printf(")\n"); 1467 1534 } … … 1476 1543 static void process_dev(char *devname) 1477 1544 { 1478 int fd;1545 /*int fd;*/ 1479 1546 long parm, multcount; 1480 1547 #ifndef HDIO_DRIVE_CMD … … 1486 1553 const char *fmt = " %s\t= %2ld"; 1487 1554 1488 fd = xopen(devname, O_RDONLY|O_NONBLOCK); 1555 /*fd = xopen_nonblocking(devname);*/ 1556 xmove_fd(xopen_nonblocking(devname), fd); 1489 1557 printf("\n%s:\n", devname); 1490 1558 1491 if ( set_readahead) {1492 print_flag(get _readahead, "fs readahead", Xreadahead);1559 if (getset_readahead == IS_SET) { 1560 print_flag(getset_readahead, "fs readahead", Xreadahead); 1493 1561 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead); 1494 1562 } … … 1500 1568 #endif 1501 1569 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 1502 if (scan_hwif ) {1570 if (scan_hwif == IS_SET) { 1503 1571 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq); 1504 1572 args[0] = hwif_data; … … 1524 1592 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode); 1525 1593 } 1526 if ( set_io32bit) {1527 print_flag(get _io32bit, "32-bit IO_support flag", io32bit);1594 if (getset_io32bit == IS_SET) { 1595 print_flag(getset_io32bit, "32-bit IO_support flag", io32bit); 1528 1596 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit); 1529 1597 } 1530 if ( set_mult) {1531 print_flag(get _mult, "multcount", mult);1598 if (getset_mult == IS_SET) { 1599 print_flag(getset_mult, "multcount", mult); 1532 1600 #ifdef HDIO_DRIVE_CMD 1533 1601 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult); … … 1536 1604 #endif 1537 1605 } 1538 if ( set_readonly) {1539 print_flag_on_off(get _readonly, "readonly", readonly);1606 if (getset_readonly == IS_SET) { 1607 print_flag_on_off(getset_readonly, "readonly", readonly); 1540 1608 ioctl_or_warn(fd, BLKROSET, &readonly); 1541 1609 } 1542 if ( set_unmask) {1543 print_flag_on_off(get _unmask, "unmaskirq", unmask);1610 if (getset_unmask == IS_SET) { 1611 print_flag_on_off(getset_unmask, "unmaskirq", unmask); 1544 1612 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask); 1545 1613 } 1546 1614 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 1547 if ( set_dma) {1548 print_flag_on_off(get _dma, "using_dma", dma);1615 if (getset_dma == IS_SET) { 1616 print_flag_on_off(getset_dma, "using_dma", dma); 1549 1617 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma); 1550 1618 } 1551 1619 #endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */ 1552 if (set_dma_q) { 1553 print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q); 1620 #ifdef HDIO_SET_QDMA 1621 if (getset_dma_q == IS_SET) { 1622 print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q); 1554 1623 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q); 1555 1624 } 1556 if (set_nowerr) { 1557 print_flag_on_off(get_nowerr, "nowerr", nowerr); 1625 #endif 1626 if (getset_nowerr == IS_SET) { 1627 print_flag_on_off(getset_nowerr, "nowerr", nowerr); 1558 1628 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr); 1559 1629 } 1560 if ( set_keep) {1561 print_flag_on_off(get _keep, "keep_settings", keep);1630 if (getset_keep == IS_SET) { 1631 print_flag_on_off(getset_keep, "keep_settings", keep); 1562 1632 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep); 1563 1633 } 1564 1634 #ifdef HDIO_DRIVE_CMD 1565 if ( set_doorlock) {1635 if (getset_doorlock == IS_SET) { 1566 1636 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK; 1567 1637 args[2] = 0; 1568 print_flag_on_off(get _doorlock, "drive doorlock", doorlock);1638 print_flag_on_off(getset_doorlock, "drive doorlock", doorlock); 1569 1639 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1570 1640 args[0] = WIN_SETFEATURES; 1571 1641 } 1572 if ( set_dkeep) {1642 if (getset_dkeep == IS_SET) { 1573 1643 /* lock/unlock the drive's "feature" settings */ 1574 print_flag_on_off(get _dkeep, "drive keep features", dkeep);1644 print_flag_on_off(getset_dkeep, "drive keep features", dkeep); 1575 1645 args[2] = dkeep ? 0x66 : 0xcc; 1576 1646 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1577 1647 } 1578 if ( set_defects) {1648 if (getset_defects == IS_SET) { 1579 1649 args[2] = defects ? 0x04 : 0x84; 1580 print_flag(get _defects, "drive defect-mgmt", defects);1650 print_flag(getset_defects, "drive defect-mgmt", defects); 1581 1651 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1582 1652 } 1583 if ( set_prefetch) {1653 if (getset_prefetch == IS_SET) { 1584 1654 args[1] = prefetch; 1585 1655 args[2] = 0xab; 1586 print_flag(get _prefetch, "drive prefetch", prefetch);1656 print_flag(getset_prefetch, "drive prefetch", prefetch); 1587 1657 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1588 1658 args[1] = 0; … … 1591 1661 args[1] = xfermode_requested; 1592 1662 args[2] = 3; 1593 if (get_xfermode) { 1594 print_flag(1, "xfermode", xfermode_requested); 1595 interpret_xfermode(xfermode_requested); 1596 } 1663 print_flag(1, "xfermode", xfermode_requested); 1664 interpret_xfermode(xfermode_requested); 1597 1665 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1598 1666 args[1] = 0; 1599 1667 } 1600 if ( set_lookahead) {1668 if (getset_lookahead == IS_SET) { 1601 1669 args[2] = lookahead ? 0xaa : 0x55; 1602 print_flag_on_off(get _lookahead, "drive read-lookahead", lookahead);1670 print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead); 1603 1671 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1604 1672 } 1605 if (set_apmmode) { 1606 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */ 1673 if (getset_apmmode == IS_SET) { 1674 /* feature register */ 1675 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; 1607 1676 args[1] = apmmode; /* sector count register 1-255 */ 1608 if (get_apmmode) 1609 printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode); 1677 printf(" setting APM level to %s 0x%02lX (%ld)\n", 1678 (apmmode == 255) ? "disabled" : "", 1679 apmmode, apmmode); 1610 1680 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1611 1681 args[1] = 0; 1612 1682 } 1613 if ( set_wcache){1683 if (getset_wcache == IS_SET) { 1614 1684 #ifdef DO_FLUSHCACHE 1615 1685 #ifndef WIN_FLUSHCACHE 1616 1686 #define WIN_FLUSHCACHE 0xe7 1617 1687 #endif 1618 static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };1619 1688 #endif /* DO_FLUSHCACHE */ 1620 1689 args[2] = wcache ? 0x02 : 0x82; 1621 print_flag_on_off(get _wcache, "drive write-caching", wcache);1690 print_flag_on_off(getset_wcache, "drive write-caching", wcache); 1622 1691 #ifdef DO_FLUSHCACHE 1623 1692 if (!wcache) … … 1642 1711 #define WIN_STANDBYNOW2 0x94 1643 1712 #endif 1644 if (get_standbynow)printf(" issuing standby command\n");1713 printf(" issuing standby command\n"); 1645 1714 args[0] = WIN_STANDBYNOW1; 1646 ioctl_alt_or_warn( fd,HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);1715 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2); 1647 1716 } 1648 1717 if (set_sleepnow) { … … 1653 1722 #define WIN_SLEEPNOW2 0x99 1654 1723 #endif 1655 if (get_sleepnow)printf(" issuing sleep command\n");1724 printf(" issuing sleep command\n"); 1656 1725 args[0] = WIN_SLEEPNOW1; 1657 ioctl_alt_or_warn( fd,HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);1726 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2); 1658 1727 } 1659 1728 if (set_seagate) { 1660 1729 args[0] = 0xfb; 1661 if (get_seagate)printf(" disabling Seagate auto powersaving mode\n");1730 printf(" disabling Seagate auto powersaving mode\n"); 1662 1731 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1663 1732 } 1664 if ( set_standby) {1733 if (getset_standby == IS_SET) { 1665 1734 args[0] = WIN_SETIDLE1; 1666 1735 args[1] = standby_requested; 1667 if (get_standby) { 1668 print_flag(1, "standby", standby_requested); 1669 interpret_standby(standby_requested); 1670 } 1736 print_flag(1, "standby", standby_requested); 1737 interpret_standby(standby_requested); 1671 1738 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1672 1739 args[1] = 0; … … 1675 1742 if (force_operation) { 1676 1743 char buf[512]; 1677 flush_buffer_cache( fd);1744 flush_buffer_cache(); 1678 1745 if (-1 == read(fd, buf, sizeof(buf))) 1679 bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1); 1680 } 1681 #endif /* HDIO_DRIVE_CMD */ 1682 1683 if (get_mult || get_identity) { 1746 bb_perror_msg("read of 512 bytes failed"); 1747 } 1748 #endif /* HDIO_DRIVE_CMD */ 1749 if (getset_mult || get_identity) { 1684 1750 multcount = -1; 1685 1751 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) { 1686 if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */ 1752 /* To be coherent with ioctl_or_warn. */ 1753 if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR) 1687 1754 bb_perror_msg("HDIO_GET_MULTCOUNT"); 1688 1755 else 1689 1756 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT); 1690 } else if (get _mult) {1757 } else if (getset_mult) { 1691 1758 printf(fmt, "multcount", multcount); 1692 1759 on_off(multcount != 0); 1693 1760 } 1694 1761 } 1695 if (get _io32bit) {1762 if (getset_io32bit) { 1696 1763 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) { 1697 1764 printf(" IO_support\t=%3ld (", parm); … … 1710 1777 } 1711 1778 } 1712 if (get _unmask) {1713 if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, (unsigned long *)parm))1779 if (getset_unmask) { 1780 if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm)) 1714 1781 print_value_on_off("unmaskirq", parm); 1715 1782 } 1716 1717 1718 1783 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 1719 if (get _dma) {1784 if (getset_dma) { 1720 1785 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) { 1721 1786 printf(fmt, "using_dma", parm); … … 1727 1792 } 1728 1793 #endif 1729 if (get_dma_q) { 1730 if(!ioctl_or_warn(fd, HDIO_GET_QDMA, (unsigned long *)parm)) 1794 #ifdef HDIO_GET_QDMA 1795 if (getset_dma_q) { 1796 if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm)) 1731 1797 print_value_on_off("queue_depth", parm); 1732 1798 } 1733 if (get_keep) { 1734 if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, (unsigned long *)parm)) 1799 #endif 1800 if (getset_keep) { 1801 if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm)) 1735 1802 print_value_on_off("keepsettings", parm); 1736 1803 } 1737 1738 if (get_nowerr) { 1739 if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, (unsigned long *)parm)) 1804 if (getset_nowerr) { 1805 if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm)) 1740 1806 print_value_on_off("nowerr", parm); 1741 1807 } 1742 if (get _readonly) {1743 if (!ioctl_or_warn(fd, BLKROGET, (unsigned long *)parm))1808 if (getset_readonly) { 1809 if (!ioctl_or_warn(fd, BLKROGET, &parm)) 1744 1810 print_value_on_off("readonly", parm); 1745 1811 } 1746 if (get _readahead) {1747 if (!ioctl_or_warn(fd, BLKRAGET, (unsigned long *)parm))1812 if (getset_readahead) { 1813 if (!ioctl_or_warn(fd, BLKRAGET, &parm)) 1748 1814 print_value_on_off("readahead", parm); 1749 1815 } … … 1754 1820 if (!ioctl_or_warn(fd, HDIO_GETGEO, &g)) 1755 1821 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n", 1756 1822 g.cylinders, g.heads, g.sectors, parm, g.start); 1757 1823 } 1758 1824 } … … 1768 1834 1769 1835 args[0] = WIN_CHECKPOWERMODE1; 1770 if (ioctl_alt_or_warn( fd,HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {1836 if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) { 1771 1837 if (errno != EIO || args[0] != 0 || args[1] != 0) 1772 1838 state = "unknown"; … … 1817 1883 args1[0] = WIN_IDENTIFY; 1818 1884 args1[3] = 1; 1819 if (!ioctl_alt_or_warn( fd,HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))1885 if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY)) 1820 1886 identify((void *)(args1 + 4)); 1821 1887 } 1822 1888 #endif 1823 1889 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1824 if (set_busstate) { 1825 if (get_busstate) { 1826 print_flag(1, "bus state", busstate); 1827 bus_state_value(busstate); 1828 } 1890 if (getset_busstate == IS_SET) { 1891 print_flag(1, "bus state", busstate); 1892 bus_state_value(busstate); 1829 1893 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate); 1830 1894 } 1831 if (get _busstate) {1895 if (getset_busstate) { 1832 1896 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) { 1833 1897 printf(fmt, "bus state", parm); … … 1840 1904 1841 1905 if (do_ctimings) 1842 do_time( 0, fd); /* time cache */1906 do_time(1 /*,fd*/); /* time cache */ 1843 1907 if (do_timings) 1844 do_time( 1, fd); /* time device */1908 do_time(0 /*,fd*/); /* time device */ 1845 1909 if (do_flush) 1846 flush_buffer_cache( fd);1910 flush_buffer_cache(); 1847 1911 close(fd); 1848 1912 } … … 1858 1922 } 1859 1923 1924 static void identify_from_stdin(void) NORETURN; 1860 1925 static void identify_from_stdin(void) 1861 1926 { … … 1865 1930 int i; 1866 1931 1867 xread( 0, buf, 1280);1932 xread(STDIN_FILENO, buf, 1280); 1868 1933 1869 1934 // Convert the newline-separated hex data into an identify block. … … 1879 1944 identify(sbuf); 1880 1945 } 1946 #else 1947 void identify_from_stdin(void); 1881 1948 #endif 1882 1949 1883 1950 /* busybox specific stuff */ 1884 static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max) 1885 { 1886 if (get) { 1887 *get = 1; 1888 } 1951 static int parse_opts(unsigned long *value, int min, int max) 1952 { 1889 1953 if (optarg) { 1890 *set = 1;1891 1954 *value = xatol_range(optarg, min, max); 1892 } 1955 return IS_SET; 1956 } 1957 return IS_GET; 1958 } 1959 static int parse_opts_0_max(unsigned long *value, int max) 1960 { 1961 return parse_opts(value, 0, max); 1962 } 1963 static int parse_opts_0_1(unsigned long *value) 1964 { 1965 return parse_opts(value, 0, 1); 1966 } 1967 static int parse_opts_0_INTMAX(unsigned long *value) 1968 { 1969 return parse_opts(value, 0, INT_MAX); 1893 1970 } 1894 1971 … … 1896 1973 { 1897 1974 if (flag) { 1898 *get = 1;1975 *get = IS_GET; 1899 1976 if (optarg) { 1900 1977 *value = translate_xfermode(optarg); … … 1906 1983 /*------- getopt short options --------*/ 1907 1984 static const char hdparm_options[] ALIGN1 = 1908 "gfu::n::p:r::m::c::k::a::B:tT h"1909 USE_FEATURE_HDPARM_GET_IDENTITY("iI")1910 USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")1985 "gfu::n::p:r::m::c::k::a::B:tT" 1986 IF_FEATURE_HDPARM_GET_IDENTITY("iI") 1987 IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::") 1911 1988 #ifdef HDIO_DRIVE_CMD 1912 1989 "S:D:P:X:K:A:L:W:CyYzZ" 1913 1990 #endif 1914 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")1991 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:") 1915 1992 #ifdef HDIO_GET_QDMA 1916 1993 #ifdef HDIO_SET_QDMA … … 1920 1997 #endif 1921 1998 #endif 1922 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")1923 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")1924 USE_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");1999 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w") 2000 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:") 2001 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:"); 1925 2002 /*-------------------------------------*/ 1926 2003 1927 2004 /* our main() routine: */ 1928 int hdparm_main(int argc, char **argv) ;2005 int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1929 2006 int hdparm_main(int argc, char **argv) 1930 2007 { … … 1934 2011 while ((c = getopt(argc, argv, hdparm_options)) >= 0) { 1935 2012 flagcount++; 1936 if (c == 'h') bb_show_usage(); /* EXIT */ 1937 USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I')); 1938 USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i')); 2013 IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I')); 2014 IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i')); 1939 2015 get_geom |= (c == 'g'); 1940 2016 do_flush |= (c == 'f'); 1941 if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1); 1942 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9)); 1943 if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1); 2017 if (c == 'u') getset_unmask = parse_opts_0_1(&unmask); 2018 IF_FEATURE_HDPARM_HDIO_GETSET_DMA( 2019 if (c == 'd') getset_dma = parse_opts_0_max(&dma, 9); 2020 ) 2021 if (c == 'n') getset_nowerr = parse_opts_0_1(&nowerr); 1944 2022 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode); 1945 if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1);1946 if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX/*32*/);1947 if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX/*8*/);1948 if (c == 'k') parse_opts(&get_keep, &set_keep, &keep, 0, 1);1949 if (c == 'a') parse_opts(&get_readahead, &set_readahead, &Xreadahead, 0, INT_MAX);1950 if (c == 'B') parse_opts(&get_apmmode, &set_apmmode,&apmmode, 1, 255);2023 if (c == 'r') getset_readonly = parse_opts_0_1(&readonly); 2024 if (c == 'm') getset_mult = parse_opts_0_INTMAX(&mult /*32*/); 2025 if (c == 'c') getset_io32bit = parse_opts_0_INTMAX(&io32bit /*8*/); 2026 if (c == 'k') getset_keep = parse_opts_0_1(&keep); 2027 if (c == 'a') getset_readahead = parse_opts_0_INTMAX(&Xreadahead); 2028 if (c == 'B') getset_apmmode = parse_opts(&apmmode, 1, 255); 1951 2029 do_flush |= do_timings |= (c == 't'); 1952 2030 do_flush |= do_ctimings |= (c == 'T'); 1953 2031 #ifdef HDIO_DRIVE_CMD 1954 if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);1955 if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX);1956 if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX);2032 if (c == 'S') getset_standby = parse_opts_0_max(&standby_requested, 255); 2033 if (c == 'D') getset_defects = parse_opts_0_INTMAX(&defects); 2034 if (c == 'P') getset_prefetch = parse_opts_0_INTMAX(&prefetch); 1957 2035 parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested); 1958 if (c == 'K') parse_opts(&get_dkeep, &set_dkeep, &prefetch, 0, 1);1959 if (c == 'A') parse_opts(&get_lookahead, &set_lookahead, &lookahead, 0, 1);1960 if (c == 'L') parse_opts(&get_doorlock, &set_doorlock, &doorlock, 0, 1);1961 if (c == 'W') parse_opts(&get_wcache, &set_wcache, &wcache, 0, 1);2036 if (c == 'K') getset_dkeep = parse_opts_0_1(&prefetch); 2037 if (c == 'A') getset_lookahead = parse_opts_0_1(&lookahead); 2038 if (c == 'L') getset_doorlock = parse_opts_0_1(&doorlock); 2039 if (c == 'W') getset_wcache = parse_opts_0_1(&wcache); 1962 2040 get_powermode |= (c == 'C'); 1963 get_standbynow =set_standbynow |= (c == 'y');1964 get_sleepnow =set_sleepnow |= (c == 'Y');2041 set_standbynow |= (c == 'y'); 2042 set_sleepnow |= (c == 'Y'); 1965 2043 reread_partn |= (c == 'z'); 1966 get_seagate =set_seagate |= (c == 'Z');1967 #endif 1968 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));2044 set_seagate |= (c == 'Z'); 2045 #endif 2046 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif)); 1969 2047 #ifdef HDIO_GET_QDMA 1970 2048 if (c == 'Q') { 1971 #ifdef HDIO_SET_QDMA 1972 parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX); 1973 #else 1974 parse_opts(&get_dma_q, NULL, NULL, 0, 0); 1975 #endif 1976 } 1977 #endif 1978 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r')); 1979 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1)); 1980 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2)); 2049 getset_dma_q = parse_opts_0_INTMAX(&dma_q); 2050 } 2051 #endif 2052 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r')); 2053 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') perform_tristate = parse_opts_0_1(&tristate)); 2054 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') getset_busstate = parse_opts_0_max(&busstate, 2)); 1981 2055 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 1982 2056 if (c == 'R') { 1983 parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);1984 hwif_ctrl = xatoi_ u((argv[optind]) ? argv[optind] : "");1985 hwif_irq = xatoi_ u((argv[optind+1]) ? argv[optind+1] : "");2057 scan_hwif = parse_opts_0_INTMAX(&hwif_data); 2058 hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : ""); 2059 hwif_irq = xatoi_positive((argv[optind+1]) ? argv[optind+1] : ""); 1986 2060 /* Move past the 2 additional arguments */ 1987 2061 argv += 2; … … 1992 2066 /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */ 1993 2067 if (!flagcount) { 1994 get _mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1;1995 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1);2068 getset_mult = getset_io32bit = getset_unmask = getset_keep = getset_readonly = getset_readahead = get_geom = IS_GET; 2069 IF_FEATURE_HDPARM_HDIO_GETSET_DMA(getset_dma = IS_GET); 1996 2070 } 1997 2071 argv += optind; … … 2000 2074 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO)) 2001 2075 identify_from_stdin(); /* EXIT */ 2002 elsebb_show_usage();2076 bb_show_usage(); 2003 2077 } 2004 2078 -
branches/2.2.9/mindi-busybox/miscutils/last.c
r1765 r2725 5 5 * Copyright (C) 2003-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.7 * Licensed under GPLv2, see file LICENSE in this source tree. 8 8 */ 9 9 … … 11 11 #include <utmp.h> 12 12 13 /* NB: ut_name and ut_user are the same field, use only one name (ut_user) 14 * to reduce confusion */ 15 13 16 #ifndef SHUTDOWN_TIME 14 17 # define SHUTDOWN_TIME 254 15 18 #endif 16 19 17 /* Grr... utmp char[] members 20 /* Grr... utmp char[] members do not have to be nul-terminated. 18 21 * Do what we can while still keeping this reasonably small. 19 22 * Note: We are assuming the ut_id[] size is fixed at 4. */ … … 27 30 #endif 28 31 29 int last_main(int argc, char **argv); 30 int last_main(int argc, char **argv) 32 #if EMPTY != 0 || RUN_LVL != 1 || BOOT_TIME != 2 || NEW_TIME != 3 || \ 33 OLD_TIME != 4 34 #error Values for the ut_type field of struct utmp changed 35 #endif 36 37 int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 38 int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 31 39 { 32 40 struct utmp ut; 33 41 int n, file = STDIN_FILENO; 34 42 time_t t_tmp; 43 off_t pos; 44 static const char _ut_usr[] ALIGN1 = 45 "runlevel\0" "reboot\0" "shutdown\0"; 46 static const char _ut_lin[] ALIGN1 = 47 "~\0" "{\0" "|\0" /* "LOGIN\0" "date\0" */; 48 enum { 49 TYPE_RUN_LVL = RUN_LVL, /* 1 */ 50 TYPE_BOOT_TIME = BOOT_TIME, /* 2 */ 51 TYPE_SHUTDOWN_TIME = SHUTDOWN_TIME 52 }; 53 enum { 54 _TILDE = EMPTY, /* 0 */ 55 TYPE_NEW_TIME, /* NEW_TIME, 3 */ 56 TYPE_OLD_TIME /* OLD_TIME, 4 */ 57 }; 35 58 36 if (arg c > 1) {59 if (argv[1]) { 37 60 bb_show_usage(); 38 61 } 39 62 file = xopen(bb_path_wtmp_file, O_RDONLY); 40 63 41 printf("%-10s %-14s %-18s %-12.12s %s\n", "USER", "TTY", "HOST", "LOGIN", "TIME"); 42 while ((n = safe_read(file, (void*)&ut, sizeof(struct utmp))) != 0) { 43 44 if (n != sizeof(struct utmp)) { 64 printf("%-10s %-14s %-18s %-12.12s %s\n", 65 "USER", "TTY", "HOST", "LOGIN", "TIME"); 66 /* yikes. We reverse over the file and that is a not too elegant way */ 67 pos = xlseek(file, 0, SEEK_END); 68 pos = lseek(file, pos - sizeof(ut), SEEK_SET); 69 while ((n = full_read(file, &ut, sizeof(ut))) > 0) { 70 if (n != sizeof(ut)) { 45 71 bb_perror_msg_and_die("short read"); 46 72 } 47 48 if (ut.ut_line[0] == '~') { 73 n = index_in_strings(_ut_lin, ut.ut_line); 74 if (n == _TILDE) { /* '~' */ 75 #if 1 76 /* do we really need to be cautious here? */ 77 n = index_in_strings(_ut_usr, ut.ut_user); 78 if (++n > 0) 79 ut.ut_type = n != 3 ? n : SHUTDOWN_TIME; 80 #else 49 81 if (strncmp(ut.ut_user, "shutdown", 8) == 0) 50 82 ut.ut_type = SHUTDOWN_TIME; 51 83 else if (strncmp(ut.ut_user, "reboot", 6) == 0) 52 84 ut.ut_type = BOOT_TIME; 53 else if (strncmp(ut.ut_user, "runlevel", 7) == 0)85 else if (strncmp(ut.ut_user, "runlevel", 8) == 0) 54 86 ut.ut_type = RUN_LVL; 87 #endif 55 88 } else { 56 if (!ut.ut_name[0] || strcmp(ut.ut_name, "LOGIN") == 0 || 57 ut.ut_name[0] == 0) 58 { 89 if (ut.ut_user[0] == '\0' || strcmp(ut.ut_user, "LOGIN") == 0) { 59 90 /* Don't bother. This means we can't find how long 60 91 * someone was logged in for. Oh well. */ 61 continue;92 goto next; 62 93 } 63 if (ut.ut_type != DEAD_PROCESS && 64 ut.ut_name[0] && ut.ut_line[0]) 65 { 94 if (ut.ut_type != DEAD_PROCESS 95 && ut.ut_user[0] 96 && ut.ut_line[0] 97 ) { 66 98 ut.ut_type = USER_PROCESS; 67 99 } 68 if (strcmp(ut.ut_name, "date") == 0) { 69 if (ut.ut_line[0] == '|') ut.ut_type = OLD_TIME; 70 if (ut.ut_line[0] == '{') ut.ut_type = NEW_TIME; 100 if (strcmp(ut.ut_user, "date") == 0) { 101 if (n == TYPE_OLD_TIME) { /* '|' */ 102 ut.ut_type = OLD_TIME; 103 } 104 if (n == TYPE_NEW_TIME) { /* '{' */ 105 ut.ut_type = NEW_TIME; 106 } 71 107 } 72 108 } 73 109 74 if (ut.ut_type !=USER_PROCESS) {110 if (ut.ut_type != USER_PROCESS) { 75 111 switch (ut.ut_type) { 76 112 case OLD_TIME: … … 78 114 case RUN_LVL: 79 115 case SHUTDOWN_TIME: 80 continue;116 goto next; 81 117 case BOOT_TIME: 82 118 strcpy(ut.ut_line, "system boot"); 83 break;84 119 } 85 120 } 121 /* manpages say ut_tv.tv_sec *is* time_t, 122 * but some systems have it wrong */ 86 123 t_tmp = (time_t)ut.ut_tv.tv_sec; 87 printf("%-10s %-14s %-18s %-12.12s\n", ut.ut_user, ut.ut_line, ut.ut_host, 88 ctime(&t_tmp) + 4); 124 printf("%-10s %-14s %-18s %-12.12s\n", 125 ut.ut_user, ut.ut_line, ut.ut_host, ctime(&t_tmp) + 4); 126 next: 127 pos -= sizeof(ut); 128 if (pos <= 0) 129 break; /* done. */ 130 xlseek(file, pos, SEEK_SET); 89 131 } 90 132 -
branches/2.2.9/mindi-busybox/miscutils/less.c
r1765 r2725 5 5 * Copyright (C) 2005 by Rob Sullivan <cogito.ergo.cogito@gmail.com> 6 6 * 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 */ 9 9 … … 22 22 */ 23 23 24 #include <sched.h> 24 #include <sched.h> /* sched_yield() */ 25 25 26 26 #include "libbb.h" … … 29 29 #endif 30 30 31 /* FIXME: currently doesn't work right */ 32 #undef ENABLE_FEATURE_LESS_FLAGCS 33 #define ENABLE_FEATURE_LESS_FLAGCS 0 34 31 32 #define ESC "\033" 35 33 /* The escape codes for highlighted and normal text */ 36 #define HIGHLIGHT "\033[7m" 37 #define NORMAL "\033[0m" 38 /* The escape code to clear the screen */ 39 #define CLEAR "\033[H\033[J" 40 /* The escape code to clear to end of line */ 41 #define CLEAR_2_EOL "\033[K" 42 43 /* These are the escape sequences corresponding to special keys */ 34 #define HIGHLIGHT ESC"[7m" 35 #define NORMAL ESC"[0m" 36 /* The escape code to home and clear to the end of screen */ 37 #define CLEAR ESC"[H\033[J" 38 /* The escape code to clear to the end of line */ 39 #define CLEAR_2_EOL ESC"[K" 40 44 41 enum { 45 REAL_KEY_UP = 'A',46 REAL_KEY_DOWN = 'B',47 REAL_KEY_RIGHT = 'C',48 REAL_KEY_LEFT = 'D',49 REAL_PAGE_UP = '5',50 REAL_PAGE_DOWN = '6',51 REAL_KEY_HOME = '7', // vt100? linux vt? or what?52 REAL_KEY_END = '8',53 REAL_KEY_HOME_ALT = '1', // ESC [1~ (vt100? linux vt? or what?)54 REAL_KEY_END_ALT = '4', // ESC [4~55 REAL_KEY_HOME_XTERM = 'H',56 REAL_KEY_END_XTERM = 'F',57 58 /* These are the special codes assigned by this program to the special keys */59 KEY_UP = 20,60 KEY_DOWN = 21,61 KEY_RIGHT = 22,62 KEY_LEFT = 23,63 PAGE_UP = 24,64 PAGE_DOWN = 25,65 KEY_HOME = 26,66 KEY_END = 27,67 68 42 /* Absolute max of lines eaten */ 69 43 MAXLINES = CONFIG_FEATURE_LESS_MAXLINES, 70 71 44 /* This many "after the end" lines we will show (at max) */ 72 45 TILDES = 1, … … 75 48 /* Command line options */ 76 49 enum { 77 FLAG_E = 1 ,50 FLAG_E = 1 << 0, 78 51 FLAG_M = 1 << 1, 79 52 FLAG_m = 1 << 2, 80 53 FLAG_N = 1 << 3, 81 54 FLAG_TILDE = 1 << 4, 55 FLAG_I = 1 << 5, 56 FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD, 82 57 /* hijack command line options variable for internal state vars */ 83 58 LESS_STATE_MATCH_BACKWARDS = 1 << 15, … … 91 66 int cur_fline; /* signed */ 92 67 int kbd_fd; /* fd to get input from */ 68 int less_gets_pos; 93 69 /* last position in last line, taking into account tabs */ 94 size_t linepos; 95 unsigned max_displayed_line; 70 size_t last_line_pos; 96 71 unsigned max_fline; 97 72 unsigned max_lineno; /* this one tracks linewrap */ 73 unsigned max_displayed_line; 98 74 unsigned width; 75 #if ENABLE_FEATURE_LESS_WINCH 76 unsigned winch_counter; 77 #endif 99 78 ssize_t eof_error; /* eof if 0, error if < 0 */ 100 s ize_t readpos;101 s ize_t readeof;79 ssize_t readpos; 80 ssize_t readeof; /* must be signed */ 102 81 const char **buffer; 103 82 const char **flines; … … 114 93 unsigned *match_lines; 115 94 int match_pos; /* signed! */ 116 unsigned num_matches; 95 int wanted_match; /* signed! */ 96 int num_matches; 117 97 regex_t pattern; 118 98 smallint pattern_valid; … … 120 100 smallint terminated; 121 101 struct termios term_orig, term_less; 102 char kbd_input[KEYCODE_BUFFER_SIZE]; 122 103 }; 123 104 #define G (*ptr_to_globals) 124 105 #define cur_fline (G.cur_fline ) 125 106 #define kbd_fd (G.kbd_fd ) 126 #define l inepos (G.linepos)127 #define max_displayed_line (G.max_displayed_line)107 #define less_gets_pos (G.less_gets_pos ) 108 #define last_line_pos (G.last_line_pos ) 128 109 #define max_fline (G.max_fline ) 129 110 #define max_lineno (G.max_lineno ) 111 #define max_displayed_line (G.max_displayed_line) 130 112 #define width (G.width ) 113 #define winch_counter (G.winch_counter ) 114 /* This one is 100% not cached by compiler on read access */ 115 #define WINCH_COUNTER (*(volatile unsigned *)&winch_counter) 131 116 #define eof_error (G.eof_error ) 132 117 #define readpos (G.readpos ) … … 145 130 #define match_pos (G.match_pos ) 146 131 #define num_matches (G.num_matches ) 132 #define wanted_match (G.wanted_match ) 147 133 #define pattern (G.pattern ) 148 134 #define pattern_valid (G.pattern_valid ) … … 151 137 #define term_orig (G.term_orig ) 152 138 #define term_less (G.term_less ) 139 #define kbd_input (G.kbd_input ) 153 140 #define INIT_G() do { \ 154 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ 155 empty_line_marker = "~"; \ 156 num_files = 1; \ 157 current_file = 1; \ 158 eof_error = 1; \ 159 terminated = 1; \ 160 } while (0) 141 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 142 less_gets_pos = -1; \ 143 empty_line_marker = "~"; \ 144 num_files = 1; \ 145 current_file = 1; \ 146 eof_error = 1; \ 147 terminated = 1; \ 148 IF_FEATURE_LESS_REGEXP(wanted_match = -1;) \ 149 } while (0) 150 151 /* flines[] are lines read from stdin, each in malloc'ed buffer. 152 * Line numbers are stored as uint32_t prepended to each line. 153 * Pointer is adjusted so that flines[i] points directly past 154 * line number. Accesor: */ 155 #define MEMPTR(p) ((char*)(p) - 4) 156 #define LINENO(p) (*(uint32_t*)((p) - 4)) 157 161 158 162 159 /* Reset terminal input to normal */ 163 160 static void set_tty_cooked(void) 164 161 { 165 fflush (stdout);162 fflush_all(); 166 163 tcsetattr(kbd_fd, TCSANOW, &term_orig); 167 }168 169 /* Exit the program gracefully */170 static void less_exit(int code)171 {172 /* TODO: We really should save the terminal state when we start,173 * and restore it when we exit. Less does this with the174 * "ti" and "te" termcap commands; can this be done with175 * only termios.h? */176 putchar('\n');177 fflush_stdout_and_exit(code);178 164 } 179 165 … … 182 168 static void move_cursor(int line, int row) 183 169 { 184 printf( "\033[%u;%uH", line, row);170 printf(ESC"[%u;%uH", line, row); 185 171 } 186 172 187 173 static void clear_line(void) 188 174 { 189 printf( "\033[%u;0H" CLEAR_2_EOL, max_displayed_line + 2);175 printf(ESC"[%u;0H" CLEAR_2_EOL, max_displayed_line + 2); 190 176 } 191 177 … … 200 186 printf(HIGHLIGHT"%.*s"NORMAL, width - 1, str); 201 187 } 188 189 /* Exit the program gracefully */ 190 static void less_exit(int code) 191 { 192 set_tty_cooked(); 193 clear_line(); 194 if (code < 0) 195 kill_myself_with_sig(- code); /* does not return */ 196 exit(code); 197 } 198 199 #if (ENABLE_FEATURE_LESS_DASHCMD && ENABLE_FEATURE_LESS_LINENUMS) \ 200 || ENABLE_FEATURE_LESS_WINCH 201 static void re_wrap(void) 202 { 203 int w = width; 204 int new_line_pos; 205 int src_idx; 206 int dst_idx; 207 int new_cur_fline = 0; 208 uint32_t lineno; 209 char linebuf[w + 1]; 210 const char **old_flines = flines; 211 const char *s; 212 char **new_flines = NULL; 213 char *d; 214 215 if (option_mask32 & FLAG_N) 216 w -= 8; 217 218 src_idx = 0; 219 dst_idx = 0; 220 s = old_flines[0]; 221 lineno = LINENO(s); 222 d = linebuf; 223 new_line_pos = 0; 224 while (1) { 225 *d = *s; 226 if (*d != '\0') { 227 new_line_pos++; 228 if (*d == '\t') /* tab */ 229 new_line_pos += 7; 230 s++; 231 d++; 232 if (new_line_pos >= w) { 233 int sz; 234 /* new line is full, create next one */ 235 *d = '\0'; 236 next_new: 237 sz = (d - linebuf) + 1; /* + 1: NUL */ 238 d = ((char*)xmalloc(sz + 4)) + 4; 239 LINENO(d) = lineno; 240 memcpy(d, linebuf, sz); 241 new_flines = xrealloc_vector(new_flines, 8, dst_idx); 242 new_flines[dst_idx] = d; 243 dst_idx++; 244 if (new_line_pos < w) { 245 /* if we came here thru "goto next_new" */ 246 if (src_idx > max_fline) 247 break; 248 lineno = LINENO(s); 249 } 250 d = linebuf; 251 new_line_pos = 0; 252 } 253 continue; 254 } 255 /* *d == NUL: old line ended, go to next old one */ 256 free(MEMPTR(old_flines[src_idx])); 257 /* btw, convert cur_fline... */ 258 if (cur_fline == src_idx) 259 new_cur_fline = dst_idx; 260 src_idx++; 261 /* no more lines? finish last new line (and exit the loop) */ 262 if (src_idx > max_fline) 263 goto next_new; 264 s = old_flines[src_idx]; 265 if (lineno != LINENO(s)) { 266 /* this is not a continuation line! 267 * create next _new_ line too */ 268 goto next_new; 269 } 270 } 271 272 free(old_flines); 273 flines = (const char **)new_flines; 274 275 max_fline = dst_idx - 1; 276 last_line_pos = new_line_pos; 277 cur_fline = new_cur_fline; 278 /* max_lineno is screen-size independent */ 279 #if ENABLE_FEATURE_LESS_REGEXP 280 pattern_valid = 0; 281 #endif 282 } 283 #endif 202 284 203 285 #if ENABLE_FEATURE_LESS_REGEXP … … 226 308 * readbuf[0..readeof-1] - small preliminary buffer. 227 309 * readbuf[readpos] - next character to add to current line. 228 * l inepos - screen line position of next char to be read310 * last_line_pos - screen line position of next char to be read 229 311 * (takes into account tabs and backspaces) 230 312 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error … … 234 316 #define readbuf bb_common_bufsiz1 235 317 char *current_line, *p; 236 USE_FEATURE_LESS_REGEXP(unsigned old_max_fline = max_fline;)237 318 int w = width; 238 319 char last_terminated = terminated; 320 #if ENABLE_FEATURE_LESS_REGEXP 321 unsigned old_max_fline = max_fline; 322 time_t last_time = 0; 323 unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */ 324 #endif 239 325 240 326 if (option_mask32 & FLAG_N) 241 327 w -= 8; 242 328 243 current_line = xmalloc(w); 244 p = current_line; 329 IF_FEATURE_LESS_REGEXP(again0:) 330 331 p = current_line = ((char*)xmalloc(w + 4)) + 4; 245 332 max_fline += last_terminated; 246 333 if (!last_terminated) { 247 334 const char *cp = flines[max_fline]; 248 if (option_mask32 & FLAG_N) 249 cp += 8; 250 strcpy(current_line, cp); 335 strcpy(p, cp); 251 336 p += strlen(current_line); 252 /* linepos is still valid from previous read_lines() */ 337 free(MEMPTR(flines[max_fline])); 338 /* last_line_pos is still valid from previous read_lines() */ 253 339 } else { 254 linepos = 0; 255 } 256 257 while (1) { 258 again: 340 last_line_pos = 0; 341 } 342 343 while (1) { /* read lines until we reach cur_fline or wanted_match */ 259 344 *p = '\0'; 260 345 terminated = 0; 261 while (1) { 346 while (1) { /* read chars until we have a line */ 262 347 char c; 263 348 /* if no unprocessed chars left, eat more */ 264 349 if (readpos >= readeof) { 265 smallint yielded = 0;266 267 350 ndelay_on(0); 268 read_again: 269 eof_error = safe_read(0, readbuf, sizeof(readbuf));351 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); 352 ndelay_off(0); 270 353 readpos = 0; 271 354 readeof = eof_error; 272 if (eof_error < 0) { 273 if (errno == EAGAIN && !yielded) { 274 /* We can hit EAGAIN while searching for regexp match. 275 * Yield is not 100% reliable solution in general, 276 * but for less it should be good enough - 277 * we give stdin supplier some CPU time to produce 278 * more input. We do it just once. 279 * Currently, we do not stop when we found the Nth 280 * occurrence we were looking for. We read till end 281 * (or double EAGAIN). TODO? */ 282 sched_yield(); 283 yielded = 1; 284 goto read_again; 285 } 286 readeof = 0; 287 if (errno != EAGAIN) 288 print_statusline("read error"); 289 } 290 ndelay_off(0); 291 292 if (eof_error <= 0) { 355 if (eof_error <= 0) 293 356 goto reached_eof; 294 }295 357 } 296 358 c = readbuf[readpos]; … … 298 360 /* <tab><bs> is (a) insane and */ 299 361 /* (b) harder to do correctly, so we refuse to do it */ 300 if (c == '\x8' && l inepos && p[-1] != '\t') {362 if (c == '\x8' && last_line_pos && p[-1] != '\t') { 301 363 readpos++; /* eat it */ 302 l inepos--;364 last_line_pos--; 303 365 /* was buggy (p could end up <= current_line)... */ 304 366 *--p = '\0'; … … 306 368 } 307 369 { 308 size_t new_l inepos = linepos + 1;370 size_t new_last_line_pos = last_line_pos + 1; 309 371 if (c == '\t') { 310 new_l inepos += 7;311 new_l inepos &= (~7);372 new_last_line_pos += 7; 373 new_last_line_pos &= (~7); 312 374 } 313 if ( new_linepos >= w)375 if ((int)new_last_line_pos >= w) 314 376 break; 315 l inepos = new_linepos;377 last_line_pos = new_last_line_pos; 316 378 } 317 379 /* ok, we will eat this char */ … … 319 381 if (c == '\n') { 320 382 terminated = 1; 321 l inepos = 0;383 last_line_pos = 0; 322 384 break; 323 385 } … … 326 388 *p++ = c; 327 389 *p = '\0'; 328 } 390 } /* end of "read chars until we have a line" loop */ 329 391 /* Corner case: linewrap with only "" wrapping to next line */ 330 392 /* Looks ugly on screen, so we do not store this empty line */ … … 332 394 last_terminated = 1; 333 395 max_lineno++; 334 goto again;396 continue; 335 397 } 336 398 reached_eof: 337 399 last_terminated = terminated; 338 flines = xrealloc(flines, (max_fline+1) * sizeof(char *)); 339 if (option_mask32 & FLAG_N) { 340 /* Width of 7 preserves tab spacing in the text */ 341 flines[max_fline] = xasprintf( 342 (max_lineno <= 9999999) ? "%7u %s" : "%07u %s", 343 max_lineno % 10000000, current_line); 344 free(current_line); 345 if (terminated) 346 max_lineno++; 347 } else { 348 flines[max_fline] = xrealloc(current_line, strlen(current_line)+1); 349 } 400 flines = xrealloc_vector(flines, 8, max_fline); 401 402 flines[max_fline] = (char*)xrealloc(MEMPTR(current_line), strlen(current_line) + 1 + 4) + 4; 403 LINENO(flines[max_fline]) = max_lineno; 404 if (terminated) 405 max_lineno++; 406 350 407 if (max_fline >= MAXLINES) { 351 408 eof_error = 0; /* Pretend we saw EOF */ 352 409 break; 353 410 } 354 if (max_fline > cur_fline + max_displayed_line) 411 if (!(option_mask32 & FLAG_S) 412 ? (max_fline > cur_fline + max_displayed_line) 413 : (max_fline >= cur_fline 414 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) 415 ) { 416 #if !ENABLE_FEATURE_LESS_REGEXP 355 417 break; 418 #else 419 if (wanted_match >= num_matches) { /* goto_match called us */ 420 fill_match_lines(old_max_fline); 421 old_max_fline = max_fline; 422 } 423 if (wanted_match < num_matches) 424 break; 425 #endif 426 } 356 427 if (eof_error <= 0) { 357 if (eof_error < 0 && errno == EAGAIN) { 358 /* not yet eof or error, reset flag (or else 359 * we will hog CPU - select() will return 360 * immediately */ 361 eof_error = 1; 428 if (eof_error < 0) { 429 if (errno == EAGAIN) { 430 /* not yet eof or error, reset flag (or else 431 * we will hog CPU - select() will return 432 * immediately */ 433 eof_error = 1; 434 } else { 435 print_statusline(bb_msg_read_error); 436 } 362 437 } 438 #if !ENABLE_FEATURE_LESS_REGEXP 363 439 break; 440 #else 441 if (wanted_match < num_matches) { 442 break; 443 } else { /* goto_match called us */ 444 time_t t = time(NULL); 445 if (t != last_time) { 446 last_time = t; 447 if (--seconds_p1 == 0) 448 break; 449 } 450 sched_yield(); 451 goto again0; /* go loop again (max 2 seconds) */ 452 } 453 #endif 364 454 } 365 455 max_fline++; 366 current_line = xmalloc(w);456 current_line = ((char*)xmalloc(w + 4)) + 4; 367 457 p = current_line; 368 l inepos = 0;369 } 458 last_line_pos = 0; 459 } /* end of "read lines until we reach cur_fline" loop */ 370 460 fill_match_lines(old_max_fline); 461 #if ENABLE_FEATURE_LESS_REGEXP 462 /* prevent us from being stuck in search for a match */ 463 wanted_match = -1; 464 #endif 371 465 #undef readbuf 372 466 } … … 385 479 { 386 480 int percentage; 481 482 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ 483 return; 387 484 388 485 clear_line(); … … 393 490 cur_fline + 1, cur_fline + max_displayed_line + 1, 394 491 max_fline + 1); 395 if (cur_fline >= max_fline - max_displayed_line) {492 if (cur_fline >= (int)(max_fline - max_displayed_line)) { 396 493 printf("(END)"NORMAL); 397 494 if (num_files > 1 && current_file != num_files) … … 408 505 { 409 506 const char *p; 507 508 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ 509 return; 410 510 411 511 /* Change the status if flags have been set */ … … 419 519 420 520 clear_line(); 421 if (cur_fline && cur_fline < max_fline - max_displayed_line) {422 putchar(':');521 if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) { 522 bb_putchar(':'); 423 523 return; 424 524 } … … 445 545 diff = max_fline - (cur_fline + max_displayed_line) + TILDES; 446 546 /* As the number of lines requested was too large, we just move 447 to the end of the file */547 * to the end of the file */ 448 548 if (diff > 0) 449 549 cur_fline += diff; … … 457 557 "\x7f\x9b"; /* DEL and infamous Meta-ESC :( */ 458 558 static const char ctrlconv[] ALIGN1 = 459 /* '\n': it's a former NUL - subst with '@', not 'J' */ 559 /* why 40 instead of 4a below? - it is a replacement for '\n'. 560 * '\n' is a former NUL - we subst it with @, not J */ 460 561 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" 461 562 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; 563 564 static void lineno_str(char *nbuf9, const char *line) 565 { 566 nbuf9[0] = '\0'; 567 if (option_mask32 & FLAG_N) { 568 const char *fmt; 569 unsigned n; 570 571 if (line == empty_line_marker) { 572 memset(nbuf9, ' ', 8); 573 nbuf9[8] = '\0'; 574 return; 575 } 576 /* Width of 7 preserves tab spacing in the text */ 577 fmt = "%7u "; 578 n = LINENO(line) + 1; 579 if (n > 9999999) { 580 n %= 10000000; 581 fmt = "%07u "; 582 } 583 sprintf(nbuf9, fmt, n); 584 } 585 } 586 462 587 463 588 #if ENABLE_FEATURE_LESS_REGEXP … … 470 595 471 596 char buf[width]; 597 char nbuf9[9]; 472 598 const char *str = line; 473 599 char *p = buf; … … 502 628 while (match_status == 0) { 503 629 char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL, 504 growline ? : "",630 growline ? growline : "", 505 631 match_structs.rm_so, str, 506 632 match_structs.rm_eo - match_structs.rm_so, 507 633 str + match_structs.rm_so); 508 free(growline); growline = new; 634 free(growline); 635 growline = new; 509 636 str += match_structs.rm_eo; 510 637 line += match_structs.rm_eo; … … 513 640 /* Most of the time doesn't find the regex, optimize for that */ 514 641 match_status = regexec(&pattern, line, 1, &match_structs, eflags); 515 } 516 642 /* if even "" matches, treat it as "not a match" */ 643 if (match_structs.rm_so >= match_structs.rm_eo) 644 match_status = 1; 645 } 646 647 lineno_str(nbuf9, line); 517 648 if (!growline) { 518 printf(CLEAR_2_EOL"%s \n", str);649 printf(CLEAR_2_EOL"%s%s\n", nbuf9, str); 519 650 return; 520 651 } 521 printf(CLEAR_2_EOL"%s%s \n", growline, str);652 printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str); 522 653 free(growline); 523 654 } … … 529 660 { 530 661 char buf[width]; 662 char nbuf9[9]; 531 663 char *p; 532 664 size_t n; 533 665 534 printf(CLEAR_2_EOL); 666 lineno_str(nbuf9, str); 667 printf(CLEAR_2_EOL"%s", nbuf9); 668 535 669 while (*str) { 536 670 n = strcspn(str, controls); … … 562 696 static void buffer_print(void) 563 697 { 564 inti;698 unsigned i; 565 699 566 700 move_cursor(0, 0); … … 575 709 static void buffer_fill_and_print(void) 576 710 { 577 int i; 711 unsigned i; 712 #if ENABLE_FEATURE_LESS_DASHCMD 713 int fpos = cur_fline; 714 715 if (option_mask32 & FLAG_S) { 716 /* Go back to the beginning of this line */ 717 while (fpos && LINENO(flines[fpos]) == LINENO(flines[fpos-1])) 718 fpos--; 719 } 720 721 i = 0; 722 while (i <= max_displayed_line && fpos <= max_fline) { 723 int lineno = LINENO(flines[fpos]); 724 buffer[i] = flines[fpos]; 725 i++; 726 do { 727 fpos++; 728 } while ((fpos <= max_fline) 729 && (option_mask32 & FLAG_S) 730 && lineno == LINENO(flines[fpos]) 731 ); 732 } 733 #else 578 734 for (i = 0; i <= max_displayed_line && cur_fline + i <= max_fline; i++) { 579 735 buffer[i] = flines[cur_fline + i]; 580 736 } 737 #endif 581 738 for (; i <= max_displayed_line; i++) { 582 739 buffer[i] = empty_line_marker; … … 619 776 { 620 777 if (filename) { 621 int fd = xopen(filename, O_RDONLY); 622 dup2(fd, 0); 623 if (fd) close(fd); 778 xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); 624 779 } else { 625 780 /* "less" with no arguments in argv[] */ … … 629 784 readpos = 0; 630 785 readeof = 0; 631 l inepos = 0;786 last_line_pos = 0; 632 787 terminated = 1; 633 788 read_lines(); … … 637 792 static void reinitialize(void) 638 793 { 639 inti;794 unsigned i; 640 795 641 796 if (flines) { 642 797 for (i = 0; i <= max_fline; i++) 643 free( (void*)(flines[i]));798 free(MEMPTR(flines[i])); 644 799 free(flines); 645 800 flines = NULL; … … 653 808 } 654 809 655 static void getch_nowait(char* input, int sz) 656 { 657 ssize_t rd; 658 fd_set readfds; 810 static int getch_nowait(void) 811 { 812 int rd; 813 struct pollfd pfd[2]; 814 815 pfd[0].fd = STDIN_FILENO; 816 pfd[0].events = POLLIN; 817 pfd[1].fd = kbd_fd; 818 pfd[1].events = POLLIN; 659 819 again: 660 fflush(stdout); 661 662 /* NB: select returns whenever read will not block. Therefore: 663 * (a) with O_NONBLOCK'ed fds select will return immediately 664 * (b) if eof is reached, select will also return 665 * because read will immediately return 0 bytes. 666 * Even if select says that input is available, read CAN block 820 tcsetattr(kbd_fd, TCSANOW, &term_less); 821 /* NB: select/poll returns whenever read will not block. Therefore: 822 * if eof is reached, select/poll will return immediately 823 * because read will immediately return 0 bytes. 824 * Even if select/poll says that input is available, read CAN block 667 825 * (switch fd into O_NONBLOCK'ed mode to avoid it) 668 826 */ 669 FD_ZERO(&readfds); 670 if (max_fline <= cur_fline + max_displayed_line 671 && eof_error > 0 /* did NOT reach eof yet */ 827 rd = 1; 828 /* Are we interested in stdin? */ 829 //TODO: reuse code for determining this 830 if (!(option_mask32 & FLAG_S) 831 ? !(max_fline > cur_fline + max_displayed_line) 832 : !(max_fline >= cur_fline 833 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) 672 834 ) { 673 /* We are interested in stdin */ 674 FD_SET(0, &readfds); 675 } 676 FD_SET(kbd_fd, &readfds); 677 tcsetattr(kbd_fd, TCSANOW, &term_less); 678 select(kbd_fd + 1, &readfds, NULL, NULL, NULL); 679 680 input[0] = '\0'; 681 ndelay_on(kbd_fd); 682 rd = read(kbd_fd, input, sz); 683 ndelay_off(kbd_fd); 684 if (rd < 0) { 685 /* No keyboard input, but we have input on stdin! */ 686 if (errno != EAGAIN) /* Huh?? */ 687 return; 688 read_lines(); 689 buffer_fill_and_print(); 835 if (eof_error > 0) /* did NOT reach eof yet */ 836 rd = 0; /* yes, we are interested in stdin */ 837 } 838 /* Position cursor if line input is done */ 839 if (less_gets_pos >= 0) 840 move_cursor(max_displayed_line + 2, less_gets_pos + 1); 841 fflush_all(); 842 843 if (kbd_input[0] == 0) { /* if nothing is buffered */ 844 #if ENABLE_FEATURE_LESS_WINCH 845 while (1) { 846 int r; 847 /* NB: SIGWINCH interrupts poll() */ 848 r = poll(pfd + rd, 2 - rd, -1); 849 if (/*r < 0 && errno == EINTR &&*/ winch_counter) 850 return '\\'; /* anything which has no defined function */ 851 if (r) break; 852 } 853 #else 854 safe_poll(pfd + rd, 2 - rd, -1); 855 #endif 856 } 857 858 /* We have kbd_fd in O_NONBLOCK mode, read inside read_key() 859 * would not block even if there is no input available */ 860 rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); 861 if (rd == -1) { 862 if (errno == EAGAIN) { 863 /* No keyboard input available. Since poll() did return, 864 * we should have input on stdin */ 865 read_lines(); 866 buffer_fill_and_print(); 867 goto again; 868 } 869 /* EOF/error (ssh session got killed etc) */ 870 less_exit(0); 871 } 872 set_tty_cooked(); 873 return rd; 874 } 875 876 /* Grab a character from input without requiring the return key. 877 * May return KEYCODE_xxx values. 878 * Note that this function works best with raw input. */ 879 static int less_getch(int pos) 880 { 881 int i; 882 883 again: 884 less_gets_pos = pos; 885 i = getch_nowait(); 886 less_gets_pos = -1; 887 888 /* Discard Ctrl-something chars */ 889 if (i >= 0 && i < ' ' && i != 0x0d && i != 8) 690 890 goto again; 691 }692 }693 694 /* Grab a character from input without requiring the return key. If the695 * character is ASCII \033, get more characters and assign certain sequences696 * special return codes. Note that this function works best with raw input. */697 static int less_getch(void)698 {699 char input[16];700 unsigned i;701 again:702 memset(input, 0, sizeof(input));703 getch_nowait(input, sizeof(input));704 705 /* Detect escape sequences (i.e. arrow keys) and handle706 * them accordingly */707 if (input[0] == '\033' && input[1] == '[') {708 set_tty_cooked();709 i = input[2] - REAL_KEY_UP;710 if (i < 4)711 return 20 + i;712 i = input[2] - REAL_PAGE_UP;713 if (i < 4)714 return 24 + i;715 if (input[2] == REAL_KEY_HOME_XTERM)716 return KEY_HOME;717 if (input[2] == REAL_KEY_HOME_ALT)718 return KEY_HOME;719 if (input[2] == REAL_KEY_END_XTERM)720 return KEY_END;721 if (input[2] == REAL_KEY_END_ALT)722 return KEY_END;723 return 0;724 }725 /* Reject almost all control chars */726 i = input[0];727 if (i < ' ' && i != 0x0d && i != 8) goto again;728 set_tty_cooked();729 891 return i; 730 892 } … … 732 894 static char* less_gets(int sz) 733 895 { 734 charc;735 inti = 0;896 int c; 897 unsigned i = 0; 736 898 char *result = xzalloc(1); 899 737 900 while (1) { 738 fflush(stdout);739 740 /* I be damned if I know why is it needed *repeatedly*,741 * but it is needed. Is it because of stdio? */742 tcsetattr(kbd_fd, TCSANOW, &term_less);743 744 901 c = '\0'; 745 read(kbd_fd, &c, 1); 746 if (c == 0x0d) 902 less_gets_pos = sz + i; 903 c = getch_nowait(); 904 if (c == 0x0d) { 905 result[i] = '\0'; 906 less_gets_pos = -1; 747 907 return result; 908 } 748 909 if (c == 0x7f) 749 910 c = 8; … … 752 913 i--; 753 914 } 754 if (c < ' ') 915 if (c < ' ') /* filters out KEYCODE_xxx too (<0) */ 755 916 continue; 756 917 if (i >= width - sz - 1) 757 918 continue; /* len limit */ 758 putchar(c);919 bb_putchar(c); 759 920 result[i++] = c; 760 921 result = xrealloc(result, i+1); 761 result[i] = '\0';762 922 } 763 923 } … … 765 925 static void examine_file(void) 766 926 { 927 char *new_fname; 928 767 929 print_statusline("Examine: "); 930 new_fname = less_gets(sizeof("Examine: ") - 1); 931 if (!new_fname[0]) { 932 status_print(); 933 err: 934 free(new_fname); 935 return; 936 } 937 if (access(new_fname, R_OK) != 0) { 938 print_statusline("Cannot read this file"); 939 goto err; 940 } 768 941 free(filename); 769 filename = less_gets(sizeof("Examine: ")-1);942 filename = new_fname; 770 943 /* files start by = argv. why we assume that argv is infinitely long?? 771 944 files[num_files] = filename; … … 795 968 static void remove_current_file(void) 796 969 { 797 inti;970 unsigned i; 798 971 799 972 if (num_files < 2) … … 821 994 print_statusline(" :"); 822 995 823 keypress = less_getch( );996 keypress = less_getch(2); 824 997 switch (keypress) { 825 998 case 'd': … … 841 1014 break; 842 1015 case 'q': 843 less_exit( 0);1016 less_exit(EXIT_SUCCESS); 844 1017 break; 845 1018 case 'x': … … 861 1034 static void goto_match(int match) 862 1035 { 863 int sv;864 865 1036 if (!pattern_valid) 866 1037 return; 867 1038 if (match < 0) 868 1039 match = 0; 869 sv = cur_fline;870 1040 /* Try to find next match if eof isn't reached yet */ 871 1041 if (match >= num_matches && eof_error > 0) { 872 cur_fline = MAXLINES; /* look as far as needed*/1042 wanted_match = match; /* "I want to read until I see N'th match" */ 873 1043 read_lines(); 874 1044 } 875 1045 if (num_matches) { 876 cap_cur_fline(cur_fline);877 1046 normalize_match_pos(match); 878 1047 buffer_line(match_lines[match_pos]); 879 1048 } else { 880 cur_fline = sv;881 1049 print_statusline("No matches found"); 882 1050 } … … 894 1062 && !(num_matches && match_lines[num_matches-1] == pos) 895 1063 ) { 896 match_lines = xrealloc (match_lines, (num_matches+1) * sizeof(int));1064 match_lines = xrealloc_vector(match_lines, 4, num_matches); 897 1065 match_lines[num_matches++] = pos; 898 1066 } … … 917 1085 /* Get the uncompiled regular expression from the user */ 918 1086 clear_line(); 919 putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/');1087 bb_putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/'); 920 1088 uncomp_regex = less_gets(1); 921 1089 if (!uncomp_regex[0]) { … … 926 1094 927 1095 /* Compile the regex and check for errors */ 928 err = regcomp_or_errmsg(&pattern, uncomp_regex, 0); 1096 err = regcomp_or_errmsg(&pattern, uncomp_regex, 1097 (option_mask32 & FLAG_I) ? REG_ICASE : 0); 929 1098 free(uncomp_regex); 930 1099 if (err) { … … 938 1107 fill_match_lines(0); 939 1108 while (match_pos < num_matches) { 940 if ( match_lines[match_pos] > cur_fline)1109 if ((int)match_lines[match_pos] > cur_fline) 941 1110 break; 942 1111 match_pos++; … … 954 1123 static void number_process(int first_digit) 955 1124 { 956 int i = 1;1125 unsigned i; 957 1126 int num; 1127 int keypress; 958 1128 char num_input[sizeof(int)*4]; /* more than enough */ 959 char keypress;960 1129 961 1130 num_input[0] = first_digit; … … 966 1135 967 1136 /* Receive input until a letter is given */ 1137 i = 1; 968 1138 while (i < sizeof(num_input)-1) { 969 num_input[i] = less_getch();970 if ( !num_input[i]|| !isdigit(num_input[i]))1139 keypress = less_getch(i + 1); 1140 if ((unsigned)keypress > 255 || !isdigit(num_input[i])) 971 1141 break; 972 putchar(num_input[i]); 1142 num_input[i] = keypress; 1143 bb_putchar(keypress); 973 1144 i++; 974 1145 } 975 1146 976 /* Take the final letter out of the digits string */977 keypress = num_input[i];978 1147 num_input[i] = '\0'; 979 1148 num = bb_strtou(num_input, NULL, 10); … … 986 1155 /* We now know the number and the letter entered, so we process them */ 987 1156 switch (keypress) { 988 case KEY _DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':1157 case KEYCODE_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015': 989 1158 buffer_down(num); 990 1159 break; 991 case KEY _UP: case 'b': case 'w': case 'y': case 'u':1160 case KEYCODE_UP: case 'b': case 'w': case 'y': case 'u': 992 1161 buffer_up(num); 993 1162 break; … … 1019 1188 } 1020 1189 1021 #if ENABLE_FEATURE_LESS_ FLAGCS1190 #if ENABLE_FEATURE_LESS_DASHCMD 1022 1191 static void flag_change(void) 1023 1192 { … … 1025 1194 1026 1195 clear_line(); 1027 putchar('-');1028 keypress = less_getch( );1196 bb_putchar('-'); 1197 keypress = less_getch(1); 1029 1198 1030 1199 switch (keypress) { … … 1041 1210 option_mask32 ^= FLAG_TILDE; 1042 1211 break; 1043 } 1044 } 1045 1212 case 'S': 1213 option_mask32 ^= FLAG_S; 1214 buffer_fill_and_print(); 1215 break; 1216 #if ENABLE_FEATURE_LESS_LINENUMS 1217 case 'N': 1218 option_mask32 ^= FLAG_N; 1219 re_wrap(); 1220 buffer_fill_and_print(); 1221 break; 1222 #endif 1223 } 1224 } 1225 1226 #ifdef BLOAT 1046 1227 static void show_flag_status(void) 1047 1228 { … … 1050 1231 1051 1232 clear_line(); 1052 putchar('_');1053 keypress = less_getch( );1233 bb_putchar('_'); 1234 keypress = less_getch(1); 1054 1235 1055 1236 switch (keypress) { … … 1079 1260 #endif 1080 1261 1262 #endif /* ENABLE_FEATURE_LESS_DASHCMD */ 1263 1081 1264 static void save_input_to_file(void) 1082 1265 { 1083 1266 const char *msg = ""; 1084 1267 char *current_line; 1085 inti;1268 unsigned i; 1086 1269 FILE *fp; 1087 1270 1088 1271 print_statusline("Log file: "); 1089 1272 current_line = less_gets(sizeof("Log file: ")-1); 1090 if ( strlen(current_line) > 0) {1091 fp = fopen (current_line, "w");1273 if (current_line[0]) { 1274 fp = fopen_for_write(current_line); 1092 1275 if (!fp) { 1093 1276 msg = "Error opening log file"; … … 1110 1293 1111 1294 print_statusline("Mark: "); 1112 letter = less_getch( );1295 letter = less_getch(sizeof("Mark: ") - 1); 1113 1296 1114 1297 if (isalpha(letter)) { … … 1131 1314 1132 1315 print_statusline("Go to mark: "); 1133 letter = less_getch( );1316 letter = less_getch(sizeof("Go to mark: ") - 1); 1134 1317 clear_line(); 1135 1318 … … 1151 1334 { 1152 1335 switch (bracket) { 1153 case '{': case '[': 1154 return bracket + 2; 1155 case '(': 1156 return ')'; 1157 case '}': case ']': 1158 return bracket - 2; 1159 case ')': 1160 return '('; 1161 } 1162 return 0; 1336 case '{': case '[': /* '}' == '{' + 2. Same for '[' */ 1337 bracket++; 1338 case '(': /* ')' == '(' + 1 */ 1339 bracket++; 1340 break; 1341 case '}': case ']': 1342 bracket--; 1343 case ')': 1344 bracket--; 1345 break; 1346 }; 1347 return bracket; 1163 1348 } 1164 1349 1165 1350 static void match_right_bracket(char bracket) 1166 1351 { 1167 int bracket_line = -1; 1168 int i; 1352 unsigned i; 1169 1353 1170 1354 if (strchr(flines[cur_fline], bracket) == NULL) { … … 1172 1356 return; 1173 1357 } 1358 bracket = opp_bracket(bracket); 1174 1359 for (i = cur_fline + 1; i < max_fline; i++) { 1175 if (strchr(flines[i], opp_bracket(bracket)) != NULL) { 1176 bracket_line = i; 1177 break; 1178 } 1179 } 1180 if (bracket_line == -1) 1181 print_statusline("No matching bracket found"); 1182 buffer_line(bracket_line - max_displayed_line); 1360 if (strchr(flines[i], bracket) != NULL) { 1361 buffer_line(i); 1362 return; 1363 } 1364 } 1365 print_statusline("No matching bracket found"); 1183 1366 } 1184 1367 1185 1368 static void match_left_bracket(char bracket) 1186 1369 { 1187 int bracket_line = -1;1188 1370 int i; 1189 1371 … … 1193 1375 } 1194 1376 1377 bracket = opp_bracket(bracket); 1195 1378 for (i = cur_fline + max_displayed_line; i >= 0; i--) { 1196 if (strchr(flines[i], opp_bracket(bracket)) != NULL) { 1197 bracket_line = i; 1198 break; 1199 } 1200 } 1201 if (bracket_line == -1) 1202 print_statusline("No matching bracket found"); 1203 buffer_line(bracket_line); 1379 if (strchr(flines[i], bracket) != NULL) { 1380 buffer_line(i); 1381 return; 1382 } 1383 } 1384 print_statusline("No matching bracket found"); 1204 1385 } 1205 1386 #endif /* FEATURE_LESS_BRACKETS */ … … 1208 1389 { 1209 1390 switch (keypress) { 1210 case KEY _DOWN: case 'e': case 'j': case 0x0d:1391 case KEYCODE_DOWN: case 'e': case 'j': case 0x0d: 1211 1392 buffer_down(1); 1212 1393 break; 1213 case KEY _UP: case 'y': case 'k':1394 case KEYCODE_UP: case 'y': case 'k': 1214 1395 buffer_up(1); 1215 1396 break; 1216 case PAGE_DOWN: case ' ': case 'z':1397 case KEYCODE_PAGEDOWN: case ' ': case 'z': case 'f': 1217 1398 buffer_down(max_displayed_line + 1); 1218 1399 break; 1219 case PAGE_UP: case 'w': case 'b':1400 case KEYCODE_PAGEUP: case 'w': case 'b': 1220 1401 buffer_up(max_displayed_line + 1); 1221 1402 break; … … 1226 1407 buffer_up((max_displayed_line + 1) / 2); 1227 1408 break; 1228 case KEY _HOME: case 'g': case 'p': case '<': case '%':1409 case KEYCODE_HOME: case 'g': case 'p': case '<': case '%': 1229 1410 buffer_line(0); 1230 1411 break; 1231 case KEY _END: case 'G': case '>':1412 case KEYCODE_END: case 'G': case '>': 1232 1413 cur_fline = MAXLINES; 1233 1414 read_lines(); … … 1235 1416 break; 1236 1417 case 'q': case 'Q': 1237 less_exit( 0);1418 less_exit(EXIT_SUCCESS); 1238 1419 break; 1239 1420 #if ENABLE_FEATURE_LESS_MARKS … … 1280 1461 break; 1281 1462 #endif 1282 #if ENABLE_FEATURE_LESS_ FLAGCS1463 #if ENABLE_FEATURE_LESS_DASHCMD 1283 1464 case '-': 1284 1465 flag_change(); 1285 1466 buffer_print(); 1286 1467 break; 1468 #ifdef BLOAT 1287 1469 case '_': 1288 1470 show_flag_status(); 1289 1471 break; 1472 #endif 1290 1473 #endif 1291 1474 #if ENABLE_FEATURE_LESS_BRACKETS … … 1306 1489 } 1307 1490 1308 static void sig_catcher(int sig ATTRIBUTE_UNUSED) 1309 { 1310 set_tty_cooked(); 1311 exit(1); 1312 } 1313 1314 int less_main(int argc, char **argv); 1491 static void sig_catcher(int sig) 1492 { 1493 less_exit(- sig); 1494 } 1495 1496 #if ENABLE_FEATURE_LESS_WINCH 1497 static void sigwinch_handler(int sig UNUSED_PARAM) 1498 { 1499 winch_counter++; 1500 } 1501 #endif 1502 1503 int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1315 1504 int less_main(int argc, char **argv) 1316 1505 { … … 1322 1511 /* -xxx: newline also */ 1323 1512 /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */ 1324 getopt32(argv, "EMmN~ ");1513 getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S")); 1325 1514 argc -= optind; 1326 1515 argv += optind; … … 1331 1520 * is not a tty and turns into cat. This makes sense. */ 1332 1521 if (!isatty(STDOUT_FILENO)) 1333 return bb_cat(argv);1334 kbd_fd = open(CURRENT_TTY, O_RDONLY);1335 if (kbd_fd < 0)1336 1522 return bb_cat(argv); 1337 1523 … … 1342 1528 bb_show_usage(); 1343 1529 } 1344 } else 1530 } else { 1345 1531 filename = xstrdup(files[0]); 1346 1347 get_terminal_width_height(kbd_fd, &width, &max_displayed_line); 1348 /* 20: two tabstops + 4 */ 1349 if (width < 20 || max_displayed_line < 3) 1350 bb_error_msg_and_die("too narrow here"); 1351 max_displayed_line -= 2; 1352 1353 buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); 1532 } 1533 1354 1534 if (option_mask32 & FLAG_TILDE) 1355 1535 empty_line_marker = ""; 1356 1536 1537 kbd_fd = open(CURRENT_TTY, O_RDONLY); 1538 if (kbd_fd < 0) 1539 return bb_cat(argv); 1540 ndelay_on(kbd_fd); 1541 1357 1542 tcgetattr(kbd_fd, &term_orig); 1358 signal(SIGTERM, sig_catcher);1359 signal(SIGINT, sig_catcher);1360 1543 term_less = term_orig; 1361 1544 term_less.c_lflag &= ~(ICANON | ECHO); … … 1365 1548 term_less.c_cc[VTIME] = 0; 1366 1549 1367 /* Want to do it just once, but it doesn't work, */ 1368 /* so we are redoing it (see code above). Mystery... */ 1369 /*tcsetattr(kbd_fd, TCSANOW, &term_less);*/ 1370 1550 get_terminal_width_height(kbd_fd, &width, &max_displayed_line); 1551 /* 20: two tabstops + 4 */ 1552 if (width < 20 || max_displayed_line < 3) 1553 return bb_cat(argv); 1554 max_displayed_line -= 2; 1555 1556 /* We want to restore term_orig on exit */ 1557 bb_signals(BB_FATAL_SIGS, sig_catcher); 1558 #if ENABLE_FEATURE_LESS_WINCH 1559 signal(SIGWINCH, sigwinch_handler); 1560 #endif 1561 1562 buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); 1371 1563 reinitialize(); 1372 1564 while (1) { 1373 keypress = less_getch(); 1565 #if ENABLE_FEATURE_LESS_WINCH 1566 while (WINCH_COUNTER) { 1567 again: 1568 winch_counter--; 1569 get_terminal_width_height(kbd_fd, &width, &max_displayed_line); 1570 /* 20: two tabstops + 4 */ 1571 if (width < 20) 1572 width = 20; 1573 if (max_displayed_line < 3) 1574 max_displayed_line = 3; 1575 max_displayed_line -= 2; 1576 free(buffer); 1577 buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); 1578 /* Avoid re-wrap and/or redraw if we already know 1579 * we need to do it again. These ops are expensive */ 1580 if (WINCH_COUNTER) 1581 goto again; 1582 re_wrap(); 1583 if (WINCH_COUNTER) 1584 goto again; 1585 buffer_fill_and_print(); 1586 /* This took some time. Loop back and check, 1587 * were there another SIGWINCH? */ 1588 } 1589 #endif 1590 keypress = less_getch(-1); /* -1: do not position cursor */ 1374 1591 keypress_process(keypress); 1375 1592 } 1376 1593 } 1594 1595 /* 1596 Help text of less version 418 is below. 1597 If you are implementing something, keeping 1598 key and/or command line switch compatibility is a good idea: 1599 1600 1601 SUMMARY OF LESS COMMANDS 1602 1603 Commands marked with * may be preceded by a number, N. 1604 Notes in parentheses indicate the behavior if N is given. 1605 h H Display this help. 1606 q :q Q :Q ZZ Exit. 1607 --------------------------------------------------------------------------- 1608 MOVING 1609 e ^E j ^N CR * Forward one line (or N lines). 1610 y ^Y k ^K ^P * Backward one line (or N lines). 1611 f ^F ^V SPACE * Forward one window (or N lines). 1612 b ^B ESC-v * Backward one window (or N lines). 1613 z * Forward one window (and set window to N). 1614 w * Backward one window (and set window to N). 1615 ESC-SPACE * Forward one window, but don't stop at end-of-file. 1616 d ^D * Forward one half-window (and set half-window to N). 1617 u ^U * Backward one half-window (and set half-window to N). 1618 ESC-) RightArrow * Left one half screen width (or N positions). 1619 ESC-( LeftArrow * Right one half screen width (or N positions). 1620 F Forward forever; like "tail -f". 1621 r ^R ^L Repaint screen. 1622 R Repaint screen, discarding buffered input. 1623 --------------------------------------------------- 1624 Default "window" is the screen height. 1625 Default "half-window" is half of the screen height. 1626 --------------------------------------------------------------------------- 1627 SEARCHING 1628 /pattern * Search forward for (N-th) matching line. 1629 ?pattern * Search backward for (N-th) matching line. 1630 n * Repeat previous search (for N-th occurrence). 1631 N * Repeat previous search in reverse direction. 1632 ESC-n * Repeat previous search, spanning files. 1633 ESC-N * Repeat previous search, reverse dir. & spanning files. 1634 ESC-u Undo (toggle) search highlighting. 1635 --------------------------------------------------- 1636 Search patterns may be modified by one or more of: 1637 ^N or ! Search for NON-matching lines. 1638 ^E or * Search multiple files (pass thru END OF FILE). 1639 ^F or @ Start search at FIRST file (for /) or last file (for ?). 1640 ^K Highlight matches, but don't move (KEEP position). 1641 ^R Don't use REGULAR EXPRESSIONS. 1642 --------------------------------------------------------------------------- 1643 JUMPING 1644 g < ESC-< * Go to first line in file (or line N). 1645 G > ESC-> * Go to last line in file (or line N). 1646 p % * Go to beginning of file (or N percent into file). 1647 t * Go to the (N-th) next tag. 1648 T * Go to the (N-th) previous tag. 1649 { ( [ * Find close bracket } ) ]. 1650 } ) ] * Find open bracket { ( [. 1651 ESC-^F <c1> <c2> * Find close bracket <c2>. 1652 ESC-^B <c1> <c2> * Find open bracket <c1> 1653 --------------------------------------------------- 1654 Each "find close bracket" command goes forward to the close bracket 1655 matching the (N-th) open bracket in the top line. 1656 Each "find open bracket" command goes backward to the open bracket 1657 matching the (N-th) close bracket in the bottom line. 1658 m<letter> Mark the current position with <letter>. 1659 '<letter> Go to a previously marked position. 1660 '' Go to the previous position. 1661 ^X^X Same as '. 1662 --------------------------------------------------- 1663 A mark is any upper-case or lower-case letter. 1664 Certain marks are predefined: 1665 ^ means beginning of the file 1666 $ means end of the file 1667 --------------------------------------------------------------------------- 1668 CHANGING FILES 1669 :e [file] Examine a new file. 1670 ^X^V Same as :e. 1671 :n * Examine the (N-th) next file from the command line. 1672 :p * Examine the (N-th) previous file from the command line. 1673 :x * Examine the first (or N-th) file from the command line. 1674 :d Delete the current file from the command line list. 1675 = ^G :f Print current file name. 1676 --------------------------------------------------------------------------- 1677 MISCELLANEOUS COMMANDS 1678 -<flag> Toggle a command line option [see OPTIONS below]. 1679 --<name> Toggle a command line option, by name. 1680 _<flag> Display the setting of a command line option. 1681 __<name> Display the setting of an option, by name. 1682 +cmd Execute the less cmd each time a new file is examined. 1683 !command Execute the shell command with $SHELL. 1684 |Xcommand Pipe file between current pos & mark X to shell command. 1685 v Edit the current file with $VISUAL or $EDITOR. 1686 V Print version number of "less". 1687 --------------------------------------------------------------------------- 1688 OPTIONS 1689 Most options may be changed either on the command line, 1690 or from within less by using the - or -- command. 1691 Options may be given in one of two forms: either a single 1692 character preceded by a -, or a name preceeded by --. 1693 -? ........ --help 1694 Display help (from command line). 1695 -a ........ --search-skip-screen 1696 Forward search skips current screen. 1697 -b [N] .... --buffers=[N] 1698 Number of buffers. 1699 -B ........ --auto-buffers 1700 Don't automatically allocate buffers for pipes. 1701 -c ........ --clear-screen 1702 Repaint by clearing rather than scrolling. 1703 -d ........ --dumb 1704 Dumb terminal. 1705 -D [xn.n] . --color=xn.n 1706 Set screen colors. (MS-DOS only) 1707 -e -E .... --quit-at-eof --QUIT-AT-EOF 1708 Quit at end of file. 1709 -f ........ --force 1710 Force open non-regular files. 1711 -F ........ --quit-if-one-screen 1712 Quit if entire file fits on first screen. 1713 -g ........ --hilite-search 1714 Highlight only last match for searches. 1715 -G ........ --HILITE-SEARCH 1716 Don't highlight any matches for searches. 1717 -h [N] .... --max-back-scroll=[N] 1718 Backward scroll limit. 1719 -i ........ --ignore-case 1720 Ignore case in searches that do not contain uppercase. 1721 -I ........ --IGNORE-CASE 1722 Ignore case in all searches. 1723 -j [N] .... --jump-target=[N] 1724 Screen position of target lines. 1725 -J ........ --status-column 1726 Display a status column at left edge of screen. 1727 -k [file] . --lesskey-file=[file] 1728 Use a lesskey file. 1729 -L ........ --no-lessopen 1730 Ignore the LESSOPEN environment variable. 1731 -m -M .... --long-prompt --LONG-PROMPT 1732 Set prompt style. 1733 -n -N .... --line-numbers --LINE-NUMBERS 1734 Don't use line numbers. 1735 -o [file] . --log-file=[file] 1736 Copy to log file (standard input only). 1737 -O [file] . --LOG-FILE=[file] 1738 Copy to log file (unconditionally overwrite). 1739 -p [pattern] --pattern=[pattern] 1740 Start at pattern (from command line). 1741 -P [prompt] --prompt=[prompt] 1742 Define new prompt. 1743 -q -Q .... --quiet --QUIET --silent --SILENT 1744 Quiet the terminal bell. 1745 -r -R .... --raw-control-chars --RAW-CONTROL-CHARS 1746 Output "raw" control characters. 1747 -s ........ --squeeze-blank-lines 1748 Squeeze multiple blank lines. 1749 -S ........ --chop-long-lines 1750 Chop long lines. 1751 -t [tag] .. --tag=[tag] 1752 Find a tag. 1753 -T [tagsfile] --tag-file=[tagsfile] 1754 Use an alternate tags file. 1755 -u -U .... --underline-special --UNDERLINE-SPECIAL 1756 Change handling of backspaces. 1757 -V ........ --version 1758 Display the version number of "less". 1759 -w ........ --hilite-unread 1760 Highlight first new line after forward-screen. 1761 -W ........ --HILITE-UNREAD 1762 Highlight first new line after any forward movement. 1763 -x [N[,...]] --tabs=[N[,...]] 1764 Set tab stops. 1765 -X ........ --no-init 1766 Don't use termcap init/deinit strings. 1767 --no-keypad 1768 Don't use termcap keypad init/deinit strings. 1769 -y [N] .... --max-forw-scroll=[N] 1770 Forward scroll limit. 1771 -z [N] .... --window=[N] 1772 Set size of window. 1773 -" [c[c]] . --quotes=[c[c]] 1774 Set shell quote characters. 1775 -~ ........ --tilde 1776 Don't display tildes after end of file. 1777 -# [N] .... --shift=[N] 1778 Horizontal scroll amount (0 = one half screen width) 1779 1780 --------------------------------------------------------------------------- 1781 LINE EDITING 1782 These keys can be used to edit text being entered 1783 on the "command line" at the bottom of the screen. 1784 RightArrow ESC-l Move cursor right one character. 1785 LeftArrow ESC-h Move cursor left one character. 1786 CNTL-RightArrow ESC-RightArrow ESC-w Move cursor right one word. 1787 CNTL-LeftArrow ESC-LeftArrow ESC-b Move cursor left one word. 1788 HOME ESC-0 Move cursor to start of line. 1789 END ESC-$ Move cursor to end of line. 1790 BACKSPACE Delete char to left of cursor. 1791 DELETE ESC-x Delete char under cursor. 1792 CNTL-BACKSPACE ESC-BACKSPACE Delete word to left of cursor. 1793 CNTL-DELETE ESC-DELETE ESC-X Delete word under cursor. 1794 CNTL-U ESC (MS-DOS only) Delete entire line. 1795 UpArrow ESC-k Retrieve previous command line. 1796 DownArrow ESC-j Retrieve next command line. 1797 TAB Complete filename & cycle. 1798 SHIFT-TAB ESC-TAB Complete filename & reverse cycle. 1799 CNTL-L Complete filename, list all. 1800 */ -
branches/2.2.9/mindi-busybox/miscutils/makedevs.c
r1765 r2725 11 11 12 12 #if ENABLE_FEATURE_MAKEDEVS_LEAF 13 int makedevs_main(int argc, char **argv); 13 /* 14 makedevs NAME TYPE MAJOR MINOR FIRST LAST [s] 15 TYPEs: 16 b Block device 17 c Character device 18 f FIFO 19 20 FIRST..LAST specify numbers appended to NAME. 21 If 's' is the last argument, the base device is created as well. 22 Examples: 23 makedevs /dev/ttyS c 4 66 2 63 -> ttyS2-ttyS63 24 makedevs /dev/hda b 3 0 0 8 s -> hda,hda1-hda8 25 */ 26 int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 14 27 int makedevs_main(int argc, char **argv) 15 28 { 16 29 mode_t mode; 17 char *basedev, *type, *nodname, buf[255];30 char *basedev, *type, *nodname, *buf; 18 31 int Smajor, Sminor, S, E; 19 32 20 if (argc < 7 || *argv[1]=='-')33 if (argc < 7 || argv[1][0] == '-') 21 34 bb_show_usage(); 22 35 23 36 basedev = argv[1]; 37 buf = xasprintf("%s%u", argv[1], (unsigned)-1); 24 38 type = argv[2]; 25 Smajor = xatoi_ u(argv[3]);26 Sminor = xatoi_ u(argv[4]);27 S = xatoi_ u(argv[5]);28 E = xatoi_ u(argv[6]);29 nodname = arg c == 8? basedev : buf;39 Smajor = xatoi_positive(argv[3]); 40 Sminor = xatoi_positive(argv[4]); 41 S = xatoi_positive(argv[5]); 42 E = xatoi_positive(argv[6]); 43 nodname = argv[7] ? basedev : buf; 30 44 31 45 mode = 0660; 32 33 46 switch (type[0]) { 34 47 case 'c': … … 46 59 47 60 while (S <= E) { 48 int sz; 49 50 sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S); 51 if (sz < 0 || sz >= sizeof(buf)) /* libc different */ 52 bb_error_msg_and_die("%s too large", basedev); 53 54 /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */ 55 61 sprintf(buf, "%s%u", basedev, S); 62 63 /* if mode != S_IFCHR and != S_IFBLK, 64 * third param in mknod() ignored */ 56 65 if (mknod(nodname, mode, makedev(Smajor, Sminor))) 57 bb_ error_msg("failed to create: %s", nodname);58 59 if (nodname == basedev)/* ex. /dev/hda - to /dev/hda1 ... */66 bb_perror_msg("can't create '%s'", nodname); 67 68 /*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */ 60 69 nodname = buf; 61 70 S++; … … 68 77 #elif ENABLE_FEATURE_MAKEDEVS_TABLE 69 78 70 /* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */71 72 int makedevs_main(int argc, char **argv) ;73 int makedevs_main(int argc , char **argv)79 /* Licensed under GPLv2 or later, see file LICENSE in this source tree. */ 80 81 int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 82 int makedevs_main(int argc UNUSED_PARAM, char **argv) 74 83 { 75 FILE *table = stdin; 76 char *rootdir = NULL; 77 char *line = NULL; 78 int linenum = 0; 84 parser_t *parser; 85 char *line = (char *)"-"; 79 86 int ret = EXIT_SUCCESS; 80 87 88 opt_complementary = "=1"; /* exactly one param */ 81 89 getopt32(argv, "d:", &line); 82 if (line) 83 table = xfopen(line, "r"); 84 85 if (optind >= argc || (rootdir=argv[optind])==NULL) { 86 bb_error_msg_and_die("root directory not specified"); 87 } 88 89 xchdir(rootdir); 90 argv += optind; 91 92 xchdir(*argv); /* ensure root dir exists */ 90 93 91 94 umask(0); 92 95 93 printf("rootdir=%s\n ", rootdir);94 if ( line) {95 printf(" table='%s'\n", line);96 printf("rootdir=%s\ntable=", *argv); 97 if (NOT_LONE_DASH(line)) { 98 printf("'%s'\n", line); 96 99 } else { 97 printf("table=<stdin>\n"); 98 } 99 100 while ((line = xmalloc_getline(table))) { 100 puts("<stdin>"); 101 } 102 103 parser = config_open(line); 104 while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) { 105 int linenum; 101 106 char type; 102 unsigned intmode = 0755;103 unsigned intmajor = 0;104 unsigned intminor = 0;105 unsigned intcount = 0;106 unsigned in t increment = 0;107 unsigned intstart = 0;107 unsigned mode = 0755; 108 unsigned major = 0; 109 unsigned minor = 0; 110 unsigned count = 0; 111 unsigned increment = 0; 112 unsigned start = 0; 108 113 char name[41]; 109 114 char user[41]; 110 115 char group[41]; 111 char *full_name ;116 char *full_name = name; 112 117 uid_t uid; 113 118 gid_t gid; 114 119 115 linenum++; 116 117 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name, 118 &type, &mode, user, group, &major, 119 &minor, &start, &increment, &count)) || 120 ((major | minor | start | count | increment) > 255)) 121 { 122 if (*line=='\0' || *line=='#' || isspace(*line)) 123 continue; 124 bb_error_msg("line %d invalid: '%s'", linenum, line); 120 linenum = parser->lineno; 121 122 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", 123 name, &type, &mode, user, group, 124 &major, &minor, &start, &increment, &count)) 125 || ((unsigned)(major | minor | start | count | increment) > 255) 126 ) { 127 bb_error_msg("invalid line %d: '%s'", linenum, line); 125 128 ret = EXIT_FAILURE; 126 129 continue; 127 130 } 128 if (name[0] == '#') {129 continue;130 }131 131 132 132 gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid(); 133 133 uid = (*user) ? get_ug_id(user, xuname2uid) : getuid(); 134 full_name = concat_path_file(rootdir, name); 134 /* We are already in the right root dir, 135 * so make absolute paths relative */ 136 if ('/' == *full_name) 137 full_name++; 135 138 136 139 if (type == 'd') { 137 140 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR); 138 141 if (chown(full_name, uid, gid) == -1) { 139 bb_perror_msg("line %d: chown failed for %s", linenum, full_name); 140 ret = EXIT_FAILURE; 141 goto loop; 142 } 143 if ((mode != -1) && (chmod(full_name, mode) < 0)){ 144 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); 145 ret = EXIT_FAILURE; 146 goto loop; 142 chown_fail: 143 bb_perror_msg("line %d: can't chown %s", linenum, full_name); 144 ret = EXIT_FAILURE; 145 continue; 146 } 147 if (chmod(full_name, mode) < 0) { 148 chmod_fail: 149 bb_perror_msg("line %d: can't chmod %s", linenum, full_name); 150 ret = EXIT_FAILURE; 151 continue; 147 152 } 148 153 } else if (type == 'f') { … … 151 156 bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name); 152 157 ret = EXIT_FAILURE; 153 goto loop; 154 } 155 if (chown(full_name, uid, gid) == -1) { 156 bb_perror_msg("line %d: chown failed for %s", linenum, full_name); 157 ret = EXIT_FAILURE; 158 goto loop; 159 } 160 if ((mode != -1) && (chmod(full_name, mode) < 0)){ 161 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); 162 ret = EXIT_FAILURE; 163 goto loop; 164 } 158 continue; 159 } 160 if (chown(full_name, uid, gid) < 0) 161 goto chown_fail; 162 if (chmod(full_name, mode) < 0) 163 goto chmod_fail; 165 164 } else { 166 165 dev_t rdev; 166 unsigned i; 167 char *full_name_inc; 167 168 168 169 if (type == 'p') { 169 170 mode |= S_IFIFO; 170 } 171 else if (type == 'c') { 171 } else if (type == 'c') { 172 172 mode |= S_IFCHR; 173 } 174 else if (type == 'b') { 173 } else if (type == 'b') { 175 174 mode |= S_IFBLK; 176 175 } else { 177 176 bb_error_msg("line %d: unsupported file type %c", linenum, type); 178 177 ret = EXIT_FAILURE; 179 goto loop; 180 } 181 182 if (count > 0) { 183 int i; 184 char *full_name_inc; 185 186 full_name_inc = xmalloc(strlen(full_name) + 4); 187 for (i = start; i < count; i++) { 188 sprintf(full_name_inc, "%s%d", full_name, i); 189 rdev = makedev(major, minor + (i * increment - start)); 190 if (mknod(full_name_inc, mode, rdev) == -1) { 191 bb_perror_msg("line %d: cannot create node %s", linenum, full_name_inc); 192 ret = EXIT_FAILURE; 193 } 194 else if (chown(full_name_inc, uid, gid) == -1) { 195 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc); 196 ret = EXIT_FAILURE; 197 } 198 if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){ 199 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc); 200 ret = EXIT_FAILURE; 201 } 202 } 203 free(full_name_inc); 204 } else { 205 rdev = makedev(major, minor); 206 if (mknod(full_name, mode, rdev) == -1) { 207 bb_perror_msg("line %d: cannot create node %s", linenum, full_name); 178 continue; 179 } 180 181 full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2); 182 if (count) 183 count--; 184 for (i = start; i <= start + count; i++) { 185 sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i); 186 rdev = makedev(major, minor + (i - start) * increment); 187 if (mknod(full_name_inc, mode, rdev) < 0) { 188 bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc); 189 ret = EXIT_FAILURE; 190 } else if (chown(full_name_inc, uid, gid) < 0) { 191 bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc); 192 ret = EXIT_FAILURE; 193 } else if (chmod(full_name_inc, mode) < 0) { 194 bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc); 208 195 ret = EXIT_FAILURE; 209 196 } 210 else if (chown(full_name, uid, gid) == -1) { 211 bb_perror_msg("line %d: chown failed for %s", linenum, full_name); 212 ret = EXIT_FAILURE; 213 } 214 if ((mode != -1) && (chmod(full_name, mode) < 0)){ 215 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); 216 ret = EXIT_FAILURE; 217 } 218 } 197 } 198 free(full_name_inc); 219 199 } 220 loop: 221 free(line); 222 free(full_name); 223 } 224 fclose(table); 200 } 201 if (ENABLE_FEATURE_CLEAN_UP) 202 config_close(parser); 225 203 226 204 return ret; -
branches/2.2.9/mindi-busybox/miscutils/mountpoint.c
r1765 r2725 3 3 * mountpoint implementation for busybox 4 4 * 5 * Copyright (C) 2005 Bernhard Fischer5 * Copyright (C) 2005 Bernhard Reutner-Fischer 6 6 * 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 * 9 9 * Based on sysvinit's mountpoint … … 12 12 #include "libbb.h" 13 13 14 int mountpoint_main(int argc, char **argv) ;15 int mountpoint_main(int argc , char **argv)14 int mountpoint_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 15 int mountpoint_main(int argc UNUSED_PARAM, char **argv) 16 16 { 17 17 struct stat st; 18 const char *msg; 18 19 char *arg; 19 int opt = getopt32(argv, "qdx"); 20 int rc, opt; 21 22 opt_complementary = "=1"; /* must have one argument */ 23 opt = getopt32(argv, "qdxn"); 20 24 #define OPT_q (1) 21 25 #define OPT_d (2) 22 26 #define OPT_x (4) 27 #define OPT_n (8) 28 arg = argv[optind]; 29 msg = "%s"; 23 30 24 if (optind != argc - 1) 25 bb_show_usage(); 31 rc = (opt & OPT_x) ? stat(arg, &st) : lstat(arg, &st); 32 if (rc != 0) 33 goto err; 26 34 27 arg = argv[optind]; 35 if (opt & OPT_x) { 36 if (S_ISBLK(st.st_mode)) { 37 printf("%u:%u\n", major(st.st_rdev), 38 minor(st.st_rdev)); 39 return EXIT_SUCCESS; 40 } 41 errno = 0; /* make perror_msg work as error_msg */ 42 msg = "%s: not a block device"; 43 goto err; 44 } 28 45 29 if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) { 30 if (opt & OPT_x) { 31 if (S_ISBLK(st.st_mode)) { 32 printf("%u:%u\n", major(st.st_rdev), 33 minor(st.st_rdev)); 34 return EXIT_SUCCESS; 35 } else { 36 if (opt & OPT_q) 37 putchar('\n'); 38 else 39 bb_error_msg("%s: not a block device", arg); 46 errno = ENOTDIR; 47 if (S_ISDIR(st.st_mode)) { 48 dev_t st_dev = st.st_dev; 49 ino_t st_ino = st.st_ino; 50 char *p = xasprintf("%s/..", arg); 51 52 if (stat(p, &st) == 0) { 53 //int is_mnt = (st_dev != st.st_dev) || (st_dev == st.st_dev && st_ino == st.st_ino); 54 int is_not_mnt = (st_dev == st.st_dev) && (st_ino != st.st_ino); 55 56 if (opt & OPT_d) 57 printf("%u:%u\n", major(st_dev), minor(st_dev)); 58 if (opt & OPT_n) { 59 const char *d = find_block_device(arg); 60 /* name is undefined, but device is mounted -> anonymous superblock! */ 61 /* happens with btrfs */ 62 if (!d) { 63 d = "UNKNOWN"; 64 /* TODO: iterate /proc/mounts, or /proc/self/mountinfo 65 * to find out the device name */ 66 } 67 printf("%s %s\n", d, arg); 40 68 } 41 return EXIT_FAILURE; 42 } else 43 if (S_ISDIR(st.st_mode)) { 44 dev_t st_dev = st.st_dev; 45 ino_t st_ino = st.st_ino; 46 char *p = xasprintf("%s/..", arg); 69 if (!(opt & (OPT_q | OPT_d | OPT_n))) 70 printf("%s is %sa mountpoint\n", arg, is_not_mnt ? "not " : ""); 71 return is_not_mnt; 72 } 73 arg = p; 74 /* else: stat had set errno, just fall through */ 75 } 47 76 48 if (stat(p, &st) == 0) { 49 int ret = (st_dev != st.st_dev) || 50 (st_dev == st.st_dev && st_ino == st.st_ino); 51 if (opt & OPT_d) 52 printf("%u:%u\n", major(st_dev), minor(st_dev)); 53 else if (!(opt & OPT_q)) 54 printf("%s is %sa mountpoint\n", arg, ret?"":"not "); 55 return !ret; 56 } 57 } else { 58 if (!(opt & OPT_q)) 59 bb_error_msg("%s: not a directory", arg); 60 return EXIT_FAILURE; 61 } 62 } 77 err: 63 78 if (!(opt & OPT_q)) 64 bb_perror_msg( "%s", arg);79 bb_perror_msg(msg, arg); 65 80 return EXIT_FAILURE; 66 81 } -
branches/2.2.9/mindi-busybox/miscutils/mt.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 5 … … 7 7 #include <sys/mtio.h> 8 8 9 struct mt_opcodes { 10 const char *name; 11 short value; 9 /* missing: eod/seod, stoptions, stwrthreshold, densities */ 10 static const short opcode_value[] = { 11 MTBSF, 12 MTBSFM, 13 MTBSR, 14 MTBSS, 15 MTCOMPRESSION, 16 MTEOM, 17 MTERASE, 18 MTFSF, 19 MTFSFM, 20 MTFSR, 21 MTFSS, 22 MTLOAD, 23 MTLOCK, 24 MTMKPART, 25 MTNOP, 26 MTOFFL, 27 MTOFFL, 28 MTRAS1, 29 MTRAS2, 30 MTRAS3, 31 MTRESET, 32 MTRETEN, 33 MTREW, 34 MTSEEK, 35 MTSETBLK, 36 MTSETDENSITY, 37 MTSETDRVBUFFER, 38 MTSETPART, 39 MTTELL, 40 MTWSM, 41 MTUNLOAD, 42 MTUNLOCK, 43 MTWEOF, 44 MTWEOF 12 45 }; 13 46 14 /* missing: eod/seod, stoptions, stwrthreshold, densities */ 15 static const struct mt_opcodes opcodes[] = { 16 {"bsf", MTBSF}, 17 {"bsfm", MTBSFM}, 18 {"bsr", MTBSR}, 19 {"bss", MTBSS}, 20 {"datacompression", MTCOMPRESSION}, 21 {"eom", MTEOM}, 22 {"erase", MTERASE}, 23 {"fsf", MTFSF}, 24 {"fsfm", MTFSFM}, 25 {"fsr", MTFSR}, 26 {"fss", MTFSS}, 27 {"load", MTLOAD}, 28 {"lock", MTLOCK}, 29 {"mkpart", MTMKPART}, 30 {"nop", MTNOP}, 31 {"offline", MTOFFL}, 32 {"rewoffline", MTOFFL}, 33 {"ras1", MTRAS1}, 34 {"ras2", MTRAS2}, 35 {"ras3", MTRAS3}, 36 {"reset", MTRESET}, 37 {"retension", MTRETEN}, 38 {"rewind", MTREW}, 39 {"seek", MTSEEK}, 40 {"setblk", MTSETBLK}, 41 {"setdensity", MTSETDENSITY}, 42 {"drvbuffer", MTSETDRVBUFFER}, 43 {"setpart", MTSETPART}, 44 {"tell", MTTELL}, 45 {"wset", MTWSM}, 46 {"unload", MTUNLOAD}, 47 {"unlock", MTUNLOCK}, 48 {"eof", MTWEOF}, 49 {"weof", MTWEOF}, 50 {0, 0} 51 }; 47 static const char opcode_name[] ALIGN1 = 48 "bsf" "\0" 49 "bsfm" "\0" 50 "bsr" "\0" 51 "bss" "\0" 52 "datacompression" "\0" 53 "eom" "\0" 54 "erase" "\0" 55 "fsf" "\0" 56 "fsfm" "\0" 57 "fsr" "\0" 58 "fss" "\0" 59 "load" "\0" 60 "lock" "\0" 61 "mkpart" "\0" 62 "nop" "\0" 63 "offline" "\0" 64 "rewoffline" "\0" 65 "ras1" "\0" 66 "ras2" "\0" 67 "ras3" "\0" 68 "reset" "\0" 69 "retension" "\0" 70 "rewind" "\0" 71 "seek" "\0" 72 "setblk" "\0" 73 "setdensity" "\0" 74 "drvbuffer" "\0" 75 "setpart" "\0" 76 "tell" "\0" 77 "wset" "\0" 78 "unload" "\0" 79 "unlock" "\0" 80 "eof" "\0" 81 "weof" "\0"; 52 82 53 int mt_main(int argc, char **argv) ;54 int mt_main(int argc , char **argv)83 int mt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 84 int mt_main(int argc UNUSED_PARAM, char **argv) 55 85 { 56 86 const char *file = "/dev/tape"; 57 const struct mt_opcodes *code = opcodes;58 87 struct mtop op; 59 88 struct mtpos position; 60 int fd, mode ;89 int fd, mode, idx; 61 90 62 if ( argc < 2) {91 if (!argv[1]) { 63 92 bb_show_usage(); 64 93 } 65 94 66 95 if (strcmp(argv[1], "-f") == 0) { 67 if ( argc < 4) {96 if (!argv[2] || !argv[3]) 68 97 bb_show_usage(); 69 }70 98 file = argv[2]; 71 99 argv += 2; 72 argc -= 2;73 100 } 74 101 75 while (code->name != 0) { 76 if (strcmp(code->name, argv[1]) == 0) 77 break; 78 code++; 79 } 102 idx = index_in_strings(opcode_name, argv[1]); 80 103 81 if (code->name == 0) { 82 bb_error_msg("unrecognized opcode %s", argv[1]); 83 return EXIT_FAILURE; 84 } 104 if (idx < 0) 105 bb_error_msg_and_die("unrecognized opcode %s", argv[1]); 85 106 86 op.mt_op = code->value;87 if (arg c >= 3)88 op.mt_count = xatoi_ u(argv[2]);107 op.mt_op = opcode_value[idx]; 108 if (argv[2]) 109 op.mt_count = xatoi_positive(argv[2]); 89 110 else 90 op.mt_count = 1; 111 op.mt_count = 1; /* One, not zero, right? */ 91 112 92 switch ( code->value) {113 switch (opcode_value[idx]) { 93 114 case MTWEOF: 94 115 case MTERASE: … … 105 126 fd = xopen(file, mode); 106 127 107 switch ( code->value) {128 switch (opcode_value[idx]) { 108 129 case MTTELL: 109 130 ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file); 110 printf("At block %d .\n", (int) position.mt_blkno);131 printf("At block %d\n", (int) position.mt_blkno); 111 132 break; 112 133 -
branches/2.2.9/mindi-busybox/miscutils/raidautorun.c
r1765 r2725 3 3 * raidautorun implementation for busybox 4 4 * 5 * Copyright (C) 2006 Bernhard Fischer5 * Copyright (C) 2006 Bernhard Reutner-Fischer 6 6 * 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 * 9 9 */ … … 14 14 #include <linux/raid/md_u.h> 15 15 16 int raidautorun_main(int argc, char **argv) ;17 int raidautorun_main(int argc , char **argv)16 int raidautorun_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 17 int raidautorun_main(int argc UNUSED_PARAM, char **argv) 18 18 { 19 if (argc != 2) 20 bb_show_usage(); 21 22 xioctl(xopen(argv[1], O_RDONLY), RAID_AUTORUN, NULL); 23 19 xioctl(xopen(single_argv(argv), O_RDONLY), RAID_AUTORUN, NULL); 24 20 return EXIT_SUCCESS; 25 21 } -
branches/2.2.9/mindi-busybox/miscutils/readahead.c
r1765 r2725 8 8 * Copyright (C) 2006 Michael Opdenacker <michael@free-electrons.com> 9 9 * 10 * Licensed under GPLv2 or later, see file L icense in this tarball for details.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 11 */ 12 12 13 13 #include "libbb.h" 14 14 15 int readahead_main(int argc, char **argv) ;16 int readahead_main(int argc , char **argv)15 int readahead_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 16 int readahead_main(int argc UNUSED_PARAM, char **argv) 17 17 { 18 FILE *f;19 18 int retval = EXIT_SUCCESS; 20 19 21 if (argc == 1) bb_show_usage(); 20 if (!argv[1]) { 21 bb_show_usage(); 22 } 22 23 23 24 while (*++argv) { 24 if ((f = fopen_or_warn(*argv, "r")) != NULL) { 25 int r, fd=fileno(f); 25 int fd = open_or_warn(*argv, O_RDONLY); 26 if (fd >= 0) { 27 off_t len; 28 int r; 26 29 27 r = readahead(fd, 0, fdlength(fd)); 28 fclose(f); 29 if (r >= 0) continue; 30 /* fdlength was reported to be unreliable - use seek */ 31 len = xlseek(fd, 0, SEEK_END); 32 xlseek(fd, 0, SEEK_SET); 33 r = readahead(fd, 0, len); 34 close(fd); 35 if (r >= 0) 36 continue; 30 37 } 31 38 retval = EXIT_FAILURE; -
branches/2.2.9/mindi-busybox/miscutils/runlevel.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * runlevelPrints out the previous and the current runlevel.3 * Prints out the previous and the current runlevel. 4 4 * 5 * Version: 5 * Version: @(#)runlevel 1.20 16-Apr-1997 MvS 6 6 * 7 * 8 * 7 * This file is part of the sysvinit suite, 8 * Copyright 1991-1997 Miquel van Smoorenburg. 9 9 * 10 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 11 * 12 * initially busyboxified by Bernhard Fischer12 * initially busyboxified by Bernhard Reutner-Fischer 13 13 */ 14 #include "libbb.h" 15 #include <utmp.h> 14 16 15 #include <utmp.h> 16 #include "libbb.h" 17 18 int runlevel_main(int argc, char **argv); 19 int runlevel_main(int argc, char **argv) 17 int runlevel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 18 int runlevel_main(int argc UNUSED_PARAM, char **argv) 20 19 { 21 20 struct utmp *ut; 22 21 char prev; 23 22 24 if (arg c > 1) utmpname(argv[1]);23 if (argv[1]) utmpname(argv[1]); 25 24 26 25 setutent(); -
branches/2.2.9/mindi-busybox/miscutils/rx.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 /*------------------------------------------------------------------------- 3 * Filename: xmodem.c 2 /* 4 3 * Copyright: Copyright (C) 2001, Hewlett-Packard Company 5 4 * Author: Christopher Hoover <ch@hpl.hp.com> … … 7 6 * and the like 8 7 * Created at: Thu Dec 20 01:58:08 PST 2001 9 *-----------------------------------------------------------------------*/ 10 /* 11 * xmodem.c: xmodem functionality for uploading of kernels and 12 * the like 8 * 9 * xmodem functionality for uploading of kernels and the like 13 10 * 14 11 * Copyright (C) 2001 Hewlett-Packard Laboratories 15 12 * 16 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 17 14 * 18 15 * This was originally written for blob and then adapted for busybox. 19 *20 16 */ 21 17 … … 28 24 #define NAK 0x15 29 25 #define BS 0x08 26 #define PAD 0x1A 30 27 31 28 /* 32 33 29 Cf: 34 35 30 http://www.textfiles.com/apple/xmodem 36 31 http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt 37 32 http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt 38 33 http://www.phys.washington.edu/~belonis/xmodem/modmprot.col 39 40 34 */ 41 35 … … 44 38 #define MAXERRORS 10 45 39 46 static int read_byte(int fd, unsigned int timeout) 47 { 48 char buf[1]; 40 #define read_fd STDIN_FILENO 41 #define write_fd STDOUT_FILENO 42 43 static int read_byte(unsigned timeout) 44 { 45 unsigned char buf; 49 46 int n; 50 47 51 48 alarm(timeout); 52 53 n = read(fd, &buf, 1); 54 49 /* NOT safe_read! We want ALRM to interrupt us */ 50 n = read(read_fd, &buf, 1); 55 51 alarm(0); 56 57 52 if (n == 1) 58 return buf[0] & 0xff; 59 else 60 return -1; 61 } 62 63 static int receive(char *error_buf, size_t error_buf_size, 64 int ttyfd, int filefd) 65 { 66 char blockBuf[1024]; 67 unsigned int errors = 0; 68 unsigned int wantBlockNo = 1; 69 unsigned int length = 0; 70 int docrc = 1; 71 char nak = 'C'; 72 unsigned int timeout = TIMEOUT_LONG; 73 74 #define note_error(fmt,args...) \ 75 snprintf(error_buf, error_buf_size, fmt,##args) 53 return buf; 54 return -1; 55 } 56 57 static int receive(/*int read_fd, */int file_fd) 58 { 59 unsigned char blockBuf[1024]; 60 unsigned blockLength = 0; 61 unsigned errors = 0; 62 unsigned wantBlockNo = 1; 63 unsigned length = 0; 64 int do_crc = 1; 65 char reply_char; 66 unsigned timeout = TIMEOUT_LONG; 76 67 77 68 /* Flush pending input */ 78 tcflush( ttyfd, TCIFLUSH);69 tcflush(read_fd, TCIFLUSH); 79 70 80 71 /* Ask for CRC; if we get errors, we will go with checksum */ 81 write(ttyfd, &nak, 1); 72 reply_char = 'C'; 73 full_write(write_fd, &reply_char, 1); 82 74 83 75 for (;;) { 84 76 int blockBegin; 85 77 int blockNo, blockNoOnesCompl; 86 int blockLength; 87 int cksum = 0; 88 int crcHi = 0; 89 int crcLo = 0; 90 91 blockBegin = read_byte(ttyfd, timeout); 78 int cksum_or_crc; 79 int expected; 80 int i, j; 81 82 blockBegin = read_byte(timeout); 92 83 if (blockBegin < 0) 93 84 goto timeout; 94 85 86 /* If last block, remove padding */ 87 if (blockBegin == EOT) { 88 /* Data blocks can be padded with ^Z characters */ 89 /* This code tries to detect and remove them */ 90 if (blockLength >= 3 91 && blockBuf[blockLength - 1] == PAD 92 && blockBuf[blockLength - 2] == PAD 93 && blockBuf[blockLength - 3] == PAD 94 ) { 95 while (blockLength 96 && blockBuf[blockLength - 1] == PAD 97 ) { 98 blockLength--; 99 } 100 } 101 } 102 /* Write previously received block */ 103 if (blockLength) { 104 errno = 0; 105 if (full_write(file_fd, blockBuf, blockLength) != blockLength) { 106 bb_perror_msg("can't write to file"); 107 goto fatal; 108 } 109 } 110 95 111 timeout = TIMEOUT; 96 nak= NAK;112 reply_char = NAK; 97 113 98 114 switch (blockBegin) { … … 100 116 case STX: 101 117 break; 102 103 118 case EOT: 104 nak = ACK; 105 write(ttyfd, &nak, 1); 106 goto done; 107 119 reply_char = ACK; 120 full_write(write_fd, &reply_char, 1); 121 return length; 108 122 default: 109 123 goto error; 110 124 } 111 125 112 /* block no */113 blockNo = read_byte( ttyfd,TIMEOUT);126 /* Block no */ 127 blockNo = read_byte(TIMEOUT); 114 128 if (blockNo < 0) 115 129 goto timeout; 116 130 117 /* block no one's compliment*/118 blockNoOnesCompl = read_byte( ttyfd,TIMEOUT);131 /* Block no, in one's complement form */ 132 blockNoOnesCompl = read_byte(TIMEOUT); 119 133 if (blockNoOnesCompl < 0) 120 134 goto timeout; 121 135 122 136 if (blockNo != (255 - blockNoOnesCompl)) { 123 note_error("bad block ones compl");137 bb_error_msg("bad block ones compl"); 124 138 goto error; 125 139 } … … 127 141 blockLength = (blockBegin == SOH) ? 128 : 1024; 128 142 129 { 130 int i; 131 132 for (i = 0; i < blockLength; i++) { 133 int cc = read_byte(ttyfd, TIMEOUT); 134 if (cc < 0) 135 goto timeout; 136 blockBuf[i] = cc; 137 } 138 } 139 140 if (docrc) { 141 crcHi = read_byte(ttyfd, TIMEOUT); 142 if (crcHi < 0) 143 goto timeout; 144 145 crcLo = read_byte(ttyfd, TIMEOUT); 146 if (crcLo < 0) 143 for (i = 0; i < blockLength; i++) { 144 int cc = read_byte(TIMEOUT); 145 if (cc < 0) 146 goto timeout; 147 blockBuf[i] = cc; 148 } 149 150 if (do_crc) { 151 cksum_or_crc = read_byte(TIMEOUT); 152 if (cksum_or_crc < 0) 153 goto timeout; 154 cksum_or_crc = (cksum_or_crc << 8) | read_byte(TIMEOUT); 155 if (cksum_or_crc < 0) 147 156 goto timeout; 148 157 } else { 149 cksum = read_byte(ttyfd,TIMEOUT);150 if (cksum < 0)158 cksum_or_crc = read_byte(TIMEOUT); 159 if (cksum_or_crc < 0) 151 160 goto timeout; 152 161 } … … 157 166 /* meta data. */ 158 167 goto next; 159 } else if (blockNo != (wantBlockNo & 0xff)) { 160 note_error("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); 161 goto error; 162 } 163 164 if (docrc) { 165 int crc = 0; 166 int i, j; 167 int expectedCrcHi; 168 int expectedCrcLo; 169 168 } 169 if (blockNo != (wantBlockNo & 0xff)) { 170 bb_error_msg("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); 171 goto error; 172 } 173 174 expected = 0; 175 if (do_crc) { 170 176 for (i = 0; i < blockLength; i++) { 171 crc = crc ^ (int)blockBuf[i] << 8;172 for (j = 0; j < 8; j++) 173 if ( crc& 0x8000)174 crc = crc << 1^ 0x1021;177 expected = expected ^ blockBuf[i] << 8; 178 for (j = 0; j < 8; j++) { 179 if (expected & 0x8000) 180 expected = (expected << 1) ^ 0x1021; 175 181 else 176 crc = crc << 1; 177 } 178 179 expectedCrcHi = (crc >> 8) & 0xff; 180 expectedCrcLo = crc & 0xff; 181 182 if ((crcHi != expectedCrcHi) || 183 (crcLo != expectedCrcLo)) { 184 note_error("crc error, expected 0x%02x 0x%02x, got 0x%02x 0x%02x", expectedCrcHi, expectedCrcLo, crcHi, crcLo); 185 goto error; 186 } 182 expected = (expected << 1); 183 } 184 } 185 expected &= 0xffff; 187 186 } else { 188 unsigned char expectedCksum = 0;189 int i;190 191 187 for (i = 0; i < blockLength; i++) 192 expectedCksum += blockBuf[i]; 193 194 if (cksum != expectedCksum) { 195 note_error("checksum error, expected 0x%02x, got 0x%02x", expectedCksum, cksum); 196 goto error; 197 } 188 expected += blockBuf[i]; 189 expected &= 0xff; 190 } 191 if (cksum_or_crc != expected) { 192 bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x" 193 : "checksum error, expected 0x%02x, got 0x%02x", 194 expected, cksum_or_crc); 195 goto error; 198 196 } 199 197 200 198 wantBlockNo++; 201 199 length += blockLength; 202 203 if (full_write(filefd, blockBuf, blockLength) < 0) { 204 note_error("write to file failed: %m"); 205 goto fatal; 206 } 207 208 next: 200 next: 209 201 errors = 0; 210 nak= ACK;211 write(ttyfd, &nak, 1);202 reply_char = ACK; 203 full_write(write_fd, &reply_char, 1); 212 204 continue; 213 214 error: 215 timeout: 205 error: 206 timeout: 216 207 errors++; 217 208 if (errors == MAXERRORS) { 218 209 /* Abort */ 219 210 220 / / if using crc, try again w/o crc221 if ( nak== 'C') {222 nak= NAK;211 /* If were asking for crc, try again w/o crc */ 212 if (reply_char == 'C') { 213 reply_char = NAK; 223 214 errors = 0; 224 docrc = 0; 225 goto timeout; 226 } 227 228 note_error("too many errors; giving up"); 229 230 fatal: 231 /* 5 CAN followed by 5 BS */ 232 write(ttyfd, "\030\030\030\030\030\010\010\010\010\010", 10); 215 do_crc = 0; 216 goto timeout; 217 } 218 bb_error_msg("too many errors; giving up"); 219 fatal: 220 /* 5 CAN followed by 5 BS. Don't try too hard... */ 221 safe_write(write_fd, "\030\030\030\030\030\010\010\010\010\010", 10); 233 222 return -1; 234 223 } 235 224 236 225 /* Flush pending input */ 237 tcflush(ttyfd, TCIFLUSH); 238 239 write(ttyfd, &nak, 1); 226 tcflush(read_fd, TCIFLUSH); 227 228 full_write(write_fd, &reply_char, 1); 229 } /* for (;;) */ 230 } 231 232 static void sigalrm_handler(int UNUSED_PARAM signum) 233 { 234 } 235 236 int rx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 237 int rx_main(int argc UNUSED_PARAM, char **argv) 238 { 239 struct termios tty, orig_tty; 240 int termios_err; 241 int file_fd; 242 int n; 243 244 /* Disabled by vda: 245 * why we can't receive from stdin? Why we *require* 246 * controlling tty?? */ 247 /*read_fd = xopen(CURRENT_TTY, O_RDWR);*/ 248 file_fd = xopen(single_argv(argv), O_RDWR|O_CREAT|O_TRUNC); 249 250 termios_err = tcgetattr(read_fd, &tty); 251 if (termios_err == 0) { 252 orig_tty = tty; 253 cfmakeraw(&tty); 254 tcsetattr(read_fd, TCSAFLUSH, &tty); 240 255 } 241 256 242 done: 243 return length; 244 245 #undef note_error 246 } 247 248 static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) 249 { 250 } 251 252 int rx_main(int argc, char **argv); 253 int rx_main(int argc, char **argv) 254 { 255 char *fn; 256 int ttyfd, filefd; 257 struct termios tty, orig_tty; 258 struct sigaction act; 259 int n; 260 char error_buf[256]; 261 262 if (argc != 2) 263 bb_show_usage(); 264 265 fn = argv[1]; 266 ttyfd = xopen(CURRENT_TTY, O_RDWR); 267 filefd = xopen(fn, O_RDWR|O_CREAT|O_TRUNC); 268 269 if (tcgetattr(ttyfd, &tty) < 0) 270 bb_perror_msg_and_die("tcgetattr"); 271 272 orig_tty = tty; 273 274 cfmakeraw(&tty); 275 tcsetattr(ttyfd, TCSAFLUSH, &tty); 276 277 memset(&act, 0, sizeof(act)); 278 act.sa_handler = sigalrm_handler; 279 sigaction(SIGALRM, &act, 0); 280 281 n = receive(error_buf, sizeof(error_buf), ttyfd, filefd); 282 283 close(filefd); 284 285 tcsetattr(ttyfd, TCSAFLUSH, &orig_tty); 286 287 if (n < 0) 288 bb_error_msg_and_die("\nreceive failed:\n %s", error_buf); 289 290 fflush_stdout_and_exit(EXIT_SUCCESS); 291 } 257 /* No SA_RESTART: we want ALRM to interrupt read() */ 258 signal_no_SA_RESTART_empty_mask(SIGALRM, sigalrm_handler); 259 260 n = receive(file_fd); 261 262 if (termios_err == 0) 263 tcsetattr(read_fd, TCSAFLUSH, &orig_tty); 264 if (ENABLE_FEATURE_CLEAN_UP) 265 close(file_fd); 266 fflush_stdout_and_exit(n >= 0); 267 } -
branches/2.2.9/mindi-busybox/miscutils/setsid.c
r1765 r2725 5 5 * In the public domain. 6 6 * 7 * 1999-02-22 Arkadiusz Mi ¶kiewicz <misiek@pld.ORG.PL>7 * 1999-02-22 Arkadiusz Mickiewicz <misiek@pld.ORG.PL> 8 8 * - added Native Language Support 9 9 * … … 17 17 #include "libbb.h" 18 18 19 int setsid_main(int argc, char **argv) ;20 int setsid_main(int argc , char **argv)19 int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 20 int setsid_main(int argc UNUSED_PARAM, char **argv) 21 21 { 22 if ( argc < 2)22 if (!argv[1]) 23 23 bb_show_usage(); 24 24 25 /* Comment why is this necessary? */ 26 if (getpgrp() == getpid()) 27 forkexit_or_rexec(argv); 25 /* setsid() is allowed only when we are not a process group leader. 26 * Otherwise our PID serves as PGID of some existing process group 27 * and cannot be used as PGID of a new process group. */ 28 if (setsid() < 0) { 29 pid_t pid = fork_or_rexec(argv); 30 if (pid != 0) { 31 /* parent */ 32 /* TODO: 33 * we can waitpid(pid, &status, 0) and then even 34 * emulate exitcode, making the behavior consistent 35 * in both forked and non forked cases. 36 * However, the code is larger and upstream 37 * does not do such trick. 38 */ 39 exit(EXIT_SUCCESS); 40 } 28 41 29 setsid(); /* no error possible */ 42 /* child */ 43 /* now there should be no error: */ 44 setsid(); 45 } 30 46 31 BB_EXECVP(argv[1], argv + 1);32 bb_perror_msg_and_die("%s", argv[1]);47 argv++; 48 BB_EXECVP_or_die(argv); 33 49 } -
branches/2.2.9/mindi-busybox/miscutils/strings.c
r1765 r2725 3 3 * strings implementation for busybox 4 4 * 5 * Copyright Tito Ragusa <farmatito@tiscali.it>5 * Copyright 2003 Tito Ragusa <farmatito@tiscali.it> 6 6 * 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 */ 9 10 #include <getopt.h>11 9 12 10 #include "libbb.h" 13 11 14 #define WHOLE_FILE 15 #define PRINT_NAME 16 #define PRINT_OFFSET 17 #define SIZE 12 #define WHOLE_FILE 1 13 #define PRINT_NAME 2 14 #define PRINT_OFFSET 4 15 #define SIZE 8 18 16 19 int strings_main(int argc, char **argv) ;20 int strings_main(int argc , char **argv)17 int strings_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 18 int strings_main(int argc UNUSED_PARAM, char **argv) 21 19 { 22 20 int n, c, status = EXIT_SUCCESS; 23 unsigned opt;24 21 unsigned count; 25 22 off_t offset; 26 FILE *file = stdin;23 FILE *file; 27 24 char *string; 28 25 const char *fmt = "%s: "; 29 26 const char *n_arg = "4"; 30 27 31 opt =getopt32(argv, "afon:", &n_arg);28 getopt32(argv, "afon:", &n_arg); 32 29 /* -a is our default behaviour */ 33 30 /*argc -= optind;*/ … … 41 38 fmt = "{%s}: "; 42 39 *--argv = (char *)bb_msg_standard_input; 43 goto PIPE;44 40 } 45 41 46 42 do { 47 file = fopen_or_warn (*argv, "r");43 file = fopen_or_warn_stdin(*argv); 48 44 if (!file) { 49 45 status = EXIT_FAILURE; 50 46 continue; 51 47 } 52 PIPE:53 48 offset = 0; 54 49 count = 0; 55 50 do { 56 51 c = fgetc(file); 57 if (isprint (c) || c == '\t') {52 if (isprint_asciionly(c) || c == '\t') { 58 53 if (count > n) { 59 putchar(c);54 bb_putchar(c); 60 55 } else { 61 56 string[count] = c; 62 57 if (count == n) { 63 if (opt & PRINT_NAME) {58 if (option_mask32 & PRINT_NAME) { 64 59 printf(fmt, *argv); 65 60 } 66 if (opt & PRINT_OFFSET) {61 if (option_mask32 & PRINT_OFFSET) { 67 62 printf("%7"OFF_FMT"o ", offset - n); 68 63 } … … 73 68 } else { 74 69 if (count > n) { 75 putchar('\n');70 bb_putchar('\n'); 76 71 } 77 72 count = 0; -
branches/2.2.9/mindi-busybox/miscutils/taskset.c
r1765 r2725 2 2 /* 3 3 * taskset - retrieve or set a processes' CPU affinity 4 * Copyright (c) 2006 Bernhard Fischer4 * Copyright (c) 2006 Bernhard Reutner-Fischer 5 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 7 */ 8 8 9 9 #include <sched.h> 10 #include <getopt.h> /* optind */11 10 #include "libbb.h" 12 11 13 12 #if ENABLE_FEATURE_TASKSET_FANCY 14 13 #define TASKSET_PRINTF_MASK "%s" 15 #define from_cpuset(x) __from_cpuset(&x)16 14 /* craft a string from the mask */ 17 static char * __from_cpuset(cpu_set_t *mask)15 static char *from_cpuset(cpu_set_t *mask) 18 16 { 19 17 int i; 20 char *ret = 0, *str = xzalloc(9); 18 char *ret = NULL; 19 char *str = xzalloc((CPU_SETSIZE / 4) + 1); /* we will leak it */ 21 20 22 21 for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { 23 charval = 0;22 int val = 0; 24 23 int off; 25 24 for (off = 0; off <= 3; ++off) 26 if (CPU_ISSET(i+off, mask)) 27 val |= 1<<off; 28 25 if (CPU_ISSET(i + off, mask)) 26 val |= 1 << off; 29 27 if (!ret && val) 30 28 ret = str; 31 *str++ = (val-'0'<=9) ? (val+48) : (val+87);29 *str++ = bb_hexdigits_upcase[val] | 0x20; 32 30 } 33 31 return ret; 34 32 } 35 33 #else 36 #define TASKSET_PRINTF_MASK "%x" 37 /* (void*) cast is for battling gcc: */ 38 /* "dereferencing type-punned pointer will break strict-aliasing rules" */ 39 #define from_cpuset(mask) (*(unsigned*)(void*)&(mask)) 34 #define TASKSET_PRINTF_MASK "%llx" 35 static unsigned long long from_cpuset(cpu_set_t *mask) 36 { 37 struct BUG_CPU_SETSIZE_is_too_small { 38 char BUG_CPU_SETSIZE_is_too_small[ 39 CPU_SETSIZE < sizeof(int) ? -1 : 1]; 40 }; 41 char *p = (void*)mask; 42 43 /* Take the least significant bits. Careful! 44 * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases 45 */ 46 #if BB_BIG_ENDIAN 47 /* For big endian, it means LAST bits */ 48 if (CPU_SETSIZE < sizeof(long)) 49 p += CPU_SETSIZE - sizeof(int); 50 else if (CPU_SETSIZE < sizeof(long long)) 51 p += CPU_SETSIZE - sizeof(long); 52 else 53 p += CPU_SETSIZE - sizeof(long long); 54 #endif 55 if (CPU_SETSIZE < sizeof(long)) 56 return *(unsigned*)p; 57 if (CPU_SETSIZE < sizeof(long long)) 58 return *(unsigned long*)p; 59 return *(unsigned long long*)p; 60 } 40 61 #endif 41 62 42 #define OPT_p 143 63 44 int taskset_main(int argc, char ** argv);45 int taskset_main(int argc , char**argv)64 int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 65 int taskset_main(int argc UNUSED_PARAM, char **argv) 46 66 { 47 cpu_set_t mask , new_mask;67 cpu_set_t mask; 48 68 pid_t pid = 0; 49 unsigned opt; 50 const char *state = "current\0new"; 51 char *p_opt = NULL, *aff = NULL; 69 unsigned opt_p; 70 const char *current_new; 71 char *pid_str; 72 char *aff = aff; /* for compiler */ 52 73 53 opt = getopt32(argv, "+p:", &p_opt); 74 /* NB: we mimic util-linux's taskset: -p does not take 75 * an argument, i.e., "-pN" is NOT valid, only "-p N"! 76 * Indeed, util-linux-2.13-pre7 uses: 77 * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */ 54 78 55 if (opt & OPT_p) { 56 if (argc == optind+1) { /* -p <aff> <pid> */ 57 aff = p_opt; 58 p_opt = argv[optind]; 79 opt_complementary = "-1"; /* at least 1 arg */ 80 opt_p = getopt32(argv, "+p"); 81 argv += optind; 82 83 if (opt_p) { 84 pid_str = *argv++; 85 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */ 86 aff = pid_str; 87 pid_str = *argv; /* NB: *argv != NULL in this case */ 59 88 } 60 argv += optind; /* me -p <arg>*/61 pid = xatoul_range(p _opt, 1, ULONG_MAX); /* -p <pid> */62 } else 63 aff = * ++argv; /* <aff> <cmd...> */64 if (aff) {65 unsigned i = 0;66 unsigned long l = xstrtol_range(aff, 0, 1, LONG_MAX);89 /* else it was just "-p <pid>", and *argv == NULL */ 90 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); 91 } else { 92 aff = *argv++; /* <aff> <cmd...> */ 93 if (!*argv) 94 bb_show_usage(); 95 } 67 96 68 CPU_ZERO(&new_mask); 69 while (i < CPU_SETSIZE && l >= (1<<i)) { 70 if ((1<<i) & l) 71 CPU_SET(i, &new_mask); 72 ++i; 97 current_new = "current\0new"; 98 if (opt_p) { 99 print_aff: 100 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) 101 bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); 102 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 103 pid, current_new, from_cpuset(&mask)); 104 if (!*argv) { 105 /* Either it was just "-p <pid>", 106 * or it was "-p <aff> <pid>" and we came here 107 * for the second time (see goto below) */ 108 return EXIT_SUCCESS; 109 } 110 *argv = NULL; 111 current_new += 8; /* "new" */ 112 } 113 114 { /* Affinity was specified, translate it into cpu_set_t */ 115 unsigned i; 116 /* Do not allow zero mask: */ 117 unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); 118 enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 }; 119 120 CPU_ZERO(&mask); 121 for (i = 0; i < CNT_BIT; i++) { 122 unsigned long long bit = (1ULL << i); 123 if (bit & m) 124 CPU_SET(i, &mask); 73 125 } 74 126 } 75 127 76 if (opt & OPT_p) { 77 print_aff: 78 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) 79 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 'g', pid); 80 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 81 pid, state, from_cpuset(mask)); 82 if (!*argv) /* no new affinity given or we did print already, done. */ 83 return EXIT_SUCCESS; 84 } 128 /* Set pid's or our own (pid==0) affinity */ 129 if (sched_setaffinity(pid, sizeof(mask), &mask)) 130 bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid); 85 131 86 if (sched_setaffinity(pid, sizeof(new_mask), &new_mask)) 87 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 's', pid); 88 if (opt & OPT_p) { 89 state += 8; 90 ++argv; 91 goto print_aff; 92 } 93 ++argv; 94 BB_EXECVP(*argv, argv); 95 bb_perror_msg_and_die("%s", *argv); 132 if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */ 133 goto print_aff; /* print new affinity and exit */ 134 135 BB_EXECVP_or_die(argv); 96 136 } 97 #undef OPT_p98 #undef TASKSET_PRINTF_MASK99 #undef from_cpuset -
branches/2.2.9/mindi-busybox/miscutils/time.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 /* `time' utility to display resource usage of processes.2 /* 'time' utility to display resource usage of processes. 3 3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc. 4 4 5 Licensed under GPL version 2, see file LICENSE in this tarball for details.5 Licensed under GPLv2, see file LICENSE in this source tree. 6 6 */ 7 7 /* Originally written by David Keppel <pardo@cs.washington.edu>. … … 28 28 /* The output format for the -p option .*/ 29 29 static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; 30 31 30 32 31 /* Format string for printing all statistics verbosely. … … 57 56 "\tExit status: %x"; 58 57 59 60 58 /* Wait for and fill in data on child process PID. 61 59 Return 0 on error, 1 if ok. */ 62 63 60 /* pid_t is short on BSDI, so don't try to promote it. */ 64 static int resuse_end(pid_t pid, resource_t * resp) 65 { 66 int status; 61 static void resuse_end(pid_t pid, resource_t *resp) 62 { 67 63 pid_t caught; 68 64 69 65 /* Ignore signals, but don't ignore the children. When wait3 70 66 returns the child process, set the time the command finished. */ 71 while ((caught = wait3(&status, 0, &resp->ru)) != pid) { 72 if (caught == -1) 73 return 0; 67 while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) { 68 if (caught == -1 && errno != EINTR) { 69 bb_perror_msg("wait"); 70 return; 71 } 74 72 } 75 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms; 76 resp->waitstatus = status; 77 return 1; 78 } 79 80 /* Print ARGV, with each entry in ARGV separated by FILLER. */ 81 static void printargv(char *const *argv, const char *filler) 82 { 83 fputs(*argv, stdout); 84 while (*++argv) { 85 fputs(filler, stdout); 86 fputs(*argv, stdout); 87 } 73 resp->elapsed_ms = monotonic_ms() - resp->elapsed_ms; 74 } 75 76 static void printargv(char *const *argv) 77 { 78 const char *fmt = " %s" + 1; 79 do { 80 printf(fmt, *argv); 81 fmt = " %s"; 82 } while (*++argv); 88 83 } 89 84 … … 95 90 Note: Some machines express getrusage statistics in terms of K, 96 91 others in terms of pages. */ 97 98 static unsigned long ptok(unsigned long pages) 99 { 100 static unsigned long ps; 92 static unsigned long ptok(const unsigned pagesize, const unsigned long pages) 93 { 101 94 unsigned long tmp; 102 95 103 /* Initialization. */104 if (ps == 0)105 ps = getpagesize();106 107 96 /* Conversion. */ 108 if (pages > (LONG_MAX / p s)) {/* Could overflow. */109 tmp = pages / 1024; 110 return tmp * p s;/* then larger. */97 if (pages > (LONG_MAX / pagesize)) { /* Could overflow. */ 98 tmp = pages / 1024; /* Smaller first, */ 99 return tmp * pagesize; /* then larger. */ 111 100 } 112 101 /* Could underflow. */ 113 tmp = pages * p s;/* Larger first, */114 return tmp / 1024; 102 tmp = pages * pagesize; /* Larger first, */ 103 return tmp / 1024; /* then smaller. */ 115 104 } 116 105 … … 163 152 #endif 164 153 165 static void summarize(const char *fmt, char **command, resource_t * 154 static void summarize(const char *fmt, char **command, resource_t *resp) 166 155 { 167 156 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ 168 157 unsigned cpu_ticks; /* Same, in "CPU ticks" */ 169 158 unsigned pagesize = getpagesize(); 159 160 /* Impossible: we do not use WUNTRACED flag in wait()... 170 161 if (WIFSTOPPED(resp->waitstatus)) 171 162 printf("Command stopped by signal %u\n", 172 163 WSTOPSIG(resp->waitstatus)); 173 else if (WIFSIGNALED(resp->waitstatus)) 164 else */ 165 if (WIFSIGNALED(resp->waitstatus)) 174 166 printf("Command terminated by signal %u\n", 175 167 WTERMSIG(resp->waitstatus)); … … 182 174 183 175 #if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 184 /* 1000 is exactly divisible by TICKS_PER_SEC */176 /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */ 185 177 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); 186 178 #else … … 188 180 #endif 189 181 if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ 190 191 /* putchar() != putc(stdout) in glibc! */192 182 193 183 while (*fmt) { … … 206 196 * for everything. With this we do a lot of 1-byte writes */ 207 197 default: 208 putc(*fmt, stdout);198 bb_putchar(*fmt); 209 199 break; 210 200 #endif … … 216 206 /* and we do not take format str from user */ 217 207 default: 218 putc('%', stdout);208 bb_putchar('%'); 219 209 /*FALLTHROUGH*/ 220 210 case '%': 221 211 if (!*fmt) goto ret; 222 putc(*fmt, stdout);212 bb_putchar(*fmt); 223 213 break; 224 214 #endif 225 215 case 'C': /* The command that got timed. */ 226 printargv(command , " ");216 printargv(command); 227 217 break; 228 218 case 'D': /* Average unshared data size. */ 229 219 printf("%lu", 230 ptok((UL) resp->ru.ru_idrss) / cpu_ticks+231 ptok((UL) resp->ru.ru_isrss) / cpu_ticks);220 (ptok(pagesize, (UL) resp->ru.ru_idrss) + 221 ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); 232 222 break; 233 223 case 'E': { /* Elapsed real (wall clock) time. */ … … 253 243 case 'K': /* Average mem usage == data+stack+text. */ 254 244 printf("%lu", 255 ptok((UL) resp->ru.ru_idrss) / cpu_ticks+256 ptok((UL) resp->ru.ru_isrss) / cpu_ticks+257 ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);245 (ptok(pagesize, (UL) resp->ru.ru_idrss) + 246 ptok(pagesize, (UL) resp->ru.ru_isrss) + 247 ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks); 258 248 break; 259 249 case 'M': /* Maximum resident set size. */ 260 printf("%lu", ptok( (UL) resp->ru.ru_maxrss));250 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss)); 261 251 break; 262 252 case 'O': /* Outputs. */ … … 311 301 break; 312 302 case 'X': /* Average shared text size. */ 313 printf("%lu", ptok( (UL) resp->ru.ru_ixrss) / cpu_ticks);303 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks); 314 304 break; 315 305 case 'Z': /* Page size. */ 316 printf("%u", getpagesize());306 printf("%u", pagesize); 317 307 break; 318 308 case 'c': /* Involuntary context switches. */ … … 328 318 break; 329 319 case 'p': /* Average stack segment. */ 330 printf("%lu", ptok( (UL) resp->ru.ru_isrss) / cpu_ticks);320 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks); 331 321 break; 332 322 case 'r': /* Incoming socket messages received. */ … … 337 327 break; 338 328 case 't': /* Average resident set size. */ 339 printf("%lu", ptok( (UL) resp->ru.ru_idrss) / cpu_ticks);329 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks); 340 330 break; 341 331 case 'w': /* Voluntary context switches. */ … … 352 342 switch (*++fmt) { 353 343 default: 354 putc('\\', stdout);344 bb_putchar('\\'); 355 345 /*FALLTHROUGH*/ 356 346 case '\\': 357 347 if (!*fmt) goto ret; 358 putc(*fmt, stdout);348 bb_putchar(*fmt); 359 349 break; 360 350 case 't': 361 putc('\t', stdout);351 bb_putchar('\t'); 362 352 break; 363 353 case 'n': 364 putc('\n', stdout);354 bb_putchar('\n'); 365 355 break; 366 356 } … … 371 361 } 372 362 /* ret: */ 373 putc('\n', stdout);363 bb_putchar('\n'); 374 364 } 375 365 376 366 /* Run command CMD and return statistics on it. 377 367 Put the statistics in *RESP. */ 378 static void run_command(char *const *cmd, resource_t * resp) 379 { 380 pid_t pid; /* Pid of child. */ 381 __sighandler_t interrupt_signal, quit_signal; 382 383 resp->elapsed_ms = monotonic_us() / 1000; 384 pid = vfork(); /* Run CMD as child process. */ 385 if (pid < 0) 386 bb_error_msg_and_die("cannot fork"); 387 else if (pid == 0) { /* If child. */ 388 /* Don't cast execvp arguments; that causes errors on some systems, 389 versus merely warnings if the cast is left off. */ 390 BB_EXECVP(cmd[0], cmd); 391 bb_error_msg("cannot run %s", cmd[0]); 392 _exit(errno == ENOENT ? 127 : 126); 368 static void run_command(char *const *cmd, resource_t *resp) 369 { 370 pid_t pid; 371 void (*interrupt_signal)(int); 372 void (*quit_signal)(int); 373 374 resp->elapsed_ms = monotonic_ms(); 375 pid = xvfork(); 376 if (pid == 0) { 377 /* Child */ 378 BB_EXECVP_or_die((char**)cmd); 393 379 } 394 380 395 381 /* Have signals kill the child but not self (if possible). */ 382 //TODO: just block all sigs? and reenable them in the very end in main? 396 383 interrupt_signal = signal(SIGINT, SIG_IGN); 397 384 quit_signal = signal(SIGQUIT, SIG_IGN); 398 385 399 if (resuse_end(pid, resp) == 0) 400 bb_error_msg("error waiting for child process"); 386 resuse_end(pid, resp); 401 387 402 388 /* Re-enable signals. */ … … 405 391 } 406 392 407 int time_main(int argc, char **argv) ;408 int time_main(int argc , char **argv)393 int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 394 int time_main(int argc UNUSED_PARAM, char **argv) 409 395 { 410 396 resource_t res; 411 397 const char *output_format = default_format; 412 char c; 413 414 goto next; 415 /* Parse any options -- don't use getopt() here so we don't 416 * consume the args of our client application... */ 417 while (argc > 0 && argv[0][0] == '-') { 418 while ((c = *++*argv)) { 419 switch (c) { 420 case 'v': 421 output_format = long_format; 422 break; 423 case 'p': 424 output_format = posix_format; 425 break; 426 default: 427 bb_show_usage(); 428 } 429 } 430 next: 431 argv++; 432 argc--; 433 if (!argc) 434 bb_show_usage(); 435 } 398 int opt; 399 400 opt_complementary = "-1"; /* at least one arg */ 401 /* "+": stop on first non-option */ 402 opt = getopt32(argv, "+vp"); 403 argv += optind; 404 if (opt & 1) 405 output_format = long_format; 406 if (opt & 2) 407 output_format = posix_format; 436 408 437 409 run_command(argv, &res); 438 410 439 411 /* Cheat. printf's are shorter :) */ 440 stdout = stderr; 441 dup2(2, 1); /* just in case libc does something silly :( */ 412 xdup2(STDERR_FILENO, STDOUT_FILENO); 442 413 summarize(output_format, argv, &res); 443 414 … … 448 419 if (WIFEXITED(res.waitstatus)) 449 420 return WEXITSTATUS(res.waitstatus); 450 fflush_stdout_and_exit( 0);451 } 421 fflush_stdout_and_exit(EXIT_SUCCESS); 422 } -
branches/2.2.9/mindi-busybox/miscutils/ttysize.c
r1765 r2725 8 8 * Copyright (C) 2007 by Denys Vlasenko <vda.linux@googlemail.com> 9 9 * 10 * Licensed under the GPL v2, see the file LICENSE in this tarball.10 * Licensed under GPLv2, see file LICENSE in this source tree. 11 11 */ 12 12 #include "libbb.h" 13 13 14 int ttysize_main(int argc, char **argv) ;15 int ttysize_main(int argc , char **argv)14 int ttysize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 15 int ttysize_main(int argc UNUSED_PARAM, char **argv) 16 16 { 17 unsigned w, h;17 unsigned w, h; 18 18 struct winsize wsz; 19 19 … … 25 25 } 26 26 27 if ( argc == 1) {27 if (!argv[1]) { 28 28 printf("%u %u", w, h); 29 29 } else { … … 40 40 } 41 41 } 42 putchar('\n');42 bb_putchar('\n'); 43 43 return 0; 44 44 } -
branches/2.2.9/mindi-busybox/miscutils/watchdog.c
r1765 r2725 4 4 * 5 5 * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> 6 * Copyright (C) 2006 Bernhard Fischer <busybox@busybox.net> 6 * Copyright (C) 2006 Bernhard Reutner-Fischer <busybox@busybox.net> 7 * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com> 7 8 * 8 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 10 */ 10 11 11 12 #include "libbb.h" 13 #include "linux/types.h" /* for __u32 */ 14 #include "linux/watchdog.h" 12 15 13 #define OPT_FOREGROUND 0x01 14 #define OPT_TIMER 0x02 16 #define OPT_FOREGROUND (1 << 0) 17 #define OPT_STIMER (1 << 1) 18 #define OPT_HTIMER (1 << 2) 15 19 16 static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) ATTRIBUTE_NORETURN; 17 static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) 20 static void watchdog_shutdown(int sig UNUSED_PARAM) 18 21 { 19 write(3, "V", 1); /* Magic, see watchdog-api.txt in kernel */ 22 static const char V = 'V'; 23 24 write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ 20 25 if (ENABLE_FEATURE_CLEAN_UP) 21 26 close(3); 22 exit(0);27 _exit(EXIT_SUCCESS); 23 28 } 24 29 25 int watchdog_main(int argc, char **argv) ;30 int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 26 31 int watchdog_main(int argc, char **argv) 27 32 { 33 static const struct suffix_mult suffixes[] = { 34 { "ms", 1 }, 35 { "", 1000 }, 36 { "", 0 } 37 }; 38 28 39 unsigned opts; 29 unsigned timer_duration = 30; /* Userspace timer duration, in seconds */ 30 char *t_arg; 40 unsigned stimer_duration; /* how often to restart */ 41 unsigned htimer_duration = 60000; /* reboots after N ms if not restarted */ 42 char *st_arg; 43 char *ht_arg; 31 44 32 opt_complementary = "=1"; /* must have 1 argument */33 opts = getopt32(argv, "Ft: ", &t_arg);45 opt_complementary = "=1"; /* must have exactly 1 argument */ 46 opts = getopt32(argv, "Ft:T:", &st_arg, &ht_arg); 34 47 35 if (opts & OPT_TIMER) 36 timer_duration = xatou(t_arg); 48 /* We need to daemonize *before* opening the watchdog as many drivers 49 * will only allow one process at a time to do so. Since daemonizing 50 * is not perfect (child may run before parent finishes exiting), we 51 * can't rely on parent exiting before us (let alone *cleanly* releasing 52 * the watchdog fd -- something else that may not even be allowed). 53 */ 54 if (!(opts & OPT_FOREGROUND)) 55 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 37 56 38 if (!(opts & OPT_FOREGROUND)) { 39 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 40 } 57 if (opts & OPT_HTIMER) 58 htimer_duration = xatou_sfx(ht_arg, suffixes); 59 stimer_duration = htimer_duration / 2; 60 if (opts & OPT_STIMER) 61 stimer_duration = xatou_sfx(st_arg, suffixes); 41 62 42 signal(SIGHUP, watchdog_shutdown); 43 signal(SIGINT, watchdog_shutdown); 63 bb_signals(BB_FATAL_SIGS, watchdog_shutdown); 44 64 45 65 /* Use known fd # - avoid needing global 'int fd' */ 46 66 xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3); 47 67 68 /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */ 69 htimer_duration = htimer_duration / 1000; 70 #ifndef WDIOC_SETTIMEOUT 71 # error WDIOC_SETTIMEOUT is not defined, cannot compile watchdog applet 72 #else 73 # if defined WDIOC_SETOPTIONS && defined WDIOS_ENABLECARD 74 { 75 static const int enable = WDIOS_ENABLECARD; 76 ioctl_or_warn(3, WDIOC_SETOPTIONS, (void*) &enable); 77 } 78 # endif 79 ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration); 80 #endif 81 82 #if 0 83 ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration); 84 printf("watchdog: SW timer is %dms, HW timer is %ds\n", 85 stimer_duration, htimer_duration * 1000); 86 #endif 87 48 88 while (1) { 49 89 /* 50 * Make sure we clear the counter before sleeping, as the counter value51 * is undefined at this point -- PFM90 * Make sure we clear the counter before sleeping, 91 * as the counter value is undefined at this point -- PFM 52 92 */ 53 write(3, "", 1); 54 sleep(timer_duration);93 write(3, "", 1); /* write zero byte */ 94 usleep(stimer_duration * 1000L); 55 95 } 56 57 watchdog_shutdown(0); 58 /* return EXIT_SUCCESS; */ 96 return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */ 59 97 }
Note:
See TracChangeset
for help on using the changeset viewer.