Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/miscutils
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- Location:
- branches/stable/mindi-busybox/miscutils
- Files:
-
- 2 deleted
- 20 edited
- 6 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/miscutils/Config.in
r821 r1770 6 6 menu "Miscellaneous Utilities" 7 7 8 config CONFIG_ADJTIMEX8 config ADJTIMEX 9 9 bool "adjtimex" 10 10 default n … … 13 13 the Linux clock adjustment algorithm. 14 14 15 config CONFIG_BBCONFIG15 config BBCONFIG 16 16 bool "bbconfig" 17 17 default n … … 20 20 busybox was built. 21 21 22 config CONFIG_CROND 22 config CHRT 23 bool "chrt" 24 default n 25 help 26 manipulate real-time attributes of a process. 27 This requires sched_{g,s}etparam support in your libc. 28 29 config CROND 23 30 bool "crond" 24 31 default n 25 select CONFIG_FEATURE_SUID 32 select FEATURE_SUID 33 select FEATURE_SYSLOG 26 34 help 27 35 Crond is a background daemon that parses individual crontab … … 35 43 work properly. 36 44 37 config CONFIG_DEBUG_CROND_OPTION45 config DEBUG_CROND_OPTION 38 46 bool "Support debug option -d" 39 depends on C ONFIG_CROND47 depends on CROND 40 48 default n 41 49 help 42 50 Support option -d to enter debug mode. 43 51 44 config CONFIG_FEATURE_CROND_CALL_SENDMAIL52 config FEATURE_CROND_CALL_SENDMAIL 45 53 bool "Using /usr/sbin/sendmail?" 46 54 default n 47 depends on C ONFIG_CROND55 depends on CROND 48 56 help 49 57 Support calling /usr/sbin/sendmail for send cmd outputs. 50 58 51 config C ONFIG_CRONTAB59 config CRONTAB 52 60 bool "crontab" 53 61 default n 54 select CONFIG_FEATURE_SUID62 select FEATURE_SUID 55 63 help 56 64 Crontab manipulates the crontab for a particular user. Only 57 65 the superuser may specify a different user and/or crontab directory. 58 66 59 config CONFIG_DC67 config DC 60 68 bool "dc" 61 69 default n … … 64 72 precision arithmetic. 65 73 66 config CONFIG_DEVFSD74 config DEVFSD 67 75 bool "devfsd (obsolete)" 68 76 default n 69 help 70 This is deprecated, and will be going away in a future release. 77 select FEATURE_SYSLOG 78 help 79 This is deprecated, and will be removed at the end of 2008. 71 80 72 81 Provides compatibility with old device names on a devfs systems. … … 79 88 But only if they are written UPPERCASE!!!!!!!! 80 89 81 config CONFIG_DEVFSD_MODLOAD90 config DEVFSD_MODLOAD 82 91 bool "Adds support for MODLOAD keyword in devsfd.conf" 83 92 default n 84 depends on CONFIG_DEVFSD93 depends on DEVFSD 85 94 help 86 95 This actually doesn't work with busybox modutils but needs 87 96 the external modutils. 88 97 89 config CONFIG_DEVFSD_FG_NP98 config DEVFSD_FG_NP 90 99 bool "Enables the -fg and -np options" 91 100 default n 92 depends on CONFIG_DEVFSD101 depends on DEVFSD 93 102 help 94 103 -fg Run the daemon in the foreground. 95 104 -np Exit after parsing the configuration file. Do not poll for events. 96 105 97 config CONFIG_DEVFSD_VERBOSE106 config DEVFSD_VERBOSE 98 107 bool "Increases logging (and size)" 99 108 default n 100 depends on CONFIG_DEVFSD109 depends on DEVFSD 101 110 help 102 111 Increases logging to stderr or syslog. 103 112 104 config CONFIG_FEATURE_DEVFS113 config FEATURE_DEVFS 105 114 bool " Use devfs names for all devices (obsolete)" 106 115 default n 107 116 help 117 This is obsolete and will be going away at the end of 2008.. 118 108 119 This tells busybox to look for names like /dev/loop/0 instead of 109 120 /dev/loop0. If your /dev directory has normal names instead of 110 121 devfs names, you don't want this. 111 122 112 This is obsolete and will be going away someday. Consider it 113 deprecated. 114 115 config CONFIG_EJECT 123 config EJECT 116 124 bool "eject" 117 125 default n … … 119 127 Used to eject cdroms. (defaults to /dev/cdrom) 120 128 121 config CONFIG_LAST129 config LAST 122 130 bool "last" 123 131 default n 124 select CONFIG_FEATURE_WTMP132 select FEATURE_WTMP 125 133 help 126 134 'last' displays a list of the last users that logged into the system. 127 135 128 config CONFIG_LESS136 config LESS 129 137 bool "less" 130 138 default n … … 133 141 a wide array of features, and is an improvement over 'more'. 134 142 135 config CONFIG_FEATURE_LESS_BRACKETS 143 config FEATURE_LESS_MAXLINES 144 int "Max number of input lines less will try to eat" 145 default 9999999 146 depends on LESS 147 148 config FEATURE_LESS_BRACKETS 136 149 bool "Enable bracket searching" 137 150 default y 138 depends on CONFIG_LESS151 depends on LESS 139 152 help 140 153 This option adds the capability to search for matching left and right 141 154 brackets, facilitating programming. 142 155 143 config CONFIG_FEATURE_LESS_FLAGS156 config FEATURE_LESS_FLAGS 144 157 bool "Enable extra flags" 145 158 default y 146 depends on CONFIG_LESS159 depends on LESS 147 160 help 148 161 The extra flags provided do the following: … … 151 164 The -m flag enables a simpler status line with a percentage. 152 165 153 config CONFIG_FEATURE_LESS_FLAGCS166 config FEATURE_LESS_FLAGCS 154 167 bool "Enable flag changes" 155 168 default n 156 depends on CONFIG_LESS169 depends on LESS 157 170 help 158 171 This enables the ability to change command-line flags within 159 172 less itself. 160 173 161 config CONFIG_FEATURE_LESS_MARKS174 config FEATURE_LESS_MARKS 162 175 bool "Enable marks" 163 176 default n 164 depends on CONFIG_LESS177 depends on LESS 165 178 help 166 179 Marks enable positions in a file to be stored for easy reference. 167 180 168 config CONFIG_FEATURE_LESS_REGEXP181 config FEATURE_LESS_REGEXP 169 182 bool "Enable regular expressions" 170 183 default n 171 depends on CONFIG_LESS184 depends on LESS 172 185 help 173 186 Enable regular expressions, allowing complex file searches. 174 187 175 config CONFIG_HDPARM188 config HDPARM 176 189 bool "hdparm" 177 190 default n … … 179 192 Get/Set hard drive parameters. Primarily intended for ATA 180 193 drives. Adds about 13k (or around 30k if you enable the 181 CONFIG_FEATURE_HDPARM_GET_IDENTITY option)....182 183 config CONFIG_FEATURE_HDPARM_GET_IDENTITY194 FEATURE_HDPARM_GET_IDENTITY option).... 195 196 config FEATURE_HDPARM_GET_IDENTITY 184 197 bool "Support obtaining detailed information directly from drives" 185 198 default y 186 depends on CONFIG_HDPARM199 depends on HDPARM 187 200 help 188 201 Enables the -I and -i options to obtain detailed information … … 191 204 identify data from stdin. Enabling this option will add about 16k... 192 205 193 config CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF206 config FEATURE_HDPARM_HDIO_SCAN_HWIF 194 207 bool "Register an IDE interface (DANGEROUS)" 195 208 default n 196 depends on CONFIG_HDPARM209 depends on HDPARM 197 210 help 198 211 Enables the 'hdparm -R' option to register an IDE interface. 199 212 This is dangerous stuff, so you should probably say N. 200 213 201 config CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF214 config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 202 215 bool "Un-register an IDE interface (DANGEROUS)" 203 216 default n 204 depends on CONFIG_HDPARM217 depends on HDPARM 205 218 help 206 219 Enables the 'hdparm -U' option to un-register an IDE interface. 207 220 This is dangerous stuff, so you should probably say N. 208 221 209 config CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET222 config FEATURE_HDPARM_HDIO_DRIVE_RESET 210 223 bool "perform device reset (DANGEROUS)" 211 224 default n 212 depends on CONFIG_HDPARM225 depends on HDPARM 213 226 help 214 227 Enables the 'hdparm -w' option to perform a device reset. 215 228 This is dangerous stuff, so you should probably say N. 216 229 217 config CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF230 config FEATURE_HDPARM_HDIO_TRISTATE_HWIF 218 231 bool "tristate device for hotswap (DANGEROUS)" 219 232 default n 220 depends on CONFIG_HDPARM233 depends on HDPARM 221 234 help 222 235 Enables the 'hdparm -x' option to tristate device for hotswap, … … 224 237 stuff, so you should probably say N. 225 238 226 config CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA239 config FEATURE_HDPARM_HDIO_GETSET_DMA 227 240 bool "get/set using_dma flag (DANGEROUS)" 228 241 default n 229 depends on CONFIG_HDPARM242 depends on HDPARM 230 243 help 231 244 Enables the 'hdparm -d' option to get/set using_dma flag. 232 245 This is dangerous stuff, so you should probably say N. 233 246 234 config CONFIG_MAKEDEVS247 config MAKEDEVS 235 248 bool "makedevs" 236 249 default n … … 245 258 devices of a particluar type to be created per command. 246 259 e.g. /dev/hda[0-9] 247 260 Device properties are passed as command line arguments. 248 261 . 249 262 'table' reads device properties from a file or stdin, allowing 250 263 a batch of unrelated devices to be made with one command. 251 264 User/group names are allowed as an alternative to uid/gid. 252 265 253 266 choice 254 267 prompt "Choose makedevs behaviour" 255 depends CONFIG_MAKEDEVS256 default CONFIG_FEATURE_MAKEDEVS_TABLE257 258 config CONFIG_FEATURE_MAKEDEVS_LEAF259 260 261 config CONFIG_FEATURE_MAKEDEVS_TABLE268 depends on MAKEDEVS 269 default FEATURE_MAKEDEVS_TABLE 270 271 config FEATURE_MAKEDEVS_LEAF 272 bool "leaf" 273 274 config FEATURE_MAKEDEVS_TABLE 262 275 bool "table" 263 276 264 277 endchoice 265 278 266 config CONFIG_MOUNTPOINT279 config MOUNTPOINT 267 280 bool "mountpoint" 268 281 default n … … 270 283 mountpoint checks if the directory is a mountpoint. 271 284 272 config CONFIG_MT285 config MT 273 286 bool "mt" 274 287 default n … … 278 291 files on the tape. 279 292 280 config CONFIG_RUNLEVEL 281 bool "runlevel" 282 default n 283 help 284 find the current and previous system runlevel. 293 config RAIDAUTORUN 294 bool "raidautorun" 295 default n 296 help 297 raidautorun tells the kernel md driver to 298 search and start RAID arrays. 299 300 config READAHEAD 301 bool "readahead" 302 default n 303 depends on LFS 304 help 305 Preload the files listed on the command line into RAM cache so that 306 subsequent reads on these files will not block on disk I/O. 307 308 This applet just calls the readahead(2) system call on each file. 309 It is mainly useful in system startup scripts to preload files 310 or executables before they are used. When used at the right time 311 (in particular when a CPU boundprocess is running) it can 312 significantly speed up system startup. 313 314 As readahead(2) blocks until each file has been read, it is best to 315 run this applet as a background job. 316 317 config RUNLEVEL 318 bool "runlevel" 319 default n 320 help 321 find the current and previous system runlevel. 285 322 286 323 This applet uses utmp but does not rely on busybox supporing 287 324 utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc. 288 325 289 config CONFIG_RX290 291 default n 292 help 293 294 295 config CONFIG_STRINGS326 config RX 327 bool "rx" 328 default n 329 help 330 Receive files using the Xmodem protocol. 331 332 config STRINGS 296 333 bool "strings" 297 334 default n … … 300 337 specified. 301 338 302 config CONFIG_SETSID339 config SETSID 303 340 bool "setsid" 304 341 default n … … 306 343 setsid runs a program in a new session 307 344 308 config CONFIG_TASKSET345 config TASKSET 309 346 bool "taskset" 310 347 default n 311 348 help 312 Retrieve or set a processes's CPU affinity 313 314 config CONFIG_TASKSET 315 bool "taskset" 316 default n 317 help 318 Retrieve or set a processes's CPU affinity (on linux) 319 320 config CONFIG_TIME 349 Retrieve or set a processes's CPU affinity. 350 This requires sched_{g,s}etaffinity support in your libc. 351 352 config FEATURE_TASKSET_FANCY 353 bool "fancy output" 354 default y 355 depends on TASKSET 356 help 357 Add code for fancy output. This merely silences a compiler-warning 358 and adds about 135 Bytes. May be needed for machines with alot 359 of CPUs. 360 361 config TIME 321 362 bool "time" 322 363 default n … … 326 367 giving timing statistics about this program run. 327 368 328 config CONFIG_WATCHDOG 369 config TTYSIZE 370 bool "ttysize" 371 default n 372 help 373 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`. 376 377 config WATCHDOG 329 378 bool "watchdog" 330 379 default n -
branches/stable/mindi-busybox/miscutils/adjtimex.c
r821 r1770 12 12 */ 13 13 14 #include "busybox.h" 15 #include <stdio.h> 16 #include <sys/types.h> 17 #include <stdlib.h> 18 #include <unistd.h> 14 #include "libbb.h" 19 15 #include <sys/timex.h> 20 16 21 static const struct {int bit; const char *name;} statlist[] = { 17 static const struct { 18 int bit; 19 const char *name; 20 } statlist[] = { 22 21 { STA_PLL, "PLL" }, 23 22 { STA_PPSFREQ, "PPSFREQ" }, … … 33 32 { STA_PPSERROR, "PPSERROR" }, 34 33 { STA_CLOCKERR, "CLOCKERR" }, 35 { 0, NULL } }; 34 { 0, NULL } 35 }; 36 36 37 static const char * 37 static const char *const ret_code_descript[] = { 38 38 "clock synchronized", 39 39 "insert leap second", … … 41 41 "leap second in progress", 42 42 "leap second has occurred", 43 "clock not synchronized" }; 43 "clock not synchronized" 44 }; 44 45 46 int adjtimex_main(int argc, char **argv); 45 47 int adjtimex_main(int argc, char **argv) 46 48 { 49 enum { 50 OPT_quiet = 0x1 51 }; 52 unsigned opt; 53 char *opt_o, *opt_f, *opt_p, *opt_t; 47 54 struct timex txc; 48 int quiet=0; 49 int c, i, ret, sep; 55 int i, ret, sep; 50 56 const char *descript; 51 57 txc.modes=0; 52 for (;;) { 53 c = getopt( argc, argv, "qo:f:p:t:"); 54 if (c == EOF) break; 55 switch (c) { 56 case 'q': 57 quiet=1; 58 break; 59 case 'o': 60 txc.offset = atoi(optarg); 61 txc.modes |= ADJ_OFFSET_SINGLESHOT; 62 break; 63 case 'f': 64 txc.freq = atoi(optarg); 65 txc.modes |= ADJ_FREQUENCY; 66 break; 67 case 'p': 68 txc.constant = atoi(optarg); 69 txc.modes |= ADJ_TIMECONST; 70 break; 71 case 't': 72 txc.tick = atoi(optarg); 73 txc.modes |= ADJ_TICK; 74 break; 75 default: 76 bb_show_usage(); 77 exit(1); 78 } 58 59 opt = getopt32(argv, "qo:f:p:t:", 60 &opt_o, &opt_f, &opt_p, &opt_t); 61 //if (opt & 0x1) // -q 62 if (opt & 0x2) { // -o 63 txc.offset = xatol(opt_o); 64 txc.modes |= ADJ_OFFSET_SINGLESHOT; 65 } 66 if (opt & 0x4) { // -f 67 txc.freq = xatol(opt_f); 68 txc.modes |= ADJ_FREQUENCY; 69 } 70 if (opt & 0x8) { // -p 71 txc.constant = xatol(opt_p); 72 txc.modes |= ADJ_TIMECONST; 73 } 74 if (opt & 0x10) { // -t 75 txc.tick = xatol(opt_t); 76 txc.modes |= ADJ_TICK; 79 77 } 80 78 if (argc != optind) { /* no valid non-option parameters */ 81 79 bb_show_usage(); 82 exit(1);83 80 } 84 81 … … 87 84 if (ret < 0) perror("adjtimex"); 88 85 89 if (! quiet&& ret>=0) {86 if (!(opt & OPT_quiet) && ret>=0) { 90 87 printf( 91 88 " mode: %d\n" -
branches/stable/mindi-busybox/miscutils/bbconfig.c
r821 r1770 2 2 /* This file was released into the public domain by Paul Fox. 3 3 */ 4 #include " busybox.h"4 #include "libbb.h" 5 5 #include "bbconfigopts.h" 6 6 7 int bbconfig_main(int argc, char **argv); 7 8 int bbconfig_main(int argc, char **argv) 8 9 { -
branches/stable/mindi-busybox/miscutils/crond.c
r821 r1770 6 6 * 7 7 * Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com) 8 * (version 2.3.2) 8 9 * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002 9 10 * … … 11 12 */ 12 13 13 #define VERSION "2.3.2" 14 15 #include "busybox.h" 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <stdarg.h> 19 #include <string.h> 20 #include <errno.h> 21 #include <time.h> 22 #include <dirent.h> 23 #include <fcntl.h> 24 #include <unistd.h> 25 #include <syslog.h> 26 #include <signal.h> 27 #include <getopt.h> 28 #include <sys/ioctl.h> 29 #include <sys/wait.h> 30 #include <sys/stat.h> 31 #include <sys/resource.h> 32 33 #define arysize(ary) (sizeof(ary)/sizeof((ary)[0])) 14 #include <sys/syslog.h> 15 #include "libbb.h" 34 16 35 17 #ifndef CRONTABS … … 40 22 #endif 41 23 #ifndef SENDMAIL 42 #define SENDMAIL " /usr/sbin/sendmail"24 #define SENDMAIL "sendmail" 43 25 #endif 44 26 #ifndef SENDMAIL_ARGS … … 81 63 82 64 #if ENABLE_DEBUG_CROND_OPTION 83 static shortDebugOpt;84 #endif 85 86 static shortLogLevel = 8;65 static unsigned DebugOpt; 66 #endif 67 68 static unsigned LogLevel = 8; 87 69 static const char *LogFile; 88 70 static const char *CDir = CRONTABS; … … 130 112 vsyslog(type, fmt, va); 131 113 } else { 114 #if !ENABLE_DEBUG_CROND_OPTION 132 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 133 119 if (logfd >= 0) { 134 120 vdprintf(logfd, fmt, va); 135 121 close(logfd); 136 #if ENABLE_DEBUG_CROND_OPTION137 } else {138 bb_perror_msg("Can't open log file");139 #endif140 122 } 141 123 } … … 147 129 } 148 130 131 int crond_main(int ac, char **av); 149 132 int crond_main(int ac, char **av) 150 133 { 151 unsigned longopt;134 unsigned opt; 152 135 char *lopt, *Lopt, *copt; 153 154 #if ENABLE_DEBUG_CROND_OPTION 155 char *dopt; 156 157 bb_opt_complementally = "f-b:b-f:S-L:L-S:d-l"; 158 #else 159 bb_opt_complementally = "f-b:b-f:S-L:L-S"; 160 #endif 161 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"); 162 139 opterr = 0; /* disable getopt 'errors' message. */ 163 opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:" 164 #if ENABLE_DEBUG_CROND_OPTION 165 "d:" 166 #endif 167 , &lopt, &Lopt, &copt 168 #if ENABLE_DEBUG_CROND_OPTION 169 , &dopt 170 #endif 171 ); 172 if (opt & 1) { 173 LogLevel = atoi(lopt); 174 } 175 if (opt & 2) { 176 if (*Lopt != 0) { 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) 177 146 LogFile = Lopt; 178 } 179 } 180 if (opt & 32) { 181 if (*copt != 0) { 147 if (opt & 32) /* -c */ 148 if (*copt) 182 149 CDir = copt; 183 } 184 } 185 #if ENABLE_DEBUG_CROND_OPTION 186 if (opt & 64) { 187 DebugOpt = atoi(dopt); 150 #if ENABLE_DEBUG_CROND_OPTION 151 if (opt & 64) { /* -d */ 152 DebugOpt = xatou(dopt); 188 153 LogLevel = 0; 189 154 } 190 155 #endif 191 156 192 /* 193 * change directory 194 */ 195 196 bb_xchdir(CDir); 197 signal(SIGHUP, SIG_IGN); /* hmm.. but, if kill -HUP original 198 * version - his died. ;( 199 */ 200 /* 201 * close stdin and stdout, stderr. 157 /* close stdin and stdout, stderr. 202 158 * close unused descriptors - don't need. 203 159 * optional detach from controlling terminal 204 160 */ 205 206 if (!(opt & 4)) { 207 #ifdef BB_NOMMU 208 /* reexec for vfork() do continue parent */ 209 vfork_daemon_rexec(1, 0, ac, av, "-f"); 210 #else 211 bb_xdaemon(1, 0); 212 #endif 213 } 214 215 (void) startlogger(); /* need if syslog mode selected */ 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 */ 216 168 217 169 /* … … 219 171 * of 1 second. 220 172 */ 221 222 crondlog("\011%s " VERSION " dillon, started, log level %d\n", 223 bb_applet_name, LogLevel); 173 crondlog("\011%s " BB_VER " started, log level %d\n", 174 applet_name, LogLevel); 224 175 225 176 SynchronizeDir(); … … 232 183 short sleep_time = 60; 233 184 185 write_pidfile("/var/run/crond.pid"); 234 186 for (;;) { 235 187 sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time)); … … 280 232 } 281 233 } 282 bb_fflush_stdout_and_exit(EXIT_SUCCESS); /* not reached */234 return 0; /* not reached */ 283 235 } 284 236 … … 294 246 if (pas == 0) { 295 247 crondlog("\011failed to get uid for %s", user); 296 return (-1);248 return -1; 297 249 } 298 250 setenv("USER", pas->pw_name, 1); … … 306 258 if (err_msg) { 307 259 crondlog("\011%s for user %s", err_msg, user); 308 return (-1);260 return -1; 309 261 } 310 262 if (chdir(pas->pw_dir) < 0) { … … 312 264 if (chdir(TMPDIR) < 0) { 313 265 crondlog("\011chdir failed: %s: %m", TMPDIR); 314 return (-1);315 } 316 } 317 return (pas->pw_uid);266 return -1; 267 } 268 } 269 return pas->pw_uid; 318 270 } 319 271 … … 321 273 { 322 274 if (LogFile == 0) { 323 openlog( bb_applet_name, LOG_CONS | LOG_PID, LOG_CRON);275 openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); 324 276 } 325 277 #if ENABLE_DEBUG_CROND_OPTION … … 327 279 int logfd; 328 280 329 if ((logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600)) >= 0) { 281 logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600); 282 if (logfd >= 0) { 330 283 close(logfd); 331 } else { 332 bb_perror_msg("Failed to open log file '%s' reason", LogFile); 333 } 334 } 335 #endif 336 } 337 338 339 static const char *const DowAry[] = { 340 "sun", 341 "mon", 342 "tue", 343 "wed", 344 "thu", 345 "fri", 346 "sat", 347 348 "Sun", 349 "Mon", 350 "Tue", 351 "Wed", 352 "Thu", 353 "Fri", 354 "Sat", 355 NULL 356 }; 357 358 static const char *const MonAry[] = { 359 "jan", 360 "feb", 361 "mar", 362 "apr", 363 "may", 364 "jun", 365 "jul", 366 "aug", 367 "sep", 368 "oct", 369 "nov", 370 "dec", 371 372 "Jan", 373 "Feb", 374 "Mar", 375 "Apr", 376 "May", 377 "Jun", 378 "Jul", 379 "Aug", 380 "Sep", 381 "Oct", 382 "Nov", 383 "Dec", 384 NULL 385 }; 284 } 285 } 286 #endif 287 } 288 289 290 static const char DowAry[] ALIGN1 = 291 "sun""mon""tue""wed""thu""fri""sat" 292 /* "Sun""Mon""Tue""Wed""Thu""Fri""Sat" */ 293 ; 294 295 static const char MonAry[] ALIGN1 = 296 "jan""feb""mar""apr""may""jun""jul""aug""sep""oct""nov""dec" 297 /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */ 298 ; 386 299 387 300 static char *ParseField(char *user, char *ary, int modvalue, int off, 388 const char *const *names, char *ptr) 301 const char *names, char *ptr) 302 /* 'names' is a pointer to a set of 3-char abbreviations */ 389 303 { 390 304 char *base = ptr; … … 393 307 394 308 if (base == NULL) { 395 return (NULL);309 return NULL; 396 310 } 397 311 … … 416 330 int i; 417 331 418 for (i = 0; names[i]; ++i) { 419 if (strncmp(ptr, names[i], strlen(names[i])) == 0) { 332 for (i = 0; names[i]; i += 3) { 333 /* was using strncmp before... */ 334 if (strncasecmp(ptr, &names[i], 3) == 0) { 335 ptr += 3; 336 if (n1 < 0) { 337 n1 = i / 3; 338 } else { 339 n2 = i / 3; 340 } 341 skip = 1; 420 342 break; 421 343 } 422 }423 if (names[i]) {424 ptr += strlen(names[i]);425 if (n1 < 0) {426 n1 = i;427 } else {428 n2 = i;429 }430 skip = 1;431 344 } 432 345 } … … 436 349 if (skip == 0) { 437 350 crondlog("\111failed user %s parsing %s\n", user, base); 438 return (NULL);351 return NULL; 439 352 } 440 353 if (*ptr == '-' && n2 < 0) { … … 476 389 if (failsafe == 0) { 477 390 crondlog("\111failed user %s parsing %s\n", user, base); 478 return (NULL);391 return NULL; 479 392 } 480 393 } … … 489 402 if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') { 490 403 crondlog("\111failed user %s parsing %s\n", user, base); 491 return (NULL);404 return NULL; 492 405 } 493 406 … … 506 419 #endif 507 420 508 return (ptr);421 return ptr; 509 422 } 510 423 … … 515 428 int daysUsed = 0; 516 429 517 for (i = 0; i < (int)( arysize(line->cl_Dow)); ++i) {430 for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Dow)); ++i) { 518 431 if (line->cl_Dow[i] == 0) { 519 432 weekUsed = 1; … … 521 434 } 522 435 } 523 for (i = 0; i < (int)( arysize(line->cl_Days)); ++i) {436 for (i = 0; i < (int)(ARRAY_SIZE(line->cl_Days)); ++i) { 524 437 if (line->cl_Days[i] == 0) { 525 438 daysUsed = 1; … … 558 471 559 472 if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { 560 CronFile *file = calloc(1,sizeof(CronFile));473 CronFile *file = xzalloc(sizeof(CronFile)); 561 474 CronLine **pline; 562 475 … … 602 515 FixDayDow(&line); 603 516 604 *pline = calloc(1,sizeof(CronLine));517 *pline = xzalloc(sizeof(CronLine)); 605 518 **pline = line; 606 519 … … 670 583 remove(CRONUPDATE); 671 584 if (chdir(CDir) < 0) { 672 crondlog("\311 unable tofind %s\n", CDir);585 crondlog("\311cannot find %s\n", CDir); 673 586 } 674 587 { … … 689 602 closedir(dir); 690 603 } else { 691 crondlog("\311 Unable toopen current dir!\n");604 crondlog("\311cannot open current dir!\n"); 692 605 } 693 606 } … … 793 706 } 794 707 } 795 return (nJobs);708 return nJobs; 796 709 } 797 710 … … 859 772 nStillRunning += file->cf_Running; 860 773 } 861 return (nStillRunning);774 return nStillRunning; 862 775 } 863 776 … … 892 805 } 893 806 execl(prog, prog, cmd, arg, NULL); 894 crondlog("\024 unable toexec, user %s cmd %s %s %s\n", user, prog, cmd, arg);807 crondlog("\024cannot exec, user %s cmd %s %s %s\n", user, prog, cmd, arg); 895 808 if (mailf) { 896 809 fdprintf(1, "Exec failed: %s -c %s\n", prog, arg); … … 899 812 } else if (pid < 0) { 900 813 /* FORK FAILED */ 901 crondlog("\024c ouldn't fork, user %s\n", user);814 crondlog("\024cannot fork, user %s\n", user); 902 815 line->cl_Pid = 0; 903 816 if (mailf) { … … 940 853 fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, 941 854 line->cl_Shell); 942 line->cl_MailPos = lseek(mailFd, 0, 1);855 line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR); 943 856 } else { 944 crondlog("\024 unable tocreate mail file user %s file %s, output to /dev/null\n", user, mailFile);857 crondlog("\024cannot create mail file user %s file %s, output to /dev/null\n", user, mailFile); 945 858 } 946 859 … … 989 902 } 990 903 991 if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid || sbuf.st_nlink != 0 || 992 sbuf.st_size == line->cl_MailPos || !S_ISREG(sbuf.st_mode)) { 904 if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid 905 || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos 906 || !S_ISREG(sbuf.st_mode) 907 ) { 993 908 close(mailFd); 994 909 return; … … 1019 934 1020 935 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL); 1021 crondlog("\024 unable toexec, user %s cmd %s -c %s\n", user,936 crondlog("\024cannot exec, user %s cmd %s -c %s\n", user, 1022 937 DEFAULT_SHELL, line->cl_Shell); 1023 938 exit(0); 1024 939 } else if (pid < 0) { 1025 940 /* FORK FAILED */ 1026 crondlog("\024c ouldn't fork, user %s\n", user);941 crondlog("\024cannot, user %s\n", user); 1027 942 pid = 0; 1028 943 } -
branches/stable/mindi-busybox/miscutils/crontab.c
r821 r1770 11 11 */ 12 12 13 #include "busybox.h" 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <stdarg.h> 17 #include <string.h> 18 #include <errno.h> 19 #include <time.h> 20 #include <dirent.h> 21 #include <fcntl.h> 22 #include <unistd.h> 23 #include <syslog.h> 24 #include <signal.h> 25 #include <getopt.h> 26 #include <sys/ioctl.h> 27 #include <sys/wait.h> 28 #include <sys/stat.h> 29 #include <sys/resource.h> 13 #include "libbb.h" 30 14 31 15 #ifndef CRONTABS … … 39 23 #endif 40 24 #ifndef PATH_VI 41 #define PATH_VI "/bin/vi" /* location of vi 25 #define PATH_VI "/bin/vi" /* location of vi */ 42 26 #endif 43 27 44 static const char 28 static const char *CDir = CRONTABS; 45 29 46 30 static void EditFile(const char *user, const char *file); 47 31 static int GetReplaceStream(const char *user, const char *file); 48 static int 49 50 int 51 crontab_main(int ac, char **av)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) 52 36 { 53 enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE; 54 const struct passwd *pas; 55 const char *repFile = NULL; 56 int repFd = 0; 57 int i; 58 char caller[256]; /* user that ran program */ 59 int UserId; 60 61 UserId = getuid(); 62 if ((pas = getpwuid(UserId)) == NULL) 63 bb_perror_msg_and_die("getpwuid"); 64 65 safe_strncpy(caller, pas->pw_name, sizeof(caller)); 66 67 i = 1; 68 if (ac > 1) { 69 if (av[1][0] == '-' && av[1][1] == 0) { 70 option = REPLACE; 71 ++i; 72 } else if (av[1][0] != '-') { 73 option = REPLACE; 74 ++i; 75 repFile = av[1]; 76 } 77 } 78 79 for (; i < ac; ++i) { 80 char *ptr = av[i]; 81 82 if (*ptr != '-') 83 break; 84 ptr += 2; 85 86 switch(ptr[-1]) { 87 case 'l': 88 if (ptr[-1] == 'l') 89 option = LIST; 90 /* fall through */ 91 case 'e': 92 if (ptr[-1] == 'e') 93 option = EDIT; 94 /* fall through */ 95 case 'd': 96 if (ptr[-1] == 'd') 97 option = DELETE; 98 /* fall through */ 99 case 'u': 100 if (i + 1 < ac && av[i+1][0] != '-') { 101 ++i; 102 if (getuid() == geteuid()) { 103 pas = getpwnam(av[i]); 104 if (pas) { 105 UserId = pas->pw_uid; 106 } else { 107 bb_error_msg_and_die("user %s unknown", av[i]); 108 } 109 } else { 110 bb_error_msg_and_die("only the superuser may specify a user"); 111 } 112 } 113 break; 114 case 'c': 115 if (getuid() == geteuid()) { 116 CDir = (*ptr) ? ptr : av[++i]; 117 } else { 118 bb_error_msg_and_die("-c option: superuser only"); 119 } 120 break; 37 enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE; 38 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 != '-') 69 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: 121 207 default: 122 i = ac;123 break;124 }125 }126 if (i != ac || option == NONE)127 bb_show_usage();128 129 /*130 * Get password entry131 */132 133 if ((pas = getpwuid(UserId)) == NULL)134 bb_perror_msg_and_die("getpwuid");135 136 /*137 * If there is a replacement file, obtain a secure descriptor to it.138 */139 140 if (repFile) {141 repFd = GetReplaceStream(caller, repFile);142 if (repFd < 0)143 bb_error_msg_and_die("unable to read replacement file");144 }145 146 /*147 * Change directory to our crontab directory148 */149 150 bb_xchdir(CDir);151 152 /*153 * Handle options as appropriate154 */155 156 switch(option) {157 case LIST:158 {159 FILE *fi;160 char buf[1024];161 162 if ((fi = fopen(pas->pw_name, "r"))) {163 while (fgets(buf, sizeof(buf), fi) != NULL)164 fputs(buf, stdout);165 fclose(fi);166 } else {167 bb_error_msg("no crontab for %s", pas->pw_name);168 }169 }170 break;171 case EDIT:172 {173 FILE *fi;174 int fd;175 int n;176 char tmp[128];177 char buf[1024];178 179 snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid());180 fd = bb_xopen3(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600);181 chown(tmp, getuid(), getgid());182 if ((fi = fopen(pas->pw_name, "r"))) {183 while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)184 write(fd, buf, n);185 }186 EditFile(caller, tmp);187 remove(tmp);188 lseek(fd, 0L, 0);189 repFd = fd;190 }191 option = REPLACE;192 /* fall through */193 case REPLACE:194 {195 char buf[1024];196 char path[1024];197 int fd;198 int n;199 200 snprintf(path, sizeof(path), "%s.new", pas->pw_name);201 if ((fd = open(path, O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0600)) >= 0) {202 while ((n = read(repFd, buf, sizeof(buf))) > 0) {203 write(fd, buf, n);204 }205 close(fd);206 rename(path, pas->pw_name);207 } else {208 bb_error_msg("unable to create %s/%s", CDir, path);209 }210 close(repFd);211 }212 break;213 case DELETE:214 remove(pas->pw_name);215 break;216 case NONE:217 default:218 break;219 }220 221 /*222 * Bump notification file. Handle window where crond picks file up223 * before we can write our entry out.224 */225 226 if (option == REPLACE || option == DELETE) {227 FILE *fo;228 struct stat st;229 230 while ((fo = fopen(CRONUPDATE, "a"))) {231 fprintf(fo, "%s\n", pas->pw_name);232 fflush(fo);233 if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) {234 fclose(fo);235 208 break; 236 } 237 fclose(fo); 238 /* loop */ 239 } 240 if (fo == NULL) { 241 bb_error_msg("unable to append to %s/%s", CDir, CRONUPDATE); 242 } 243 } 244 return 0; 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 } 233 } 234 return 0; 245 235 } 246 236 247 static int 248 GetReplaceStream(const char *user, const char *file) 237 static int GetReplaceStream(const char *user, const char *file) 249 238 { 250 int filedes[2]; 251 int pid; 252 int fd; 253 int n; 254 char buf[1024]; 255 256 if (pipe(filedes) < 0) { 257 perror("pipe"); 258 return(-1); 259 } 260 if ((pid = fork()) < 0) { 261 perror("fork"); 262 return(-1); 263 } 264 if (pid > 0) { 265 /* 266 * PARENT 267 */ 268 269 close(filedes[1]); 270 if (read(filedes[0], buf, 1) != 1) { 271 close(filedes[0]); 272 filedes[0] = -1; 273 } 274 return(filedes[0]); 275 } 276 277 /* 278 * CHILD 279 */ 280 281 close(filedes[0]); 282 283 if (ChangeUser(user, 0) < 0) 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 * PARENT 257 */ 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 * CHILD 269 */ 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 } 284 283 exit(0); 285 286 bb_default_error_retval = 0;287 fd = bb_xopen3(file, O_RDONLY, 0);288 buf[0] = 0;289 write(filedes[1], buf, 1);290 while ((n = read(fd, buf, sizeof(buf))) > 0) {291 write(filedes[1], buf, n);292 }293 exit(0);294 284 } 295 285 296 static void 297 EditFile(const char *user, const char *file) 286 static void EditFile(const char *user, const char *file) 298 287 { 299 int pid; 300 301 if ((pid = fork()) == 0) { 302 /* 303 * CHILD - change user and run editor 304 */ 305 char *ptr; 306 char visual[1024]; 307 308 if (ChangeUser(user, 1) < 0) 309 exit(0); 310 if ((ptr = getenv("VISUAL")) == NULL || strlen(ptr) > 256) 311 ptr = PATH_VI; 312 313 snprintf(visual, sizeof(visual), "%s %s", ptr, file); 314 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", visual, NULL); 315 perror("exec"); 316 exit(0); 317 } 318 if (pid < 0) { 319 /* 320 * PARENT - failure 321 */ 322 bb_perror_msg_and_die("fork"); 323 } 324 wait4(pid, NULL, 0, NULL); 288 int pid = fork(); 289 290 if (pid == 0) { 291 /* 292 * CHILD - change user and run editor 293 */ 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 - failure 311 */ 312 bb_perror_msg_and_die("fork"); 313 } 314 wait4(pid, NULL, 0, NULL); 325 315 } 326 316 327 static int 328 ChangeUser(const char *user, short dochdir) 317 static int ChangeUser(const char *user, short dochdir) 329 318 { 330 331 332 333 334 335 336 if ((pas = getpwnam(user)) == NULL) { 337 bb_perror_msg_and_die("failed to get uid for %s", user);338 return(-1);339 340 341 342 343 344 345 346 347 348 349 350 if (chdir(pas->pw_dir) < 0) {351 bb_perror_msg("chdir failed: %s %s", user, pas->pw_dir);352 bb_xchdir(TMPDIR);353 }354 355 return(pas->pw_uid);319 struct passwd *pas; 320 321 /* 322 * Obtain password entry and change privileges 323 */ 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 question 335 */ 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; 356 345 } -
branches/stable/mindi-busybox/miscutils/dc.c
r821 r1770 1 1 /* vi: set sw=4 ts=4: */ 2 #include "busybox.h" 3 #include <ctype.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 4 */ 5 6 #include "libbb.h" 8 7 #include <math.h> 9 8 10 9 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ 11 10 12 static double stack[100]; 11 enum { STACK_SIZE = COMMON_BUFSIZE / sizeof(double) }; 12 13 #define stack ((double*)&bb_common_bufsiz1) 13 14 static unsigned int pointer; 14 15 static unsigned char base; … … 16 17 static void push(double a) 17 18 { 18 if (pointer >= (sizeof(stack) / sizeof(*stack)))19 if (pointer >= STACK_SIZE) 19 20 bb_error_msg_and_die("stack overflow"); 20 21 stack[pointer++] = a; … … 88 89 static void set_output_base(void) 89 90 { 90 base =(unsigned char)pop();91 base = (unsigned char)pop(); 91 92 if ((base != 10) && (base != 16)) { 92 fprintf(stderr, "Error: base = %d is not supported.\n", base);93 base =10;93 bb_error_msg("error, base %d is not supported", base); 94 base = 10; 94 95 } 95 96 } … … 100 101 printf("%x\n", (unsigned int)print); 101 102 else 102 printf("%g\n", print);103 printf("%g\n", print); 103 104 } 104 105 105 106 static void print_stack_no_pop(void) 106 107 { 107 unsigned int i =pointer;108 unsigned int i = pointer; 108 109 while (i) 109 110 print_base(stack[--i]); … … 116 117 117 118 struct op { 118 const char *name;119 const char name[4]; 119 120 void (*function) (void); 120 121 }; … … 142 143 {"f", print_stack_no_pop}, 143 144 {"o", set_output_base}, 144 { 0,0}145 {"", 0} 145 146 }; 146 147 … … 161 162 } 162 163 163 while (o->name != 0) {164 while (o->name[0]) { 164 165 if (strcmp(o->name, argument) == 0) { 165 (*(o->function))();166 o->function(); 166 167 return; 167 168 } 168 169 o++; 169 170 } 170 bb_error_msg_and_die("%s: syntax error .", argument);171 bb_error_msg_and_die("%s: syntax error", argument); 171 172 } 172 173 … … 176 177 static char *get_token(char **buffer) 177 178 { 178 char *start 179 char *current = *buffer;180 181 while (isspace(*current)) { current++; }179 char *start = NULL; 180 char *current; 181 182 current = skip_whitespace(*buffer); 182 183 if (*current != 0) { 183 184 start = current; 184 while (!isspace(*current) && *current != 0) { current++; }185 current = skip_non_whitespace(current); 185 186 *buffer = current; 186 187 } … … 197 198 } 198 199 200 int dc_main(int argc, char **argv); 199 201 int dc_main(int argc, char **argv) 200 202 { … … 205 207 char *cursor = NULL; 206 208 char *token = NULL; 207 while ((line = bb_get_chomped_line_from_file(stdin))) {209 while ((line = xmalloc_getline(stdin))) { 208 210 cursor = line; 209 211 len = number_of_tokens(line); … … 216 218 } 217 219 } else { 218 if (*argv[1] =='-')220 if (*argv[1] == '-') 219 221 bb_show_usage(); 220 222 while (argc >= 2) { -
branches/stable/mindi-busybox/miscutils/devfsd.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 4 */ 5 1 6 /* 2 7 devfsd implementation for busybox … … 50 55 */ 51 56 52 #include "busybox.h" 53 #include "xregex.h" 54 #include <unistd.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <stdarg.h> 58 #include <string.h> 59 #include <ctype.h> 60 #include <sys/stat.h> 61 #include <sys/types.h> 62 #include <sys/wait.h> 63 #include <sys/ioctl.h> 64 #include <sys/socket.h> 57 //#include <sys/wait.h> 58 //#include <sys/ioctl.h> 59 //#include <sys/socket.h> 65 60 #include <sys/un.h> 66 61 #include <dirent.h> 67 #include <fcntl.h>68 62 #include <syslog.h> 69 #include <signal.h>70 #include <errno.h>71 63 #include <sys/sysmacros.h> 64 #include "libbb.h" 65 #include "xregex.h" 72 66 73 67 … … 165 159 struct permissions_type 166 160 { 167 168 169 161 mode_t mode; 162 uid_t uid; 163 gid_t gid; 170 164 }; 171 165 172 166 struct execute_type 173 167 { 174 168 char *argv[MAX_ARGS + 1]; /* argv[0] must always be the programme */ 175 169 }; 176 170 177 171 struct copy_type 178 172 { 179 180 173 const char *source; 174 const char *destination; 181 175 }; 182 176 183 177 struct action_type 184 178 { 185 186 179 unsigned int what; 180 unsigned int when; 187 181 }; 188 182 189 183 struct config_entry_struct 190 184 { 191 192 193 194 185 struct action_type action; 186 regex_t preg; 187 union 188 { 195 189 struct permissions_type permissions; 196 190 struct execute_type execute; 197 191 struct copy_type copy; 198 199 200 192 } 193 u; 194 struct config_entry_struct *next; 201 195 }; 202 196 203 197 struct get_variable_info 204 198 { 205 206 207 199 const struct devfsd_notify_struct *info; 200 const char *devname; 201 char devpath[STRING_LENGTH]; 208 202 }; 209 203 210 static void dir_operation(int , const char * , int, unsigned long* 204 static void dir_operation(int , const char * , int, unsigned long*); 211 205 static void service(struct stat statbuf, char *path); 212 static int st_expr_expand(char *, unsigned, const char *, const char *(*) 206 static int st_expr_expand(char *, unsigned, const char *, const char *(*)(const char *, void *), void *); 213 207 static const char *get_old_name(const char *, unsigned, char *, unsigned, unsigned); 214 static int mksymlink 215 static void read_config_file 216 static void process_config_line 217 static int do_servicing 218 static void service_name 219 static void action_permissions 220 static void action_execute 208 static int mksymlink(const char *oldpath, const char *newpath); 209 static void read_config_file(char *path, int optional, unsigned long *event_mask); 210 static void process_config_line(const char *, unsigned long *); 211 static int do_servicing(int, unsigned long); 212 static void service_name(const struct devfsd_notify_struct *); 213 static void action_permissions(const struct devfsd_notify_struct *, const struct config_entry_struct *); 214 static void action_execute(const struct devfsd_notify_struct *, const struct config_entry_struct *, 221 215 const regmatch_t *, unsigned); 222 static void action_modload 223 static void action_copy 216 static void action_modload(const struct devfsd_notify_struct *info, const struct config_entry_struct *entry); 217 static void action_copy(const struct devfsd_notify_struct *, const struct config_entry_struct *, 224 218 const regmatch_t *, unsigned); 225 static void action_compat 226 static void free_config 219 static void action_compat(const struct devfsd_notify_struct *, unsigned); 220 static void free_config(void); 227 221 static void restore(char *spath, struct stat source_stat, int rootlen); 228 static int copy_inode 229 static mode_t get_mode 230 static void signal_handler 231 static const char *get_variable 232 static int make_dir_tree 222 static int copy_inode(const char *, const struct stat *, mode_t, const char *, const struct stat *); 223 static mode_t get_mode(const char *); 224 static void signal_handler(int); 225 static const char *get_variable(const char *, void *); 226 static int make_dir_tree(const char *); 233 227 static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *, 234 const char *, const regmatch_t *, unsigned 235 static void expand_regexp (char *, size_t, const char *, const char *, const regmatch_t *, unsigned);228 const char *, const regmatch_t *, unsigned); 229 static void expand_regexp(char *, size_t, const char *, const char *, const regmatch_t *, unsigned); 236 230 static const char *expand_variable( char *, unsigned, unsigned *, const char *, 237 const char *(*) (const char *, void *), void *);238 static const char *get_variable_v2(const char *, const char *(*) 239 static char get_old_ide_name 240 static char *write_old_sd_name (char *, unsigned, unsigned,char *);231 const char *(*)(const char *, void *), void *); 232 static const char *get_variable_v2(const char *, const char *(*)(const char *, void *), void *); 233 static char get_old_ide_name(unsigned , unsigned); 234 static char *write_old_sd_name(char *, unsigned, unsigned, const char *); 241 235 242 236 /* busybox functions */ 243 static void msg_logger(int pri, const char * fmt, ... )__attribute__ ((format (printf, 2, 3))); 244 static void msg_logger_and_die(int pri, const char * fmt, ... )__attribute__ ((noreturn, format (printf, 2, 3))); 245 static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag); 246 static void fork_and_execute(int die, char *arg0, char **arg ); 247 static int get_uid_gid ( int, const char *); 248 static void safe_memcpy( char * dest, const char * src, int len); 249 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr); 250 static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr); 237 static int get_uid_gid(int flag, const char *string); 238 static void safe_memcpy(char * dest, const char * src, int len); 239 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, const char *ptr); 240 static unsigned int scan_dev_name(const char *d, unsigned int n, const char *ptr); 251 241 252 242 /* Structs and vars */ 253 243 static struct config_entry_struct *first_config = NULL; 254 244 static struct config_entry_struct *last_config = NULL; 255 static c onst char *mount_point = NULL;245 static char *mount_point = NULL; 256 246 static volatile int caught_signal = FALSE; 257 247 static volatile int caught_sighup = FALSE; 258 static struct initial_symlink_struct 259 { 260 char *dest; 261 char *name; 262 } initial_symlinks[] = 263 { 264 {"/proc/self/fd", "fd"}, 265 {"fd/0", "stdin"}, 266 {"fd/1", "stdout"}, 267 {"fd/2", "stderr"}, 268 {NULL, NULL}, 248 static struct initial_symlink_struct { 249 const char *dest; 250 const char *name; 251 } initial_symlinks[] = { 252 {"/proc/self/fd", "fd"}, 253 {"fd/0", "stdin"}, 254 {"fd/1", "stdout"}, 255 {"fd/2", "stderr"}, 256 {NULL, NULL}, 269 257 }; 270 258 271 static struct event_type 272 { 273 unsigned int type; /* The DEVFSD_NOTIFY_* value */ 274 const char *config_name; /* The name used in the config file */ 275 } event_types[] = 276 { 277 {DEVFSD_NOTIFY_REGISTERED, "REGISTER"}, 278 {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER"}, 279 {DEVFSD_NOTIFY_ASYNC_OPEN, "ASYNC_OPEN"}, 280 {DEVFSD_NOTIFY_CLOSE, "CLOSE"}, 281 {DEVFSD_NOTIFY_LOOKUP, "LOOKUP"}, 282 {DEVFSD_NOTIFY_CHANGE, "CHANGE"}, 283 {DEVFSD_NOTIFY_CREATE, "CREATE"}, 284 {DEVFSD_NOTIFY_DELETE, "DELETE"}, 285 {0xffffffff, NULL} 259 static struct event_type { 260 unsigned int type; /* The DEVFSD_NOTIFY_* value */ 261 const char *config_name; /* The name used in the config file */ 262 } event_types[] = { 263 {DEVFSD_NOTIFY_REGISTERED, "REGISTER"}, 264 {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER"}, 265 {DEVFSD_NOTIFY_ASYNC_OPEN, "ASYNC_OPEN"}, 266 {DEVFSD_NOTIFY_CLOSE, "CLOSE"}, 267 {DEVFSD_NOTIFY_LOOKUP, "LOOKUP"}, 268 {DEVFSD_NOTIFY_CHANGE, "CHANGE"}, 269 {DEVFSD_NOTIFY_CREATE, "CREATE"}, 270 {DEVFSD_NOTIFY_DELETE, "DELETE"}, 271 {0xffffffff, NULL} 286 272 }; 287 273 288 274 /* Busybox messages */ 289 275 290 static const char * const bb_msg_proto_rev = "protocol revision"; 291 static const char * const bb_msg_bad_config = "bad %s config file: %s"; 292 static const char * const bb_msg_small_buffer = "buffer too small"; 293 static const char * const bb_msg_variable_not_found = "variable: %s not found"; 294 295 /* Busybox functions */ 296 static void msg_logger(int pri, const char * fmt, ... ) 297 { 298 va_list ap; 299 int ret; 300 301 va_start(ap, fmt); 302 ret = access ("/dev/log", F_OK); 303 if (ret == 0) { 304 openlog(bb_applet_name, 0, LOG_DAEMON); 305 vsyslog( pri , fmt, ap); 306 /* Man: A trailing newline is added when needed. */ 307 closelog(); 308 } 309 /* ENABLE_DEVFSD_VERBOSE is always enabled if msg_logger is used */ 310 if ((ENABLE_DEVFSD_VERBOSE && ret) || ENABLE_DEBUG) { 311 bb_error_msg(fmt, ap); 312 } 313 va_end(ap); 314 } 315 316 static void msg_logger_and_die(int pri, const char* fmt, ...) 317 { 318 va_list ap; 319 320 va_start(ap, fmt); 321 msg_logger(pri, fmt, ap); 322 va_end(ap); 323 exit(EXIT_FAILURE); 324 } 276 static const char bb_msg_proto_rev[] ALIGN1 = "protocol revision"; 277 static const char bb_msg_bad_config[] ALIGN1 = "bad %s config file: %s"; 278 static const char bb_msg_small_buffer[] ALIGN1 = "buffer too small"; 279 static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; 325 280 326 281 /* Busybox stuff */ 327 #if defined(CONFIG_DEVFSD_VERBOSE) || defined(CONFIG_DEBUG)328 #define devfsd_error_msg(fmt, args...) bb_error_msg(fmt, ## args)329 #define devfsd_perror_msg_and_die(fmt, args...) bb_perror_msg_and_die(fmt, ## args)330 #define devfsd_error_msg_and_die(fmt, args...)bb_error_msg_and_die(fmt, ## args)331 # if defined(CONFIG_DEBUG)332 #define debug_msg_logger(x, fmt, args...) msg_logger(x,fmt, ## args)282 #if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG 283 #define info_logger(p, fmt, args...) bb_info_msg(fmt, ## args) 284 #define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args) 285 #define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args) 286 #define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args) 287 #define error_logger_and_die(p, fmt, args...) bb_perror_msg_and_die(fmt, ## args) 333 288 #else 334 #define debug_msg_logger(x, fmt, args...) 335 #endif 336 #else 337 #define debug_msg_logger(x, fmt, args...) 289 #define info_logger(p, fmt, args...) 338 290 #define msg_logger(p, fmt, args...) 339 291 #define msg_logger_and_die(p, fmt, args...) exit(1) 340 #define devfsd_perror_msg_and_die(fmt, args...) exit(1) 341 #define devfsd_error_msg_and_die(fmt, args...) exit(1) 342 #define devfsd_error_msg(fmt, args...) 292 #define error_logger(p, fmt, args...) 293 #define error_logger_and_die(p, fmt, args...) exit(1) 343 294 #endif 344 295 345 static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag) 346 { 347 if (ioctl (fd, request, event_mask_flag) == -1) 348 msg_logger_and_die(LOG_ERR, "ioctl"); 349 } 350 351 static void fork_and_execute(int die, char *arg0, char **arg ) 352 { 353 switch ( fork () ) 354 { 355 case 0: 356 /* Child */ 357 break; 358 case -1: 359 /* Parent: Error : die or return */ 360 msg_logger(LOG_ERR,(char *) bb_msg_memory_exhausted); 361 if(die) 362 exit(EXIT_FAILURE); 363 return; 364 default: 365 /* Parent : ok : return or exit */ 366 if(arg0 != NULL) 367 { 368 wait (NULL); 369 return; 370 } 371 exit (EXIT_SUCCESS); 372 } 373 /* Child : if arg0 != NULL do execvp */ 374 if(arg0 != NULL ) 375 { 376 execvp (arg0, arg); 377 msg_logger_and_die(LOG_ERR, "execvp"); 378 } 379 } 380 381 static void safe_memcpy( char *dest, const char *src, int len) 382 { 383 memcpy (dest , src , len ); 296 static void safe_memcpy(char *dest, const char *src, int len) 297 { 298 memcpy(dest , src, len); 384 299 dest[len] = '\0'; 385 300 } 386 301 387 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr) 388 { 389 if( d[n - 4]=='d' && d[n - 3]=='i' && d[n - 2]=='s' && d[n - 1]=='c') 390 return (2 + addendum); 391 else if( d[n - 2]=='c' && d[n - 1]=='d') 392 return (3 + addendum); 393 else if(ptr[0]=='p' && ptr[1]=='a' && ptr[2]=='r' && ptr[3]=='t') 394 return (4 + addendum); 395 else if( ptr[n - 2]=='m' && ptr[n - 1]=='t') 396 return (5 + addendum); 397 else 398 return 0; 302 static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, const char *ptr) 303 { 304 if (d[n - 4] == 'd' && d[n - 3] == 'i' && d[n - 2] == 's' && d[n - 1] == 'c') 305 return 2 + addendum; 306 if (d[n - 2] == 'c' && d[n - 1] == 'd') 307 return 3 + addendum; 308 if (ptr[0] == 'p' && ptr[1] == 'a' && ptr[2] == 'r' && ptr[3] == 't') 309 return 4 + addendum; 310 if (ptr[n - 2] == 'm' && ptr[n - 1] == 't') 311 return 5 + addendum; 312 return 0; 399 313 } 400 314 401 static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr) 402 { 403 if(d[0]=='s' && d[1]=='c' && d[2]=='s' && d[3]=='i' && d[4]=='/') 404 { 405 if( d[n - 7]=='g' && d[n - 6]=='e' && d[n - 5]=='n' && 406 d[n - 4]=='e' && d[n - 3]=='r' && d[n - 2]=='i' && 407 d[n - 1]=='c' ) 315 static unsigned int scan_dev_name(const char *d, unsigned int n, const char *ptr) 316 { 317 if (d[0] == 's' && d[1] == 'c' && d[2] == 's' && d[3] == 'i' && d[4] == '/') { 318 if (d[n - 7] == 'g' && d[n - 6] == 'e' && d[n - 5] == 'n' 319 && d[n - 4] == 'e' && d[n - 3] == 'r' && d[n - 2] == 'i' && d[n - 1] == 'c' 320 ) 408 321 return 1; 409 322 return scan_dev_name_common(d, n, 0, ptr); 410 323 } 411 else if(d[0]=='i' && d[1]=='d' && d[2]=='e' && d[3]=='/' &&412 d[4]=='h' && d[5]=='o' && d[6]=='s' && d[7]=='t')413 {324 if (d[0] == 'i' && d[1] == 'd' && d[2] == 'e' && d[3] == '/' 325 && d[4] == 'h' && d[5] == 'o' && d[6] == 's' && d[7] == 't' 326 ) 414 327 return scan_dev_name_common(d, n, 4, ptr); 415 } 416 else if(d[0]=='s' && d[1]=='b' && d[2]=='p' && d[3]=='/') 417 { 328 if (d[0] == 's' && d[1] == 'b' && d[2] == 'p' && d[3] == '/') 418 329 return 10; 419 } 420 else if(d[0]=='v' && d[1]=='c' && d[2]=='c' && d[3]=='/') 421 { 330 if (d[0] == 'v' && d[1] == 'c' && d[2] == 'c' && d[3] == '/') 422 331 return 11; 423 } 424 else if(d[0]=='p' && d[1]=='t' && d[2]=='y' && d[3]=='/') 425 { 332 if (d[0] == 'p' && d[1] == 't' && d[2] == 'y' && d[3] == '/') 426 333 return 12; 427 }428 334 return 0; 429 335 } … … 431 337 /* Public functions follow */ 432 338 433 int devfsd_main (int argc, char **argv) 339 int devfsd_main(int argc, char **argv); 340 int devfsd_main(int argc, char **argv) 434 341 { 435 342 int print_version = FALSE; … … 445 352 bb_show_usage(); 446 353 447 for (count = 2; count < argc; ++count) 448 { 449 if(argv[count][0] == '-') 450 { 451 if(argv[count][1]=='v' && !argv[count][2]) /* -v */ 452 print_version = TRUE; 453 else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='f' 454 && argv[count][2]=='g' && !argv[count][3]) /* -fg */ 455 do_daemon = FALSE; 456 else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='n' 457 && argv[count][2]=='p' && !argv[count][3]) /* -np */ 458 no_polling = TRUE; 354 for (count = 2; count < argc; ++count) { 355 if (argv[count][0] == '-') { 356 if (argv[count][1] == 'v' && !argv[count][2]) /* -v */ 357 print_version = TRUE; 358 else if (ENABLE_DEVFSD_FG_NP && argv[count][1] == 'f' 359 && argv[count][2] == 'g' && !argv[count][3]) /* -fg */ 360 do_daemon = FALSE; 361 else if (ENABLE_DEVFSD_FG_NP && argv[count][1] == 'n' 362 && argv[count][2] == 'p' && !argv[count][3]) /* -np */ 363 no_polling = TRUE; 459 364 else 460 365 bb_show_usage(); … … 462 367 } 463 368 464 /* strip last / from mount point, so we don't need to check for it later */ 465 while( argv[1][1]!='\0' && argv[1][strlen(argv[1])-1] == '/' ) 466 argv[1][strlen(argv[1]) -1] = '\0'; 467 468 mount_point = argv[1]; 469 470 if (chdir (mount_point) != 0) 471 devfsd_perror_msg_and_die(mount_point); 472 473 fd = bb_xopen (".devfsd", O_RDONLY); 474 475 if (fcntl (fd, F_SETFD, FD_CLOEXEC) != 0) 476 devfsd_perror_msg_and_die("FD_CLOEXEC"); 477 478 if (ioctl (fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev) == -1) 479 msg_logger_and_die(LOG_ERR, "ioctl"); 369 mount_point = bb_simplify_path(argv[1]); 370 371 xchdir(mount_point); 372 373 fd = xopen(".devfsd", O_RDONLY); 374 375 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) 376 bb_perror_msg_and_die("FD_CLOEXEC"); 377 378 xioctl(fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev); 480 379 481 380 /*setup initial entries */ 482 483 symlink 381 for (curr = initial_symlinks; curr->dest != NULL; ++curr) 382 symlink(curr->dest, curr->name); 484 383 485 384 /* NB: The check for CONFIG_FILE is done in read_config_file() */ 486 385 487 if ( print_version || (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) ) 488 { 489 bb_printf( "%s v%s\nDaemon %s:\t%d\nKernel-side %s:\t%d\n", 490 bb_applet_name,DEVFSD_VERSION,bb_msg_proto_rev, 491 DEVFSD_PROTOCOL_REVISION_DAEMON,bb_msg_proto_rev, proto_rev); 386 if (print_version || (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev)) { 387 printf("%s v%s\nDaemon %s:\t%d\nKernel-side %s:\t%d\n", 388 applet_name, DEVFSD_VERSION, bb_msg_proto_rev, 389 DEVFSD_PROTOCOL_REVISION_DAEMON, bb_msg_proto_rev, proto_rev); 492 390 if (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) 493 bb_error_msg_and_die( "%s mismatch!",bb_msg_proto_rev);391 bb_error_msg_and_die("%s mismatch!", bb_msg_proto_rev); 494 392 exit(EXIT_SUCCESS); /* -v */ 495 393 } 496 /* Tell kernel we are special 497 do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, 0);498 499 sigemptyset 394 /* Tell kernel we are special(i.e. we get to see hidden entries) */ 395 xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); 396 397 sigemptyset(&new_action.sa_mask); 500 398 new_action.sa_flags = 0; 501 399 502 400 /* Set up SIGHUP and SIGUSR1 handlers */ 503 401 new_action.sa_handler = signal_handler; 504 if (sigaction (SIGHUP, &new_action, NULL) != 0 || sigaction (SIGUSR1, &new_action, NULL) != 0)505 devfsd_error_msg_and_die("sigaction");506 507 bb_printf("%s v%s started for %s\n",bb_applet_name, DEVFSD_VERSION, mount_point);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); 508 406 509 407 /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ 510 umask 511 read_config_file (CONFIG_FILE, FALSE, &event_mask);408 umask(0); 409 read_config_file((char*)CONFIG_FILE, FALSE, &event_mask); 512 410 /* Do the scan before forking, so that boot scripts see the finished product */ 513 dir_operation(SERVICE, mount_point,0,NULL);411 dir_operation(SERVICE, mount_point, 0, NULL); 514 412 515 413 if (ENABLE_DEVFSD_FG_NP && no_polling) 516 exit (0); 517 if (do_daemon) 518 { 414 exit(0); 415 416 if (ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG) 417 logmode = LOGMODE_BOTH; 418 else if (do_daemon == TRUE) 419 logmode = LOGMODE_SYSLOG; 420 /* This is the default */ 421 /*else 422 logmode = LOGMODE_STDIO; */ 423 424 if (do_daemon) { 519 425 /* Release so that the child can grab it */ 520 do_ioctl_and_die(fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0); 521 fork_and_execute(DIE, NULL, NULL); 522 setsid (); /* Prevent hangups and become pgrp leader */ 523 } else if(ENABLE_DEVFSD_FG_NP) { 524 setpgid (0, 0); /* Become process group leader */ 525 } 526 527 while (TRUE) 528 { 529 do_scan = do_servicing (fd, event_mask); 530 531 free_config (); 532 read_config_file (CONFIG_FILE, FALSE, &event_mask); 426 xioctl(fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0); 427 bb_daemonize_or_rexec(0, argv); 428 } else if (ENABLE_DEVFSD_FG_NP) { 429 setpgid(0, 0); /* Become process group leader */ 430 } 431 432 while (TRUE) { 433 do_scan = do_servicing(fd, event_mask); 434 435 free_config(); 436 read_config_file((char*)CONFIG_FILE, FALSE, &event_mask); 533 437 if (do_scan) 534 dir_operation(SERVICE,mount_point,0,NULL); 535 } 438 dir_operation(SERVICE, mount_point, 0, NULL); 439 } 440 if (ENABLE_FEATURE_CLEAN_UP) free(mount_point); 536 441 } /* End Function main */ 537 442 … … 539 444 /* Private functions follow */ 540 445 541 static void read_config_file 446 static void read_config_file(char *path, int optional, unsigned long *event_mask) 542 447 /* [SUMMARY] Read a configuration database. 543 448 <path> The path to read the database from. If this is a directory, all 544 entries in that directory will be read 449 entries in that directory will be read(except hidden entries). 545 450 <optional> If TRUE, the routine will silently ignore a missing config file. 546 451 <event_mask> The event mask is written here. This is not initialised. … … 551 456 FILE *fp; 552 457 char buf[STRING_LENGTH]; 553 char *line=NULL; 554 555 debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, path); 556 557 if (stat (path, &statbuf) == 0 ) 558 { 458 char *line = NULL; 459 char *p; 460 461 if (stat(path, &statbuf) == 0) { 559 462 /* Don't read 0 length files: ignored */ 560 /*if ( statbuf.st_size == 0)463 /*if (statbuf.st_size == 0) 561 464 return;*/ 562 if ( S_ISDIR (statbuf.st_mode) ) 563 { 564 /* strip last / from dirname so we don't need to check for it later */ 565 while( path && path[1]!='\0' && path[strlen(path)-1] == '/') 566 path[strlen(path) -1] = '\0'; 567 568 dir_operation(READ_CONFIG, path, 0, event_mask); 465 if (S_ISDIR(statbuf.st_mode)) { 466 p = bb_simplify_path(path); 467 dir_operation(READ_CONFIG, p, 0, event_mask); 468 free(p); 569 469 return; 570 470 } 571 if ( ( fp = fopen (path, "r") ) != NULL ) 572 { 573 while (fgets (buf, STRING_LENGTH, fp) != NULL) 574 { 471 if ((fp = fopen(path, "r")) != NULL) { 472 while (fgets(buf, STRING_LENGTH, fp) != NULL) { 575 473 /* Skip whitespace */ 576 for (line = buf; isspace (*line); ++line)577 /*VOID*/;578 if (line[0] == '\0' || line[0] == '#' 474 line = buf; 475 line = skip_whitespace(line); 476 if (line[0] == '\0' || line[0] == '#') 579 477 continue; 580 process_config_line 478 process_config_line(line, event_mask); 581 479 } 582 fclose 480 fclose(fp); 583 481 } else { 584 482 goto read_config_file_err; … … 586 484 } else { 587 485 read_config_file_err: 588 if(optional == 0 && errno == ENOENT) 589 msg_logger_and_die(LOG_ERR, "read config file: %s: %m", path); 590 } 591 return; 486 if (optional == 0 && errno == ENOENT) 487 error_logger_and_die(LOG_ERR, "read config file: %s", path); 488 } 592 489 } /* End Function read_config_file */ 593 490 594 static void process_config_line 491 static void process_config_line(const char *line, unsigned long *event_mask) 595 492 /* [SUMMARY] Process a line from a configuration file. 596 493 <line> The configuration line. … … 604 501 char when[STRING_LENGTH], what[STRING_LENGTH]; 605 502 char name[STRING_LENGTH]; 606 c har * msg="";503 const char *msg = ""; 607 504 char *ptr; 608 505 int i; 609 506 610 507 /* !!!! Only Uppercase Keywords in devsfd.conf */ 611 static const char *const options[] = { 612 "CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE", 613 "RESTORE", "PERMISSIONS", "MODLOAD", "EXECUTE", 614 "COPY", "IGNORE", "MKOLDCOMPAT", "MKNEWCOMPAT", 615 "RMOLDCOMPAT", "RMNEWCOMPAT", 0 616 }; 617 618 debug_msg_logger(LOG_INFO, __FUNCTION__); 619 620 for (count = 0; count < MAX_ARGS; ++count) p[count][0] = '\0'; 621 num_args = sscanf (line, "%s %s %s %s %s %s %s %s %s %s", 508 static const char options[] ALIGN1 = 509 "CLEAR_CONFIG\0""INCLUDE\0""OPTIONAL_INCLUDE\0" 510 "RESTORE\0""PERMISSIONS\0""MODLOAD\0""EXECUTE\0" 511 "COPY\0""IGNORE\0""MKOLDCOMPAT\0""MKNEWCOMPAT\0" 512 "RMOLDCOMPAT\0""RMNEWCOMPAT\0"; 513 514 for (count = 0; count < MAX_ARGS; ++count) 515 p[count][0] = '\0'; 516 num_args = sscanf(line, "%s %s %s %s %s %s %s %s %s %s", 622 517 when, name, what, 623 518 p[0], p[1], p[2], p[3], p[4], p[5], p[6]); 624 519 625 i = compare_string_array(options, when ); 626 627 /*"CLEAR_CONFIG"*/ 628 if( i == 0) 629 { 630 free_config (); 520 i = index_in_strings(options, when); 521 522 /* "CLEAR_CONFIG" */ 523 if (i == 0) { 524 free_config(); 631 525 *event_mask = 0; 632 526 return; 633 527 } 634 528 635 if ( 529 if (num_args < 2) 636 530 goto process_config_line_err; 637 531 638 532 /* "INCLUDE" & "OPTIONAL_INCLUDE" */ 639 if( i == 1 || i == 2 ) 640 { 641 st_expr_expand (name, STRING_LENGTH, name, get_variable, NULL ); 642 msg_logger(LOG_INFO, "%sinclude: %s",(toupper (when[0]) == 'I') ? "": "optional_", name); 643 read_config_file (name, (toupper (when[0]) == 'I') ? FALSE : TRUE, event_mask); 533 if (i == 1 || i == 2) { 534 st_expr_expand(name, STRING_LENGTH, name, get_variable, NULL); 535 info_logger(LOG_INFO, "%sinclude: %s", (toupper(when[0]) == 'I') ? "": "optional_", name); 536 read_config_file(name, (toupper(when[0]) == 'I') ? FALSE : TRUE, event_mask); 644 537 return; 645 538 } 646 539 /* "RESTORE" */ 647 if( i == 3) 648 { 649 dir_operation(RESTORE,name, strlen (name),NULL); 540 if (i == 3) { 541 dir_operation(RESTORE, name, strlen(name),NULL); 650 542 return; 651 543 } … … 653 545 goto process_config_line_err; 654 546 655 new = xmalloc (sizeof *new); 656 memset (new, 0, sizeof *new); 657 658 for (count = 0; event_types[count].config_name != NULL; ++count) 659 { 660 if (strcasecmp (when, event_types[count].config_name) != 0) 547 new = xzalloc(sizeof *new); 548 549 for (count = 0; event_types[count].config_name != NULL; ++count) { 550 if (strcasecmp(when, event_types[count].config_name) != 0) 661 551 continue; 662 552 new->action.when = event_types[count].type; 663 553 break; 664 554 } 665 if (event_types[count].config_name == NULL) 666 { 667 msg="WHEN in"; 555 if (event_types[count].config_name == NULL) { 556 msg = "WHEN in"; 668 557 goto process_config_line_err; 669 558 } 670 559 671 i = compare_string_array(options, what ); 672 673 switch(i) 674 { 560 i = index_in_strings(options, what); 561 562 switch (i) { 675 563 case 4: /* "PERMISSIONS" */ 676 564 new->action.what = AC_PERMISSIONS; 677 565 /* Get user and group */ 678 if ( ( ptr = strchr (p[0], '.') ) == NULL ) 679 { 680 msg="UID.GID"; 566 if ((ptr = strchr(p[0], '.')) == NULL) { 567 msg = "UID.GID"; 681 568 goto process_config_line_err; /*"missing '.' in UID.GID"*/ 682 569 } 683 570 684 571 *ptr++ = '\0'; 685 new->u.permissions.uid = get_uid_gid 686 new->u.permissions.gid = get_uid_gid 572 new->u.permissions.uid = get_uid_gid(UID, p[0]); 573 new->u.permissions.gid = get_uid_gid(GID, ptr); 687 574 /* Get mode */ 688 new->u.permissions.mode = get_mode 575 new->u.permissions.mode = get_mode(p[1]); 689 576 break; 690 577 case 5: /* MODLOAD */ 691 /*This action will pass "/dev/$devname" 578 /*This action will pass "/dev/$devname"(i.e. "/dev/" prefixed to 692 579 the device name) to the module loading facility. In addition, 693 580 the /etc/modules.devfs configuration file is used.*/ … … 700 587 701 588 for (count = 0; count < num_args; ++count) 702 new->u.execute.argv[count] = bb_xstrdup(p[count]);589 new->u.execute.argv[count] = xstrdup(p[count]); 703 590 704 591 new->u.execute.argv[num_args] = NULL; … … 710 597 goto process_config_line_err; /* missing path and function in line */ 711 598 712 new->u.copy.source = bb_xstrdup(p[0]);713 new->u.copy.destination = bb_xstrdup(p[1]);599 new->u.copy.source = xstrdup(p[0]); 600 new->u.copy.destination = xstrdup(p[1]); 714 601 break; 715 602 case 8: /* IGNORE */ … … 730 617 break; 731 618 default: 732 msg = "WHAT in";619 msg = "WHAT in"; 733 620 goto process_config_line_err; 734 621 /*esac*/ 735 622 } /* switch (i) */ 736 623 737 xregcomp( 624 xregcomp(&new->preg, name, REG_EXTENDED); 738 625 739 626 *event_mask |= 1 << new->action.when; … … 745 632 last_config = new; 746 633 return; 747 process_config_line_err: 634 635 process_config_line_err: 748 636 msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg , line); 749 637 } /* End Function process_config_line */ 750 638 751 static int do_servicing 639 static int do_servicing(int fd, unsigned long event_mask) 752 640 /* [SUMMARY] Service devfs changes until a signal is received. 753 641 <fd> The open control file. … … 758 646 ssize_t bytes; 759 647 struct devfsd_notify_struct info; 760 unsigned long tmp_event_mask; 761 762 debug_msg_logger(LOG_INFO, __FUNCTION__); 763 764 /* Tell devfs what events we care about */ 765 tmp_event_mask = event_mask; 766 do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, tmp_event_mask); 767 while (!caught_signal) 768 { 648 649 /* (void*) cast is only in order to match prototype */ 650 xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, (void*)event_mask); 651 while (!caught_signal) { 769 652 errno = 0; 770 bytes = read (fd,(char *) &info, sizeof info);653 bytes = read(fd,(char *) &info, sizeof info); 771 654 if (caught_signal) 772 655 break; /* Must test for this first */ … … 775 658 if (bytes < 1) 776 659 break; 777 service_name (&info); 778 } 779 if (caught_signal) 780 { 660 service_name(&info); 661 } 662 if (caught_signal) { 781 663 int c_sighup = caught_sighup; 782 664 783 665 caught_signal = FALSE; 784 666 caught_sighup = FALSE; 785 return (c_sighup);667 return c_sighup; 786 668 } 787 669 msg_logger_and_die(LOG_ERR, "read error on control file"); 788 670 } /* End Function do_servicing */ 789 671 790 static void service_name 672 static void service_name(const struct devfsd_notify_struct *info) 791 673 /* [SUMMARY] Service a single devfs change. 792 674 <info> The devfs change. … … 798 680 struct config_entry_struct *entry; 799 681 800 debug_msg_logger(LOG_INFO, __FUNCTION__);801 682 if (ENABLE_DEBUG && info->overrun_count > 0) 802 debug_msg_logger(LOG_ERR, "lost %u events", info->overrun_count);683 msg_logger(LOG_ERR, "lost %u events", info->overrun_count); 803 684 804 685 /* Discard lookups on "/dev/log" and "/dev/initctl" */ 805 if( info->type == DEVFSD_NOTIFY_LOOKUP && 806 ((info->devname[0]=='l' && info->devname[1]=='o' && 807 info->devname[2]=='g' && !info->devname[3]) || 808 ( info->devname[0]=='i' && info->devname[1]=='n' && 809 info->devname[2]=='i' && info->devname[3]=='t' && 810 info->devname[4]=='c' && info->devname[5]=='t' && 811 info->devname[6]=='l' && !info->devname[7]))) 812 return; 813 for (entry = first_config; entry != NULL; entry = entry->next) 814 { 686 if (info->type == DEVFSD_NOTIFY_LOOKUP 687 && ((info->devname[0] == 'l' && info->devname[1] == 'o' 688 && info->devname[2] == 'g' && !info->devname[3]) 689 || (info->devname[0] == 'i' && info->devname[1] == 'n' 690 && info->devname[2] == 'i' && info->devname[3] == 't' 691 && info->devname[4] == 'c' && info->devname[5] == 't' 692 && info->devname[6] == 'l' && !info->devname[7])) 693 ) 694 return; 695 696 for (entry = first_config; entry != NULL; entry = entry->next) { 815 697 /* First check if action matches the type, then check if name matches */ 816 if (info->type != entry->action.when || regexec (&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0 ) 698 if (info->type != entry->action.when 699 || regexec(&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0) 817 700 continue; 818 for (n = 0; 701 for (n = 0;(n < MAX_SUBEXPR) && (mbuf[n].rm_so != -1); ++n) 819 702 /* VOID */; 820 703 821 debug_msg_logger(LOG_INFO, "%s: action.what %d", __FUNCTION__, entry->action.what); 822 823 switch (entry->action.what) 824 { 704 switch (entry->action.what) { 825 705 case AC_PERMISSIONS: 826 action_permissions 706 action_permissions(info, entry); 827 707 break; 828 708 case AC_MODLOAD: 829 if (ENABLE_DEVFSD_MODLOAD)830 action_modload 709 if (ENABLE_DEVFSD_MODLOAD) 710 action_modload(info, entry); 831 711 break; 832 712 case AC_EXECUTE: 833 action_execute 713 action_execute(info, entry, mbuf, n); 834 714 break; 835 715 case AC_COPY: 836 action_copy 716 action_copy(info, entry, mbuf, n); 837 717 break; 838 718 case AC_IGNORE: … … 843 723 case AC_RMOLDCOMPAT: 844 724 case AC_RMNEWCOMPAT: 845 action_compat 725 action_compat(info, entry->action.what); 846 726 break; 847 727 default: … … 851 731 } /* End Function service_name */ 852 732 853 static void action_permissions 733 static void action_permissions(const struct devfsd_notify_struct *info, 854 734 const struct config_entry_struct *entry) 855 735 /* [SUMMARY] Update permissions for a device entry. … … 861 741 struct stat statbuf; 862 742 863 debug_msg_logger(LOG_INFO, __FUNCTION__); 864 865 if ( stat (info->devname, &statbuf) != 0 || 866 chmod (info->devname,(statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT)) != 0 || 867 chown (info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0) 868 { 869 msg_logger(LOG_ERR, "Can't chmod or chown: %s: %m",info->devname); 870 } 743 if (stat(info->devname, &statbuf) != 0 744 || chmod(info->devname, (statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT)) != 0 745 || chown(info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0 746 ) 747 error_logger(LOG_ERR, "Can't chmod or chown: %s", info->devname); 871 748 } /* End Function action_permissions */ 872 749 873 static void action_modload 750 static void action_modload(const struct devfsd_notify_struct *info, 874 751 const struct config_entry_struct *entry ATTRIBUTE_UNUSED) 875 752 /* [SUMMARY] Load a module. … … 880 757 { 881 758 char *argv[6]; 882 char device[STRING_LENGTH]; 883 884 argv[0] = MODPROBE; 885 argv[1] = MODPROBE_SWITCH_1; /* "-k" */ 886 argv[2] = MODPROBE_SWITCH_2; /* "-C" */ 887 argv[3] = CONFIG_MODULES_DEVFS; 888 argv[4] = device; 759 760 argv[0] = (char*)MODPROBE; 761 argv[1] = (char*)MODPROBE_SWITCH_1; /* "-k" */ 762 argv[2] = (char*)MODPROBE_SWITCH_2; /* "-C" */ 763 argv[3] = (char*)CONFIG_MODULES_DEVFS; 764 argv[4] = concat_path_file("/dev", info->devname); /* device */ 889 765 argv[5] = NULL; 890 766 891 snprintf (device, sizeof (device), "/dev/%s", info->devname); 892 debug_msg_logger(LOG_INFO, "%s: %s %s %s %s %s",__FUNCTION__, argv[0],argv[1],argv[2],argv[3],argv[4]); 893 fork_and_execute(DIE, argv[0], argv); 767 wait4pid(xspawn(argv)); 768 free(argv[4]); 894 769 } /* End Function action_modload */ 895 770 896 static void action_execute 771 static void action_execute(const struct devfsd_notify_struct *info, 897 772 const struct config_entry_struct *entry, 898 773 const regmatch_t *regexpr, unsigned int numexpr) … … 900 775 <info> The devfs change. 901 776 <entry> The config file entry. 902 <regexpr> The number of subexpression 777 <regexpr> The number of subexpression(start, end) offsets within the 903 778 device name. 904 779 <numexpr> The number of elements within <<regexpr>>. … … 911 786 char largv[MAX_ARGS + 1][STRING_LENGTH]; 912 787 913 debug_msg_logger(LOG_INFO ,__FUNCTION__);914 788 gv_info.info = info; 915 789 gv_info.devname = info->devname; 916 snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s", mount_point, info->devname); 917 for (count = 0; entry->u.execute.argv[count] != NULL; ++count) 918 { 919 expand_expression (largv[count], STRING_LENGTH, 790 snprintf(gv_info.devpath, sizeof(gv_info.devpath), "%s/%s", mount_point, info->devname); 791 for (count = 0; entry->u.execute.argv[count] != NULL; ++count) { 792 expand_expression(largv[count], STRING_LENGTH, 920 793 entry->u.execute.argv[count], 921 794 get_variable, &gv_info, 922 gv_info.devname, regexpr, numexpr 795 gv_info.devname, regexpr, numexpr); 923 796 argv[count] = largv[count]; 924 797 } 925 798 argv[count] = NULL; 926 fork_and_execute(NO_DIE, argv[0], argv);799 wait4pid(spawn(argv)); 927 800 } /* End Function action_execute */ 928 801 929 802 930 static void action_copy 803 static void action_copy(const struct devfsd_notify_struct *info, 931 804 const struct config_entry_struct *entry, 932 805 const regmatch_t *regexpr, unsigned int numexpr) … … 934 807 <info> The devfs change. 935 808 <entry> The config file entry. 936 <regexpr> This list of subexpression 809 <regexpr> This list of subexpression(start, end) offsets within the 937 810 device name. 938 811 <numexpr> The number of elements in <<regexpr>>. … … 946 819 int ret = 0; 947 820 948 debug_msg_logger(LOG_INFO, __FUNCTION__);949 950 821 dest_stat.st_mode = 0; 951 822 952 if ( (info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK (info->mode))823 if ((info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK(info->mode)) 953 824 return; 954 825 gv_info.info = info; 955 826 gv_info.devname = info->devname; 956 827 957 snprintf (gv_info.devpath, sizeof(gv_info.devpath), "%s/%s", mount_point, info->devname);958 expand_expression 828 snprintf(gv_info.devpath, sizeof(gv_info.devpath), "%s/%s", mount_point, info->devname); 829 expand_expression(source, STRING_LENGTH, entry->u.copy.source, 959 830 get_variable, &gv_info, gv_info.devname, 960 831 regexpr, numexpr); 961 832 962 expand_expression 833 expand_expression(destination, STRING_LENGTH, entry->u.copy.destination, 963 834 get_variable, &gv_info, gv_info.devname, 964 835 regexpr, numexpr); 965 836 966 if ( !make_dir_tree (destination) || lstat(source, &source_stat) != 0)837 if (!make_dir_tree(destination) || lstat(source, &source_stat) != 0) 967 838 return; 968 lstat 839 lstat(destination, &dest_stat); 969 840 new_mode = source_stat.st_mode & ~S_ISVTX; 970 841 if (info->type == DEVFSD_NOTIFY_CREATE) 971 842 new_mode |= S_ISVTX; 972 else if ( (info->type == DEVFSD_NOTIFY_CHANGE) && (dest_stat.st_mode & S_ISVTX))843 else if ((info->type == DEVFSD_NOTIFY_CHANGE) &&(dest_stat.st_mode & S_ISVTX)) 973 844 new_mode |= S_ISVTX; 974 ret = copy_inode 845 ret = copy_inode(destination, &dest_stat, new_mode, source, &source_stat); 975 846 if (ENABLE_DEBUG && ret && (errno != EEXIST)) 976 debug_msg_logger(LOG_ERR, "copy_inode: %s to %s: %m", source, destination); 977 return; 847 error_logger(LOG_ERR, "copy_inode: %s to %s", source, destination); 978 848 } /* End Function action_copy */ 979 849 980 static void action_compat 850 static void action_compat(const struct devfsd_notify_struct *info, unsigned int action) 981 851 /* [SUMMARY] Process a compatibility request. 982 852 <info> The devfs change. … … 988 858 const char *compat_name = NULL; 989 859 const char *dest_name = info->devname; 990 c har *ptr=NULL;860 const char *ptr; 991 861 char compat_buf[STRING_LENGTH], dest_buf[STRING_LENGTH]; 992 862 int mode, host, bus, target, lun; … … 1009 879 1010 880 /* First construct compatibility name */ 1011 switch (action) 1012 { 881 switch (action) { 1013 882 case AC_MKOLDCOMPAT: 1014 883 case AC_RMOLDCOMPAT: 1015 compat_name = get_old_name 884 compat_name = get_old_name(info->devname, info->namelen, compat_buf, info->major, info->minor); 1016 885 break; 1017 886 case AC_MKNEWCOMPAT: 1018 887 case AC_RMNEWCOMPAT: 1019 ptr = strrchr (info->devname, '/') + 1; 1020 i=scan_dev_name(info->devname, info->namelen, ptr); 1021 1022 debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i); 888 ptr = bb_basename(info->devname); 889 i = scan_dev_name(info->devname, info->namelen, ptr); 1023 890 1024 891 /* nothing found */ 1025 if (i==0 || i > 9)892 if (i == 0 || i > 9) 1026 893 return; 1027 894 1028 sscanf (info->devname +((i<6)?5:4), "host%d/bus%d/target%d/lun%d/", &host, &bus, &target, &lun);1029 snprintf (dest_buf, sizeof (dest_buf), "../%s", info->devname + ((i>5)?4:0));895 sscanf(info->devname + ((i < 6) ? 5 : 4), "host%d/bus%d/target%d/lun%d/", &host, &bus, &target, &lun); 896 snprintf(dest_buf, sizeof(dest_buf), "../%s", info->devname + (( i > 5) ? 4 : 0)); 1030 897 dest_name = dest_buf; 1031 898 compat_name = compat_buf; … … 1033 900 1034 901 /* 1 == scsi/generic 2 == scsi/disc 3 == scsi/cd 6 == ide/host/disc 7 == ide/host/cd */ 1035 if ( i == 1 || i == 2 || i == 3 || i == 6 || i ==7)1036 sprintf (compat_buf, fmt[i], host, bus, target, lun);902 if (i == 1 || i == 2 || i == 3 || i == 6 || i ==7) 903 sprintf(compat_buf, fmt[i], host, bus, target, lun); 1037 904 1038 905 /* 4 == scsi/part 8 == ide/host/part */ 1039 if (i == 4 || i == 8)1040 sprintf ( compat_buf, fmt[i], host, bus, target, lun, atoi (ptr + 4));906 if (i == 4 || i == 8) 907 sprintf(compat_buf, fmt[i], host, bus, target, lun, atoi(ptr + 4)); 1041 908 1042 909 /* 5 == scsi/mt */ 1043 if( i == 5) 1044 { 910 if (i == 5) { 1045 911 rewind_ = info->devname[info->namelen - 1]; 1046 912 if (rewind_ != 'n') 1047 913 rewind_ = '\0'; 1048 914 mode=0; 1049 if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/)915 if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) 1050 916 mode = ptr[2] - 107; /* 1 or 2 */ 1051 if (ptr[2] == 'a')917 if (ptr[2] == 'a') 1052 918 mode = 3; 1053 sprintf (compat_buf, fmt[i], host, bus, target, lun, mode, rewind_);919 sprintf(compat_buf, fmt[i], host, bus, target, lun, mode, rewind_); 1054 920 } 1055 921 1056 922 /* 9 == ide/host/mt */ 1057 if ( i == 9)1058 snprintf (compat_buf, sizeof(compat_buf), fmt[i], host, bus, target, lun, ptr + 2);923 if (i == 9) 924 snprintf(compat_buf, sizeof(compat_buf), fmt[i], host, bus, target, lun, ptr + 2); 1059 925 /* esac */ 1060 } /* switch (action) */1061 1062 if (compat_name == NULL)926 } /* switch (action) */ 927 928 if (compat_name == NULL) 1063 929 return; 1064 930 1065 debug_msg_logger( LOG_INFO, "%s: %s", __FUNCTION__, compat_name);1066 1067 931 /* Now decide what to do with it */ 1068 switch (action) 1069 { 932 switch (action) { 1070 933 case AC_MKOLDCOMPAT: 1071 934 case AC_MKNEWCOMPAT: 1072 mksymlink 935 mksymlink(dest_name, compat_name); 1073 936 break; 1074 937 case AC_RMOLDCOMPAT: 1075 938 case AC_RMNEWCOMPAT: 1076 ret = unlink 939 ret = unlink(compat_name); 1077 940 if (ENABLE_DEBUG && ret) 1078 debug_msg_logger(LOG_ERR, "unlink: %s: %m", compat_name);941 error_logger(LOG_ERR, "unlink: %s", compat_name); 1079 942 break; 1080 943 /*esac*/ 1081 } /* switch (action) */944 } /* switch (action) */ 1082 945 } /* End Function action_compat */ 1083 946 1084 947 static void restore(char *spath, struct stat source_stat, int rootlen) 1085 948 { 1086 char dpath[STRING_LENGTH];949 char *dpath; 1087 950 struct stat dest_stat; 1088 951 1089 debug_msg_logger(LOG_INFO, __FUNCTION__);1090 1091 952 dest_stat.st_mode = 0; 1092 snprintf (dpath, sizeof dpath, "%s%s",mount_point, spath + rootlen);1093 lstat 1094 1095 if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX))1096 copy_inode (dpath, &dest_stat,(source_stat.st_mode & ~S_ISVTX) , spath, &source_stat);1097 1098 if ( S_ISDIR (source_stat.st_mode))953 dpath = concat_path_file(mount_point, spath + rootlen); 954 lstat(dpath, &dest_stat); 955 free(dpath); 956 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); 958 959 if (S_ISDIR(source_stat.st_mode)) 1099 960 dir_operation(RESTORE, spath, rootlen,NULL); 1100 961 } 1101 962 1102 963 1103 static int copy_inode 964 static int copy_inode(const char *destpath, const struct stat *dest_stat, 1104 965 mode_t new_mode, 1105 966 const char *sourcepath, const struct stat *source_stat) … … 1119 980 char symlink_val[STRING_LENGTH]; 1120 981 1121 debug_msg_logger(LOG_INFO, __FUNCTION__); 1122 1123 if ( (source_stat->st_mode & S_IFMT) == (dest_stat->st_mode & S_IFMT) ) 1124 { 982 if ((source_stat->st_mode & S_IFMT) ==(dest_stat->st_mode & S_IFMT)) { 1125 983 /* Same type */ 1126 if ( S_ISLNK (source_stat->st_mode) )1127 {1128 if (( source_len = readlink (sourcepath, source_link, STRING_LENGTH - 1) ) < 0 ||1129 ( dest_len = readlink (destpath , dest_link , STRING_LENGTH - 1) ) < 0)1130 return (FALSE);984 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 987 ) 988 return FALSE; 1131 989 source_link[source_len] = '\0'; 1132 990 dest_link[dest_len] = '\0'; 1133 if ( (source_len != dest_len) || (strcmp (source_link, dest_link) != 0) ) 1134 { 1135 unlink (destpath); 1136 symlink (source_link, destpath); 991 if ((source_len != dest_len) || (strcmp(source_link, dest_link) != 0)) { 992 unlink(destpath); 993 symlink(source_link, destpath); 1137 994 } 1138 return (TRUE);995 return TRUE; 1139 996 } /* Else not a symlink */ 1140 chmod 1141 chown 1142 return (TRUE);997 chmod(destpath, new_mode & ~S_IFMT); 998 chown(destpath, source_stat->st_uid, source_stat->st_gid); 999 return TRUE; 1143 1000 } 1144 1001 /* Different types: unlink and create */ 1145 unlink (destpath); 1146 switch (source_stat->st_mode & S_IFMT) 1147 { 1002 unlink(destpath); 1003 switch (source_stat->st_mode & S_IFMT) { 1148 1004 case S_IFSOCK: 1149 if ( ( fd = socket (AF_UNIX, SOCK_STREAM, 0) ) < 0)1005 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 1150 1006 break; 1151 1007 un_addr.sun_family = AF_UNIX; 1152 snprintf (un_addr.sun_path, sizeof(un_addr.sun_path), "%s", destpath);1153 val = bind (fd, (struct sockaddr *) &un_addr,(int) sizeof un_addr);1154 close 1155 if (val != 0 || chmod 1008 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s", destpath); 1009 val = bind(fd,(struct sockaddr *) &un_addr,(int) sizeof un_addr); 1010 close(fd); 1011 if (val != 0 || chmod(destpath, new_mode & ~S_IFMT) != 0) 1156 1012 break; 1157 1013 goto do_chown; 1158 1014 case S_IFLNK: 1159 if ( ( val = readlink (sourcepath, symlink_val, STRING_LENGTH - 1) ) < 0)1015 if ((val = readlink(sourcepath, symlink_val, STRING_LENGTH - 1)) < 0) 1160 1016 break; 1161 1017 symlink_val[val] = '\0'; 1162 if (symlink 1163 return (TRUE);1018 if (symlink(symlink_val, destpath) == 0) 1019 return TRUE; 1164 1020 break; 1165 1021 case S_IFREG: 1166 if ( ( fd = open (destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT) ) < 0)1022 if ((fd = open(destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT)) < 0) 1167 1023 break; 1168 close 1169 if (chmod 1024 close(fd); 1025 if (chmod(destpath, new_mode & ~S_IFMT) != 0) 1170 1026 break; 1171 1027 goto do_chown; … … 1173 1029 case S_IFCHR: 1174 1030 case S_IFIFO: 1175 if (mknod 1031 if (mknod(destpath, new_mode, source_stat->st_rdev) != 0) 1176 1032 break; 1177 1033 goto do_chown; 1178 1034 case S_IFDIR: 1179 if (mkdir 1035 if (mkdir(destpath, new_mode & ~S_IFMT) != 0) 1180 1036 break; 1181 1037 do_chown: 1182 if (chown 1183 return (TRUE);1038 if (chown(destpath, source_stat->st_uid, source_stat->st_gid) == 0) 1039 return TRUE; 1184 1040 /*break;*/ 1185 1041 } 1186 return (FALSE);1042 return FALSE; 1187 1043 } /* End Function copy_inode */ 1188 1044 1189 static void free_config 1045 static void free_config(void) 1190 1046 /* [SUMMARY] Free the configuration information. 1191 1047 [RETURNS] Nothing. … … 1195 1051 void *next; 1196 1052 1197 debug_msg_logger(LOG_INFO, __FUNCTION__); 1198 1199 for (c_entry = first_config; c_entry != NULL; c_entry = next) 1200 { 1053 for (c_entry = first_config; c_entry != NULL; c_entry = next) { 1201 1054 unsigned int count; 1202 1055 1203 1056 next = c_entry->next; 1204 regfree (&c_entry->preg); 1205 if (c_entry->action.what == AC_EXECUTE) 1206 { 1207 for (count = 0; count < MAX_ARGS; ++count) 1208 { 1057 regfree(&c_entry->preg); 1058 if (c_entry->action.what == AC_EXECUTE) { 1059 for (count = 0; count < MAX_ARGS; ++count) { 1209 1060 if (c_entry->u.execute.argv[count] == NULL) 1210 1061 break; 1211 free 1062 free(c_entry->u.execute.argv[count]); 1212 1063 } 1213 1064 } 1214 free 1065 free(c_entry); 1215 1066 } 1216 1067 first_config = NULL; … … 1218 1069 } /* End Function free_config */ 1219 1070 1220 static int get_uid_gid 1071 static int get_uid_gid(int flag, const char *string) 1221 1072 /* [SUMMARY] Convert a string to a UID or GID value. 1222 1073 <flag> "UID" or "GID". … … 1227 1078 struct passwd *pw_ent; 1228 1079 struct group *grp_ent; 1229 static c har *msg;1080 static const char *msg; 1230 1081 1231 1082 if (ENABLE_DEVFSD_VERBOSE) 1232 msg="user"; 1233 1234 debug_msg_logger(LOG_INFO, __FUNCTION__); 1235 1236 if(ENABLE_DEBUG && flag != UID && flag != GID) 1237 msg_logger_and_die(LOG_ERR,"%s: flag != UID && flag != GID", __FUNCTION__); 1238 1239 if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) ) 1240 return atoi (string); 1241 1242 if ( flag == UID && ( pw_ent = getpwnam (string) ) != NULL ) 1243 return (pw_ent->pw_uid); 1244 1245 if ( flag == GID && ( grp_ent = getgrnam (string) ) != NULL ) 1246 return (grp_ent->gr_gid); 1247 else if(ENABLE_DEVFSD_VERBOSE) 1248 msg="group"; 1249 1250 if(ENABLE_DEVFSD_VERBOSE) 1083 msg = "user"; 1084 1085 if (isdigit(string[0]) ||((string[0] == '-') && isdigit(string[1]))) 1086 return atoi(string); 1087 1088 if (flag == UID && (pw_ent = getpwnam(string)) != NULL) 1089 return pw_ent->pw_uid; 1090 1091 if (flag == GID && (grp_ent = getgrnam(string)) != NULL) 1092 return grp_ent->gr_gid; 1093 else if (ENABLE_DEVFSD_VERBOSE) 1094 msg = "group"; 1095 1096 if (ENABLE_DEVFSD_VERBOSE) 1251 1097 msg_logger(LOG_ERR,"unknown %s: %s, defaulting to %cid=0", msg, string, msg[0]); 1252 return (0);1098 return 0; 1253 1099 }/* End Function get_uid_gid */ 1254 1100 1255 static mode_t get_mode 1101 static mode_t get_mode(const char *string) 1256 1102 /* [SUMMARY] Convert a string to a mode value. 1257 1103 <string> The string. … … 1262 1108 int i; 1263 1109 1264 debug_msg_logger(LOG_INFO, __FUNCTION__); 1265 1266 if ( isdigit (string[0]) ) 1267 return strtoul (string, NULL, 8); 1268 if (strlen (string) != 9) 1110 if (isdigit(string[0])) 1111 return strtoul(string, NULL, 8); 1112 if (strlen(string) != 9) 1269 1113 msg_logger_and_die(LOG_ERR, "bad mode: %s", string); 1270 1114 1271 1115 mode = 0; 1272 i= S_IRUSR; 1273 while(i>0) 1274 { 1275 if(string[0]=='r'||string[0]=='w'||string[0]=='x') 1276 mode+=i; 1277 i=i/2; 1116 i = S_IRUSR; 1117 while (i > 0) { 1118 if (string[0] == 'r' || string[0] == 'w' || string[0] == 'x') 1119 mode += i; 1120 i = i / 2; 1278 1121 string++; 1279 1122 } 1280 return (mode);1123 return mode; 1281 1124 } /* End Function get_mode */ 1282 1125 1283 static void signal_handler (int sig) 1284 { 1285 debug_msg_logger(LOG_INFO, __FUNCTION__); 1286 1126 static void signal_handler(int sig) 1127 { 1287 1128 caught_signal = TRUE; 1288 1129 if (sig == SIGHUP) 1289 1130 caught_sighup = TRUE; 1290 1131 1291 msg_logger(LOG_INFO, "Caught signal %d", sig);1132 info_logger(LOG_INFO, "Caught signal %d", sig); 1292 1133 } /* End Function signal_handler */ 1293 1134 1294 static const char *get_variable (const char *variable, void *info) 1295 { 1135 static const char *get_variable(const char *variable, void *info) 1136 { 1137 static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */ 1138 1139 char hostname[STRING_LENGTH]; 1296 1140 struct get_variable_info *gv_info = info; 1297 static char hostname[STRING_LENGTH], sbuf[STRING_LENGTH]; 1298 const char *field_names[] = { "hostname", "mntpt", "devpath", "devname", 1299 "uid", "gid", "mode", hostname, mount_point, 1300 gv_info->devpath, gv_info->devname, 0 }; 1141 const char *field_names[] = { 1142 "hostname", "mntpt", "devpath", "devname", 1143 "uid", "gid", "mode", hostname, mount_point, 1144 gv_info->devpath, gv_info->devname, NULL 1145 }; 1301 1146 int i; 1302 1147 1303 debug_msg_logger(LOG_INFO, __FUNCTION__); 1304 1305 if (gethostname (hostname, STRING_LENGTH - 1) != 0) 1306 msg_logger_and_die(LOG_ERR, "gethostname: %m"); 1307 1148 if (gethostname(hostname, STRING_LENGTH - 1) != 0) 1308 1149 /* Here on error we should do exit(RV_SYS_ERROR), instead we do exit(EXIT_FAILURE) */ 1309 hostname[STRING_LENGTH - 1] = '\0'; 1310 1311 /* compare_string_array returns i>=0 */ 1312 i=compare_string_array(field_names, variable); 1313 1314 if ( i > 6 || i < 0 || (i > 1 && gv_info == NULL)) 1315 return (NULL); 1316 if( i >= 0 && i <= 3) 1317 { 1318 debug_msg_logger(LOG_INFO, "%s: i=%d %s", __FUNCTION__, i ,field_names[i+7]); 1319 return(field_names[i+7]); 1320 } 1321 1322 if(i == 4 ) 1323 sprintf (sbuf, "%u", gv_info->info->uid); 1324 else if(i == 5) 1325 sprintf (sbuf, "%u", gv_info->info->gid); 1326 else if(i == 6) 1327 sprintf (sbuf, "%o", gv_info->info->mode); 1328 1329 debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, sbuf); 1330 1331 return (sbuf); 1150 error_logger_and_die(LOG_ERR, "gethostname"); 1151 1152 hostname[STRING_LENGTH - 1] = '\0'; 1153 1154 /* index_in_str_array returns i>=0 */ 1155 i = index_in_str_array(field_names, variable); 1156 1157 if (i > 6 || i < 0 || (i > 1 && gv_info == NULL)) 1158 return NULL; 1159 if (i >= 0 && i <= 3) 1160 return field_names[i + 7]; 1161 1162 if (i == 4) 1163 sprintf(sbuf, "%u", gv_info->info->uid); 1164 else if (i == 5) 1165 sprintf(sbuf, "%u", gv_info->info->gid); 1166 else if (i == 6) 1167 sprintf(sbuf, "%o", gv_info->info->mode); 1168 return sbuf; 1332 1169 } /* End Function get_variable */ 1333 1170 … … 1336 1173 struct devfsd_notify_struct info; 1337 1174 1338 debug_msg_logger(LOG_INFO, __FUNCTION__); 1339 1340 memset (&info, 0, sizeof info); 1175 memset(&info, 0, sizeof info); 1341 1176 info.type = DEVFSD_NOTIFY_REGISTERED; 1342 1177 info.mode = statbuf.st_mode; 1343 info.major = major 1344 info.minor = minor 1178 info.major = major(statbuf.st_rdev); 1179 info.minor = minor(statbuf.st_rdev); 1345 1180 info.uid = statbuf.st_uid; 1346 1181 info.gid = statbuf.st_gid; 1347 snprintf (info.devname, sizeof (info.devname), "%s", path + strlen(mount_point) + 1);1348 info.namelen = strlen 1349 service_name 1350 if ( S_ISDIR (statbuf.st_mode))1351 dir_operation(SERVICE, path,0,NULL);1182 snprintf(info.devname, sizeof(info.devname), "%s", path + strlen(mount_point) + 1); 1183 info.namelen = strlen(info.devname); 1184 service_name(&info); 1185 if (S_ISDIR(statbuf.st_mode)) 1186 dir_operation(SERVICE, path, 0, NULL); 1352 1187 } 1353 1188 … … 1364 1199 DIR *dp; 1365 1200 struct dirent *de; 1366 char path[STRING_LENGTH]; 1367 1368 debug_msg_logger(LOG_INFO, __FUNCTION__); 1369 1370 if((dp = opendir( dir_name))==NULL) 1371 { 1372 debug_msg_logger(LOG_ERR, "opendir: %s: %m", dir_name); 1201 char *path; 1202 1203 if ((dp = warn_opendir(dir_name)) == NULL) 1373 1204 return; 1374 } 1375 1376 while ( (de = readdir (dp) ) != NULL ) 1377 { 1378 1379 if(de->d_name && *de->d_name == '.' && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))) 1205 1206 while ((de = readdir(dp)) != NULL) { 1207 1208 if (de->d_name && DOT_OR_DOTDOT(de->d_name)) 1380 1209 continue; 1381 snprintf (path, sizeof (path), "%s/%s", dir_name, de->d_name); 1382 debug_msg_logger(LOG_ERR, "%s: %s", __FUNCTION__, path); 1383 1384 if (lstat (path, &statbuf) != 0) 1385 { 1386 debug_msg_logger(LOG_ERR, "%s: %s: %m", __FUNCTION__, path); 1387 continue; 1210 path = concat_path_file(dir_name, de->d_name); 1211 if (lstat(path, &statbuf) == 0) { 1212 switch (type) { 1213 case SERVICE: 1214 service(statbuf, path); 1215 break; 1216 case RESTORE: 1217 restore(path, statbuf, var); 1218 break; 1219 case READ_CONFIG: 1220 read_config_file(path, var, event_mask); 1221 break; 1222 } 1388 1223 } 1389 switch(type) 1390 { 1391 case SERVICE: 1392 service(statbuf,path); 1393 break; 1394 case RESTORE: 1395 restore(path, statbuf, var); 1396 break; 1397 case READ_CONFIG: 1398 read_config_file (path, var, event_mask); 1399 break; 1400 } 1401 } 1402 closedir (dp); 1224 free(path); 1225 } 1226 closedir(dp); 1403 1227 } /* End Function do_scan_and_service */ 1404 1228 1405 static int mksymlink 1229 static int mksymlink(const char *oldpath, const char *newpath) 1406 1230 /* [SUMMARY] Create a symlink, creating intervening directories as required. 1407 1231 <oldpath> The string contained in the symlink. … … 1410 1234 */ 1411 1235 { 1412 debug_msg_logger(LOG_INFO, __FUNCTION__); 1413 1414 if ( !make_dir_tree (newpath) ) 1415 return (-1); 1416 1417 if (symlink (oldpath, newpath) != 0) 1418 { 1236 if (!make_dir_tree(newpath)) 1237 return -1; 1238 1239 if (symlink(oldpath, newpath) != 0) { 1419 1240 if (errno != EEXIST) 1420 { 1421 debug_msg_logger(LOG_ERR, "%s: %s to %s: %m", __FUNCTION__, oldpath, newpath); 1422 return (-1); 1423 } 1424 } 1425 return (0); 1241 return -1; 1242 } 1243 return 0; 1426 1244 } /* End Function mksymlink */ 1427 1245 1428 1246 1429 static int make_dir_tree 1247 static int make_dir_tree(const char *path) 1430 1248 /* [SUMMARY] Creating intervening directories for a path as required. 1431 <path> The full pathname 1249 <path> The full pathname(including the leaf node). 1432 1250 [RETURNS] TRUE on success, else FALSE. 1433 1251 */ 1434 1252 { 1435 debug_msg_logger(LOG_INFO, __FUNCTION__); 1436 1437 if (bb_make_directory( dirname((char *)path), -1, FILEUTILS_RECUR )==-1) 1438 { 1439 debug_msg_logger(LOG_ERR, "%s: %s: %m",__FUNCTION__, path); 1440 return (FALSE); 1441 } 1442 return(TRUE); 1253 if (bb_make_directory(dirname((char *)path), -1, FILEUTILS_RECUR) == -1) 1254 return FALSE; 1255 return TRUE; 1443 1256 } /* End Function make_dir_tree */ 1444 1257 … … 1466 1279 char temp[STRING_LENGTH]; 1467 1280 1468 debug_msg_logger(LOG_INFO, __FUNCTION__); 1469 1470 if ( !st_expr_expand (temp, STRING_LENGTH, input, get_variable_func, info) ) 1471 return (FALSE); 1472 expand_regexp (output, outsize, temp, devname, ex, numexp); 1473 return (TRUE); 1281 if (!st_expr_expand(temp, STRING_LENGTH, input, get_variable_func, info)) 1282 return FALSE; 1283 expand_regexp(output, outsize, temp, devname, ex, numexp); 1284 return TRUE; 1474 1285 } /* End Function expand_expression */ 1475 1286 1476 static void expand_regexp 1287 static void expand_regexp(char *output, size_t outsize, const char *input, 1477 1288 const char *devname, 1478 const regmatch_t *ex, unsigned int numex 1289 const regmatch_t *ex, unsigned int numex) 1479 1290 /* [SUMMARY] Expand all occurrences of the regular subexpressions \0 to \9. 1480 1291 <output> The output expanded expression is written here. … … 1495 1306 int c = -1; 1496 1307 1497 debug_msg_logger(LOG_INFO, __FUNCTION__);1498 1499 1308 /* Guarantee NULL termination by writing an explicit '\0' character into 1500 1309 the very last byte */ … … 1504 1313 and '\0' .. '\9' with subexpressions 0 .. 9, if they exist. Other \x 1505 1314 codes are deleted */ 1506 while ( (c != '\0') && (outsize != 0) ) 1507 { 1315 while ((c != '\0') && (outsize != 0)) { 1508 1316 c = *input; 1509 1317 ++input; 1510 if (c == '\\') 1511 { 1318 if (c == '\\') { 1512 1319 c = *input; 1513 1320 ++input; 1514 if (c != '\\') 1515 { 1516 if ((c >= '0') && (c <= last_exp)) 1517 { 1321 if (c != '\\') { 1322 if ((c >= '0') && (c <= last_exp)) { 1518 1323 const regmatch_t *subexp = ex + (c - '0'); 1519 1324 unsigned int sublen = subexp->rm_eo - subexp->rm_so; … … 1522 1327 if (sublen > outsize) 1523 1328 sublen = outsize; 1524 strncpy 1329 strncpy(output, devname + subexp->rm_so, sublen); 1525 1330 output += sublen; 1526 1331 outsize -= sublen; … … 1540 1345 struct translate_struct 1541 1346 { 1542 c har *match; /* The string to match to(up to length) */1543 c har *format; /* Format of output, "%s" takes data past match string,1544 NULL is effectively "%s" 1347 const char *match; /* The string to match to(up to length) */ 1348 const char *format; /* Format of output, "%s" takes data past match string, 1349 NULL is effectively "%s"(just more efficient) */ 1545 1350 }; 1546 1351 … … 1578 1383 }; 1579 1384 1580 const char *get_old_name 1385 const char *get_old_name(const char *devname, unsigned int namelen, 1581 1386 char *buffer, unsigned int major, unsigned int minor) 1582 1387 /* [SUMMARY] Translate a kernel-supplied name into an old name. … … 1590 1395 { 1591 1396 const char *compat_name = NULL; 1592 c har *ptr;1397 const char *ptr; 1593 1398 struct translate_struct *trans; 1594 1399 unsigned int i; … … 1616 1421 }; 1617 1422 1618 debug_msg_logger(LOG_INFO, __FUNCTION__); 1619 1620 for (trans = translate_table; trans->match != NULL; ++trans) 1621 { 1622 len = strlen (trans->match); 1623 1624 if (strncmp (devname, trans->match, len) == 0) 1625 { 1423 for (trans = translate_table; trans->match != NULL; ++trans) { 1424 len = strlen(trans->match); 1425 1426 if (strncmp(devname, trans->match, len) == 0) { 1626 1427 if (trans->format == NULL) 1627 return (devname + len);1628 sprintf 1629 return (buffer);1428 return devname + len; 1429 sprintf(buffer, trans->format, devname + len); 1430 return buffer; 1630 1431 } 1631 1432 } 1632 1433 1633 ptr = (strrchr (devname, '/') + 1);1434 ptr = bb_basename(devname); 1634 1435 i = scan_dev_name(devname, namelen, ptr); 1635 1436 1636 if (i > 0 && i < 13)1437 if (i > 0 && i < 13) 1637 1438 compat_name = buffer; 1638 1439 else 1639 1440 return NULL; 1640 1441 1641 debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i);1642 1643 1442 /* 1 == scsi/generic, 3 == scsi/cd, 10 == sbp/ */ 1644 if ( i == 1 || i == 3 || i == 10)1645 sprintf 1443 if (i == 1 || i == 3 || i == 10) 1444 sprintf(buffer, fmt[i], minor); 1646 1445 1647 1446 /* 2 ==scsi/disc, 4 == scsi/part */ 1648 if (i == 2 || i == 4)1649 compat_name = write_old_sd_name (buffer, major, minor,((i == 2)?"":(ptr + 4)));1447 if (i == 2 || i == 4) 1448 compat_name = write_old_sd_name(buffer, major, minor,((i == 2) ? "" : (ptr + 4))); 1650 1449 1651 1450 /* 5 == scsi/mt */ 1652 if( i == 5) 1653 { 1451 if (i == 5) { 1654 1452 mode = ptr[2]; 1655 1453 if (mode == 'n') 1656 1454 mode = '\0'; 1657 sprintf 1455 sprintf(buffer, fmt[i], minor & 0x1f, mode); 1658 1456 if (devname[namelen - 1] != 'n') 1659 1457 ++compat_name; 1660 1458 } 1661 1459 /* 6 == ide/host/disc, 7 == ide/host/cd, 8 == ide/host/part */ 1662 if ( i == 6 || i == 7 || i == 8)1460 if (i == 6 || i == 7 || i == 8) 1663 1461 /* last arg should be ignored for i == 6 or i== 7 */ 1664 sprintf (buffer, fmt[i] , get_old_ide_name(major, minor), ptr + 4);1462 sprintf(buffer, fmt[i] , get_old_ide_name(major, minor), ptr + 4); 1665 1463 1666 1464 /* 9 == ide/host/mt */ 1667 if ( i == 9)1668 sprintf 1465 if (i == 9) 1466 sprintf(buffer, fmt[i], ptr + 2, minor & 0x7f); 1669 1467 1670 1468 /* 11 == vcc/ */ 1671 if( i == 11 ) 1672 { 1673 sprintf (buffer, fmt[i], devname + 4); 1469 if (i == 11) { 1470 sprintf(buffer, fmt[i], devname + 4); 1674 1471 if (buffer[3] == '0') 1675 1472 buffer[3] = '\0'; 1676 1473 } 1677 1474 /* 12 == pty/ */ 1678 if( i == 12 ) 1679 { 1475 if (i == 12) { 1680 1476 pty1 = "pqrstuvwxyzabcde"; 1681 1477 pty2 = "0123456789abcdef"; 1682 indexx = atoi (devname + 5); 1683 sprintf (buffer, fmt[i], (devname[4] == 'm') ? 'p' : 't', pty1[indexx >> 4], pty2[indexx & 0x0f]); 1684 } 1685 1686 if(ENABLE_DEBUG && compat_name!=NULL) 1687 msg_logger(LOG_INFO, "%s: compat_name %s", __FUNCTION__, compat_name); 1688 1689 return (compat_name); 1478 indexx = atoi(devname + 5); 1479 sprintf(buffer, fmt[i], (devname[4] == 'm') ? 'p' : 't', pty1[indexx >> 4], pty2[indexx & 0x0f]); 1480 } 1481 return compat_name; 1690 1482 } /* End Function get_old_name */ 1691 1483 1692 static char get_old_ide_name 1484 static char get_old_ide_name(unsigned int major, unsigned int minor) 1693 1485 /* [SUMMARY] Get the old IDE name for a device. 1694 1486 <major> The major number for the device. … … 1697 1489 */ 1698 1490 { 1699 char letter='y'; /* 121 */ 1700 char c='a'; /* 97 */ 1701 int i=IDE0_MAJOR; 1702 1703 debug_msg_logger(LOG_INFO, __FUNCTION__); 1491 char letter = 'y'; /* 121 */ 1492 char c = 'a'; /* 97 */ 1493 int i = IDE0_MAJOR; 1704 1494 1705 1495 /* I hope it works like the previous code as it saves a few bytes. Tito ;P */ 1706 1496 do { 1707 if( i==IDE0_MAJOR || i==IDE1_MAJOR || i==IDE2_MAJOR || 1708 i==IDE3_MAJOR || i==IDE4_MAJOR || i==IDE5_MAJOR || 1709 i==IDE6_MAJOR || i==IDE7_MAJOR || i==IDE8_MAJOR || 1710 i==IDE9_MAJOR ) 1711 { 1712 if((unsigned int)i==major) 1713 { 1714 letter=c; 1497 if (i == IDE0_MAJOR || i == IDE1_MAJOR || i == IDE2_MAJOR 1498 || i == IDE3_MAJOR || i == IDE4_MAJOR || i == IDE5_MAJOR 1499 || i == IDE6_MAJOR || i == IDE7_MAJOR || i == IDE8_MAJOR 1500 || i == IDE9_MAJOR 1501 ) { 1502 if ((unsigned int)i == major) { 1503 letter = c; 1715 1504 break; 1716 1505 } 1717 c +=2;1506 c += 2; 1718 1507 } 1719 1508 i++; 1720 } while (i<=IDE9_MAJOR);1509 } while (i <= IDE9_MAJOR); 1721 1510 1722 1511 if (minor > 63) 1723 1512 ++letter; 1724 return (letter);1513 return letter; 1725 1514 } /* End Function get_old_ide_name */ 1726 1515 1727 static char *write_old_sd_name 1516 static char *write_old_sd_name(char *buffer, 1728 1517 unsigned int major, unsigned int minor, 1729 c har *part)1518 const char *part) 1730 1519 /* [SUMMARY] Write the old SCSI disc name to a buffer. 1731 1520 <buffer> The buffer to write to. … … 1738 1527 unsigned int disc_index; 1739 1528 1740 debug_msg_logger(LOG_INFO, __FUNCTION__); 1741 1742 if (major == 8) 1743 { 1744 sprintf (buffer, "sd%c%s", 'a' + (minor >> 4), part); 1745 return (buffer); 1746 } 1747 if ( (major > 64) && (major < 72) ) 1748 { 1749 disc_index = ( (major - 64) << 4 ) + (minor >> 4); 1529 if (major == 8) { 1530 sprintf(buffer, "sd%c%s", 'a' + (minor >> 4), part); 1531 return buffer; 1532 } 1533 if ((major > 64) && (major < 72)) { 1534 disc_index = ((major - 64) << 4) +(minor >> 4); 1750 1535 if (disc_index < 26) 1751 sprintf 1536 sprintf(buffer, "sd%c%s", 'a' + disc_index, part); 1752 1537 else 1753 sprintf (buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26,part);1754 return (buffer);1755 } 1756 return (NULL);1538 sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part); 1539 return buffer; 1540 } 1541 return NULL; 1757 1542 } /* End Function write_old_sd_name */ 1758 1543 … … 1762 1547 /*EXPERIMENTAL_FUNCTION*/ 1763 1548 1764 int st_expr_expand 1765 const char *(*get_variable_func) 1549 int st_expr_expand(char *output, unsigned int length, const char *input, 1550 const char *(*get_variable_func)(const char *variable, 1766 1551 void *info), 1767 1552 void *info) … … 1785 1570 char buffer[BUFFER_SIZE], tmp[STRING_LENGTH]; 1786 1571 1787 debug_msg_logger(LOG_INFO, __FUNCTION__);1788 1789 1572 if (length > BUFFER_SIZE) 1790 1573 length = BUFFER_SIZE; 1791 for (; TRUE; ++input) 1792 { 1793 switch (ch = *input) 1794 { 1574 for (; TRUE; ++input) { 1575 switch (ch = *input) { 1795 1576 case '$': 1796 1577 /* Variable expansion */ 1797 input = expand_variable 1578 input = expand_variable(buffer, length, &out_pos, ++input, get_variable_func, info); 1798 1579 if (input == NULL) 1799 return (FALSE);1580 return FALSE; 1800 1581 break; 1801 1582 case '~': 1802 1583 /* Home directory expansion */ 1803 1584 ch = input[1]; 1804 if ( isspace (ch) || (ch == '/') || (ch == '\0') ) 1805 { 1585 if (isspace(ch) ||(ch == '/') ||(ch == '\0')) { 1806 1586 /* User's own home directory: leave separator for next time */ 1807 if ( ( env = getenv ("HOME") ) == NULL ) 1808 { 1809 msg_logger(LOG_INFO, bb_msg_variable_not_found, "HOME"); 1810 return (FALSE); 1587 if ((env = getenv("HOME")) == NULL) { 1588 info_logger(LOG_INFO, bb_msg_variable_not_found, "HOME"); 1589 return FALSE; 1811 1590 } 1812 len = strlen 1591 len = strlen(env); 1813 1592 if (len + out_pos >= length) 1814 1593 goto st_expr_expand_out; 1815 memcpy 1594 memcpy(buffer + out_pos, env, len + 1); 1816 1595 out_pos += len; 1817 1596 continue; 1818 1597 } 1819 1598 /* Someone else's home directory */ 1820 for (ptr = ++input; !isspace 1821 /* VOID */ 1599 for (ptr = ++input; !isspace(ch) && (ch != '/') && (ch != '\0'); ch = *++ptr) 1600 /* VOID */; 1822 1601 len = ptr - input; 1823 1602 if (len >= sizeof tmp) 1824 1603 goto st_expr_expand_out; 1825 safe_memcpy 1604 safe_memcpy(tmp, input, len); 1826 1605 input = ptr - 1; 1827 if ( ( pwent = getpwnam (tmp) ) == NULL ) 1828 { 1829 msg_logger(LOG_INFO, "no pwent for: %s", tmp); 1830 return (FALSE); 1606 if ((pwent = getpwnam(tmp)) == NULL) { 1607 info_logger(LOG_INFO, "no pwent for: %s", tmp); 1608 return FALSE; 1831 1609 } 1832 len = strlen 1610 len = strlen(pwent->pw_dir); 1833 1611 if (len + out_pos >= length) 1834 1612 goto st_expr_expand_out; 1835 memcpy 1613 memcpy(buffer + out_pos, pwent->pw_dir, len + 1); 1836 1614 out_pos += len; 1837 1615 break; … … 1842 1620 goto st_expr_expand_out; 1843 1621 buffer[out_pos++] = ch; 1844 if (ch == '\0') 1845 { 1846 memcpy (output, buffer, out_pos); 1847 return (TRUE); 1622 if (ch == '\0') { 1623 memcpy(output, buffer, out_pos); 1624 return TRUE; 1848 1625 } 1849 1626 break; … … 1851 1628 } 1852 1629 } 1853 return (FALSE);1630 return FALSE; 1854 1631 st_expr_expand_out: 1855 msg_logger(LOG_INFO, bb_msg_small_buffer);1856 return (FALSE);1632 info_logger(LOG_INFO, bb_msg_small_buffer); 1633 return FALSE; 1857 1634 } /* End Function st_expr_expand */ 1858 1635 … … 1860 1637 /* Private functions follow */ 1861 1638 1862 static const char *expand_variable 1639 static const char *expand_variable(char *buffer, unsigned int length, 1863 1640 unsigned int *out_pos, const char *input, 1864 const char *(*func) 1641 const char *(*func)(const char *variable, 1865 1642 void *info), 1866 1643 void *info) … … 1884 1661 char tmp[STRING_LENGTH]; 1885 1662 1886 debug_msg_logger(LOG_INFO, __FUNCTION__);1887 1888 1663 ch = input[0]; 1889 if (ch == '$') 1890 { 1664 if (ch == '$') { 1891 1665 /* Special case for "$$": PID */ 1892 sprintf ( tmp, "%d", (int) getpid ());1893 len = strlen 1666 sprintf(tmp, "%d",(int) getpid()); 1667 len = strlen(tmp); 1894 1668 if (len + *out_pos >= length) 1895 1669 goto expand_variable_out; 1896 1670 1897 memcpy 1671 memcpy(buffer + *out_pos, tmp, len + 1); 1898 1672 out_pos += len; 1899 return (input);1673 return input; 1900 1674 } 1901 1675 /* Ordinary variable expansion, possibly in braces */ 1902 if (ch != '{') 1903 { 1676 if (ch != '{') { 1904 1677 /* Simple variable expansion */ 1905 for (ptr = input; isalnum (ch) || (ch == '_') || (ch == ':');ch = *++ptr)1906 /* VOID */ 1678 for (ptr = input; isalnum(ch) || (ch == '_') || (ch == ':'); ch = *++ptr) 1679 /* VOID */; 1907 1680 len = ptr - input; 1908 1681 if ((size_t)len >= sizeof tmp) 1909 1682 goto expand_variable_out; 1910 1683 1911 safe_memcpy 1684 safe_memcpy(tmp, input, len); 1912 1685 input = ptr - 1; 1913 if ( ( env = get_variable_v2 (tmp, func, info) ) == NULL ) 1914 { 1915 msg_logger(LOG_INFO, bb_msg_variable_not_found, tmp); 1916 return (NULL); 1686 if ((env = get_variable_v2(tmp, func, info)) == NULL) { 1687 info_logger(LOG_INFO, bb_msg_variable_not_found, tmp); 1688 return NULL; 1917 1689 } 1918 len = strlen 1690 len = strlen(env); 1919 1691 if (len + *out_pos >= length) 1920 1692 goto expand_variable_out; 1921 1693 1922 memcpy 1694 memcpy(buffer + *out_pos, env, len + 1); 1923 1695 *out_pos += len; 1924 return (input);1696 return input; 1925 1697 } 1926 1698 /* Variable in braces: check for ':' tricks */ 1927 1699 ch = *++input; 1928 for (ptr = input; isalnum 1700 for (ptr = input; isalnum(ch) || (ch == '_'); ch = *++ptr) 1929 1701 /* VOID */; 1930 if (ch == '}') 1931 { 1702 if (ch == '}') { 1932 1703 /* Must be simple variable expansion with "${var}" */ 1933 1704 len = ptr - input; … … 1935 1706 goto expand_variable_out; 1936 1707 1937 safe_memcpy 1938 ptr = expand_variable (buffer, length, out_pos, tmp, func, info);1708 safe_memcpy(tmp, input, len); 1709 ptr = expand_variable(buffer, length, out_pos, tmp, func, info); 1939 1710 if (ptr == NULL) 1940 return (NULL); 1941 return (input + len); 1942 } 1943 if (ch != ':' || ptr[1] != '-' ) 1944 { 1945 msg_logger(LOG_INFO, "illegal char in var name"); 1946 return (NULL); 1711 return NULL; 1712 return input + len; 1713 } 1714 if (ch != ':' || ptr[1] != '-') { 1715 info_logger(LOG_INFO, "illegal char in var name"); 1716 return NULL; 1947 1717 } 1948 1718 /* It's that handy "${var:-word}" expression. Check if var is defined */ … … 1951 1721 goto expand_variable_out; 1952 1722 1953 safe_memcpy 1723 safe_memcpy(tmp, input, len); 1954 1724 /* Move input pointer to ':' */ 1955 1725 input = ptr; … … 1957 1727 ptr += 2; 1958 1728 ch = ptr[0]; 1959 for (open_braces = 1; open_braces > 0; ch = *++ptr) 1960 { 1961 switch (ch) 1962 { 1729 for (open_braces = 1; open_braces > 0; ch = *++ptr) { 1730 switch (ch) { 1963 1731 case '{': 1964 1732 ++open_braces; … … 1968 1736 break; 1969 1737 case '\0': 1970 msg_logger(LOG_INFO,"\"}\" not found in: %s", input);1971 return (NULL);1738 info_logger(LOG_INFO,"\"}\" not found in: %s", input); 1739 return NULL; 1972 1740 default: 1973 1741 break; … … 1976 1744 --ptr; 1977 1745 /* At this point ptr should point to closing brace of "${var:-word}" */ 1978 if ( ( env = get_variable_v2 (tmp, func, info) ) != NULL ) 1979 { 1746 if ((env = get_variable_v2(tmp, func, info)) != NULL) { 1980 1747 /* Found environment variable, so skip the input to the closing brace 1981 1748 and return the variable */ 1982 1749 input = ptr; 1983 len = strlen 1750 len = strlen(env); 1984 1751 if (len + *out_pos >= length) 1985 1752 goto expand_variable_out; 1986 1753 1987 memcpy 1754 memcpy(buffer + *out_pos, env, len + 1); 1988 1755 *out_pos += len; 1989 return (input);1756 return input; 1990 1757 } 1991 1758 /* Environment variable was not found, so process word. Advance input … … 1996 1763 goto expand_variable_out; 1997 1764 1998 safe_memcpy 1765 safe_memcpy(tmp, input, len); 1999 1766 input = ptr; 2000 if ( !st_expr_expand (tmp, STRING_LENGTH, tmp, func, info ))2001 return (NULL);2002 len = strlen 1767 if (!st_expr_expand(tmp, STRING_LENGTH, tmp, func, info)) 1768 return NULL; 1769 len = strlen(tmp); 2003 1770 if (len + *out_pos >= length) 2004 1771 goto expand_variable_out; 2005 1772 2006 memcpy 1773 memcpy(buffer + *out_pos, tmp, len + 1); 2007 1774 *out_pos += len; 2008 return (input);1775 return input; 2009 1776 expand_variable_out: 2010 msg_logger(LOG_INFO, bb_msg_small_buffer);2011 return (NULL);1777 info_logger(LOG_INFO, bb_msg_small_buffer); 1778 return NULL; 2012 1779 } /* End Function expand_variable */ 2013 1780 2014 1781 2015 static const char *get_variable_v2 2016 const char *(*func) 1782 static const char *get_variable_v2(const char *variable, 1783 const char *(*func)(const char *variable, void *info), 2017 1784 void *info) 2018 1785 /* [SUMMARY] Get a variable from the environment or . … … 2026 1793 const char *value; 2027 1794 2028 debug_msg_logger(LOG_INFO, __FUNCTION__); 2029 2030 if (func != NULL) 2031 { 2032 value = (*func) (variable, info); 1795 if (func != NULL) { 1796 value = (*func)(variable, info); 2033 1797 if (value != NULL) 2034 return (value);2035 } 2036 return getenv 1798 return value; 1799 } 1800 return getenv(variable); 2037 1801 } /* End Function get_variable */ 2038 1802 -
branches/stable/mindi-busybox/miscutils/eject.c
r821 r1770 14 14 */ 15 15 16 #include "busybox.h" 17 #include <fcntl.h> 18 #include <sys/ioctl.h> 19 #include <unistd.h> 20 #include <mntent.h> 16 #include "libbb.h" 21 17 22 18 /* various defines swiped from linux/cdrom.h */ 23 19 #define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */ 24 20 #define CDROMEJECT 0x5309 /* Ejects the cdrom media */ 25 #define DEFAULT_CDROM "/dev/cdrom" 21 #define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */ 22 /* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */ 23 #define CDS_TRAY_OPEN 2 26 24 25 #define FLAG_CLOSE 1 26 #define FLAG_SMART 2 27 28 int eject_main(int argc, char **argv); 27 29 int eject_main(int argc, char **argv) 28 30 { 29 31 unsigned long flags; 30 c har *device;31 struct mntent *m;32 const char *device; 33 int dev, cmd; 32 34 33 flags = bb_getopt_ulflags(argc, argv, "t"); 34 device = argv[optind] ? : DEFAULT_CDROM; 35 opt_complementary = "?1:t--T:T--t"; 36 flags = getopt32(argv, "tT"); 37 device = argv[optind] ? : "/dev/cdrom"; 35 38 36 if ((m = find_mount_point(device, bb_path_mtab_file))) { 37 if (umount(m->mnt_dir)) { 38 bb_error_msg_and_die("Can't umount"); 39 } else if (ENABLE_FEATURE_MTAB_SUPPORT) { 40 erase_mtab(m->mnt_fsname); 41 } 42 } 43 if (ioctl(bb_xopen(device, (O_RDONLY | O_NONBLOCK)), 44 (flags ? CDROMCLOSETRAY : CDROMEJECT))) { 45 bb_perror_msg_and_die("%s", device); 46 } 47 return (EXIT_SUCCESS); 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 47 48 dev = xopen(device, O_RDONLY|O_NONBLOCK); 49 cmd = CDROMEJECT; 50 if (flags & FLAG_CLOSE 51 || (flags & FLAG_SMART && ioctl(dev, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN)) 52 cmd = CDROMCLOSETRAY; 53 54 ioctl_or_perror_and_die(dev, cmd, NULL, "%s", device); 55 56 if (ENABLE_FEATURE_CLEAN_UP) 57 close(dev); 58 59 return EXIT_SUCCESS; 48 60 } -
branches/stable/mindi-busybox/miscutils/hdparm.c
r902 r1770 13 13 */ 14 14 15 #include "busybox.h" 16 #include <string.h> 17 #include <fcntl.h> 18 #include <errno.h> 19 #include <ctype.h> 20 #include <sys/ioctl.h> 21 #include <sys/sysmacros.h> 22 #include <sys/times.h> 23 #include <sys/mman.h> 24 #include <linux/types.h> 15 #include "libbb.h" 25 16 #include <linux/hdreg.h> 26 27 #if BB_BIG_ENDIAN && !defined(__USE_XOPEN)28 # define __USE_XOPEN29 #endif30 #include <unistd.h>31 17 32 18 /* device types */ … … 54 40 #define START_MODEL 27 /* ASCII model number */ 55 41 #define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */ 56 #define SECTOR_XFER_MAX 42 #define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */ 57 43 #define DWORD_IO 48 /* can do double-word IO (ATA-1 only) */ 58 44 #define CAPAB_0 49 /* capabilities */ … … 63 49 #define LCYLS_CUR 54 /* current logical cylinders */ 64 50 #define LHEADS_CUR 55 /* current logical heads */ 65 #define LSECTS_CUR 51 #define LSECTS_CUR 56 /* current logical sectors/track */ 66 52 #define CAPACITY_LSB 57 /* current capacity in sectors */ 67 53 #define CAPACITY_MSB 58 … … 142 128 #define CDROM 0x0005 143 129 144 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY145 static const char * 130 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 131 static const char *const pkt_str[] = { 146 132 "Direct-access device", /* word 0, bits 12-8 = 00 */ 147 133 "Sequential-access device", /* word 0, bits 12-8 = 01 */ … … 178 164 }; 179 165 180 static const char * 166 static const char *const ata1_cfg_str[] = { /* word 0 in ATA-1 mode */ 181 167 "Reserved", /* bit 0 */ 182 168 "hard sectored", /* bit 1 */ … … 215 201 216 202 /* word 49: capabilities 0 */ 217 #define STD_STBY 0x2000 /* 1=standard values supported (ATA); 218 0=vendor specific values */ 203 #define STD_STBY 0x2000 /* 1=standard values supported (ATA); 0=vendor specific values */ 219 204 #define IORDY_SUP 0x0800 /* 1=support; 0=may be supported */ 220 205 #define IORDY_OFF 0x0400 /* 1=may be disabled */ … … 254 239 /* word 81: minor version number */ 255 240 #define MINOR_MAX 0x22 256 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY 257 static const char *minor_str[MINOR_MAX+2] = { /* word 81 value: */ 258 "Unspecified", /* 0x0000 */ 259 "ATA-1 X3T9.2 781D prior to rev.4", /* 0x0001 */ 260 "ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ 261 "ATA-1 X3T9.2 781D rev.4", /* 0x0003 */ 262 "ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ 263 "ATA-2 X3T10 948D prior to rev.2k", /* 0x0005 */ 264 "ATA-3 X3T10 2008D rev.1", /* 0x0006 */ 265 "ATA-2 X3T10 948D rev.2k", /* 0x0007 */ 266 "ATA-3 X3T10 2008D rev.0", /* 0x0008 */ 267 "ATA-2 X3T10 948D rev.3", /* 0x0009 */ 268 "ATA-3 published, ANSI X3.298-199x", /* 0x000a */ 269 "ATA-3 X3T10 2008D rev.6", /* 0x000b */ 270 "ATA-3 X3T13 2008D rev.7 and 7a", /* 0x000c */ 271 "ATA/ATAPI-4 X3T13 1153D rev.6", /* 0x000d */ 272 "ATA/ATAPI-4 T13 1153D rev.13", /* 0x000e */ 273 "ATA/ATAPI-4 X3T13 1153D rev.7", /* 0x000f */ 274 "ATA/ATAPI-4 T13 1153D rev.18", /* 0x0010 */ 275 "ATA/ATAPI-4 T13 1153D rev.15", /* 0x0011 */ 276 "ATA/ATAPI-4 published, ANSI INCITS 317-1998", /* 0x0012 */ 277 "ATA/ATAPI-5 T13 1321D rev.3", 278 "ATA/ATAPI-4 T13 1153D rev.14", /* 0x0014 */ 279 "ATA/ATAPI-5 T13 1321D rev.1", /* 0x0015 */ 280 "ATA/ATAPI-5 published, ANSI INCITS 340-2000", /* 0x0016 */ 281 "ATA/ATAPI-4 T13 1153D rev.17", /* 0x0017 */ 282 "ATA/ATAPI-6 T13 1410D rev.0", /* 0x0018 */ 283 "ATA/ATAPI-6 T13 1410D rev.3a", /* 0x0019 */ 284 "ATA/ATAPI-7 T13 1532D rev.1", /* 0x001a */ 285 "ATA/ATAPI-6 T13 1410D rev.2", /* 0x001b */ 286 "ATA/ATAPI-6 T13 1410D rev.1", /* 0x001c */ 287 "ATA/ATAPI-7 published, ANSI INCITS 397-2005", /* 0x001d */ 288 "ATA/ATAPI-7 T13 1532D rev.0", /* 0x001e */ 289 "Reserved" /* 0x001f */ 290 "Reserved" /* 0x0020 */ 291 "ATA/ATAPI-7 T13 1532D rev.4a", /* 0x0021 */ 292 "ATA/ATAPI-6 published, ANSI INCITS 361-2002", /* 0x0022 */ 293 "Reserved" /* 0x0023-0xfffe*/ 241 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 242 static const char *const minor_str[MINOR_MAX + 2] = { 243 /* 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 */ 294 280 }; 295 281 #endif 296 static const char actual_ver[MINOR_MAX +2]= {297 298 0, /* 0x0000 WARNING:*/299 1, /* 0x0001 WARNING:*/300 1, /* 0x0002 WARNING:*/301 1, /* 0x0003 WARNING:*/302 2, /* 0x0004 WARNING: This array*/303 2, /* 0x0005 WARNING: corresponds*/304 3, /* 0x0006 WARNING: *exactly**/305 2, /* 0x0007 WARNING: to the ATA/*/306 3, /* 0x0008 WARNING: ATAPI version*/307 2, /* 0x0009 WARNING: listed in*/308 3, /* 0x000a WARNING: the*/309 3, /* 0x000b WARNING: minor_str*/310 3, /* 0x000c WARNING: array*/311 4, /* 0x000d WARNING: above.*/312 4, /* 0x000e WARNING:*/313 4, /* 0x000f WARNING: if you change*/314 4, /* 0x0010 WARNING: that one,*/315 4, /* 0x0011 WARNING: change this one*/316 4, /* 0x0012 WARNING: too!!!*/317 5, /* 0x0013 WARNING:*/318 4, /* 0x0014 WARNING:*/319 5, /* 0x0015 WARNING:*/320 5, /* 0x0016 WARNING:*/321 4, /* 0x0017 WARNING:*/322 6, /* 0x0018 WARNING:*/323 6, /* 0x0019 WARNING:*/324 7, /* 0x001a WARNING:*/325 6, /* 0x001b WARNING:*/326 6, /* 0x001c WARNING:*/327 7, /* 0x001d WARNING:*/328 7, /* 0x001e WARNING:*/329 0, /* 0x001f WARNING:*/330 0, /* 0x0020 WARNING:*/331 7, /* 0x0021 WARNING:*/332 6, /* 0x0022 WARNING:*/333 0 /* 0x0023-0xfffe*/282 static const char actual_ver[MINOR_MAX + 2] ALIGN1 = { 283 /* word 81 value: */ 284 0, /* 0x0000 WARNING: actual_ver[] array */ 285 1, /* 0x0001 WARNING: corresponds */ 286 1, /* 0x0002 WARNING: *exactly* */ 287 1, /* 0x0003 WARNING: to the ATA/ */ 288 2, /* 0x0004 WARNING: ATAPI version */ 289 2, /* 0x0005 WARNING: listed in */ 290 3, /* 0x0006 WARNING: the */ 291 2, /* 0x0007 WARNING: minor_str */ 292 3, /* 0x0008 WARNING: array */ 293 2, /* 0x0009 WARNING: above. */ 294 3, /* 0x000a WARNING: */ 295 3, /* 0x000b WARNING: If you change */ 296 3, /* 0x000c WARNING: that one, */ 297 4, /* 0x000d WARNING: change this one */ 298 4, /* 0x000e WARNING: too!!! */ 299 4, /* 0x000f */ 300 4, /* 0x0010 */ 301 4, /* 0x0011 */ 302 4, /* 0x0012 */ 303 5, /* 0x0013 */ 304 4, /* 0x0014 */ 305 5, /* 0x0015 */ 306 5, /* 0x0016 */ 307 4, /* 0x0017 */ 308 6, /* 0x0018 */ 309 6, /* 0x0019 */ 310 7, /* 0x001a */ 311 6, /* 0x001b */ 312 6, /* 0x001c */ 313 7, /* 0x001d */ 314 7, /* 0x001e */ 315 0, /* 0x001f */ 316 0, /* 0x0020 */ 317 7, /* 0x0021 */ 318 6, /* 0x0022 */ 319 0 /* 0x0023-0xfffe */ 334 320 }; 335 321 … … 341 327 #define NUM_CMD_FEAT_STR 48 342 328 343 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY344 static const char * 329 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 330 static const char *const cmd_feat_str[] = { 345 331 "", /* word 82 bit 15: obsolete */ 346 332 "NOP cmd", /* word 82 bit 14 */ … … 359 345 "Security Mode feature set", /* word 82 bit 1 */ 360 346 "SMART feature set", /* word 82 bit 0 */ 361 /* -------------- */347 /* -------------- */ 362 348 "", /* word 83 bit 15: !valid bit */ 363 349 "", /* word 83 bit 14: valid bit */ 364 "FLUSH CACHE EXT cmd", /* word 83 bit 13 */365 "Mandatory FLUSH CACHE cmd ", /* word 83 bit 12 */350 "FLUSH CACHE EXT cmd", /* word 83 bit 13 */ 351 "Mandatory FLUSH CACHE cmd ", /* word 83 bit 12 */ 366 352 "Device Configuration Overlay feature set ", 367 353 "48-bit Address feature set ", /* word 83 bit 10 */ … … 372 358 "Power-Up In Standby feature set", /* word 83 bit 5 */ 373 359 "Removable Media Status Notification feature set", 374 "Adv. Power Management feature set", /* word 83 bit 3 */360 "Adv. Power Management feature set", /* word 83 bit 3 */ 375 361 "CFA feature set", /* word 83 bit 2 */ 376 362 "READ/WRITE DMA QUEUED", /* word 83 bit 1 */ 377 363 "DOWNLOAD MICROCODE cmd", /* word 83 bit 0 */ 378 /* -------------- */364 /* -------------- */ 379 365 "", /* word 84 bit 15: !valid bit */ 380 366 "", /* word 84 bit 14: valid bit */ … … 408 394 409 395 /* words 89, 90, SECU ERASE TIME */ 410 #define ERASE_BITS 396 #define ERASE_BITS 0x00ff 411 397 412 398 /* word 92: master password revision */ … … 414 400 415 401 /* word 93: hw reset result */ 416 #define CBLID 417 #define RST0 418 #define DEV_DET 419 #define JUMPER_VAL 420 #define CSEL_VAL 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 */ 421 407 422 408 /* word 127: removable media status notification feature set support */ 423 #define RM_STAT_BITS 424 #define RM_STAT_SUP 409 #define RM_STAT_BITS 0x0003 410 #define RM_STAT_SUP 0x0001 425 411 426 412 /* word 128: security */ 427 #define SECU_ENABLED 428 #define SECU_LEVEL 429 #define NUM_SECU_STR 430 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY431 static const char * 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[] = { 432 418 "supported", /* word 128, bit 0 */ 433 419 "enabled", /* word 128, bit 1 */ … … 440 426 441 427 /* word 160: CFA power mode */ 442 #define VALID_W160 443 #define PWR_MODE_REQ 444 #define PWR_MODE_OFF 445 #define MAX_AMPS 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 */ 446 432 447 433 /* word 255: integrity */ 448 #define SIG 0x00ff /* signature location */ 449 #define SIG_VAL 0x00A5 /* signature value */ 450 451 #define TIMING_MB 64 452 #define TIMING_BUF_MB 1 453 #define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) 454 #define TIMING_BUF_COUNT (timing_MB / TIMING_BUF_MB) 455 #define BUFCACHE_FACTOR 2 456 457 #undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ 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 */ 458 443 459 444 /* Busybox messages and functions */ 460 static int bb_ioctl(int fd, int request, void *argp, const char *string) 461 { 462 int e = ioctl(fd, request, argp); 463 if (e && string) 464 bb_perror_msg(" %s", string); 465 return e; 466 } 467 468 static int bb_ioctl_alt(int fd, int cmd, unsigned char *args, int alt, const char *string) 445 #if ENABLE_IOCTL_HEX2STR_ERROR 446 static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt, const char *string) 469 447 { 470 448 if (!ioctl(fd, cmd, args)) 471 449 return 0; 472 450 args[0] = alt; 473 return bb_ioctl(fd, cmd, args, string); 474 } 475 476 static void on_off(unsigned int value); 477 478 static void print_flag_on_off(unsigned long get_arg, const char *s, unsigned long arg) 479 { 480 481 if (get_arg) 482 { 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) { 483 473 printf(" setting %s to %ld", s, arg); 484 474 on_off(arg); … … 486 476 } 487 477 488 static void bb_ioctl_on_off(int fd, int request, void *argp, const char *string, 489 const char * str) 490 { 491 if (ioctl(fd, request, &argp) != 0) 492 bb_perror_msg(" %s", string); 493 else 494 { 495 printf(" %s\t= %2ld", str, (unsigned long) argp); 496 on_off((unsigned long) argp); 497 } 498 } 499 500 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY 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 501 485 static void print_ascii(uint16_t *p, uint8_t length); 502 486 503 static void xprint_ascii(uint16_t *val ,int i, char * string, int n) 504 { 505 if (val[i]) 506 { 507 printf("\t%-20s",string); 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); 508 491 print_ascii(&val[i], n); 509 492 } 510 493 } 511 494 #endif 512 /* end of 513 514 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY495 /* end of busybox specific stuff */ 496 497 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 515 498 static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode) 516 499 { … … 518 501 uint8_t err_dma = 0; 519 502 520 for (ii = 0; ii <= MODE_MAX; ii++) 521 { 522 if (mode_sel & 0x0001) 523 { 524 printf("*%cdma%u ",cc,ii); 503 for (ii = 0; ii <= MODE_MAX; ii++) { 504 if (mode_sel & 0x0001) { 505 printf("*%cdma%u ", cc, ii); 525 506 if (*have_mode) 526 507 err_dma = 1; 527 508 *have_mode = 1; 528 } 529 else if (mode_sup & 0x0001) 530 printf("%cdma%u ",cc,ii); 531 532 mode_sup >>=1; 533 mode_sel >>=1; 509 } else if (mode_sup & 0x0001) 510 printf("%cdma%u ", cc, ii); 511 512 mode_sup >>= 1; 513 mode_sel >>= 1; 534 514 } 535 515 return err_dma; 536 516 } 537 517 538 static void print_ascii(uint16_t *p, uint8_t length) { 518 static void print_ascii(uint16_t *p, uint8_t length) 519 { 539 520 uint8_t ii; 540 521 char cl; 541 522 542 523 /* find first non-space & print it */ 543 for (ii = 0; ii< length; ii++) 544 { 545 if (((char) 0x00ff&((*p)>>8)) != ' ') 524 for (ii = 0; ii < length; ii++) { 525 if ((char)((*p)>>8) != ' ') 546 526 break; 547 if ((cl = (char) 0x00ff&(*p)) != ' ') 548 { 549 if (cl != '\0') printf("%c",cl); 527 cl = (char)(*p); 528 if (cl != ' ') { 529 if (cl != '\0') 530 printf("%c", cl); 550 531 p++; 551 532 ii++; … … 555 536 } 556 537 /* print the rest */ 557 for (; ii< length; ii++) 558 { 538 for (; ii< length; ii++) { 559 539 if (!(*p)) 560 540 break; /* some older devices have NULLs */ 561 printf("%c%c", (char)0x00ff&((*p)>>8),(char)(*p)&0x00ff);541 printf("%c%c", (char)((*p)>>8), (char)(*p)); 562 542 p++; 563 543 } 564 p rintf("\n");544 puts(""); 565 545 } 566 546 … … 584 564 swab(id_supplied, buf, sizeof(buf)); 585 565 val = buf; 586 } else val = id_supplied; 566 } else 567 val = id_supplied; 587 568 588 569 chksum &= 0xff; 589 570 590 571 /* check if we recognise the device type */ 591 printf("\n"); 592 if(!(val[GEN_CONFIG] & NOT_ATA)) 593 { 572 puts(""); 573 if (!(val[GEN_CONFIG] & NOT_ATA)) { 594 574 dev = ATA_DEV; 595 575 printf("ATA device, with "); 596 } 597 else if(val[GEN_CONFIG]==CFA_SUPPORT_VAL) 598 { 576 } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { 599 577 dev = ATA_DEV; 600 578 like_std = 4; 601 579 printf("CompactFlash ATA device, with "); 602 } 603 else if(!(val[GEN_CONFIG] & NOT_ATAPI)) 604 { 580 } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) { 605 581 dev = ATAPI_DEV; 606 582 eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT; 607 583 printf("ATAPI %s, with ", pkt_str[eqpt]); 608 584 like_std = 3; 609 } 610 else 585 } else 611 586 /*"Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/ 612 bb_error_msg_and_die(" Unknown device type");587 bb_error_msg_and_die("unknown device type"); 613 588 614 589 printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : ""); … … 620 595 * know yet what standard this device is using. 621 596 */ 622 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) ||623 (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL))624 {597 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) 598 || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) 599 ) { 625 600 like_std = 5; 626 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))601 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) 627 602 printf("powers-up in standby; SET FEATURES subcmd spins-up.\n"); 628 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))603 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) 629 604 printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n"); 630 605 } … … 640 615 * defined until ATA-3 & the CDROM std uses different words.) */ 641 616 printf("Standards:"); 642 if (eqpt != CDROM) 643 { 644 if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) 645 { 646 if(like_std < 3) like_std = 3; 617 if (eqpt != CDROM) { 618 if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) { 619 if (like_std < 3) like_std = 3; 647 620 std = actual_ver[val[MINOR]]; 648 if (std) printf("\n\tUsed: %s ",minor_str[val[MINOR]]);621 if (std) printf("\n\tUsed: %s ", minor_str[val[MINOR]]); 649 622 650 623 } … … 652 625 * thus, only the newest 4 issues need be supported. (That's 653 626 * what "kk" and "min_std" are all about.) */ 654 if (val[MAJOR] && (val[MAJOR] !=NOVAL_1)) 655 { 627 if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) { 656 628 printf("\n\tSupported: "); 657 629 jj = val[MAJOR] << 1; 658 630 kk = like_std >4 ? like_std-4: 0; 659 for (ii = 14; (ii >0)&&(ii>kk); ii--) 660 { 661 if (jj & 0x8000) 662 { 631 for (ii = 14; (ii >0)&&(ii>kk); ii--) { 632 if (jj & 0x8000) { 663 633 printf("%u ", ii); 664 if (like_std < ii) 665 { 634 if (like_std < ii) { 666 635 like_std = ii; 667 636 kk = like_std >4 ? like_std-4: 0; 668 637 } 669 if (min_std > ii) min_std = ii;638 if (min_std > ii) min_std = ii; 670 639 } 671 640 jj <<= 1; 672 641 } 673 if (like_std < 3) like_std = 3;642 if (like_std < 3) like_std = 3; 674 643 } 675 644 /* Figure out what standard the device is using if it hasn't told … … 677 646 * the words from the next level up. It happens. 678 647 */ 679 if (like_std < std) like_std = std;648 if (like_std < std) like_std = std; 680 649 681 650 if (((std == 5) || (!std && (like_std < 6))) && … … 683 652 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) || 684 653 ((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) && 685 ( val[CMDS_SUPP_2] & CMDS_W84) ) ) )686 {654 ( val[CMDS_SUPP_2] & CMDS_W84) ) ) 655 ) { 687 656 like_std = 6; 688 } 689 else if (((std == 4) || (!std && (like_std < 5))) && 657 } else if (((std == 4) || (!std && (like_std < 5))) && 690 658 ((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) || 691 659 (( val[HWRST_RSLT] & VALID) == VALID_VAL) || … … 694 662 { 695 663 like_std = 5; 696 } 697 else if (((std == 3) || (!std && (like_std < 4))) && 664 } else if (((std == 3) || (!std && (like_std < 4))) && 698 665 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && 699 666 ((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) || … … 701 668 (( val[CAPAB_1] & VALID) == VALID_VAL) || 702 669 (( val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) || 703 (( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) )704 {670 (( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) 671 ) { 705 672 like_std = 4; 706 } 707 else if (((std == 2) || (!std && (like_std < 3))) && 708 ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) ) 709 { 673 } else if (((std == 2) || (!std && (like_std < 3))) 674 && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) 675 ) { 710 676 like_std = 3; 711 } 712 else if (((std == 1) || (!std && (like_std < 2))) && 677 } else if (((std == 1) || (!std && (like_std < 2))) && 713 678 ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) || 714 679 (val[WHATS_VALID] & OK_W64_70)) ) … … 716 681 like_std = 2; 717 682 } 683 718 684 if (!std) 719 printf("\n\tLikely used: %u\n", like_std);685 printf("\n\tLikely used: %u\n", like_std); 720 686 else if (like_std > std) 721 printf("& some of %u\n", like_std);687 printf("& some of %u\n", like_std); 722 688 else 723 printf("\n"); 724 } 725 else 726 { 689 puts(""); 690 } else { 727 691 /* TBD: do CDROM stuff more thoroughly. For now... */ 728 692 kk = 0; 729 if (val[CDR_MINOR] == 9) 730 { 693 if (val[CDR_MINOR] == 9) { 731 694 kk = 1; 732 695 printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5"); 733 696 } 734 if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) 735 { 697 if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) { 736 698 kk = 1; 737 699 printf("\n\tSupported: CD-ROM ATAPI"); 738 700 jj = val[CDR_MAJOR] >> 1; 739 for (ii = 1; ii <15; ii++) 740 { 741 if(jj & 0x0001) printf("-%u ", ii); 701 for (ii = 1; ii < 15; ii++) { 702 if (jj & 0x0001) printf("-%u ", ii); 742 703 jj >>= 1; 743 704 } 744 705 } 745 printf("%s\n", (!kk) ? "\n\tLikely used CD-ROM ATAPI-1" : "");706 printf("%s\n", kk ? "" : "\n\tLikely used CD-ROM ATAPI-1"); 746 707 /* the cdrom stuff is more like ATA-2 than anything else, so: */ 747 708 like_std = 2; … … 753 714 printf("Configuration:\n"); 754 715 /* more info from the general configuration word */ 755 if ((eqpt != CDROM) && (like_std == 1)) 756 { 716 if ((eqpt != CDROM) && (like_std == 1)) { 757 717 jj = val[GEN_CONFIG] >> 1; 758 for (ii = 1; ii < 15; ii++) 759 {760 if(jj & 0x0001) printf("\t%s\n",ata1_cfg_str[ii]);718 for (ii = 1; ii < 15; ii++) { 719 if (jj & 0x0001) 720 printf("\t%s\n", ata1_cfg_str[ii]); 761 721 jj >>=1; 762 722 } 763 723 } 764 if (dev == ATAPI_DEV) 765 { 724 if (dev == ATAPI_DEV) { 766 725 if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_3MS_VAL) 767 726 strng = "3ms"; … … 770 729 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) 771 730 strng ="50us"; 772 else 731 else 773 732 strng = "Unknown"; 774 733 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ … … 781 740 strng = "Unknown"; 782 741 puts(strng); 783 } 784 else 785 { 742 } else { 786 743 /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */ 787 744 ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB]; 788 745 mm = 0; bbbig = 0; 789 if ( 746 if ((ll > 0x00FBFC10) && (!val[LCYLS])) 790 747 printf("\tCHS addressing not supported\n"); 791 else 792 { 748 else { 793 749 jj = val[WHATS_VALID] & OK_W54_58; 794 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", … … 796 752 797 753 if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES])) 798 printf("\tbytes/track: %u\tbytes/sector: %u\n",val[TRACK_BYTES], val[SECT_BYTES]); 799 800 if (jj) 801 { 754 printf("\tbytes/track: %u\tbytes/sector: %u\n", val[TRACK_BYTES], val[SECT_BYTES]); 755 756 if (jj) { 802 757 mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB]; 803 if (like_std < 3) 804 { 805 /* check Endian of capacity bytes */ 758 if (like_std < 3) { 759 /* check Endian of capacity bytes */ 806 760 nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR]; 807 761 oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB]; … … 809 763 mm = oo; 810 764 } 811 printf("\tCHS current addressable sectors:%11u\n", mm);765 printf("\tCHS current addressable sectors:%11u\n", mm); 812 766 } 813 767 } 814 768 /* LBA addressing */ 815 printf("\tLBA user addressable sectors:%11u\n", ll);816 if ( ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&817 (val[CMDS_SUPP_1] & SUPPORT_48_BIT))818 {819 bbbig = (uint64_t)val[LBA_64_MSB] 820 (uint64_t)val[LBA_48_MSB] 821 (uint64_t)val[LBA_MID] 822 val[LBA_LSB] 823 printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig);769 printf("\tLBA user addressable sectors:%11u\n", ll); 770 if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL) 771 && (val[CMDS_SUPP_1] & SUPPORT_48_BIT) 772 ) { 773 bbbig = (uint64_t)val[LBA_64_MSB] << 48 | 774 (uint64_t)val[LBA_48_MSB] << 32 | 775 (uint64_t)val[LBA_MID] << 16 | 776 val[LBA_LSB]; 777 printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig); 824 778 } 825 779 826 780 if (!bbbig) 827 781 bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ 828 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);829 bbbig = (bbbig <<9)/1000000;830 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);782 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); 783 bbbig = (bbbig << 9) / 1000000; 784 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); 831 785 832 786 if (bbbig > 1000) 833 787 printf("(%"PRIu64" GB)\n", bbbig/1000); 834 else 835 p rintf("\n");788 else 789 puts(""); 836 790 } 837 791 … … 839 793 printf("Capabilities:\n\t"); 840 794 841 if (dev == ATAPI_DEV) 842 { 795 if (dev == ATAPI_DEV) { 843 796 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, "); 844 797 if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, "); … … 846 799 if (val[CAPAB_0] & LBA_SUP) printf("LBA, "); 847 800 848 if (like_std != 1) 849 { 850 printf("IORDY%s(can%s be disabled)\n", 851 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", 801 if (like_std != 1) { 802 printf("IORDY%s(can%s be disabled)\n", 803 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", 852 804 (val[CAPAB_0] & IORDY_OFF) ? "" :"not"); 853 } 854 else 805 } else 855 806 printf("no IORDY\n"); 856 807 857 if ((like_std == 1) && val[BUF_TYPE]) 858 { 808 if ((like_std == 1) && val[BUF_TYPE]) { 859 809 printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE], 860 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", 810 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", 861 811 (val[BUF_TYPE] > 2) ? " with read caching ability" : ""); 862 812 } 863 813 864 if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) 865 { 866 printf("\tBuffer size: %.1fkB\n",(float)val[BUFFER__SIZE]/2); 867 } 868 if ((min_std < 4) && (val[RW_LONG])) 869 { 870 printf("\tbytes avail on r/w long: %u\n",val[RW_LONG]); 871 } 872 if ((eqpt != CDROM) && (like_std > 3)) 873 { 874 printf("\tQueue depth: %u\n",(val[QUEUE_DEPTH] & DEPTH_BITS)+1); 875 } 876 877 if (dev == ATA_DEV) 878 { 814 if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) { 815 printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2); 816 } 817 if ((min_std < 4) && (val[RW_LONG])) { 818 printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]); 819 } 820 if ((eqpt != CDROM) && (like_std > 3)) { 821 printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1); 822 } 823 824 if (dev == ATA_DEV) { 879 825 if (like_std == 1) 880 printf("\tCan%s perform double-word IO\n",(!val[DWORD_IO]) ?"not":""); 881 else 882 { 826 printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : ""); 827 else { 883 828 printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor"); 884 829 if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL)) 885 printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER)?"with":"no");830 printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no"); 886 831 else 887 printf("\n");832 puts(""); 888 833 } 889 834 printf("\tR/W multiple sector transfer: "); 890 835 if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER)) 891 836 printf("not supported\n"); 892 else 893 { 894 printf("Max = %u\tCurrent = ",val[SECTOR_XFER_MAX] & SECTOR_XFER); 837 else { 838 printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER); 895 839 if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID) 896 840 printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER); … … 898 842 printf("?\n"); 899 843 } 900 if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) 901 { 844 if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) { 902 845 /* We print out elsewhere whether the APM feature is enabled or 903 846 not. If it's not enabled, let's not repeat the info; just print 904 847 nothing here. */ 905 848 printf("\tAdvancedPM level: "); 906 if ( (val[ADV_PWR] & 0xFF00) == 0x4000 ) 907 { 849 if ((val[ADV_PWR] & 0xFF00) == 0x4000) { 908 850 uint8_t apm_level = val[ADV_PWR] & 0x00FF; 909 851 printf("%u (0x%x)\n", apm_level, apm_level); … … 914 856 if (like_std > 5 && val[ACOUSTIC]) { 915 857 printf("\tRecommended acoustic management value: %u, current value: %u\n", 916 (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff); 917 } 918 } 919 else 920 { 858 (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff); 859 } 860 } else { 921 861 /* ATAPI */ 922 862 if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ)) 923 863 printf("\tATA sw reset required\n"); 924 864 925 if (val[PKT_REL] || val[SVC_NBSY]) 926 { 865 if (val[PKT_REL] || val[SVC_NBSY]) { 927 866 printf("\tOverlap support:"); 928 if (val[PKT_REL]) printf(" %uus to release bus.", val[PKT_REL]);929 if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.", val[SVC_NBSY]);930 p rintf("\n");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(""); 931 870 } 932 871 } … … 936 875 if (!(val[CAPAB_0] & DMA_SUP)) 937 876 printf("not supported\n"); 938 else 939 { 877 else { 940 878 if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA]) 941 printf(" sdma%u\n",(val[DMA_MODE] & MODE) >> 8); 942 if (val[SINGLE_DMA]) 943 { 879 printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8); 880 if (val[SINGLE_DMA]) { 944 881 jj = val[SINGLE_DMA]; 945 882 kk = val[SINGLE_DMA] >> 8; 946 err_dma += mode_loop(jj,kk,'s',&have_mode); 947 } 948 if (val[MULTI_DMA]) 949 { 883 err_dma += mode_loop(jj, kk, 's', &have_mode); 884 } 885 if (val[MULTI_DMA]) { 950 886 jj = val[MULTI_DMA]; 951 887 kk = val[MULTI_DMA] >> 8; 952 err_dma += mode_loop(jj,kk,'m',&have_mode); 953 } 954 if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) 955 { 888 err_dma += mode_loop(jj, kk, 'm', &have_mode); 889 } 890 if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) { 956 891 jj = val[ULTRA_DMA]; 957 892 kk = val[ULTRA_DMA] >> 8; 958 err_dma += mode_loop(jj, kk,'u',&have_mode);893 err_dma += mode_loop(jj, kk, 'u', &have_mode); 959 894 } 960 895 if (err_dma || !have_mode) printf("(?)"); 961 p rintf("\n");896 puts(""); 962 897 963 898 if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP)) 964 899 printf("\t\tInterleaved DMA support\n"); 965 900 966 if ((val[WHATS_VALID] & OK_W64_70) &&967 (val[DMA_TIME_MIN] || val[DMA_TIME_NORM]))968 {901 if ((val[WHATS_VALID] & OK_W64_70) 902 && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM]) 903 ) { 969 904 printf("\t\tCycle time:"); 970 if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);971 if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);972 p rintf("\n");905 if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]); 906 if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]); 907 puts(""); 973 908 } 974 909 } … … 978 913 /* If a drive supports mode n (e.g. 3), it also supports all modes less 979 914 * than n (e.g. 3, 2, 1 and 0). Print all the modes. */ 980 if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) 981 { 915 if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) { 982 916 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; 983 for (ii = 0; ii <= PIO_MODE_MAX ; ii++) 984 { 985 if (jj & 0x0001) printf("pio%d ",ii); 917 for (ii = 0; ii <= PIO_MODE_MAX; ii++) { 918 if (jj & 0x0001) printf("pio%d ", ii); 986 919 jj >>=1; 987 920 } 988 printf("\n"); 989 } 990 else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE) ) 991 { 921 puts(""); 922 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { 992 923 for (ii = 0; ii <= val[PIO_MODE]>>8; ii++) 993 printf("pio%d ",ii); 994 printf("\n"); 995 } 996 else 924 printf("pio%d ", ii); 925 puts(""); 926 } else 997 927 printf("unknown\n"); 998 928 999 if (val[WHATS_VALID] & OK_W64_70) 1000 { 1001 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) 1002 { 929 if (val[WHATS_VALID] & OK_W64_70) { 930 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) { 1003 931 printf("\t\tCycle time:"); 1004 932 if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]); 1005 933 if (val[PIO_FLOW]) printf(" IORDY flow control=%uns", val[PIO_FLOW]); 1006 printf("\n"); 1007 } 1008 } 1009 1010 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) 1011 { 934 puts(""); 935 } 936 } 937 938 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) { 1012 939 printf("Commands/features:\n\tEnabled\tSupported:\n"); 1013 940 jj = val[CMDS_SUPP_0]; 1014 941 kk = val[CMDS_EN_0]; 1015 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) 1016 { 1017 if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) 1018 { 942 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) { 943 if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) { 1019 944 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", cmd_feat_str[ii]); 1020 945 } 1021 jj <<= 1; kk<<=1;1022 if (ii%16 == 15)1023 {946 jj <<= 1; 947 kk <<= 1; 948 if (ii % 16 == 15) { 1024 949 jj = val[CMDS_SUPP_0+1+(ii/16)]; 1025 950 kk = val[CMDS_EN_0+1+(ii/16)]; 1026 951 } 1027 if (ii == 31) 1028 { 952 if (ii == 31) { 1029 953 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) 1030 954 ii +=16; … … 1033 957 } 1034 958 /* Removable Media Status Notification feature set */ 1035 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)959 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) 1036 960 printf("\t%s supported\n", cmd_feat_str[27]); 1037 961 1038 1039 962 /* security */ 1040 if ((eqpt != CDROM) && (like_std > 3) &&1041 (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME]))1042 {963 if ((eqpt != CDROM) && (like_std > 3) 964 && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME]) 965 ) { 1043 966 printf("Security:\n"); 1044 967 if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1)) 1045 printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);968 printf("\tMaster password revision code = %u\n", val[PSWD_CODE]); 1046 969 jj = val[SECU_STATUS]; 1047 if (jj) 1048 { 1049 for (ii = 0; ii < NUM_SECU_STR; ii++) 1050 { 970 if (jj) { 971 for (ii = 0; ii < NUM_SECU_STR; ii++) { 1051 972 printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", secu_str[ii]); 1052 973 jj >>=1; 1053 974 } 1054 if (val[SECU_STATUS] & SECU_ENABLED) 1055 { 975 if (val[SECU_STATUS] & SECU_ENABLED) { 1056 976 printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high"); 1057 977 } … … 1059 979 jj = val[ERASE_TIME] & ERASE_BITS; 1060 980 kk = val[ENH_ERASE_TIME] & ERASE_BITS; 1061 if (jj || kk) 1062 { 981 if (jj || kk) { 1063 982 printf("\t"); 1064 983 if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, ""); 1065 984 if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED "); 1066 p rintf("\n");985 puts(""); 1067 986 } 1068 987 } … … 1070 989 /* reset result */ 1071 990 jj = val[HWRST_RSLT]; 1072 if ((jj & VALID) == VALID_VAL) 1073 { 991 if ((jj & VALID) == VALID_VAL) { 1074 992 if (!(oo = (jj & RST0))) 1075 993 jj >>= 8; … … 1078 996 else if ((jj & DEV_DET) == CSEL_VAL) 1079 997 strng = " determined by CSEL"; 1080 else 998 else 1081 999 strng = ""; 1082 printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n", 1000 printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n", 1083 1001 (val[HWRST_RSLT] & CBLID) ? "above" : "below", !(oo), strng); 1084 1002 } 1085 1003 1086 1004 /* more stuff from std 5 */ 1087 if ((like_std > 4) && (eqpt != CDROM)) 1088 { 1089 if (val[CFA_PWR_MODE] & VALID_W160) 1090 { 1005 if ((like_std > 4) && (eqpt != CDROM)) { 1006 if (val[CFA_PWR_MODE] & VALID_W160) { 1091 1007 printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled", 1092 1093 1094 if (val[CFA_PWR_MODE] & MAX_AMPS) printf("\tMaximum current = %uma\n",val[CFA_PWR_MODE] & MAX_AMPS);1095 }1096 if ((val[INTEGRITY] & SIG) == SIG_VAL)1097 {1008 (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : ""); 1009 1010 if (val[CFA_PWR_MODE] & MAX_AMPS) 1011 printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS); 1012 } 1013 if ((val[INTEGRITY] & SIG) == SIG_VAL) { 1098 1014 printf("Checksum: %scorrect\n", chksum ? "in" : ""); 1099 1015 } … … 1104 1020 #endif 1105 1021 1106 static int get_identity, get_geom; 1107 static int do_flush; 1108 static int do_ctimings, do_timings; 1109 static unsigned long set_readahead, get_readahead, Xreadahead; 1110 static unsigned long set_readonly, get_readonly, readonly; 1111 static unsigned long set_unmask, get_unmask, unmask; 1112 static unsigned long set_mult, get_mult, mult; 1113 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA 1114 static unsigned long set_dma, get_dma, dma; 1115 #endif 1116 static unsigned long set_dma_q, get_dma_q, dma_q; 1117 static unsigned long set_nowerr, get_nowerr, nowerr; 1118 static unsigned long set_keep, get_keep, keep; 1119 static unsigned long set_io32bit, get_io32bit, io32bit; 1120 static unsigned long set_piomode, noisy_piomode; 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; 1121 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_DMA 1046 static unsigned long dma; 1047 static smallint set_dma, get_dma; 1048 #endif 1122 1049 #ifdef HDIO_DRIVE_CMD 1123 static unsigned long set_dkeep, get_dkeep, dkeep; 1124 static unsigned long set_standby, get_standby, standby_requested; 1125 static unsigned long set_xfermode, get_xfermode; 1050 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; 1126 1063 static int xfermode_requested; 1127 static unsigned long set_lookahead, get_lookahead, lookahead; 1128 static unsigned long set_prefetch, get_prefetch, prefetch; 1129 static unsigned long set_defects, get_defects, defects; 1130 static unsigned long set_wcache, get_wcache, wcache; 1131 static unsigned long set_doorlock, get_doorlock, doorlock; 1132 static unsigned long set_seagate, get_seagate; 1133 static unsigned long set_standbynow, get_standbynow; 1134 static unsigned long set_sleepnow, get_sleepnow; 1135 static unsigned long get_powermode; 1136 static unsigned long set_apmmode, get_apmmode, apmmode; 1137 #endif 1138 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY 1139 static int get_IDentity; 1140 #endif 1141 #ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 1142 static unsigned long unregister_hwif; 1143 static unsigned long hwif; 1144 #endif 1145 #ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF 1146 static unsigned long scan_hwif; 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 #endif 1073 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_HWIF 1147 1083 static unsigned long hwif_data; 1148 1084 static unsigned long hwif_ctrl; 1149 1085 static unsigned long hwif_irq; 1150 1086 #endif 1151 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF1152 static unsigned long set_busstate, get_busstate, busstate;1153 #endif1154 static int reread_partn;1155 1156 #ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET1157 static int perform_reset;1158 #endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */1159 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF1160 static unsigned long perform_tristate, tristate;1161 #endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */1162 1087 1163 1088 // Historically, if there was no HDIO_OBSOLETE_IDENTITY, then … … 1172 1097 // Too bad, really. 1173 1098 1174 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY1175 static const char * const cfg_str[] =1176 {"", "HardSect", "SoftSect", "NotMFM",1099 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 1100 static const char *const cfg_str[] = { 1101 "", "HardSect", "SoftSect", "NotMFM", 1177 1102 "HdSw>15uSec", "SpinMotCtl", "Fixed", "Removeable", 1178 1103 "DTR<=5Mbs", "DTR>5Mbs", "DTR>10Mbs", "RotSpdTol>.5%", … … 1180 1105 }; 1181 1106 1182 static const char * const BuffType[] = {"Unknown", "1Sect", "DualPort", "DualPortCache"}; 1107 static const char *const BuffType[] = { 1108 "Unknown", "1Sect", "DualPort", "DualPortCache" 1109 }; 1183 1110 1184 1111 static void dump_identity(const struct hd_driveid *id) 1185 1112 { 1186 1113 int i; 1187 const unsigned short int *id_regs = (const void*) id;1114 const unsigned short int *id_regs = (const void*) id; 1188 1115 1189 1116 printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={", 1190 1117 id->model, id->fw_rev, id->serial_no); 1191 for (i =0; i<=15; i++) {1118 for (i = 0; i <= 15; i++) { 1192 1119 if (id->config & (1<<i)) 1193 1120 printf(" %s", cfg_str[i]); 1194 1121 } 1195 printf( 1122 printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n" 1196 1123 " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u", 1197 1124 id->cyls, id->heads, id->sectors, id->track_bytes, … … 1199 1126 id->buf_type, BuffType[(id->buf_type > 3) ? 0 : id->buf_type], 1200 1127 id->buf_size/2, id->max_multsect); 1201 if (id->max_multsect) 1202 { 1128 if (id->max_multsect) { 1203 1129 printf(", MultSect="); 1204 if (!(id->multsect_valid &1))1130 if (!(id->multsect_valid & 1)) 1205 1131 printf("?%u?", id->multsect); 1206 1132 else if (id->multsect) … … 1209 1135 printf("off"); 1210 1136 } 1211 p rintf("\n");1212 1213 if (!(id->field_valid&1))1137 puts(""); 1138 1139 if (!(id->field_valid & 1)) 1214 1140 printf(" (maybe):"); 1215 1141 1216 printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,1217 id->cur_sectors,1218 (BB_BIG_ENDIAN) ? 1219 (long unsigned int)(id->cur_capacity0 << 16) | id->cur_capacity1 :1220 (long unsigned int)(id->cur_capacity1 << 16) | id->cur_capacity0,1221 1222 1223 if (id->capability &2)1142 printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads, 1143 id->cur_sectors, 1144 (BB_BIG_ENDIAN) ? 1145 (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 : 1146 (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0, 1147 ((id->capability&2) == 0) ? "no" : "yes"); 1148 1149 if (id->capability & 2) 1224 1150 printf(", LBAsects=%u", id->lba_capacity); 1225 1151 1226 printf("\n IORDY=%s", (id->capability &8) ? (id->capability&4) ? "on/off" : "yes" : "no");1227 1228 if (((id->capability &8) || (id->field_valid&2)) && id->field_valid&2)1152 printf("\n IORDY=%s", (id->capability & 8) ? (id->capability & 4) ? "on/off" : "yes" : "no"); 1153 1154 if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2)) 1229 1155 printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy); 1230 1231 if ((id->capability &1) && (id->field_valid&2))1156 1157 if ((id->capability & 1) && (id->field_valid & 2)) 1232 1158 printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time); 1233 1159 1234 1160 printf("\n PIO modes: "); 1235 if (id->tPIO <= 5) 1236 { 1161 if (id->tPIO <= 5) { 1237 1162 printf("pio0 "); 1238 1163 if (id->tPIO >= 1) printf("pio1 "); 1239 1164 if (id->tPIO >= 2) printf("pio2 "); 1240 1165 } 1241 if (id->field_valid&2) 1242 { 1166 if (id->field_valid & 2) { 1243 1167 if (id->eide_pio_modes & 1) printf("pio3 "); 1244 1168 if (id->eide_pio_modes & 2) printf("pio4 "); 1245 1169 if (id->eide_pio_modes &~3) printf("pio? "); 1246 1170 } 1247 if (id->capability&1) 1248 { 1249 if (id->dma_1word | id->dma_mword) 1250 { 1171 if (id->capability & 1) { 1172 if (id->dma_1word | id->dma_mword) { 1251 1173 printf("\n DMA modes: "); 1252 1174 if (id->dma_1word & 0x100) printf("*"); … … 1268 1190 } 1269 1191 } 1270 if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&4) 1271 { 1192 if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) { 1272 1193 printf("\n UDMA modes: "); 1273 1194 if (id->dma_ultra & 0x100) printf("*"); … … 1278 1199 if (id->dma_ultra & 0x004) printf("udma2 "); 1279 1200 #ifdef __NEW_HD_DRIVE_ID 1280 if (id->hw_config & 0x2000) 1281 { 1201 if (id->hw_config & 0x2000) { 1282 1202 #else /* !__NEW_HD_DRIVE_ID */ 1283 if (id->word93 & 0x2000) 1284 { 1203 if (id->word93 & 0x2000) { 1285 1204 #endif /* __NEW_HD_DRIVE_ID */ 1286 1205 if (id->dma_ultra & 0x0800) printf("*"); … … 1296 1215 } 1297 1216 } 1298 printf("\n AdvancedPM=%s",((id_regs[83]&8)==0)?"no":"yes"); 1299 if (id_regs[83] & 8) 1300 { 1301 if (!(id_regs[86]&8)) 1217 printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes"); 1218 if (id_regs[83] & 8) { 1219 if (!(id_regs[86] & 8)) 1302 1220 printf(": disabled (255)"); 1303 else if ((id_regs[91] &0xFF00)!=0x4000)1221 else if ((id_regs[91] & 0xFF00) != 0x4000) 1304 1222 printf(": unknown setting"); 1305 1223 else 1306 printf(": mode=0x%02X (%u)", id_regs[91]&0xFF,id_regs[91]&0xFF);1307 } 1308 if (id_regs[82] &0x20)1309 printf(" WriteCache=%s", (id_regs[85]&0x20) ? "enabled" : "disabled");1224 printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF); 1225 } 1226 if (id_regs[82] & 0x20) 1227 printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled"); 1310 1228 #ifdef __NEW_HD_DRIVE_ID 1311 if ((id->minor_rev_num && id->minor_rev_num <= 31) || (id->major_rev_num && id->minor_rev_num <= 31)) 1312 { 1229 if ((id->minor_rev_num && id->minor_rev_num <= 31) 1230 || (id->major_rev_num && id->minor_rev_num <= 31) 1231 ) { 1313 1232 printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown"); 1314 1233 if (id->major_rev_num != 0x0000 && /* NOVAL_0 */ 1315 1234 id->major_rev_num != 0xFFFF) { /* NOVAL_1 */ 1316 for (i =0; i <= 15; i++) {1235 for (i = 0; i <= 15; i++) { 1317 1236 if (id->major_rev_num & (1<<i)) 1318 1237 printf(" ATA/ATAPI-%u", i); … … 1328 1247 { 1329 1248 fsync(fd); /* flush buffers */ 1330 bb_ioctl(fd, BLKFLSBUF, NULL,"BLKFLSBUF" ) ;/* do it again, big time */1249 ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */ 1331 1250 #ifdef HDIO_DRIVE_CMD 1332 1251 sleep(1); 1333 if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) /* await completion */ 1334 bb_perror_msg("HDIO_DRIVE_CMD"); 1252 if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */ 1253 if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ 1254 bb_perror_msg("HDIO_DRIVE_CMD"); 1255 else 1256 bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD); 1257 } 1335 1258 #endif 1336 1259 } … … 1347 1270 int i; 1348 1271 1349 if ((i = read(fd, buf, TIMING_BUF_BYTES)) != TIMING_BUF_BYTES) { 1272 i = read(fd, buf, TIMING_BUF_BYTES); 1273 if (i != TIMING_BUF_BYTES) { 1350 1274 bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i); 1351 1275 return 1; … … 1357 1281 } 1358 1282 1359 static void print_timing(int t, double e) 1360 { 1361 if (t >= e) /* more than 1MB/s */ 1362 printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e, 'M'); 1363 else 1364 printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e * 1024, 'k'); 1365 } 1366 1367 static int do_blkgetsize (int fd, unsigned long long *blksize64) 1368 { 1369 int rc; 1370 unsigned int blksize32 = 0; 1283 static int do_blkgetsize(int fd, unsigned long long *blksize64) 1284 { 1285 int rc; 1286 unsigned blksize32 = 0; 1371 1287 1372 1288 if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) { // returns bytes … … 1374 1290 return 0; 1375 1291 } 1376 rc = ioctl(fd, BLKGETSIZE, &blksize32); // returns sectors 1377 if (rc) 1378 bb_perror_msg("BLKGETSIZE"); 1292 rc = ioctl_or_warn(fd, BLKGETSIZE, &blksize32); // returns sectors 1379 1293 *blksize64 = blksize32; 1380 1294 return rc; 1381 1295 } 1382 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 1383 1305 static void do_time(int flag, int fd) 1384 /* 1385 flag = 0 time_cache 1386 flag = 1 time_device 1387 */ 1388 { 1389 struct itimerval e1, e2; 1390 double elapsed, elapsed2; 1391 unsigned int max_iterations = 1024, total_MB, iterations; 1306 /* flag = 0 time_cache, 1 time_device */ 1307 { 1308 static const struct itimerval thousand = {{1000, 0}, {1000, 0}}; 1309 1310 struct itimerval itv; 1311 unsigned elapsed, elapsed2; 1312 unsigned max_iterations, total_MB, iterations; 1392 1313 unsigned long long blksize; 1393 1314 RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES); … … 1398 1319 } 1399 1320 1321 max_iterations = 1024; 1400 1322 if (0 == do_blkgetsize(fd, &blksize)) { 1401 1323 max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB; … … 1404 1326 /* Clear out the device request queues & give them time to complete */ 1405 1327 sync(); 1406 sleep(3); 1407 1408 setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL); 1409 1410 if (flag == 0) /* Time cache */ 1411 { 1412 if (seek_to_zero (fd)) return; 1413 if (read_big_block (fd, buf)) return; 1414 printf(" Timing cached reads: "); 1415 fflush(stdout); 1416 1417 /* Now do the timing */ 1418 iterations = 0; 1419 getitimer(ITIMER_REAL, &e1); 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: "); 1335 } else { /* Time device */ 1336 printf(" Timing buffered disk reads: "); 1337 } 1338 fflush(stdout); 1339 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 */ 1346 do { 1347 ++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); 1356 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); 1420 1360 do { 1421 ++iterations; 1422 if (seek_to_zero (fd) || read_big_block (fd, buf)) 1361 if (seek_to_zero(fd)) 1423 1362 goto quit; 1424 getitimer(ITIMER_REAL, &e2); 1425 elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) 1426 + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); 1427 } while (elapsed < 2.0); 1428 total_MB = iterations * TIMING_BUF_MB; 1429 1430 /* Now remove the lseek() and getitimer() overheads from the elapsed time */ 1431 getitimer(ITIMER_REAL, &e1); 1432 do { 1433 if (seek_to_zero (fd)) 1434 goto quit; 1435 getitimer(ITIMER_REAL, &e2); 1436 elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec) 1437 + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); 1363 getitimer(ITIMER_REAL, &itv); 1364 elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000 1365 - itv.it_value.tv_usec; 1438 1366 } while (--iterations); 1439 1440 1367 elapsed -= elapsed2; 1441 print_timing(BUFCACHE_FACTOR * total_MB, elapsed);1368 total_MB *= BUFCACHE_FACTOR; 1442 1369 flush_buffer_cache(fd); 1443 sleep(1); 1444 } 1445 else /* Time device */ 1446 { 1447 printf(" Timing buffered disk reads: "); 1448 fflush(stdout); 1449 /* 1450 * getitimer() is used rather than gettimeofday() because 1451 * it is much more consistent (on my machine, at least). 1452 */ 1453 /* Now do the timings for real */ 1454 iterations = 0; 1455 getitimer(ITIMER_REAL, &e1); 1456 do { 1457 ++iterations; 1458 if (read_big_block (fd, buf)) 1459 goto quit; 1460 getitimer(ITIMER_REAL, &e2); 1461 elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) 1462 + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); 1463 } while (elapsed < 3.0 && iterations < max_iterations); 1464 1465 total_MB = iterations * TIMING_BUF_MB; 1466 print_timing(total_MB, elapsed); 1467 } 1468 quit: 1370 } 1371 print_timing(total_MB, elapsed / 1000000.0); 1372 quit: 1469 1373 munlock(buf, TIMING_BUF_BYTES); 1470 quit2:1374 quit2: 1471 1375 RELEASE_CONFIG_BUFFER(buf); 1472 1376 } 1473 1377 1474 static void on_off (unsigned int value) 1475 { 1476 printf(value ? " (on)\n" : " (off)\n"); 1477 } 1478 1479 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1480 static void bus_state_value(unsigned int value) 1378 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1379 static void bus_state_value(unsigned value) 1481 1380 { 1482 1381 if (value == BUSSTATE_ON) … … 1492 1391 1493 1392 #ifdef HDIO_DRIVE_CMD 1494 static void interpret_standby(unsigned intstandby)1495 { 1496 unsigned intt;1393 static void interpret_standby(unsigned standby) 1394 { 1395 unsigned t; 1497 1396 1498 1397 printf(" ("); … … 1507 1406 else if (standby == 255) 1508 1407 printf("21 minutes + 15 seconds"); 1509 else { 1510 if (standby <= 240) { 1511 t = standby * 5; 1512 printf("%u minutes + %u seconds", t / 60, t % 60); 1513 } else if (standby <= 251) { 1514 t = (standby - 240) * 30; 1515 printf("%u hours + %u minutes", t / 60, t % 60); 1516 } else 1517 printf("illegal value"); 1518 } 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"); 1519 1416 printf(")\n"); 1520 1417 } 1521 1418 1522 struct xfermode_entry { 1523 int val; 1524 const char *name; 1419 static const uint8_t xfermode_val[] ALIGN1 = { 1420 8, 9, 10, 11, 12, 13, 14, 15, 1421 16, 17, 18, 19, 20, 21, 22, 23, 1422 32, 33, 34, 35, 36, 37, 38, 39, 1423 64, 65, 66, 67, 68, 69, 70, 71 1525 1424 }; 1526 1527 static const struct xfermode_entry xfermode_table[] = { 1528 { 8, "pio0" }, 1529 { 9, "pio1" }, 1530 { 10, "pio2" }, 1531 { 11, "pio3" }, 1532 { 12, "pio4" }, 1533 { 13, "pio5" }, 1534 { 14, "pio6" }, 1535 { 15, "pio7" }, 1536 { 16, "sdma0" }, 1537 { 17, "sdma1" }, 1538 { 18, "sdma2" }, 1539 { 19, "sdma3" }, 1540 { 20, "sdma4" }, 1541 { 21, "sdma5" }, 1542 { 22, "sdma6" }, 1543 { 23, "sdma7" }, 1544 { 32, "mdma0" }, 1545 { 33, "mdma1" }, 1546 { 34, "mdma2" }, 1547 { 35, "mdma3" }, 1548 { 36, "mdma4" }, 1549 { 37, "mdma5" }, 1550 { 38, "mdma6" }, 1551 { 39, "mdma7" }, 1552 { 64, "udma0" }, 1553 { 65, "udma1" }, 1554 { 66, "udma2" }, 1555 { 67, "udma3" }, 1556 { 68, "udma4" }, 1557 { 69, "udma5" }, 1558 { 70, "udma6" }, 1559 { 71, "udma7" }, 1560 { 0, NULL } 1425 /* NB: we save size by _not_ storing terninating NUL! */ 1426 static const char xfermode_name[][5] ALIGN1 = { 1427 "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7", 1428 "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7", 1429 "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7", 1430 "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7" 1561 1431 }; 1562 1432 1563 static int translate_xfermode(char * name) 1564 { 1565 const struct xfermode_entry *tmp; 1566 char *endptr; 1567 int val = -1; 1568 1569 1570 for (tmp = xfermode_table; tmp->name != NULL; ++tmp) 1571 { 1572 if (!strcmp(name, tmp->name)) 1573 return tmp->val; 1574 } 1575 1576 val = strtol(name, &endptr, 10); 1577 if (*endptr == '\0') 1433 static int translate_xfermode(const char *name) 1434 { 1435 int val, i; 1436 1437 for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) { 1438 if (!strncmp(name, xfermode_name[i], 5)) 1439 if (strlen(name) <= 5) 1440 return xfermode_val[i]; 1441 } 1442 /* Negative numbers are invalid and are caught later */ 1443 val = bb_strtoi(name, NULL, 10); 1444 if (!errno) 1578 1445 return val; 1579 1580 1446 return -1; 1581 1447 } 1582 1448 1583 static void interpret_xfermode(unsigned intxfermode)1449 static void interpret_xfermode(unsigned xfermode) 1584 1450 { 1585 1451 printf(" ("); … … 1589 1455 printf("default PIO mode, disable IORDY"); 1590 1456 else if (xfermode >= 8 && xfermode <= 15) 1591 printf("PIO flow control mode%u", xfermode -8);1457 printf("PIO flow control mode%u", xfermode - 8); 1592 1458 else if (xfermode >= 16 && xfermode <= 23) 1593 printf("singleword DMA mode%u", xfermode -16);1459 printf("singleword DMA mode%u", xfermode - 16); 1594 1460 else if (xfermode >= 32 && xfermode <= 39) 1595 printf("multiword DMA mode%u", xfermode -32);1461 printf("multiword DMA mode%u", xfermode - 32); 1596 1462 else if (xfermode >= 64 && xfermode <= 71) 1597 printf("UltraDMA mode%u", xfermode -64);1463 printf("UltraDMA mode%u", xfermode - 64); 1598 1464 else 1599 1465 printf("Unknown"); … … 1602 1468 #endif /* HDIO_DRIVE_CMD */ 1603 1469 1604 static void print_flag( unsigned long flag,char *s, unsigned long value)1605 { 1606 if (flag)1470 static void print_flag(int flag, const char *s, unsigned long value) 1471 { 1472 if (flag) 1607 1473 printf(" setting %s to %ld\n", s, value); 1608 1474 } … … 1611 1477 { 1612 1478 int fd; 1613 staticlong parm, multcount;1479 long parm, multcount; 1614 1480 #ifndef HDIO_DRIVE_CMD 1615 1481 int force_operation = 0; … … 1617 1483 /* Please restore args[n] to these values after each ioctl 1618 1484 except for args[2] */ 1619 unsigned char args[4] = { WIN_SETFEATURES,0,0,0};1485 unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 }; 1620 1486 const char *fmt = " %s\t= %2ld"; 1621 1487 1622 fd = bb_xopen(devname, O_RDONLY|O_NONBLOCK);1488 fd = xopen(devname, O_RDONLY|O_NONBLOCK); 1623 1489 printf("\n%s:\n", devname); 1624 1490 1625 if (set_readahead) 1626 { 1627 print_flag(get_readahead,"fs readahead", Xreadahead); 1628 bb_ioctl(fd, BLKRASET,(int *)Xreadahead,"BLKRASET"); 1629 } 1630 #ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 1631 if (unregister_hwif) 1632 { 1491 if (set_readahead) { 1492 print_flag(get_readahead, "fs readahead", Xreadahead); 1493 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead); 1494 } 1495 #if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 1496 if (unregister_hwif) { 1633 1497 printf(" attempting to unregister hwif#%lu\n", hwif); 1634 bb_ioctl(fd, HDIO_UNREGISTER_HWIF,(int *)(unsigned long)hwif,"HDIO_UNREGISTER_HWIF"); 1635 } 1636 #endif 1637 #ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF 1638 if (scan_hwif) 1639 { 1498 ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif); 1499 } 1500 #endif 1501 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 1502 if (scan_hwif) { 1640 1503 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq); 1641 1504 args[0] = hwif_data; 1642 1505 args[1] = hwif_ctrl; 1643 1506 args[2] = hwif_irq; 1644 bb_ioctl(fd, HDIO_SCAN_HWIF, args, "HDIO_SCAN_HWIF");1507 ioctl_or_warn(fd, HDIO_SCAN_HWIF, args); 1645 1508 args[0] = WIN_SETFEATURES; 1646 1509 args[1] = 0; 1647 1510 } 1648 1511 #endif 1649 if (set_piomode) 1650 { 1651 if (noisy_piomode) 1652 { 1512 if (set_piomode) { 1513 if (noisy_piomode) { 1653 1514 printf(" attempting to "); 1654 1515 if (piomode == 255) … … 1661 1522 printf("set UDMA mode to %d\n", (piomode-200)); 1662 1523 } 1663 bb_ioctl(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode, "HDIO_SET_PIO_MODE"); 1664 } 1665 if (set_io32bit) 1666 { 1667 print_flag(get_io32bit,"32-bit IO_support flag", io32bit); 1668 bb_ioctl(fd, HDIO_SET_32BIT, (int *)io32bit, "HDIO_SET_32BIT"); 1669 } 1670 if (set_mult) 1671 { 1524 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode); 1525 } 1526 if (set_io32bit) { 1527 print_flag(get_io32bit, "32-bit IO_support flag", io32bit); 1528 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit); 1529 } 1530 if (set_mult) { 1672 1531 print_flag(get_mult, "multcount", mult); 1673 1532 #ifdef HDIO_DRIVE_CMD 1674 bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT");1533 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult); 1675 1534 #else 1676 force_operation |= (!bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT")); 1677 #endif 1678 } 1679 if (set_readonly) 1680 { 1681 print_flag_on_off(get_readonly,"readonly", readonly); 1682 bb_ioctl(fd, BLKROSET, &readonly, "BLKROSET"); 1683 } 1684 if (set_unmask) 1685 { 1686 print_flag_on_off(get_unmask,"unmaskirq", unmask); 1687 bb_ioctl(fd, HDIO_SET_UNMASKINTR, (int *)unmask, "HDIO_SET_UNMASKINTR"); 1688 } 1689 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA 1690 if (set_dma) 1691 { 1535 force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult)); 1536 #endif 1537 } 1538 if (set_readonly) { 1539 print_flag_on_off(get_readonly, "readonly", readonly); 1540 ioctl_or_warn(fd, BLKROSET, &readonly); 1541 } 1542 if (set_unmask) { 1543 print_flag_on_off(get_unmask, "unmaskirq", unmask); 1544 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask); 1545 } 1546 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 1547 if (set_dma) { 1692 1548 print_flag_on_off(get_dma, "using_dma", dma); 1693 bb_ioctl(fd, HDIO_SET_DMA, (int *)dma, "HDIO_SET_DMA"); 1694 } 1695 #endif /* CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA */ 1696 if (set_dma_q) 1697 { 1698 print_flag_on_off(get_dma_q,"DMA queue_depth", dma_q); 1699 bb_ioctl(fd, HDIO_SET_QDMA, (int *)dma_q, "HDIO_SET_QDMA"); 1700 } 1701 if (set_nowerr) 1702 { 1703 print_flag_on_off(get_nowerr,"nowerr", nowerr); 1704 bb_ioctl(fd, HDIO_SET_NOWERR, (int *)nowerr,"HDIO_SET_NOWERR"); 1705 } 1706 if (set_keep) 1707 { 1708 print_flag_on_off(get_keep,"keep_settings", keep); 1709 bb_ioctl(fd, HDIO_SET_KEEPSETTINGS, (int *)keep,"HDIO_SET_KEEPSETTINGS"); 1549 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma); 1550 } 1551 #endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */ 1552 if (set_dma_q) { 1553 print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q); 1554 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q); 1555 } 1556 if (set_nowerr) { 1557 print_flag_on_off(get_nowerr, "nowerr", nowerr); 1558 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr); 1559 } 1560 if (set_keep) { 1561 print_flag_on_off(get_keep, "keep_settings", keep); 1562 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep); 1710 1563 } 1711 1564 #ifdef HDIO_DRIVE_CMD 1712 if (set_doorlock) 1713 { 1565 if (set_doorlock) { 1714 1566 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK; 1715 1567 args[2] = 0; 1716 print_flag_on_off(get_doorlock, "drive doorlock", doorlock);1717 bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(doorlock)");1568 print_flag_on_off(get_doorlock, "drive doorlock", doorlock); 1569 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1718 1570 args[0] = WIN_SETFEATURES; 1719 1571 } 1720 if (set_dkeep) 1721 { 1572 if (set_dkeep) { 1722 1573 /* lock/unlock the drive's "feature" settings */ 1723 print_flag_on_off(get_dkeep, "drive keep features", dkeep);1574 print_flag_on_off(get_dkeep, "drive keep features", dkeep); 1724 1575 args[2] = dkeep ? 0x66 : 0xcc; 1725 bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(keepsettings)"); 1726 } 1727 if (set_defects) 1728 { 1576 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1577 } 1578 if (set_defects) { 1729 1579 args[2] = defects ? 0x04 : 0x84; 1730 print_flag(get_defects,"drive defect-mgmt", defects); 1731 bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(defectmgmt)"); 1732 } 1733 if (set_prefetch) 1734 { 1580 print_flag(get_defects, "drive defect-mgmt", defects); 1581 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1582 } 1583 if (set_prefetch) { 1735 1584 args[1] = prefetch; 1736 1585 args[2] = 0xab; 1737 print_flag(get_prefetch, "drive prefetch", prefetch);1738 bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setprefetch)");1586 print_flag(get_prefetch, "drive prefetch", prefetch); 1587 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1739 1588 args[1] = 0; 1740 1589 } 1741 if (set_xfermode) 1742 { 1590 if (set_xfermode) { 1743 1591 args[1] = xfermode_requested; 1744 1592 args[2] = 3; 1745 if (get_xfermode) 1746 { 1747 print_flag(1,"xfermode", xfermode_requested); 1593 if (get_xfermode) { 1594 print_flag(1, "xfermode", xfermode_requested); 1748 1595 interpret_xfermode(xfermode_requested); 1749 1596 } 1750 bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(setxfermode)");1597 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1751 1598 args[1] = 0; 1752 1599 } 1753 if (set_lookahead) 1754 { 1600 if (set_lookahead) { 1755 1601 args[2] = lookahead ? 0xaa : 0x55; 1756 print_flag_on_off(get_lookahead,"drive read-lookahead", lookahead); 1757 bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setreadahead)"); 1758 } 1759 if (set_apmmode) 1760 { 1602 print_flag_on_off(get_lookahead, "drive read-lookahead", lookahead); 1603 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1604 } 1605 if (set_apmmode) { 1761 1606 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */ 1762 1607 args[1] = apmmode; /* sector count register 1-255 */ 1763 1608 if (get_apmmode) 1764 1609 printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode); 1765 bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD");1610 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1766 1611 args[1] = 0; 1767 1612 } 1768 if (set_wcache) 1769 { 1613 if (set_wcache) { 1770 1614 #ifdef DO_FLUSHCACHE 1771 1615 #ifndef WIN_FLUSHCACHE 1772 1616 #define WIN_FLUSHCACHE 0xe7 1773 1617 #endif 1774 static unsigned char flushcache[4] = { WIN_FLUSHCACHE,0,0,0};1618 static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 }; 1775 1619 #endif /* DO_FLUSHCACHE */ 1776 1620 args[2] = wcache ? 0x02 : 0x82; 1777 print_flag_on_off(get_wcache, "drive write-caching", wcache);1621 print_flag_on_off(get_wcache, "drive write-caching", wcache); 1778 1622 #ifdef DO_FLUSHCACHE 1779 1623 if (!wcache) 1780 bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");1624 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache); 1781 1625 #endif /* DO_FLUSHCACHE */ 1782 bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setcache)");1626 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1783 1627 #ifdef DO_FLUSHCACHE 1784 1628 if (!wcache) 1785 bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");1629 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache); 1786 1630 #endif /* DO_FLUSHCACHE */ 1787 1631 } … … 1791 1635 args[2] = 0; 1792 1636 1793 if (set_standbynow) 1794 { 1637 if (set_standbynow) { 1795 1638 #ifndef WIN_STANDBYNOW1 1796 1639 #define WIN_STANDBYNOW1 0xE0 … … 1801 1644 if (get_standbynow) printf(" issuing standby command\n"); 1802 1645 args[0] = WIN_STANDBYNOW1; 1803 bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2, "HDIO_DRIVE_CMD(standby)"); 1804 } 1805 if (set_sleepnow) 1806 { 1646 ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2); 1647 } 1648 if (set_sleepnow) { 1807 1649 #ifndef WIN_SLEEPNOW1 1808 1650 #define WIN_SLEEPNOW1 0xE6 … … 1813 1655 if (get_sleepnow) printf(" issuing sleep command\n"); 1814 1656 args[0] = WIN_SLEEPNOW1; 1815 bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2, "HDIO_DRIVE_CMD(sleep)"); 1816 } 1817 if (set_seagate) 1818 { 1657 ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2); 1658 } 1659 if (set_seagate) { 1819 1660 args[0] = 0xfb; 1820 1661 if (get_seagate) printf(" disabling Seagate auto powersaving mode\n"); 1821 bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(seagatepwrsave)"); 1822 } 1823 if (set_standby) 1824 { 1662 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1663 } 1664 if (set_standby) { 1825 1665 args[0] = WIN_SETIDLE1; 1826 1666 args[1] = standby_requested; 1827 if (get_standby) 1828 { 1829 print_flag(1,"standby", standby_requested); 1667 if (get_standby) { 1668 print_flag(1, "standby", standby_requested); 1830 1669 interpret_standby(standby_requested); 1831 1670 } 1832 bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setidle1)");1671 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); 1833 1672 args[1] = 0; 1834 1673 } 1835 1674 #else /* HDIO_DRIVE_CMD */ 1836 if (force_operation) 1837 { 1675 if (force_operation) { 1838 1676 char buf[512]; 1839 1677 flush_buffer_cache(fd); … … 1843 1681 #endif /* HDIO_DRIVE_CMD */ 1844 1682 1845 if (get_mult || get_identity) 1846 { 1683 if (get_mult || get_identity) { 1847 1684 multcount = -1; 1848 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) 1849 { 1850 if (get_mult) 1685 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) { 1686 if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */ 1851 1687 bb_perror_msg("HDIO_GET_MULTCOUNT"); 1852 }1853 else if (get_mult)1854 {1688 else 1689 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT); 1690 } else if (get_mult) { 1855 1691 printf(fmt, "multcount", multcount); 1856 on_off(multcount); 1857 } 1858 } 1859 if (get_io32bit) 1860 { 1861 if (!bb_ioctl(fd, HDIO_GET_32BIT, &parm, "HDIO_GET_32BIT")) 1862 { 1692 on_off(multcount != 0); 1693 } 1694 } 1695 if (get_io32bit) { 1696 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) { 1863 1697 printf(" IO_support\t=%3ld (", parm); 1864 1698 if (parm == 0) … … 1876 1710 } 1877 1711 } 1878 if (get_unmask) 1879 { 1880 bb_ioctl_on_off(fd, HDIO_GET_UNMASKINTR,(unsigned long *)parm, 1881 "HDIO_GET_UNMASKINTR","unmaskirq"); 1882 } 1883 1884 1885 #ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA 1712 if (get_unmask) { 1713 if(!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, (unsigned long *)parm)) 1714 print_value_on_off("unmaskirq", parm); 1715 } 1716 1717 1718 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 1886 1719 if (get_dma) { 1887 if (!bb_ioctl(fd, HDIO_GET_DMA, &parm, "HDIO_GET_DMA")) 1888 { 1720 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) { 1889 1721 printf(fmt, "using_dma", parm); 1890 1722 if (parm == 8) 1891 1723 printf(" (DMA-Assisted-PIO)\n"); 1892 1724 else 1893 on_off(parm); 1894 } 1895 } 1896 #endif 1897 if (get_dma_q) 1898 { 1899 bb_ioctl_on_off (fd, HDIO_GET_QDMA,(unsigned long *)parm, 1900 "HDIO_GET_QDMA","queue_depth"); 1901 } 1902 if (get_keep) 1903 { 1904 bb_ioctl_on_off (fd, HDIO_GET_KEEPSETTINGS,(unsigned long *)parm, 1905 "HDIO_GET_KEEPSETTINGS","keepsettings"); 1906 } 1907 1908 if (get_nowerr) 1909 { 1910 bb_ioctl_on_off (fd, HDIO_GET_NOWERR,(unsigned long *)&parm, 1911 "HDIO_GET_NOWERR","nowerr"); 1912 } 1913 if (get_readonly) 1914 { 1915 bb_ioctl_on_off(fd, BLKROGET,(unsigned long *)parm, 1916 "BLKROGET","readonly"); 1917 } 1918 if (get_readahead) 1919 { 1920 bb_ioctl_on_off (fd, BLKRAGET, (unsigned long *) parm, 1921 "BLKRAGET","readahead"); 1922 } 1923 if (get_geom) 1924 { 1925 if (!bb_ioctl(fd, BLKGETSIZE, &parm, "BLKGETSIZE")) 1926 { 1725 on_off(parm != 0); 1726 } 1727 } 1728 #endif 1729 if (get_dma_q) { 1730 if(!ioctl_or_warn(fd, HDIO_GET_QDMA, (unsigned long *)parm)) 1731 print_value_on_off("queue_depth", parm); 1732 } 1733 if (get_keep) { 1734 if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, (unsigned long *)parm)) 1735 print_value_on_off("keepsettings", parm); 1736 } 1737 1738 if (get_nowerr) { 1739 if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, (unsigned long *)parm)) 1740 print_value_on_off("nowerr", parm); 1741 } 1742 if (get_readonly) { 1743 if(!ioctl_or_warn(fd, BLKROGET, (unsigned long *)parm)) 1744 print_value_on_off("readonly", parm); 1745 } 1746 if (get_readahead) { 1747 if(!ioctl_or_warn(fd, BLKRAGET, (unsigned long *)parm)) 1748 print_value_on_off("readahead", parm); 1749 } 1750 if (get_geom) { 1751 if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) { 1927 1752 struct hd_geometry g; 1928 1753 1929 if (! bb_ioctl(fd, HDIO_GETGEO, &g, "HDIO_GETGEO"))1754 if (!ioctl_or_warn(fd, HDIO_GETGEO, &g)) 1930 1755 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n", 1931 1756 g.cylinders, g.heads, g.sectors, parm, g.start); … … 1933 1758 } 1934 1759 #ifdef HDIO_DRIVE_CMD 1935 if (get_powermode) 1936 { 1760 if (get_powermode) { 1937 1761 #ifndef WIN_CHECKPOWERMODE1 1938 1762 #define WIN_CHECKPOWERMODE1 0xE5 … … 1944 1768 1945 1769 args[0] = WIN_CHECKPOWERMODE1; 1946 if (bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2, 0)) 1947 { 1770 if (ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) { 1948 1771 if (errno != EIO || args[0] != 0 || args[1] != 0) 1949 state = " Unknown";1772 state = "unknown"; 1950 1773 else 1951 1774 state = "sleeping"; 1952 } 1953 else 1775 } else 1954 1776 state = (args[2] == 255) ? "active/idle" : "standby"; 1955 1777 args[1] = args[2] = 0; … … 1958 1780 } 1959 1781 #endif 1960 #ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET 1961 if (perform_reset) 1962 { 1963 bb_ioctl(fd, HDIO_DRIVE_RESET, NULL, "HDIO_DRIVE_RESET"); 1964 } 1965 #endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */ 1966 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1967 if (perform_tristate) 1968 { 1782 #if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET 1783 if (perform_reset) { 1784 ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL); 1785 } 1786 #endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */ 1787 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1788 if (perform_tristate) { 1969 1789 args[0] = 0; 1970 1790 args[1] = tristate; 1971 bb_ioctl(fd, HDIO_TRISTATE_HWIF, &args, "HDIO_TRISTATE_HWIF"); 1972 } 1973 #endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */ 1974 #ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY 1975 if (get_identity) 1976 { 1977 static struct hd_driveid id; 1978 1979 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) 1980 { 1981 if (multcount != -1) 1982 { 1791 ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args); 1792 } 1793 #endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */ 1794 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 1795 if (get_identity) { 1796 struct hd_driveid id; 1797 1798 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) { 1799 if (multcount != -1) { 1983 1800 id.multsect = multcount; 1984 1801 id.multsect_valid |= 1; 1985 } 1986 else 1802 } else 1987 1803 id.multsect_valid &= ~1; 1988 1804 dump_identity(&id); 1989 } 1990 else if (errno == -ENOMSG) 1805 } else if (errno == -ENOMSG) 1991 1806 printf(" no identification info available\n"); 1807 else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ 1808 bb_perror_msg("HDIO_GET_IDENTITY"); 1992 1809 else 1993 bb_perror_msg("HDIO_GET_IDENTITY"); 1994 } 1995 1996 if (get_IDentity) 1997 { 1810 bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY); 1811 } 1812 1813 if (get_IDentity) { 1998 1814 unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */ 1999 1815 … … 2001 1817 args1[0] = WIN_IDENTIFY; 2002 1818 args1[3] = 1; 2003 if (! bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY, "HDIO_DRIVE_CMD(identify)"))1819 if (!ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY)) 2004 1820 identify((void *)(args1 + 4)); 2005 1821 } 2006 1822 #endif 2007 #ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 2008 if (set_busstate) 2009 { 2010 if (get_busstate) 2011 { 1823 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 1824 if (set_busstate) { 1825 if (get_busstate) { 2012 1826 print_flag(1, "bus state", busstate); 2013 1827 bus_state_value(busstate); 2014 1828 } 2015 bb_ioctl(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate, "HDIO_SET_BUSSTATE"); 2016 } 2017 if (get_busstate) 2018 { 2019 if (!bb_ioctl(fd, HDIO_GET_BUSSTATE, &parm, "HDIO_GET_BUSSTATE")) 2020 { 1829 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate); 1830 } 1831 if (get_busstate) { 1832 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) { 2021 1833 printf(fmt, "bus state", parm); 2022 1834 bus_state_value(parm); … … 2025 1837 #endif 2026 1838 if (reread_partn) 2027 bb_ioctl(fd, BLKRRPART, NULL, "BLKRRPART"); 2028 1839 ioctl_or_warn(fd, BLKRRPART, NULL); 2029 1840 2030 1841 if (do_ctimings) 2031 do_time(0, fd); /*time cache*/1842 do_time(0, fd); /* time cache */ 2032 1843 if (do_timings) 2033 do_time(1, fd); /*time device */1844 do_time(1, fd); /* time device */ 2034 1845 if (do_flush) 2035 1846 flush_buffer_cache(fd); … … 2037 1848 } 2038 1849 2039 #if def CONFIG_FEATURE_HDPARM_GET_IDENTITY1850 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY 2040 1851 static int fromhex(unsigned char c) 2041 1852 { 1853 if (isdigit(c)) 1854 return (c - '0'); 2042 1855 if (c >= 'a' && c <= 'f') 2043 return 10 + (c - 'a'); 2044 if (c >= '0' && c <= '9') 2045 return (c - '0'); 1856 return (c - ('a' - 10)); 2046 1857 bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c); 2047 1858 } … … 2050 1861 { 2051 1862 uint16_t sbuf[256]; 2052 unsigned char buf[1280], *b = (unsigned char *)buf;2053 int i, count = read(0, buf, 1280);2054 2055 if (count != 1280) 2056 bb_error_msg_and_die("read(%d bytes) failed (rc=%d)", 1280, count);1863 unsigned char buf[1280]; 1864 unsigned char *b = (unsigned char *)buf; 1865 int i; 1866 1867 xread(0, buf, 1280); 2057 1868 2058 1869 // Convert the newline-separated hex data into an identify block. 2059 1870 2060 for (i = 0; i<256; i++) 2061 { 1871 for (i = 0; i < 256; i++) { 2062 1872 int j; 2063 for(j=0;j<4;j++) sbuf[i] = (sbuf[i] <<4) + fromhex(*(b++)); 1873 for (j = 0; j < 4; j++) 1874 sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++)); 2064 1875 } 2065 1876 … … 2071 1882 2072 1883 /* busybox specific stuff */ 2073 static void parse_opts( unsigned long *get, unsigned long*set, unsigned long *value, int min, int max)2074 { 2075 2076 2077 2078 2079 2080 *value = bb_xgetlarg(optarg, 10, min, max);2081 2082 } 2083 2084 static void parse_xfermode(int flag, unsigned long *get, unsigned long*set, int *value)1884 static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max) 1885 { 1886 if (get) { 1887 *get = 1; 1888 } 1889 if (optarg) { 1890 *set = 1; 1891 *value = xatol_range(optarg, min, max); 1892 } 1893 } 1894 1895 static void parse_xfermode(int flag, smallint *get, smallint *set, int *value) 2085 1896 { 2086 1897 if (flag) { 2087 1898 *get = 1; 2088 1899 if (optarg) { 2089 *set = ((*value = translate_xfermode(optarg)) > -1); 1900 *value = translate_xfermode(optarg); 1901 *set = (*value > -1); 2090 1902 } 2091 1903 } … … 2093 1905 2094 1906 /*------- getopt short options --------*/ 2095 static const char hdparm_options[]= "gfu::n::p:r::m::c::k::a::B:tTh"\ 1907 static const char hdparm_options[] ALIGN1 = 1908 "gfu::n::p:r::m::c::k::a::B:tTh" 2096 1909 USE_FEATURE_HDPARM_GET_IDENTITY("iI") 2097 1910 USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::") 2098 1911 #ifdef HDIO_DRIVE_CMD 2099 1912 "S:D:P:X:K:A:L:W:CyYzZ" 2100 1913 #endif 2101 1914 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:") 2102 1915 #ifdef HDIO_GET_QDMA 2103 1916 #ifdef HDIO_SET_QDMA 2104 1917 "Q:" 2105 1918 #else 2106 1919 "Q" 2107 1920 #endif 2108 1921 #endif … … 2113 1926 2114 1927 /* our main() routine: */ 2115 int hdparm_main(int argc, char **argv) ATTRIBUTE_NORETURN;1928 int hdparm_main(int argc, char **argv); 2116 1929 int hdparm_main(int argc, char **argv) 2117 1930 { … … 2129 1942 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9)); 2130 1943 if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1); 2131 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);1944 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode); 2132 1945 if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1); 2133 1946 if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/); … … 2139 1952 do_flush |= do_ctimings |= (c == 'T'); 2140 1953 #ifdef HDIO_DRIVE_CMD 2141 if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX); 1954 if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX); 2142 1955 if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX); 2143 1956 if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX); … … 2153 1966 get_seagate = set_seagate |= (c == 'Z'); 2154 1967 #endif 2155 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX)); 1968 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX)); 2156 1969 #ifdef HDIO_GET_QDMA 2157 1970 if (c == 'Q') { … … 2159 1972 parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX); 2160 1973 #else 2161 parse_opts(&get_dma_q, NULL, NULL, 0, 0); 2162 #endif 2163 } 2164 #endif 1974 parse_opts(&get_dma_q, NULL, NULL, 0, 0); 1975 #endif 1976 } 1977 #endif 2165 1978 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r')); 2166 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1)); 2167 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2)); 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)); 2168 1981 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 2169 1982 if (c == 'R') { 2170 parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX); 2171 hwif_ctrl = bb_xgetlarg((argv[optind]) ? argv[optind] : "", 10, 0, INT_MAX);2172 hwif_irq = bb_xgetlarg((argv[optind+1]) ? argv[optind+1] : "", 10, 0, INT_MAX);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] : ""); 2173 1986 /* Move past the 2 additional arguments */ 2174 1987 argv += 2; … … 2178 1991 } 2179 1992 /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */ 2180 if (!flagcount) {1993 if (!flagcount) { 2181 1994 get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1; 2182 1995 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1); 2183 1996 } 2184 argc -= optind;2185 1997 argv += optind; 2186 1998 2187 if ( argc < 1) {1999 if (!*argv) { 2188 2000 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO)) 2189 2001 identify_from_stdin(); /* EXIT */ … … 2191 2003 } 2192 2004 2193 while (argc--){2194 process_dev(*argv );2195 argv++;2196 } 2197 exit(EXIT_SUCCESS);2198 } 2005 do { 2006 process_dev(*argv++); 2007 } while (*argv); 2008 2009 return EXIT_SUCCESS; 2010 } -
branches/stable/mindi-busybox/miscutils/last.c
r821 r1770 5 5 * Copyright (C) 2003-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 7 * Licensed under the GPL v 2 or later, see the file LICENSE in this tarball.7 * Licensed under the GPL version 2, see the file LICENSE in this tarball. 8 8 */ 9 9 10 #include "busybox.h" 11 #include <sys/types.h> 12 #include <fcntl.h> 13 #include <unistd.h> 14 #include <stdlib.h> 10 #include "libbb.h" 15 11 #include <utmp.h> 16 #include <sys/stat.h>17 #include <errno.h>18 #include <string.h>19 #include <time.h>20 12 21 13 #ifndef SHUTDOWN_TIME … … 35 27 #endif 36 28 29 int last_main(int argc, char **argv); 37 30 int last_main(int argc, char **argv) 38 31 { … … 44 37 bb_show_usage(); 45 38 } 46 file = bb_xopen(bb_path_wtmp_file, O_RDONLY);39 file = xopen(bb_path_wtmp_file, O_RDONLY); 47 40 48 41 printf("%-10s %-14s %-18s %-12.12s %s\n", "USER", "TTY", "HOST", "LOGIN", "TIME"); … … 53 46 } 54 47 55 if ( strncmp(ut.ut_line, "~", 1) == 0) {48 if (ut.ut_line[0] == '~') { 56 49 if (strncmp(ut.ut_user, "shutdown", 8) == 0) 57 50 ut.ut_type = SHUTDOWN_TIME; … … 96 89 } 97 90 98 bb_fflush_stdout_and_exit(EXIT_SUCCESS);91 fflush_stdout_and_exit(EXIT_SUCCESS); 99 92 } -
branches/stable/mindi-busybox/miscutils/less.c
r821 r1770 9 9 10 10 /* 11 * This program needs a lot of development, so consider it in a beta stage 12 * at best. 11 * TODO: 12 * - Add more regular expression support - search modifiers, certain matches, etc. 13 * - Add more complex bracket searching - currently, nested brackets are 14 * not considered. 15 * - Add support for "F" as an input. This causes less to act in 16 * a similar way to tail -f. 17 * - Allow horizontal scrolling. 13 18 * 14 * TODO: 15 * - Add more regular expression support - search modifiers, certain matches, etc. 16 * - Add more complex bracket searching - currently, nested brackets are 17 * not considered. 18 * - Add support for "F" as an input. This causes less to act in 19 * a similar way to tail -f. 20 * - Check for binary files, and prompt the user if a binary file 21 * is detected. 22 * - Allow horizontal scrolling. Currently, lines simply continue onto 23 * the next line, per the terminal's discretion 24 * 25 * Notes: 26 * - filename is an array and not a pointer because that avoids all sorts 27 * of complications involving the fact that something that is pointed to 28 * will be changed if the pointer is changed. 29 * - the inp file pointer is used so that keyboard input works after 30 * redirected input has been read from stdin 31 */ 32 33 #include "busybox.h" 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <termios.h> 38 #include <unistd.h> 39 #include <ctype.h> 40 41 #ifdef CONFIG_FEATURE_LESS_REGEXP 19 * Notes: 20 * - the inp file pointer is used so that keyboard input works after 21 * redirected input has been read from stdin 22 */ 23 24 #include <sched.h> /* sched_yield() */ 25 26 #include "libbb.h" 27 #if ENABLE_FEATURE_LESS_REGEXP 42 28 #include "xregex.h" 43 29 #endif 44 30 45 46 /* These are the escape sequences corresponding to special keys */ 47 #define REAL_KEY_UP 'A' 48 #define REAL_KEY_DOWN 'B' 49 #define REAL_KEY_RIGHT 'C' 50 #define REAL_KEY_LEFT 'D' 51 #define REAL_PAGE_UP '5' 52 #define REAL_PAGE_DOWN '6' 53 54 /* These are the special codes assigned by this program to the special keys */ 55 #define PAGE_UP 20 56 #define PAGE_DOWN 21 57 #define KEY_UP 22 58 #define KEY_DOWN 23 59 #define KEY_RIGHT 24 60 #define KEY_LEFT 25 31 /* FIXME: currently doesn't work right */ 32 #undef ENABLE_FEATURE_LESS_FLAGCS 33 #define ENABLE_FEATURE_LESS_FLAGCS 0 61 34 62 35 /* The escape codes for highlighted and normal text */ 63 36 #define HIGHLIGHT "\033[7m" 64 37 #define NORMAL "\033[0m" 65 66 38 /* The escape code to clear the screen */ 67 39 #define CLEAR "\033[H\033[J" 68 69 /* Maximum number of lines in a file */ 70 #define MAXLINES 10000 71 72 static int height; 73 static int width; 74 static char **files; 75 static char filename[256]; 76 static char **buffer; 77 static char **flines; 78 static int current_file = 1; 79 static int line_pos; 80 static int num_flines; 81 static int num_files = 1; 82 static int past_eof; 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 */ 44 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 /* Absolute max of lines eaten */ 69 MAXLINES = CONFIG_FEATURE_LESS_MAXLINES, 70 71 /* This many "after the end" lines we will show (at max) */ 72 TILDES = 1, 73 }; 83 74 84 75 /* Command line options */ 85 static unsigned long flags; 86 #define FLAG_E 1 87 #define FLAG_M (1<<1) 88 #define FLAG_m (1<<2) 89 #define FLAG_N (1<<3) 90 #define FLAG_TILDE (1<<4) 91 92 /* This is needed so that program behaviour changes when input comes from 93 stdin */ 94 static int inp_stdin; 95 96 #ifdef CONFIG_FEATURE_LESS_MARKS 97 static int mark_lines[15][2]; 98 static int num_marks; 99 #endif 100 101 #ifdef CONFIG_FEATURE_LESS_REGEXP 102 static int match_found; 103 static int *match_lines; 104 static int match_pos; 105 static int num_matches; 106 static int match_backwards; 107 static regex_t old_pattern; 108 #endif 109 110 /* Needed termios structures */ 111 static struct termios term_orig, term_vi; 112 113 /* File pointer to get input from */ 114 static FILE *inp; 76 enum { 77 FLAG_E = 1, 78 FLAG_M = 1 << 1, 79 FLAG_m = 1 << 2, 80 FLAG_N = 1 << 3, 81 FLAG_TILDE = 1 << 4, 82 /* hijack command line options variable for internal state vars */ 83 LESS_STATE_MATCH_BACKWARDS = 1 << 15, 84 }; 85 86 #if !ENABLE_FEATURE_LESS_REGEXP 87 enum { pattern_valid = 0 }; 88 #endif 89 90 struct globals { 91 int cur_fline; /* signed */ 92 int kbd_fd; /* fd to get input from */ 93 /* last position in last line, taking into account tabs */ 94 size_t linepos; 95 unsigned max_displayed_line; 96 unsigned max_fline; 97 unsigned max_lineno; /* this one tracks linewrap */ 98 unsigned width; 99 ssize_t eof_error; /* eof if 0, error if < 0 */ 100 size_t readpos; 101 size_t readeof; 102 const char **buffer; 103 const char **flines; 104 const char *empty_line_marker; 105 unsigned num_files; 106 unsigned current_file; 107 char *filename; 108 char **files; 109 #if ENABLE_FEATURE_LESS_MARKS 110 unsigned num_marks; 111 unsigned mark_lines[15][2]; 112 #endif 113 #if ENABLE_FEATURE_LESS_REGEXP 114 unsigned *match_lines; 115 int match_pos; /* signed! */ 116 unsigned num_matches; 117 regex_t pattern; 118 smallint pattern_valid; 119 #endif 120 smallint terminated; 121 struct termios term_orig, term_less; 122 }; 123 #define G (*ptr_to_globals) 124 #define cur_fline (G.cur_fline ) 125 #define kbd_fd (G.kbd_fd ) 126 #define linepos (G.linepos ) 127 #define max_displayed_line (G.max_displayed_line) 128 #define max_fline (G.max_fline ) 129 #define max_lineno (G.max_lineno ) 130 #define width (G.width ) 131 #define eof_error (G.eof_error ) 132 #define readpos (G.readpos ) 133 #define readeof (G.readeof ) 134 #define buffer (G.buffer ) 135 #define flines (G.flines ) 136 #define empty_line_marker (G.empty_line_marker ) 137 #define num_files (G.num_files ) 138 #define current_file (G.current_file ) 139 #define filename (G.filename ) 140 #define files (G.files ) 141 #define num_marks (G.num_marks ) 142 #define mark_lines (G.mark_lines ) 143 #if ENABLE_FEATURE_LESS_REGEXP 144 #define match_lines (G.match_lines ) 145 #define match_pos (G.match_pos ) 146 #define num_matches (G.num_matches ) 147 #define pattern (G.pattern ) 148 #define pattern_valid (G.pattern_valid ) 149 #endif 150 #define terminated (G.terminated ) 151 #define term_orig (G.term_orig ) 152 #define term_less (G.term_less ) 153 #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) 115 161 116 162 /* Reset terminal input to normal */ … … 118 164 { 119 165 fflush(stdout); 120 tcsetattr(fileno(inp), TCSANOW, &term_orig); 121 } 122 123 /* Set terminal input to raw mode (taken from vi.c) */ 124 static void set_tty_raw(void) 125 { 126 tcsetattr(fileno(inp), TCSANOW, &term_vi); 166 tcsetattr(kbd_fd, TCSANOW, &term_orig); 127 167 } 128 168 129 169 /* Exit the program gracefully */ 130 static void tless_exit(int code)170 static void less_exit(int code) 131 171 { 132 172 /* TODO: We really should save the terminal state when we start, 133 and restore it when we exit. Less does this with the 134 "ti" and "te" termcap commands; can this be done with 135 only termios.h? */ 136 173 * and restore it when we exit. Less does this with the 174 * "ti" and "te" termcap commands; can this be done with 175 * only termios.h? */ 137 176 putchar('\n'); 138 exit(code); 139 } 140 141 /* Grab a character from input without requiring the return key. If the 142 character is ASCII \033, get more characters and assign certain sequences 143 special return codes. Note that this function works best with raw input. */ 144 static int tless_getch(void) 145 { 146 int input; 147 148 set_tty_raw(); 149 150 input = getc(inp); 151 /* Detect escape sequences (i.e. arrow keys) and handle 152 them accordingly */ 153 154 if (input == '\033' && getc(inp) == '[') { 155 input = getc(inp); 156 set_tty_cooked(); 157 if (input == REAL_KEY_UP) 158 return KEY_UP; 159 else if (input == REAL_KEY_DOWN) 160 return KEY_DOWN; 161 else if (input == REAL_KEY_RIGHT) 162 return KEY_RIGHT; 163 else if (input == REAL_KEY_LEFT) 164 return KEY_LEFT; 165 else if (input == REAL_PAGE_UP) 166 return PAGE_UP; 167 else if (input == REAL_PAGE_DOWN) 168 return PAGE_DOWN; 169 } 170 /* The input is a normal ASCII value */ 171 else { 172 set_tty_cooked(); 173 return input; 174 } 175 return 0; 177 fflush_stdout_and_exit(code); 176 178 } 177 179 178 180 /* Move the cursor to a position (x,y), where (0,0) is the 179 181 top-left corner of the console */ 180 static void move_cursor(int x, int y)181 { 182 printf("\033[% i;%iH", x, y);182 static void move_cursor(int line, int row) 183 { 184 printf("\033[%u;%uH", line, row); 183 185 } 184 186 185 187 static void clear_line(void) 186 188 { 187 move_cursor(height, 0); 188 printf("\033[K"); 189 } 190 191 /* This adds line numbers to every line, as the -N flag necessitates */ 192 static void add_linenumbers(void) 193 { 194 char current_line[256]; 195 int i; 196 197 for (i = 0; i <= num_flines; i++) { 198 safe_strncpy(current_line, flines[i], 256); 199 flines[i] = bb_xasprintf("%5d %s", i + 1, current_line); 200 } 201 } 202 203 static void data_readlines(void) 204 { 205 int i; 206 char current_line[256]; 207 FILE *fp; 208 209 fp = (inp_stdin) ? stdin : bb_xfopen(filename, "r"); 210 flines = NULL; 211 for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) { 212 strcpy(current_line, ""); 213 fgets(current_line, 256, fp); 214 if (fp != stdin) 215 bb_xferror(fp, filename); 216 flines = xrealloc(flines, (i+1) * sizeof(char *)); 217 flines[i] = bb_xstrdup(current_line); 218 } 219 num_flines = i - 2; 220 221 /* Reset variables for a new file */ 222 223 line_pos = 0; 224 past_eof = 0; 225 226 fclose(fp); 227 228 if (inp == NULL) 229 inp = (inp_stdin) ? bb_xfopen(CURRENT_TTY, "r") : stdin; 230 231 if (flags & FLAG_N) 232 add_linenumbers(); 233 } 234 235 #ifdef CONFIG_FEATURE_LESS_FLAGS 236 237 /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes 189 printf("\033[%u;0H" CLEAR_2_EOL, max_displayed_line + 2); 190 } 191 192 static void print_hilite(const char *str) 193 { 194 printf(HIGHLIGHT"%s"NORMAL, str); 195 } 196 197 static void print_statusline(const char *str) 198 { 199 clear_line(); 200 printf(HIGHLIGHT"%.*s"NORMAL, width - 1, str); 201 } 202 203 #if ENABLE_FEATURE_LESS_REGEXP 204 static void fill_match_lines(unsigned pos); 205 #else 206 #define fill_match_lines(pos) ((void)0) 207 #endif 208 209 /* Devilishly complex routine. 210 * 211 * Has to deal with EOF and EPIPE on input, 212 * with line wrapping, with last line not ending in '\n' 213 * (possibly not ending YET!), with backspace and tabs. 214 * It reads input again if last time we got an EOF (thus supporting 215 * growing files) or EPIPE (watching output of slow process like make). 216 * 217 * Variables used: 218 * flines[] - array of lines already read. Linewrap may cause 219 * one source file line to occupy several flines[n]. 220 * flines[max_fline] - last line, possibly incomplete. 221 * terminated - 1 if flines[max_fline] is 'terminated' 222 * (if there was '\n' [which isn't stored itself, we just remember 223 * that it was seen]) 224 * max_lineno - last line's number, this one doesn't increment 225 * on line wrap, only on "real" new lines. 226 * readbuf[0..readeof-1] - small preliminary buffer. 227 * readbuf[readpos] - next character to add to current line. 228 * linepos - screen line position of next char to be read 229 * (takes into account tabs and backspaces) 230 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error 231 */ 232 static void read_lines(void) 233 { 234 #define readbuf bb_common_bufsiz1 235 char *current_line, *p; 236 USE_FEATURE_LESS_REGEXP(unsigned old_max_fline = max_fline;) 237 int w = width; 238 char last_terminated = terminated; 239 240 if (option_mask32 & FLAG_N) 241 w -= 8; 242 243 current_line = xmalloc(w); 244 p = current_line; 245 max_fline += last_terminated; 246 if (!last_terminated) { 247 const char *cp = flines[max_fline]; 248 if (option_mask32 & FLAG_N) 249 cp += 8; 250 strcpy(current_line, cp); 251 p += strlen(current_line); 252 /* linepos is still valid from previous read_lines() */ 253 } else { 254 linepos = 0; 255 } 256 257 while (1) { 258 again: 259 *p = '\0'; 260 terminated = 0; 261 while (1) { 262 char c; 263 /* if no unprocessed chars left, eat more */ 264 if (readpos >= readeof) { 265 smallint yielded = 0; 266 267 ndelay_on(0); 268 read_again: 269 eof_error = safe_read(0, readbuf, sizeof(readbuf)); 270 readpos = 0; 271 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) { 293 goto reached_eof; 294 } 295 } 296 c = readbuf[readpos]; 297 /* backspace? [needed for manpages] */ 298 /* <tab><bs> is (a) insane and */ 299 /* (b) harder to do correctly, so we refuse to do it */ 300 if (c == '\x8' && linepos && p[-1] != '\t') { 301 readpos++; /* eat it */ 302 linepos--; 303 /* was buggy (p could end up <= current_line)... */ 304 *--p = '\0'; 305 continue; 306 } 307 { 308 size_t new_linepos = linepos + 1; 309 if (c == '\t') { 310 new_linepos += 7; 311 new_linepos &= (~7); 312 } 313 if (new_linepos >= w) 314 break; 315 linepos = new_linepos; 316 } 317 /* ok, we will eat this char */ 318 readpos++; 319 if (c == '\n') { 320 terminated = 1; 321 linepos = 0; 322 break; 323 } 324 /* NUL is substituted by '\n'! */ 325 if (c == '\0') c = '\n'; 326 *p++ = c; 327 *p = '\0'; 328 } 329 /* Corner case: linewrap with only "" wrapping to next line */ 330 /* Looks ugly on screen, so we do not store this empty line */ 331 if (!last_terminated && !current_line[0]) { 332 last_terminated = 1; 333 max_lineno++; 334 goto again; 335 } 336 reached_eof: 337 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 } 350 if (max_fline >= MAXLINES) { 351 eof_error = 0; /* Pretend we saw EOF */ 352 break; 353 } 354 if (max_fline > cur_fline + max_displayed_line) 355 break; 356 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; 362 } 363 break; 364 } 365 max_fline++; 366 current_line = xmalloc(w); 367 p = current_line; 368 linepos = 0; 369 } 370 fill_match_lines(old_max_fline); 371 #undef readbuf 372 } 373 374 #if ENABLE_FEATURE_LESS_FLAGS 375 /* Interestingly, writing calc_percent as a function saves around 32 bytes 238 376 * on my build. */ 239 377 static int calc_percent(void) 240 378 { 241 return ((100 * (line_pos + height - 2) / num_flines) + 1); 379 unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); 380 return p <= 100 ? p : 100; 242 381 } 243 382 … … 247 386 int percentage; 248 387 249 if (!past_eof) { 250 if (!line_pos) { 251 if (num_files > 1) 252 printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT, filename, "(file ", current_file, " of ", num_files, ") lines ", line_pos + 1, line_pos + height - 1, num_flines + 1); 253 else { 254 printf("%s%s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1); 255 } 256 } 257 else { 258 printf("%s %s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1); 259 } 260 261 if (line_pos == num_flines - height + 2) { 262 printf("(END) %s", NORMAL); 263 if ((num_files > 1) && (current_file != num_files)) 264 printf("%s- Next: %s%s", HIGHLIGHT, files[current_file], NORMAL); 265 } 266 else { 267 percentage = calc_percent(); 268 printf("%i%% %s", percentage, NORMAL); 269 } 270 } 271 else { 272 printf("%s%s lines %i-%i/%i (END) ", HIGHLIGHT, filename, line_pos + 1, num_flines + 1, num_flines + 1); 273 if ((num_files > 1) && (current_file != num_files)) 274 printf("- Next: %s", files[current_file]); 275 printf("%s", NORMAL); 276 } 277 } 278 279 /* Print a status line if -m was specified */ 280 static void medium_status_print(void) 281 { 282 int percentage; 388 clear_line(); 389 printf(HIGHLIGHT"%s", filename); 390 if (num_files > 1) 391 printf(" (file %i of %i)", current_file, num_files); 392 printf(" lines %i-%i/%i ", 393 cur_fline + 1, cur_fline + max_displayed_line + 1, 394 max_fline + 1); 395 if (cur_fline >= max_fline - max_displayed_line) { 396 printf("(END)"NORMAL); 397 if (num_files > 1 && current_file != num_files) 398 printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); 399 return; 400 } 283 401 percentage = calc_percent(); 284 285 if (!line_pos) 286 printf("%s%s %i%%%s", HIGHLIGHT, filename, percentage, NORMAL); 287 else if (line_pos == num_flines - height + 2) 288 printf("%s(END)%s", HIGHLIGHT, NORMAL); 289 else 290 printf("%s%i%%%s", HIGHLIGHT, percentage, NORMAL); 402 printf("%i%%"NORMAL, percentage); 291 403 } 292 404 #endif … … 295 407 static void status_print(void) 296 408 { 409 const char *p; 410 297 411 /* Change the status if flags have been set */ 298 #if def CONFIG_FEATURE_LESS_FLAGS299 if ( flags & FLAG_M)412 #if ENABLE_FEATURE_LESS_FLAGS 413 if (option_mask32 & (FLAG_M|FLAG_m)) { 300 414 m_status_print(); 301 else if (flags & FLAG_m)302 medium_status_print();415 return; 416 } 303 417 /* No flags set */ 304 else { 305 #endif 306 if (!line_pos) { 307 printf("%s%s %s", HIGHLIGHT, filename, NORMAL); 308 if (num_files > 1) 309 printf("%s%s%i%s%i%s%s", HIGHLIGHT, "(file ", current_file, " of ", num_files, ")", NORMAL); 418 #endif 419 420 clear_line(); 421 if (cur_fline && cur_fline < max_fline - max_displayed_line) { 422 putchar(':'); 423 return; 424 } 425 p = "(END)"; 426 if (!cur_fline) 427 p = filename; 428 if (num_files > 1) { 429 printf(HIGHLIGHT"%s (file %i of %i)"NORMAL, 430 p, current_file, num_files); 431 return; 432 } 433 print_hilite(p); 434 } 435 436 static void cap_cur_fline(int nlines) 437 { 438 int diff; 439 if (cur_fline < 0) 440 cur_fline = 0; 441 if (cur_fline + max_displayed_line > max_fline + TILDES) { 442 cur_fline -= nlines; 443 if (cur_fline < 0) 444 cur_fline = 0; 445 diff = max_fline - (cur_fline + max_displayed_line) + TILDES; 446 /* As the number of lines requested was too large, we just move 447 to the end of the file */ 448 if (diff > 0) 449 cur_fline += diff; 450 } 451 } 452 453 static const char controls[] ALIGN1 = 454 /* NUL: never encountered; TAB: not converted */ 455 /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f" 456 "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 457 "\x7f\x9b"; /* DEL and infamous Meta-ESC :( */ 458 static const char ctrlconv[] ALIGN1 = 459 /* '\n': it's a former NUL - subst with '@', not 'J' */ 460 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" 461 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; 462 463 #if ENABLE_FEATURE_LESS_REGEXP 464 static void print_found(const char *line) 465 { 466 int match_status; 467 int eflags; 468 char *growline; 469 regmatch_t match_structs; 470 471 char buf[width]; 472 const char *str = line; 473 char *p = buf; 474 size_t n; 475 476 while (*str) { 477 n = strcspn(str, controls); 478 if (n) { 479 if (!str[n]) break; 480 memcpy(p, str, n); 481 p += n; 482 str += n; 310 483 } 311 else if (line_pos == num_flines - height + 2) { 312 printf("%s%s %s", HIGHLIGHT, "(END)", NORMAL); 313 if ((num_files > 1) && (current_file != num_files)) 314 printf("%s%s%s%s", HIGHLIGHT, "- Next: ", files[current_file], NORMAL); 484 n = strspn(str, controls); 485 memset(p, '.', n); 486 p += n; 487 str += n; 488 } 489 strcpy(p, str); 490 491 /* buf[] holds quarantined version of str */ 492 493 /* Each part of the line that matches has the HIGHLIGHT 494 and NORMAL escape sequences placed around it. 495 NB: we regex against line, but insert text 496 from quarantined copy (buf[]) */ 497 str = buf; 498 growline = NULL; 499 eflags = 0; 500 goto start; 501 502 while (match_status == 0) { 503 char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL, 504 growline ? : "", 505 match_structs.rm_so, str, 506 match_structs.rm_eo - match_structs.rm_so, 507 str + match_structs.rm_so); 508 free(growline); growline = new; 509 str += match_structs.rm_eo; 510 line += match_structs.rm_eo; 511 eflags = REG_NOTBOL; 512 start: 513 /* Most of the time doesn't find the regex, optimize for that */ 514 match_status = regexec(&pattern, line, 1, &match_structs, eflags); 515 } 516 517 if (!growline) { 518 printf(CLEAR_2_EOL"%s\n", str); 519 return; 520 } 521 printf(CLEAR_2_EOL"%s%s\n", growline, str); 522 free(growline); 523 } 524 #else 525 void print_found(const char *line); 526 #endif 527 528 static void print_ascii(const char *str) 529 { 530 char buf[width]; 531 char *p; 532 size_t n; 533 534 printf(CLEAR_2_EOL); 535 while (*str) { 536 n = strcspn(str, controls); 537 if (n) { 538 if (!str[n]) break; 539 printf("%.*s", (int) n, str); 540 str += n; 315 541 } 316 else { 317 putchar(':'); 318 } 319 #ifdef CONFIG_FEATURE_LESS_FLAGS 320 } 321 #endif 542 n = strspn(str, controls); 543 p = buf; 544 do { 545 if (*str == 0x7f) 546 *p++ = '?'; 547 else if (*str == (char)0x9b) 548 /* VT100's CSI, aka Meta-ESC. Who's inventor? */ 549 /* I want to know who committed this sin */ 550 *p++ = '{'; 551 else 552 *p++ = ctrlconv[(unsigned char)*str]; 553 str++; 554 } while (--n); 555 *p = '\0'; 556 print_hilite(buf); 557 } 558 puts(str); 322 559 } 323 560 … … 327 564 int i; 328 565 329 printf("%s", CLEAR); 330 if (num_flines >= height - 2) { 331 for (i = 0; i < height - 1; i++) 332 printf("%s", buffer[i]); 333 } 334 else { 335 for (i = 1; i < (height - 1 - num_flines); i++) 336 putchar('\n'); 337 for (i = 0; i < height - 1; i++) 338 printf("%s", buffer[i]); 339 } 340 566 move_cursor(0, 0); 567 for (i = 0; i <= max_displayed_line; i++) 568 if (pattern_valid) 569 print_found(buffer[i]); 570 else 571 print_ascii(buffer[i]); 341 572 status_print(); 342 573 } 343 574 344 /* Initialise the buffer */ 345 static void buffer_init(void) 575 static void buffer_fill_and_print(void) 346 576 { 347 577 int i; 348 349 if (buffer == NULL) { 350 /* malloc the number of lines needed for the buffer */ 351 buffer = xrealloc(buffer, height * sizeof(char *)); 352 } else { 353 for (i = 0; i < (height - 1); i++) 354 free(buffer[i]); 355 } 356 357 /* Fill the buffer until the end of the file or the 358 end of the buffer is reached */ 359 for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) { 360 buffer[i] = bb_xstrdup(flines[i]); 361 } 362 363 /* If the buffer still isn't full, fill it with blank lines */ 364 for (; i < (height - 1); i++) { 365 buffer[i] = bb_xstrdup(""); 366 } 578 for (i = 0; i <= max_displayed_line && cur_fline + i <= max_fline; i++) { 579 buffer[i] = flines[cur_fline + i]; 580 } 581 for (; i <= max_displayed_line; i++) { 582 buffer[i] = empty_line_marker; 583 } 584 buffer_print(); 367 585 } 368 586 … … 370 588 static void buffer_down(int nlines) 371 589 { 590 cur_fline += nlines; 591 read_lines(); 592 cap_cur_fline(nlines); 593 buffer_fill_and_print(); 594 } 595 596 static void buffer_up(int nlines) 597 { 598 cur_fline -= nlines; 599 if (cur_fline < 0) cur_fline = 0; 600 read_lines(); 601 buffer_fill_and_print(); 602 } 603 604 static void buffer_line(int linenum) 605 { 606 if (linenum < 0) 607 linenum = 0; 608 cur_fline = linenum; 609 read_lines(); 610 if (linenum + max_displayed_line > max_fline) 611 linenum = max_fline - max_displayed_line + TILDES; 612 if (linenum < 0) 613 linenum = 0; 614 cur_fline = linenum; 615 buffer_fill_and_print(); 616 } 617 618 static void open_file_and_read_lines(void) 619 { 620 if (filename) { 621 int fd = xopen(filename, O_RDONLY); 622 dup2(fd, 0); 623 if (fd) close(fd); 624 } else { 625 /* "less" with no arguments in argv[] */ 626 /* For status line only */ 627 filename = xstrdup(bb_msg_standard_input); 628 } 629 readpos = 0; 630 readeof = 0; 631 linepos = 0; 632 terminated = 1; 633 read_lines(); 634 } 635 636 /* Reinitialize everything for a new file - free the memory and start over */ 637 static void reinitialize(void) 638 { 372 639 int i; 373 640 374 if (!past_eof) { 375 if (line_pos + (height - 3) + nlines < num_flines) { 376 line_pos += nlines; 377 for (i = 0; i < (height - 1); i++) { 378 free(buffer[i]); 379 buffer[i] = bb_xstrdup(flines[line_pos + i]); 380 } 641 if (flines) { 642 for (i = 0; i <= max_fline; i++) 643 free((void*)(flines[i])); 644 free(flines); 645 flines = NULL; 646 } 647 648 max_fline = -1; 649 cur_fline = 0; 650 max_lineno = 0; 651 open_file_and_read_lines(); 652 buffer_fill_and_print(); 653 } 654 655 static void getch_nowait(char* input, int sz) 656 { 657 ssize_t rd; 658 fd_set readfds; 659 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 667 * (switch fd into O_NONBLOCK'ed mode to avoid it) 668 */ 669 FD_ZERO(&readfds); 670 if (max_fline <= cur_fline + max_displayed_line 671 && eof_error > 0 /* did NOT reach eof yet */ 672 ) { 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(); 690 goto again; 691 } 692 } 693 694 /* Grab a character from input without requiring the return key. If the 695 * character is ASCII \033, get more characters and assign certain sequences 696 * 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 handle 706 * 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 return i; 730 } 731 732 static char* less_gets(int sz) 733 { 734 char c; 735 int i = 0; 736 char *result = xzalloc(1); 737 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 c = '\0'; 745 read(kbd_fd, &c, 1); 746 if (c == 0x0d) 747 return result; 748 if (c == 0x7f) 749 c = 8; 750 if (c == 8 && i) { 751 printf("\x8 \x8"); 752 i--; 381 753 } 382 else { 383 /* As the number of lines requested was too large, we just move 384 to the end of the file */ 385 while (line_pos + (height - 3) + 1 < num_flines) { 386 line_pos += 1; 387 for (i = 0; i < (height - 1); i++) { 388 free(buffer[i]); 389 buffer[i] = bb_xstrdup(flines[line_pos + i]); 390 } 391 } 392 } 393 394 /* We exit if the -E flag has been set */ 395 if ((flags & FLAG_E) && (line_pos + (height - 2) == num_flines)) 396 tless_exit(0); 397 } 398 } 399 400 static void buffer_up(int nlines) 401 { 402 int i; 403 int tilde_line; 404 405 if (!past_eof) { 406 if (line_pos - nlines >= 0) { 407 line_pos -= nlines; 408 for (i = 0; i < (height - 1); i++) { 409 free(buffer[i]); 410 buffer[i] = bb_xstrdup(flines[line_pos + i]); 411 } 412 } 413 else { 414 /* As the requested number of lines to move was too large, we 415 move one line up at a time until we can't. */ 416 while (line_pos != 0) { 417 line_pos -= 1; 418 for (i = 0; i < (height - 1); i++) { 419 free(buffer[i]); 420 buffer[i] = bb_xstrdup(flines[line_pos + i]); 421 } 422 } 423 } 424 } 425 else { 426 /* Work out where the tildes start */ 427 tilde_line = num_flines - line_pos + 3; 428 429 line_pos -= nlines; 430 /* Going backwards nlines lines has taken us to a point where 431 nothing is past the EOF, so we revert to normal. */ 432 if (line_pos < num_flines - height + 3) { 433 past_eof = 0; 434 buffer_up(nlines); 435 } 436 else { 437 /* We only move part of the buffer, as the rest 438 is past the EOF */ 439 for (i = 0; i < (height - 1); i++) { 440 free(buffer[i]); 441 if (i < tilde_line - nlines + 1) 442 buffer[i] = bb_xstrdup(flines[line_pos + i]); 443 else { 444 if (line_pos >= num_flines - height + 2) 445 buffer[i] = bb_xstrdup("~\n"); 446 } 447 } 448 } 449 } 450 } 451 452 static void buffer_line(int linenum) 453 { 454 int i; 455 past_eof = 0; 456 457 if (linenum < 0 || linenum > num_flines) { 458 clear_line(); 459 printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL); 460 } 461 else if (linenum < (num_flines - height - 2)) { 462 for (i = 0; i < (height - 1); i++) { 463 free(buffer[i]); 464 buffer[i] = bb_xstrdup(flines[linenum + i]); 465 } 466 line_pos = linenum; 467 buffer_print(); 468 } 469 else { 470 for (i = 0; i < (height - 1); i++) { 471 free(buffer[i]); 472 if (linenum + i < num_flines + 2) 473 buffer[i] = bb_xstrdup(flines[linenum + i]); 474 else 475 buffer[i] = bb_xstrdup((flags & FLAG_TILDE) ? "\n" : "~\n"); 476 } 477 line_pos = linenum; 478 /* Set past_eof so buffer_down and buffer_up act differently */ 479 past_eof = 1; 480 buffer_print(); 481 } 482 } 483 484 /* Reinitialise everything for a new file - free the memory and start over */ 485 static void reinitialise(void) 486 { 487 int i; 488 489 for (i = 0; i <= num_flines; i++) 490 free(flines[i]); 491 free(flines); 492 493 data_readlines(); 494 buffer_init(); 495 buffer_print(); 754 if (c < ' ') 755 continue; 756 if (i >= width - sz - 1) 757 continue; /* len limit */ 758 putchar(c); 759 result[i++] = c; 760 result = xrealloc(result, i+1); 761 result[i] = '\0'; 762 } 496 763 } 497 764 498 765 static void examine_file(void) 499 766 { 500 int newline_offset; 501 502 clear_line(); 503 printf("Examine: "); 504 fgets(filename, 256, inp); 505 506 /* As fgets adds a newline to the end of an input string, we 507 need to remove it */ 508 newline_offset = strlen(filename) - 1; 509 filename[newline_offset] = '\0'; 510 511 files[num_files] = bb_xstrdup(filename); 767 print_statusline("Examine: "); 768 free(filename); 769 filename = less_gets(sizeof("Examine: ")-1); 770 /* files start by = argv. why we assume that argv is infinitely long?? 771 files[num_files] = filename; 512 772 current_file = num_files + 1; 513 num_files++; 514 515 inp_stdin = 0;516 reinitiali se();773 num_files++; */ 774 files[0] = filename; 775 num_files = current_file = 1; 776 reinitialize(); 517 777 } 518 778 … … 520 780 * -1: go back one file 521 781 * 0: go to the first file 522 * 1: go forward one file 523 */ 782 * 1: go forward one file */ 524 783 static void change_file(int direction) 525 784 { 526 785 if (current_file != ((direction > 0) ? num_files : 1)) { 527 786 current_file = direction ? current_file + direction : 1; 528 strcpy(filename, files[current_file - 1]); 529 reinitialise(); 530 } 531 else { 532 clear_line(); 533 printf("%s%s%s", HIGHLIGHT, (direction > 0) ? "No next file" : "No previous file", NORMAL); 787 free(filename); 788 filename = xstrdup(files[current_file - 1]); 789 reinitialize(); 790 } else { 791 print_statusline(direction > 0 ? "No next file" : "No previous file"); 534 792 } 535 793 } … … 538 796 { 539 797 int i; 798 799 if (num_files < 2) 800 return; 540 801 541 802 if (current_file != 1) { … … 544 805 files[i - 2] = files[i - 1]; 545 806 num_files--; 546 buffer_print(); 547 } 548 else { 807 } else { 549 808 change_file(1); 550 809 for (i = 2; i <= num_files; i++) … … 552 811 num_files--; 553 812 current_file--; 554 buffer_print();555 813 } 556 814 } … … 561 819 562 820 /* Clear the current line and print a prompt */ 563 clear_line(); 564 printf(" :"); 565 566 keypress = tless_getch(); 821 print_statusline(" :"); 822 823 keypress = less_getch(); 567 824 switch (keypress) { 568 case 'd': 569 remove_current_file(); 570 break; 571 case 'e': 572 examine_file(); 573 break; 574 #ifdef CONFIG_FEATURE_LESS_FLAGS 575 case 'f': 576 clear_line(); 577 m_status_print(); 578 break; 579 #endif 580 case 'n': 581 change_file(1); 582 break; 583 case 'p': 584 change_file(-1); 585 break; 586 case 'q': 587 tless_exit(0); 588 break; 589 case 'x': 590 change_file(0); 591 break; 592 default: 593 break; 594 } 595 } 596 597 #ifdef CONFIG_FEATURE_LESS_REGEXP 598 /* The below two regular expression handler functions NEED development. */ 599 600 /* Get a regular expression from the user, and then go through the current 601 file line by line, running a processing regex function on each one. */ 602 603 static char *process_regex_on_line(char *line, regex_t *pattern, int action) 604 { 605 /* This function takes the regex and applies it to the line. 606 Each part of the line that matches has the HIGHLIGHT 607 and NORMAL escape sequences placed around it by 608 insert_highlights if action = 1, or has the escape sequences 609 removed if action = 0, and then the line is returned. */ 610 int match_status; 611 char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); 612 char *growline = ""; 613 regmatch_t match_structs; 614 615 line2 = bb_xstrdup(line); 616 617 match_found = 0; 618 match_status = regexec(pattern, line2, 1, &match_structs, 0); 619 620 while (match_status == 0) { 621 if (match_found == 0) 622 match_found = 1; 623 624 if (action) { 625 growline = bb_xasprintf("%s%.*s%s%.*s%s", growline, match_structs.rm_so, line2, HIGHLIGHT, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so, NORMAL); 825 case 'd': 826 remove_current_file(); 827 break; 828 case 'e': 829 examine_file(); 830 break; 831 #if ENABLE_FEATURE_LESS_FLAGS 832 case 'f': 833 m_status_print(); 834 break; 835 #endif 836 case 'n': 837 change_file(1); 838 break; 839 case 'p': 840 change_file(-1); 841 break; 842 case 'q': 843 less_exit(0); 844 break; 845 case 'x': 846 change_file(0); 847 break; 848 } 849 } 850 851 #if ENABLE_FEATURE_LESS_REGEXP 852 static void normalize_match_pos(int match) 853 { 854 if (match >= num_matches) 855 match = num_matches - 1; 856 if (match < 0) 857 match = 0; 858 match_pos = match; 859 } 860 861 static void goto_match(int match) 862 { 863 int sv; 864 865 if (!pattern_valid) 866 return; 867 if (match < 0) 868 match = 0; 869 sv = cur_fline; 870 /* Try to find next match if eof isn't reached yet */ 871 if (match >= num_matches && eof_error > 0) { 872 cur_fline = MAXLINES; /* look as far as needed */ 873 read_lines(); 874 } 875 if (num_matches) { 876 cap_cur_fline(cur_fline); 877 normalize_match_pos(match); 878 buffer_line(match_lines[match_pos]); 879 } else { 880 cur_fline = sv; 881 print_statusline("No matches found"); 882 } 883 } 884 885 static void fill_match_lines(unsigned pos) 886 { 887 if (!pattern_valid) 888 return; 889 /* Run the regex on each line of the current file */ 890 while (pos <= max_fline) { 891 /* If this line matches */ 892 if (regexec(&pattern, flines[pos], 0, NULL, 0) == 0 893 /* and we didn't match it last time */ 894 && !(num_matches && match_lines[num_matches-1] == pos) 895 ) { 896 match_lines = xrealloc(match_lines, (num_matches+1) * sizeof(int)); 897 match_lines[num_matches++] = pos; 626 898 } 627 else { 628 growline = bb_xasprintf("%s%.*s%.*s", growline, match_structs.rm_so - 4, line2, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so); 629 } 630 631 line2 += match_structs.rm_eo; 632 match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL); 633 } 634 635 growline = bb_xasprintf("%s%s", growline, line2); 636 637 return (match_found ? growline : line); 638 639 free(growline); 640 free(line2); 641 } 642 643 static void goto_match(int match) 644 { 645 /* This goes to a specific match - all line positions of matches are 646 stored within the match_lines[] array. */ 647 if ((match < num_matches) && (match >= 0)) { 648 buffer_line(match_lines[match]); 649 match_pos = match; 899 pos++; 650 900 } 651 901 } … … 653 903 static void regex_process(void) 654 904 { 655 char uncomp_regex[100]; 656 char *current_line; 657 int i; 658 int j = 0; 659 regex_t pattern; 905 char *uncomp_regex, *err; 906 907 /* Reset variables */ 908 free(match_lines); 909 match_lines = NULL; 910 match_pos = 0; 911 num_matches = 0; 912 if (pattern_valid) { 913 regfree(&pattern); 914 pattern_valid = 0; 915 } 916 660 917 /* Get the uncompiled regular expression from the user */ 661 918 clear_line(); 662 putchar((match_backwards) ? '?' : '/'); 663 uncomp_regex[0] = 0; 664 fgets(uncomp_regex, sizeof(uncomp_regex), inp); 665 666 if (strlen(uncomp_regex) == 1) { 667 if (num_matches) 668 goto_match(match_backwards ? match_pos - 1 : match_pos + 1); 669 else 670 buffer_print(); 919 putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/'); 920 uncomp_regex = less_gets(1); 921 if (!uncomp_regex[0]) { 922 free(uncomp_regex); 923 buffer_print(); 671 924 return; 672 925 } 673 uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; 674 926 675 927 /* Compile the regex and check for errors */ 676 xregcomp(&pattern, uncomp_regex, 0); 677 678 if (num_matches) { 679 /* Get rid of all the highlights we added previously */ 680 for (i = 0; i <= num_flines; i++) { 681 current_line = process_regex_on_line(flines[i], &old_pattern, 0); 682 flines[i] = bb_xstrdup(current_line); 683 } 684 } 685 old_pattern = pattern; 686 687 /* Reset variables */ 688 match_lines = xrealloc(match_lines, sizeof(int)); 689 match_lines[0] = -1; 928 err = regcomp_or_errmsg(&pattern, uncomp_regex, 0); 929 free(uncomp_regex); 930 if (err) { 931 print_statusline(err); 932 free(err); 933 return; 934 } 935 936 pattern_valid = 1; 690 937 match_pos = 0; 691 num_matches = 0; 692 match_found = 0; 693 /* Run the regex on each line of the current file here */ 694 for (i = 0; i <= num_flines; i++) { 695 current_line = process_regex_on_line(flines[i], &pattern, 1); 696 flines[i] = bb_xstrdup(current_line); 697 if (match_found) { 698 match_lines = xrealloc(match_lines, (j + 1) * sizeof(int)); 699 match_lines[j] = i; 700 j++; 701 } 702 } 703 704 num_matches = j; 705 if ((match_lines[0] != -1) && (num_flines > height - 2)) { 706 if (match_backwards) { 707 for (i = 0; i < num_matches; i++) { 708 if (match_lines[i] > line_pos) { 709 match_pos = i - 1; 710 buffer_line(match_lines[match_pos]); 711 break; 712 } 713 } 714 } 715 else 716 buffer_line(match_lines[0]); 717 } 718 else 719 buffer_init(); 938 fill_match_lines(0); 939 while (match_pos < num_matches) { 940 if (match_lines[match_pos] > cur_fline) 941 break; 942 match_pos++; 943 } 944 if (option_mask32 & LESS_STATE_MATCH_BACKWARDS) 945 match_pos--; 946 947 /* It's possible that no matches are found yet. 948 * goto_match() will read input looking for match, 949 * if needed */ 950 goto_match(match_pos); 720 951 } 721 952 #endif … … 725 956 int i = 1; 726 957 int num; 727 char num_input[ 80];958 char num_input[sizeof(int)*4]; /* more than enough */ 728 959 char keypress; 729 char *endptr;730 960 731 961 num_input[0] = first_digit; … … 735 965 printf(":%c", first_digit); 736 966 737 /* Receive input until a letter is given (max 80 chars)*/ 738 while((i < 80) && (num_input[i] = tless_getch()) && isdigit(num_input[i])) { 967 /* Receive input until a letter is given */ 968 while (i < sizeof(num_input)-1) { 969 num_input[i] = less_getch(); 970 if (!num_input[i] || !isdigit(num_input[i])) 971 break; 739 972 putchar(num_input[i]); 740 973 i++; … … 744 977 keypress = num_input[i]; 745 978 num_input[i] = '\0'; 746 num = strtol(num_input, &endptr, 10); 747 if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) { 979 num = bb_strtou(num_input, NULL, 10); 980 /* on format error, num == -1 */ 981 if (num < 1 || num > MAXLINES) { 748 982 buffer_print(); 749 983 return; … … 752 986 /* We now know the number and the letter entered, so we process them */ 753 987 switch (keypress) { 754 case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015': 755 buffer_down(num); 756 break; 757 case KEY_UP: case 'b': case 'w': case 'y': case 'u': 758 buffer_up(num); 759 break; 760 case 'g': case '<': case 'G': case '>': 761 if (num_flines >= height - 2) 762 buffer_line(num - 1); 763 break; 764 case 'p': case '%': 765 buffer_line(((num / 100) * num_flines) - 1); 766 break; 767 #ifdef CONFIG_FEATURE_LESS_REGEXP 768 case 'n': 769 goto_match(match_pos + num); 770 break; 771 case '/': 772 match_backwards = 0; 773 regex_process(); 774 break; 775 case '?': 776 match_backwards = 1; 777 regex_process(); 778 break; 779 #endif 780 default: 781 break; 782 } 783 } 784 785 #ifdef CONFIG_FEATURE_LESS_FLAGCS 988 case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015': 989 buffer_down(num); 990 break; 991 case KEY_UP: case 'b': case 'w': case 'y': case 'u': 992 buffer_up(num); 993 break; 994 case 'g': case '<': case 'G': case '>': 995 cur_fline = num + max_displayed_line; 996 read_lines(); 997 buffer_line(num - 1); 998 break; 999 case 'p': case '%': 1000 num = num * (max_fline / 100); /* + max_fline / 2; */ 1001 cur_fline = num + max_displayed_line; 1002 read_lines(); 1003 buffer_line(num); 1004 break; 1005 #if ENABLE_FEATURE_LESS_REGEXP 1006 case 'n': 1007 goto_match(match_pos + num); 1008 break; 1009 case '/': 1010 option_mask32 &= ~LESS_STATE_MATCH_BACKWARDS; 1011 regex_process(); 1012 break; 1013 case '?': 1014 option_mask32 |= LESS_STATE_MATCH_BACKWARDS; 1015 regex_process(); 1016 break; 1017 #endif 1018 } 1019 } 1020 1021 #if ENABLE_FEATURE_LESS_FLAGCS 786 1022 static void flag_change(void) 787 1023 { … … 790 1026 clear_line(); 791 1027 putchar('-'); 792 keypress = tless_getch();1028 keypress = less_getch(); 793 1029 794 1030 switch (keypress) { 795 case 'M': 796 flags ^= FLAG_M; 797 break; 798 case 'm': 799 flags ^= FLAG_m; 800 break; 801 case 'E': 802 flags ^= FLAG_E; 803 break; 804 case '~': 805 flags ^= FLAG_TILDE; 806 break; 807 default: 808 break; 1031 case 'M': 1032 option_mask32 ^= FLAG_M; 1033 break; 1034 case 'm': 1035 option_mask32 ^= FLAG_m; 1036 break; 1037 case 'E': 1038 option_mask32 ^= FLAG_E; 1039 break; 1040 case '~': 1041 option_mask32 ^= FLAG_TILDE; 1042 break; 809 1043 } 810 1044 } … … 817 1051 clear_line(); 818 1052 putchar('_'); 819 keypress = tless_getch();1053 keypress = less_getch(); 820 1054 821 1055 switch (keypress) { 822 823 flag_val = flags& FLAG_M;824 825 826 flag_val = flags& FLAG_m;827 828 829 flag_val = flags& FLAG_TILDE;830 831 832 flag_val = flags& FLAG_N;833 834 835 flag_val = flags& FLAG_E;836 837 838 839 1056 case 'M': 1057 flag_val = option_mask32 & FLAG_M; 1058 break; 1059 case 'm': 1060 flag_val = option_mask32 & FLAG_m; 1061 break; 1062 case '~': 1063 flag_val = option_mask32 & FLAG_TILDE; 1064 break; 1065 case 'N': 1066 flag_val = option_mask32 & FLAG_N; 1067 break; 1068 case 'E': 1069 flag_val = option_mask32 & FLAG_E; 1070 break; 1071 default: 1072 flag_val = 0; 1073 break; 840 1074 } 841 1075 842 1076 clear_line(); 843 printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL); 844 } 845 #endif 846 847 static void full_repaint(void) 848 { 849 int temp_line_pos = line_pos; 850 data_readlines(); 851 buffer_init(); 852 buffer_line(temp_line_pos); 853 } 854 1077 printf(HIGHLIGHT"The status of the flag is: %u"NORMAL, flag_val != 0); 1078 } 1079 #endif 855 1080 856 1081 static void save_input_to_file(void) 857 1082 { 858 char current_line[256]; 1083 const char *msg = ""; 1084 char *current_line; 859 1085 int i; 860 1086 FILE *fp; 861 1087 862 clear_line(); 863 printf("Log file: "); 864 fgets(current_line, 256, inp); 865 current_line[strlen(current_line) - 1] = '\0'; 866 if (strlen(current_line) > 1) { 867 fp = bb_xfopen(current_line, "w"); 868 for (i = 0; i < num_flines; i++) 869 fprintf(fp, "%s", flines[i]); 1088 print_statusline("Log file: "); 1089 current_line = less_gets(sizeof("Log file: ")-1); 1090 if (strlen(current_line) > 0) { 1091 fp = fopen(current_line, "w"); 1092 if (!fp) { 1093 msg = "Error opening log file"; 1094 goto ret; 1095 } 1096 for (i = 0; i <= max_fline; i++) 1097 fprintf(fp, "%s\n", flines[i]); 870 1098 fclose(fp); 871 buffer_print(); 872 } 873 else 874 printf("%sNo log file%s", HIGHLIGHT, NORMAL); 875 } 876 877 #ifdef CONFIG_FEATURE_LESS_MARKS 1099 msg = "Done"; 1100 } 1101 ret: 1102 print_statusline(msg); 1103 free(current_line); 1104 } 1105 1106 #if ENABLE_FEATURE_LESS_MARKS 878 1107 static void add_mark(void) 879 1108 { 880 1109 int letter; 881 int mark_line; 882 883 clear_line(); 884 printf("Mark: "); 885 letter = tless_getch(); 1110 1111 print_statusline("Mark: "); 1112 letter = less_getch(); 886 1113 887 1114 if (isalpha(letter)) { 888 mark_line = line_pos;889 890 1115 /* If we exceed 15 marks, start overwriting previous ones */ 891 1116 if (num_marks == 14) … … 893 1118 894 1119 mark_lines[num_marks][0] = letter; 895 mark_lines[num_marks][1] = line_pos;1120 mark_lines[num_marks][1] = cur_fline; 896 1121 num_marks++; 897 } 898 else { 899 clear_line(); 900 printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL); 1122 } else { 1123 print_statusline("Invalid mark letter"); 901 1124 } 902 1125 } … … 907 1130 int i; 908 1131 909 clear_line(); 910 printf("Go to mark: "); 911 letter = tless_getch(); 1132 print_statusline("Go to mark: "); 1133 letter = less_getch(); 912 1134 clear_line(); 913 1135 … … 918 1140 break; 919 1141 } 920 if ((num_marks == 14) && (letter != mark_lines[14][0])) 921 printf("%s%s%s", HIGHLIGHT, "Mark not set", NORMAL); 922 } 923 else 924 printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL); 925 } 926 #endif 927 928 929 #ifdef CONFIG_FEATURE_LESS_BRACKETS 930 1142 if (num_marks == 14 && letter != mark_lines[14][0]) 1143 print_statusline("Mark not set"); 1144 } else 1145 print_statusline("Invalid mark letter"); 1146 } 1147 #endif 1148 1149 #if ENABLE_FEATURE_LESS_BRACKETS 931 1150 static char opp_bracket(char bracket) 932 1151 { 933 1152 switch (bracket) { 934 case '{': case '[': 935 return bracket + 2; 936 break; 937 case '(': 938 return ')'; 939 break; 940 case '}': case ']': 941 return bracket - 2; 942 break; 943 case ')': 944 return '('; 945 break; 946 default: 947 return 0; 948 break; 949 } 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; 950 1163 } 951 1164 … … 955 1168 int i; 956 1169 957 clear_line(); 958 959 if (strchr(flines[line_pos], bracket) == NULL) 960 printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL); 961 else { 962 for (i = line_pos + 1; i < num_flines; i++) { 963 if (strchr(flines[i], opp_bracket(bracket)) != NULL) { 964 bracket_line = i; 965 break; 966 } 1170 if (strchr(flines[cur_fline], bracket) == NULL) { 1171 print_statusline("No bracket in top line"); 1172 return; 1173 } 1174 for (i = cur_fline + 1; i < max_fline; i++) { 1175 if (strchr(flines[i], opp_bracket(bracket)) != NULL) { 1176 bracket_line = i; 1177 break; 967 1178 } 968 969 if (bracket_line == -1) 970 printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); 971 972 buffer_line(bracket_line - height + 2); 973 } 1179 } 1180 if (bracket_line == -1) 1181 print_statusline("No matching bracket found"); 1182 buffer_line(bracket_line - max_displayed_line); 974 1183 } 975 1184 … … 979 1188 int i; 980 1189 981 clear_line(); 982 983 if (strchr(flines[line_pos + height - 2], bracket) == NULL) { 984 printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL); 985 printf("%s", flines[line_pos + height]); 986 sleep(4); 987 } 988 else { 989 for (i = line_pos + height - 2; i >= 0; i--) { 990 if (strchr(flines[i], opp_bracket(bracket)) != NULL) { 991 bracket_line = i; 992 break; 993 } 1190 if (strchr(flines[cur_fline + max_displayed_line], bracket) == NULL) { 1191 print_statusline("No bracket in bottom line"); 1192 return; 1193 } 1194 1195 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; 994 1199 } 995 996 if (bracket_line == -1) 997 printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); 998 999 buffer_line(bracket_line); 1000 } 1001 } 1002 1003 #endif /* CONFIG_FEATURE_LESS_BRACKETS */ 1200 } 1201 if (bracket_line == -1) 1202 print_statusline("No matching bracket found"); 1203 buffer_line(bracket_line); 1204 } 1205 #endif /* FEATURE_LESS_BRACKETS */ 1004 1206 1005 1207 static void keypress_process(int keypress) 1006 1208 { 1007 1209 switch (keypress) { 1008 case KEY_DOWN: case 'e': case 'j': case '\015': 1009 buffer_down(1); 1010 buffer_print(); 1011 break; 1012 case KEY_UP: case 'y': case 'k': 1013 buffer_up(1); 1014 buffer_print(); 1015 break; 1016 case PAGE_DOWN: case ' ': case 'z': 1017 buffer_down(height - 1); 1018 buffer_print(); 1019 break; 1020 case PAGE_UP: case 'w': case 'b': 1021 buffer_up(height - 1); 1022 buffer_print(); 1023 break; 1024 case 'd': 1025 buffer_down((height - 1) / 2); 1026 buffer_print(); 1027 break; 1028 case 'u': 1029 buffer_up((height - 1) / 2); 1030 buffer_print(); 1031 break; 1032 case 'g': case 'p': case '<': case '%': 1033 buffer_line(0); 1034 break; 1035 case 'G': case '>': 1036 buffer_line(num_flines - height + 2); 1037 break; 1038 case 'q': case 'Q': 1039 tless_exit(0); 1040 break; 1041 #ifdef CONFIG_FEATURE_LESS_MARKS 1042 case 'm': 1043 add_mark(); 1044 buffer_print(); 1045 break; 1046 case '\'': 1047 goto_mark(); 1048 buffer_print(); 1049 break; 1050 #endif 1051 case 'r': 1052 buffer_print(); 1053 break; 1054 case 'R': 1055 full_repaint(); 1056 break; 1057 case 's': 1058 if (inp_stdin) 1059 save_input_to_file(); 1060 break; 1061 case 'E': 1062 examine_file(); 1063 break; 1064 #ifdef CONFIG_FEATURE_LESS_FLAGS 1065 case '=': 1066 clear_line(); 1067 m_status_print(); 1068 break; 1069 #endif 1070 #ifdef CONFIG_FEATURE_LESS_REGEXP 1071 case '/': 1072 match_backwards = 0; 1073 regex_process(); 1074 break; 1075 case 'n': 1076 goto_match(match_pos + 1); 1077 break; 1078 case 'N': 1079 goto_match(match_pos - 1); 1080 break; 1081 case '?': 1082 match_backwards = 1; 1083 regex_process(); 1084 break; 1085 #endif 1086 #ifdef CONFIG_FEATURE_LESS_FLAGCS 1087 case '-': 1088 flag_change(); 1089 buffer_print(); 1090 break; 1091 case '_': 1092 show_flag_status(); 1093 break; 1094 #endif 1095 #ifdef CONFIG_FEATURE_LESS_BRACKETS 1096 case '{': case '(': case '[': 1097 match_right_bracket(keypress); 1098 break; 1099 case '}': case ')': case ']': 1100 match_left_bracket(keypress); 1101 break; 1102 #endif 1103 case ':': 1104 colon_process(); 1105 break; 1106 default: 1107 break; 1210 case KEY_DOWN: case 'e': case 'j': case 0x0d: 1211 buffer_down(1); 1212 break; 1213 case KEY_UP: case 'y': case 'k': 1214 buffer_up(1); 1215 break; 1216 case PAGE_DOWN: case ' ': case 'z': 1217 buffer_down(max_displayed_line + 1); 1218 break; 1219 case PAGE_UP: case 'w': case 'b': 1220 buffer_up(max_displayed_line + 1); 1221 break; 1222 case 'd': 1223 buffer_down((max_displayed_line + 1) / 2); 1224 break; 1225 case 'u': 1226 buffer_up((max_displayed_line + 1) / 2); 1227 break; 1228 case KEY_HOME: case 'g': case 'p': case '<': case '%': 1229 buffer_line(0); 1230 break; 1231 case KEY_END: case 'G': case '>': 1232 cur_fline = MAXLINES; 1233 read_lines(); 1234 buffer_line(cur_fline); 1235 break; 1236 case 'q': case 'Q': 1237 less_exit(0); 1238 break; 1239 #if ENABLE_FEATURE_LESS_MARKS 1240 case 'm': 1241 add_mark(); 1242 buffer_print(); 1243 break; 1244 case '\'': 1245 goto_mark(); 1246 buffer_print(); 1247 break; 1248 #endif 1249 case 'r': case 'R': 1250 buffer_print(); 1251 break; 1252 /*case 'R': 1253 full_repaint(); 1254 break;*/ 1255 case 's': 1256 save_input_to_file(); 1257 break; 1258 case 'E': 1259 examine_file(); 1260 break; 1261 #if ENABLE_FEATURE_LESS_FLAGS 1262 case '=': 1263 m_status_print(); 1264 break; 1265 #endif 1266 #if ENABLE_FEATURE_LESS_REGEXP 1267 case '/': 1268 option_mask32 &= ~LESS_STATE_MATCH_BACKWARDS; 1269 regex_process(); 1270 break; 1271 case 'n': 1272 goto_match(match_pos + 1); 1273 break; 1274 case 'N': 1275 goto_match(match_pos - 1); 1276 break; 1277 case '?': 1278 option_mask32 |= LESS_STATE_MATCH_BACKWARDS; 1279 regex_process(); 1280 break; 1281 #endif 1282 #if ENABLE_FEATURE_LESS_FLAGCS 1283 case '-': 1284 flag_change(); 1285 buffer_print(); 1286 break; 1287 case '_': 1288 show_flag_status(); 1289 break; 1290 #endif 1291 #if ENABLE_FEATURE_LESS_BRACKETS 1292 case '{': case '(': case '[': 1293 match_right_bracket(keypress); 1294 break; 1295 case '}': case ')': case ']': 1296 match_left_bracket(keypress); 1297 break; 1298 #endif 1299 case ':': 1300 colon_process(); 1301 break; 1108 1302 } 1109 1303 … … 1112 1306 } 1113 1307 1114 int less_main(int argc, char **argv) { 1115 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); 1315 int less_main(int argc, char **argv) 1316 { 1116 1317 int keypress; 1117 1318 1118 flags = bb_getopt_ulflags(argc, argv, "EMmN~"); 1119 1319 INIT_G(); 1320 1321 /* TODO: -x: do not interpret backspace, -xx: tab also */ 1322 /* -xxx: newline also */ 1323 /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */ 1324 getopt32(argv, "EMmN~"); 1120 1325 argc -= optind; 1121 1326 argv += optind; 1327 num_files = argc; 1122 1328 files = argv; 1123 num_files = argc; 1329 1330 /* Another popular pager, most, detects when stdout 1331 * is not a tty and turns into cat. This makes sense. */ 1332 if (!isatty(STDOUT_FILENO)) 1333 return bb_cat(argv); 1334 kbd_fd = open(CURRENT_TTY, O_RDONLY); 1335 if (kbd_fd < 0) 1336 return bb_cat(argv); 1124 1337 1125 1338 if (!num_files) { 1126 if (ttyname(STDIN_FILENO) == NULL) 1127 inp_stdin = 1; 1128 else { 1129 bb_error_msg("Missing filename"); 1339 if (isatty(STDIN_FILENO)) { 1340 /* Just "less"? No args and no redirection? */ 1341 bb_error_msg("missing filename"); 1130 1342 bb_show_usage(); 1131 1343 } 1132 } 1133 1134 strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]); 1135 get_terminal_width_height(0, &width, &height); 1136 data_readlines(); 1137 tcgetattr(fileno(inp), &term_orig); 1138 term_vi = term_orig; 1139 term_vi.c_lflag &= (~ICANON & ~ECHO); 1140 term_vi.c_iflag &= (~IXON & ~ICRNL); 1141 term_vi.c_oflag &= (~ONLCR); 1142 term_vi.c_cc[VMIN] = 1; 1143 term_vi.c_cc[VTIME] = 0; 1144 buffer_init(); 1145 buffer_print(); 1146 1344 } else 1345 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 *)); 1354 if (option_mask32 & FLAG_TILDE) 1355 empty_line_marker = ""; 1356 1357 tcgetattr(kbd_fd, &term_orig); 1358 signal(SIGTERM, sig_catcher); 1359 signal(SIGINT, sig_catcher); 1360 term_less = term_orig; 1361 term_less.c_lflag &= ~(ICANON | ECHO); 1362 term_less.c_iflag &= ~(IXON | ICRNL); 1363 /*term_less.c_oflag &= ~ONLCR;*/ 1364 term_less.c_cc[VMIN] = 1; 1365 term_less.c_cc[VTIME] = 0; 1366 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 1371 reinitialize(); 1147 1372 while (1) { 1148 keypress = tless_getch();1373 keypress = less_getch(); 1149 1374 keypress_process(keypress); 1150 1375 } -
branches/stable/mindi-busybox/miscutils/makedevs.c
r821 r1770 8 8 */ 9 9 10 #include "busybox.h" 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <fcntl.h> 15 #include <time.h> 16 #include <ctype.h> 17 #include <unistd.h> 18 #include <sys/types.h> 19 #include <sys/sysmacros.h> /* major() and minor() */ 20 21 #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF 10 #include "libbb.h" 11 12 #if ENABLE_FEATURE_MAKEDEVS_LEAF 13 int makedevs_main(int argc, char **argv); 22 14 int makedevs_main(int argc, char **argv) 23 15 { … … 31 23 basedev = argv[1]; 32 24 type = argv[2]; 33 Smajor = atoi(argv[3]);34 Sminor = atoi(argv[4]);35 S = atoi(argv[5]);36 E = atoi(argv[6]);25 Smajor = xatoi_u(argv[3]); 26 Sminor = xatoi_u(argv[4]); 27 S = xatoi_u(argv[5]); 28 E = xatoi_u(argv[6]); 37 29 nodname = argc == 8 ? basedev : buf; 38 30 … … 57 49 58 50 sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S); 59 if (sz<0 || sz>=sizeof(buf)) /* libc different */51 if (sz < 0 || sz >= sizeof(buf)) /* libc different */ 60 52 bb_error_msg_and_die("%s too large", basedev); 61 53 … … 63 55 64 56 if (mknod(nodname, mode, makedev(Smajor, Sminor))) 65 bb_error_msg(" Failed to create: %s", nodname);57 bb_error_msg("failed to create: %s", nodname); 66 58 67 59 if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */ … … 74 66 } 75 67 76 #elif defined CONFIG_FEATURE_MAKEDEVS_TABLE68 #elif ENABLE_FEATURE_MAKEDEVS_TABLE 77 69 78 70 /* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */ 79 71 72 int makedevs_main(int argc, char **argv); 80 73 int makedevs_main(int argc, char **argv) 81 74 { … … 86 79 int ret = EXIT_SUCCESS; 87 80 88 unsigned long flags; 89 flags = bb_getopt_ulflags(argc, argv, "d:", &line); 81 getopt32(argv, "d:", &line); 90 82 if (line) 91 table = bb_xfopen(line, "r");83 table = xfopen(line, "r"); 92 84 93 85 if (optind >= argc || (rootdir=argv[optind])==NULL) { … … 95 87 } 96 88 97 bb_xchdir(rootdir);89 xchdir(rootdir); 98 90 99 91 umask(0); … … 106 98 } 107 99 108 while ((line = bb_get_chomped_line_from_file(table))) {100 while ((line = xmalloc_getline(table))) { 109 101 char type; 110 102 unsigned int mode = 0755; … … 130 122 if (*line=='\0' || *line=='#' || isspace(*line)) 131 123 continue; 132 bb_error_msg("line %d invalid: '%s' \n", linenum, line);124 bb_error_msg("line %d invalid: '%s'", linenum, line); 133 125 ret = EXIT_FAILURE; 134 126 continue; … … 138 130 } 139 131 140 gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();141 uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();132 gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid(); 133 uid = (*user) ? get_ug_id(user, xuname2uid) : getuid(); 142 134 full_name = concat_path_file(rootdir, name); 143 135 … … 171 163 goto loop; 172 164 } 173 } else 174 { 165 } else { 175 166 dev_t rdev; 176 167 … … 196 187 for (i = start; i < count; i++) { 197 188 sprintf(full_name_inc, "%s%d", full_name, i); 198 rdev = (major << 8) + minor + (i * increment - start);189 rdev = makedev(major, minor + (i * increment - start)); 199 190 if (mknod(full_name_inc, mode, rdev) == -1) { 200 bb_perror_msg("line %d: c ouldnot create node %s", linenum, full_name_inc);191 bb_perror_msg("line %d: cannot create node %s", linenum, full_name_inc); 201 192 ret = EXIT_FAILURE; 202 193 } … … 212 203 free(full_name_inc); 213 204 } else { 214 rdev = (major << 8) + minor;205 rdev = makedev(major, minor); 215 206 if (mknod(full_name, mode, rdev) == -1) { 216 bb_perror_msg("line %d: c ouldnot create node %s", linenum, full_name);207 bb_perror_msg("line %d: cannot create node %s", linenum, full_name); 217 208 ret = EXIT_FAILURE; 218 209 } -
branches/stable/mindi-busybox/miscutils/mountpoint.c
r821 r1770 10 10 */ 11 11 12 #include "busybox.h" 13 #include <sys/stat.h> 14 #include <errno.h> /* errno */ 15 #include <string.h> /* strerror */ 16 #include <getopt.h> /* optind */ 12 #include "libbb.h" 17 13 14 int mountpoint_main(int argc, char **argv); 18 15 int mountpoint_main(int argc, char **argv) 19 16 { 20 int opt = bb_getopt_ulflags(argc, argv, "qdx"); 17 struct stat st; 18 char *arg; 19 int opt = getopt32(argv, "qdx"); 21 20 #define OPT_q (1) 22 21 #define OPT_d (2) … … 25 24 if (optind != argc - 1) 26 25 bb_show_usage(); 27 {28 char *arg = argv[optind];29 struct stat st;30 26 31 if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) { 32 if (opt & OPT_x) { 33 if (S_ISBLK(st.st_mode)) 34 { 35 bb_printf("%u:%u\n", major(st.st_rdev), 36 minor(st.st_rdev)); 37 return EXIT_SUCCESS; 38 } else { 39 if (opt & OPT_q) 40 putchar('\n'); 41 else 42 bb_error_msg("%s: not a block device", arg); 43 } 44 return EXIT_FAILURE; 45 } else 46 if (S_ISDIR(st.st_mode)) { 47 dev_t st_dev = st.st_dev; 48 ino_t st_ino = st.st_ino; 49 char *p = bb_xasprintf("%s/..", arg); 27 arg = argv[optind]; 50 28 51 if (stat(p, &st) == 0) { 52 short ret = (st_dev != st.st_dev) || 53 (st_dev == st.st_dev && st_ino == st.st_ino); 54 if (opt & OPT_d) 55 bb_printf("%u:%u\n", major(st_dev), minor(st_dev)); 56 else if (!(opt & OPT_q)) 57 bb_printf("%s is %sa mountpoint\n", arg, ret?"":"not "); 58 return !ret; 59 } 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; 60 35 } else { 61 if (!(opt & OPT_q)) 62 bb_error_msg("%s: not a directory", arg); 63 return EXIT_FAILURE; 36 if (opt & OPT_q) 37 putchar('\n'); 38 else 39 bb_error_msg("%s: not a block device", arg); 64 40 } 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); 47 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; 65 61 } 66 if (!(opt & OPT_q))67 bb_perror_msg("%s", arg);68 return EXIT_FAILURE;69 62 } 63 if (!(opt & OPT_q)) 64 bb_perror_msg("%s", arg); 65 return EXIT_FAILURE; 70 66 } -
branches/stable/mindi-busybox/miscutils/mt.c
r821 r1770 1 1 /* vi: set sw=4 ts=4: */ 2 #include "busybox.h" 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 4 */ 5 6 #include "libbb.h" 6 7 #include <sys/mtio.h> 7 #include <fcntl.h>8 8 9 9 struct mt_opcodes { 10 c har *name;10 const char *name; 11 11 short value; 12 12 }; … … 51 51 }; 52 52 53 int mt_main(int argc, char **argv); 53 54 int mt_main(int argc, char **argv) 54 55 { … … 79 80 80 81 if (code->name == 0) { 81 bb_error_msg("unrecognized opcode %s .", argv[1]);82 bb_error_msg("unrecognized opcode %s", argv[1]); 82 83 return EXIT_FAILURE; 83 84 } … … 85 86 op.mt_op = code->value; 86 87 if (argc >= 3) 87 op.mt_count = atoi(argv[2]);88 op.mt_count = xatoi_u(argv[2]); 88 89 else 89 90 op.mt_count = 1; /* One, not zero, right? */ … … 102 103 } 103 104 104 fd = bb_xopen3(file, mode, 0);105 fd = xopen(file, mode); 105 106 106 107 switch (code->value) { 107 108 case MTTELL: 108 if (ioctl(fd, MTIOCPOS, &position) < 0) 109 bb_perror_msg_and_die("%s", file); 110 printf ("At block %d.\n", (int) position.mt_blkno); 109 ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file); 110 printf("At block %d.\n", (int) position.mt_blkno); 111 111 break; 112 112 113 113 default: 114 if (ioctl(fd, MTIOCTOP, &op) != 0) 115 bb_perror_msg_and_die("%s", file); 114 ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file); 116 115 break; 117 116 } -
branches/stable/mindi-busybox/miscutils/runlevel.c
r821 r1770 13 13 */ 14 14 15 #include "busybox.h"16 #include <stdio.h>17 15 #include <utmp.h> 18 #include <time.h> 19 #include <stdlib.h> 16 #include "libbb.h" 20 17 21 int runlevel_main(int argc, char *argv[]) 18 int runlevel_main(int argc, char **argv); 19 int runlevel_main(int argc, char **argv) 22 20 { 23 24 21 struct utmp *ut; 22 char prev; 25 23 26 24 if (argc > 1) utmpname(argv[1]); 27 25 28 setutent(); 29 while ((ut = getutent()) != NULL) { 30 if (ut->ut_type == RUN_LVL) { 31 prev = ut->ut_pid / 256; 32 if (prev == 0) prev = 'N'; 33 printf("%c %c\n", prev, ut->ut_pid % 256); 26 setutent(); 27 while ((ut = getutent()) != NULL) { 28 if (ut->ut_type == RUN_LVL) { 29 prev = ut->ut_pid / 256; 30 if (prev == 0) prev = 'N'; 31 printf("%c %c\n", prev, ut->ut_pid % 256); 32 if (ENABLE_FEATURE_CLEAN_UP) 33 endutent(); 34 return 0; 35 } 36 } 37 38 puts("unknown"); 39 40 if (ENABLE_FEATURE_CLEAN_UP) 34 41 endutent(); 35 return (0); 36 } 37 } 38 39 printf("unknown\n"); 40 endutent(); 41 return (1); 42 return 1; 42 43 } 43 -
branches/stable/mindi-busybox/miscutils/rx.c
r821 r1770 2 2 /*------------------------------------------------------------------------- 3 3 * Filename: xmodem.c 4 * Version: $Id: rx.c,v 1.2 2004/03/15 08:28:46 andersen Exp $5 4 * Copyright: Copyright (C) 2001, Hewlett-Packard Company 6 5 * Author: Christopher Hoover <ch@hpl.hp.com> … … 21 20 */ 22 21 23 #include "busybox.h" 24 #include <stdlib.h> 25 #include <stdarg.h> 26 #include <stdio.h> 27 #include <unistd.h> 28 #include <errno.h> 29 #include <termios.h> 30 #include <signal.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 #include <string.h> 35 22 #include "libbb.h" 36 23 37 24 #define SOH 0x01 … … 57 44 #define MAXERRORS 10 58 45 59 static int read_byte(int fd, unsigned int timeout) { 46 static int read_byte(int fd, unsigned int timeout) 47 { 60 48 char buf[1]; 61 49 int n; … … 213 201 length += blockLength; 214 202 215 if ( bb_full_write(filefd, blockBuf, blockLength) < 0) {203 if (full_write(filefd, blockBuf, blockLength) < 0) { 216 204 note_error("write to file failed: %m"); 217 205 goto fatal; … … 262 250 } 263 251 252 int rx_main(int argc, char **argv); 264 253 int rx_main(int argc, char **argv) 265 254 { … … 275 264 276 265 fn = argv[1]; 277 ttyfd = bb_xopen3(CURRENT_TTY, O_RDWR, 0);278 filefd = bb_xopen3(fn, O_RDWR|O_CREAT|O_TRUNC, 0666);266 ttyfd = xopen(CURRENT_TTY, O_RDWR); 267 filefd = xopen(fn, O_RDWR|O_CREAT|O_TRUNC); 279 268 280 269 if (tcgetattr(ttyfd, &tty) < 0) 281 bb_ error_msg_and_die("%s: tcgetattr failed: %m\n", argv[0]);270 bb_perror_msg_and_die("tcgetattr"); 282 271 283 272 orig_tty = tty; … … 297 286 298 287 if (n < 0) 299 bb_error_msg_and_die("\n%s: receive failed:\n %s\n", 300 argv[0], error_buf); 301 302 bb_fflush_stdout_and_exit(EXIT_SUCCESS); 303 } 288 bb_error_msg_and_die("\nreceive failed:\n %s", error_buf); 289 290 fflush_stdout_and_exit(EXIT_SUCCESS); 291 } -
branches/stable/mindi-busybox/miscutils/setsid.c
r821 r1770 15 15 */ 16 16 17 #include "busybox.h" 18 #include <stdio.h> 19 #include <unistd.h> 20 #include <stdlib.h> 17 #include "libbb.h" 21 18 22 int setsid_main(int argc, char *argv[]) 19 int setsid_main(int argc, char **argv); 20 int setsid_main(int argc, char **argv) 23 21 { 24 22 if (argc < 2) 25 23 bb_show_usage(); 26 24 27 if (getpgrp() == getpid()) { 28 switch(fork()){ 29 case -1: 30 bb_perror_msg_and_die("fork"); 31 case 0: 32 break; 33 default: /* parent */ 34 exit(0); 35 } 36 /* child falls through */ 37 } 25 /* Comment why is this necessary? */ 26 if (getpgrp() == getpid()) 27 forkexit_or_rexec(argv); 38 28 39 29 setsid(); /* no error possible */ 40 30 41 execvp(argv[1], argv + 1); 42 31 BB_EXECVP(argv[1], argv + 1); 43 32 bb_perror_msg_and_die("%s", argv[1]); 44 33 } -
branches/stable/mindi-busybox/miscutils/strings.c
r821 r1770 3 3 * strings implementation for busybox 4 4 * 5 * Copyright (c) 1980, 1987 6 * The Regents of the University of California. All rights reserved. 5 * Copyright Tito Ragusa <farmatito@tiscali.it> 7 6 * 8 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 9 *10 * Original copyright notice is retained at the end of this file.11 *12 * Modified for BusyBox by Erik Andersen <andersen@codepoet.org>13 * Badly hacked by Tito Ragusa <farmatito@tiscali.it>14 8 */ 15 9 16 #include "busybox.h"17 #include <stdio.h>18 #include <stdlib.h>19 10 #include <getopt.h> 20 #include <ctype.h> 11 12 #include "libbb.h" 21 13 22 14 #define WHOLE_FILE 1 … … 25 17 #define SIZE 8 26 18 19 int strings_main(int argc, char **argv); 27 20 int strings_main(int argc, char **argv) 28 21 { 29 int n, c, i = 0, status = EXIT_SUCCESS; 30 unsigned long opt; 31 unsigned long count; 22 int n, c, status = EXIT_SUCCESS; 23 unsigned opt; 24 unsigned count; 25 off_t offset; 32 26 FILE *file = stdin; 33 27 char *string; 34 28 const char *fmt = "%s: "; 35 c har *n_arg = "4";29 const char *n_arg = "4"; 36 30 37 opt = bb_getopt_ulflags(argc,argv, "afon:", &n_arg);31 opt = getopt32(argv, "afon:", &n_arg); 38 32 /* -a is our default behaviour */ 39 40 argc -= optind; 33 /*argc -= optind;*/ 41 34 argv += optind; 42 35 43 n = bb_xgetlarg(n_arg, 10, 1, INT_MAX);36 n = xatou_range(n_arg, 1, INT_MAX); 44 37 string = xzalloc(n + 1); 45 38 n--; 46 39 47 if ( argc == 0) {40 if (!*argv) { 48 41 fmt = "{%s}: "; 49 * argv = (char *)bb_msg_standard_input;42 *--argv = (char *)bb_msg_standard_input; 50 43 goto PIPE; 51 44 } 52 45 53 46 do { 54 if ((file = bb_wfopen(*argv, "r"))) { 55 PIPE: 56 count = 0; 57 do { 58 c = fgetc(file); 59 if (isprint(c) || c == '\t') { 60 if (i <= n) { 61 string[i] = c; 62 } else { 63 putchar(c); 64 } 65 if (i == n) { 47 file = fopen_or_warn(*argv, "r"); 48 if (!file) { 49 status = EXIT_FAILURE; 50 continue; 51 } 52 PIPE: 53 offset = 0; 54 count = 0; 55 do { 56 c = fgetc(file); 57 if (isprint(c) || c == '\t') { 58 if (count > n) { 59 putchar(c); 60 } else { 61 string[count] = c; 62 if (count == n) { 66 63 if (opt & PRINT_NAME) { 67 64 printf(fmt, *argv); 68 65 } 69 66 if (opt & PRINT_OFFSET) { 70 printf("%7 lo ", count - n);67 printf("%7"OFF_FMT"o ", offset - n); 71 68 } 72 printf("%s", string);69 fputs(string, stdout); 73 70 } 74 i++; 75 } else { 76 if (i > n) { 77 putchar('\n'); 78 } 79 i = 0; 71 count++; 80 72 } 81 count++; 82 } while (c != EOF); 83 bb_fclose_nonstdin(file); 84 } else { 85 status = EXIT_FAILURE; 86 } 87 } while (--argc > 0); 73 } else { 74 if (count > n) { 75 putchar('\n'); 76 } 77 count = 0; 78 } 79 offset++; 80 } while (c != EOF); 81 fclose_if_not_stdin(file); 82 } while (*++argv); 88 83 89 84 if (ENABLE_FEATURE_CLEAN_UP) 90 85 free(string); 91 86 92 bb_fflush_stdout_and_exit(status);87 fflush_stdout_and_exit(status); 93 88 } 94 95 /*96 * Copyright (c) 1980, 198797 * The Regents of the University of California. All rights reserved.98 *99 * Redistribution and use in source and binary forms, with or without100 * modification, are permitted provided that the following conditions101 * are met:102 * 1. Redistributions of source code must retain the above copyright103 * notice, this list of conditions and the following disclaimer.104 * 2. Redistributions in binary form must reproduce the above copyright105 * notice, this list of conditions and the following disclaimer in the106 * documentation and/or other materials provided with the distribution.107 *108 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change109 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>110 *111 * 4. Neither the name of the University nor the names of its contributors112 * may be used to endorse or promote products derived from this software113 * without specific prior written permission.114 *115 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND116 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE117 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE118 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE119 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL120 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS121 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)122 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT123 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY124 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF125 * SUCH DAMAGE.126 */ -
branches/stable/mindi-busybox/miscutils/time.c
r821 r1770 3 3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc. 4 4 5 Licensed under GPL v2 or later, see file LICENSE in this tarball for details.5 Licensed under GPL version 2, see file LICENSE in this tarball for details. 6 6 */ 7 7 /* Originally written by David Keppel <pardo@cs.washington.edu>. … … 10 10 */ 11 11 12 #include "busybox.h" 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <signal.h> 16 #include <errno.h> 17 #include <getopt.h> 18 #include <string.h> 19 #include <limits.h> 20 #include <unistd.h> 21 #include <sys/types.h> /* For pid_t. */ 22 #include <sys/wait.h> 23 #include <sys/param.h> /* For getpagesize, maybe. */ 24 25 #define TV_MSEC tv_usec / 1000 26 #include <sys/resource.h> 12 #include "libbb.h" 27 13 28 14 /* Information on the resources used by a child process. */ … … 30 16 int waitstatus; 31 17 struct rusage ru; 32 struct timeval start, elapsed; /* Wallclock time of process. */18 unsigned elapsed_ms; /* Wallclock time of process. */ 33 19 } resource_t; 34 20 … … 36 22 usec = microseconds = 1/1,000,000 (1*10e-6) second. */ 37 23 38 #ifndef TICKS_PER_SEC39 #define TICKS_PER_SEC 10040 #endif41 42 /* The number of milliseconds in one `tick' used by the `rusage' structure. */43 #define MSEC_PER_TICK (1000 / TICKS_PER_SEC)44 45 /* Return the number of clock ticks that occur in M milliseconds. */46 #define MSEC_TO_TICKS(m) ((m) / MSEC_PER_TICK)47 48 24 #define UL unsigned long 49 25 50 static const char *const default_format= "real\t%E\nuser\t%u\nsys\t%T";26 static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T"; 51 27 52 28 /* The output format for the -p option .*/ 53 static const char *const posix_format= "real %e\nuser %U\nsys %S";29 static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; 54 30 55 31 56 32 /* Format string for printing all statistics verbosely. 57 33 Keep this output to 24 lines so users on terminals can see it all.*/ 58 static const char *const long_format=34 static const char long_format[] ALIGN1 = 59 35 "\tCommand being timed: \"%C\"\n" 60 36 "\tUser time (seconds): %U\n" … … 78 54 "\tSocket messages received: %r\n" 79 55 "\tSignals delivered: %k\n" 80 "\tPage size (bytes): %Z\n" "\tExit status: %x"; 81 82 83 /* Wait for and fill in data on child process PID. 84 Return 0 on error, 1 if ok. */ 56 "\tPage size (bytes): %Z\n" 57 "\tExit status: %x"; 58 59 60 /* Wait for and fill in data on child process PID. 61 Return 0 on error, 1 if ok. */ 85 62 86 63 /* pid_t is short on BSDI, so don't try to promote it. */ … … 88 65 { 89 66 int status; 90 91 67 pid_t caught; 92 68 … … 97 73 return 0; 98 74 } 99 100 gettimeofday(&resp->elapsed, (struct timezone *) 0); 101 resp->elapsed.tv_sec -= resp->start.tv_sec; 102 if (resp->elapsed.tv_usec < resp->start.tv_usec) { 103 /* Manually carry a one from the seconds field. */ 104 resp->elapsed.tv_usec += 1000000; 105 --resp->elapsed.tv_sec; 106 } 107 resp->elapsed.tv_usec -= resp->start.tv_usec; 108 75 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms; 109 76 resp->waitstatus = status; 110 111 77 return 1; 112 78 } 113 79 114 /* Print ARGV to FP, with each entry in ARGV separated by FILLER. */ 115 static void fprintargv(FILE * fp, char *const *argv, const char *filler) 116 { 117 char *const *av; 118 119 av = argv; 120 fputs(*av, fp); 121 while (*++av) { 122 fputs(filler, fp); 123 fputs(*av, fp); 124 } 125 if (ferror(fp)) 126 bb_error_msg_and_die(bb_msg_write_error); 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 } 127 88 } 128 89 … … 137 98 static unsigned long ptok(unsigned long pages) 138 99 { 139 static unsigned long ps = 0;100 static unsigned long ps; 140 101 unsigned long tmp; 141 static long size = LONG_MAX;142 102 143 103 /* Initialization. */ 144 104 if (ps == 0) 145 ps = (long)getpagesize();105 ps = getpagesize(); 146 106 147 107 /* Conversion. */ 148 108 if (pages > (LONG_MAX / ps)) { /* Could overflow. */ 149 109 tmp = pages / 1024; /* Smaller first, */ 150 size = tmp * ps; /* then larger. */ 151 } else { /* Could underflow. */ 152 tmp = pages * ps; /* Larger first, */ 153 size = tmp / 1024; /* then smaller. */ 154 } 155 return size; 110 return tmp * ps; /* then larger. */ 111 } 112 /* Could underflow. */ 113 tmp = pages * ps; /* Larger first, */ 114 return tmp / 1024; /* then smaller. */ 156 115 } 157 116 158 117 /* summarize: Report on the system use of a command. 159 118 160 Copy the FMT argument to FPexcept that `%' sequences119 Print the FMT argument except that `%' sequences 161 120 have special meaning, and `\n' and `\t' are translated into 162 121 newline and tab, respectively, and `\\' is translated into `\'. … … 196 155 and dividing by elapsed real time. 197 156 198 FP is the stream to print to.199 157 FMT is the format string, interpreted as described above. 200 158 COMMAND is the command and args that are being summarized. 201 159 RESP is resource information on the command. */ 202 160 203 static void summarize(FILE * fp, const char *fmt, char **command, 204 resource_t * resp) 205 { 206 unsigned long r; /* Elapsed real milliseconds. */ 207 unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ 161 #ifndef TICKS_PER_SEC 162 #define TICKS_PER_SEC 100 163 #endif 164 165 static void summarize(const char *fmt, char **command, resource_t * resp) 166 { 167 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ 168 unsigned cpu_ticks; /* Same, in "CPU ticks" */ 208 169 209 170 if (WIFSTOPPED(resp->waitstatus)) 210 fprintf(fp, "Command stopped by signal %d\n",171 printf("Command stopped by signal %u\n", 211 172 WSTOPSIG(resp->waitstatus)); 212 173 else if (WIFSIGNALED(resp->waitstatus)) 213 fprintf(fp, "Command terminated by signal %d\n",174 printf("Command terminated by signal %u\n", 214 175 WTERMSIG(resp->waitstatus)); 215 176 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) 216 fprintf(fp, "Command exited with non-zero status %d\n",177 printf("Command exited with non-zero status %u\n", 217 178 WEXITSTATUS(resp->waitstatus)); 218 179 219 /* Convert all times to milliseconds. Occasionally, one of these values 220 comes out as zero. Dividing by zero causes problems, so we first 221 check the time value. If it is zero, then we take `evasive action' 222 instead of calculating a value. */ 223 224 r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000; 225 226 v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC + 227 resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC; 180 vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000 181 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; 182 183 #if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 184 /* 1000 is exactly divisible by TICKS_PER_SEC */ 185 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); 186 #else 187 cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; 188 #endif 189 if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ 190 191 /* putchar() != putc(stdout) in glibc! */ 228 192 229 193 while (*fmt) { 194 /* Handle leading literal part */ 195 int n = strcspn(fmt, "%\\"); 196 if (n) { 197 printf("%.*s", n, fmt); 198 fmt += n; 199 continue; 200 } 201 230 202 switch (*fmt) { 203 #ifdef NOT_NEEDED 204 /* Handle literal char */ 205 /* Usually we optimize for size, but there is a limit 206 * for everything. With this we do a lot of 1-byte writes */ 207 default: 208 putc(*fmt, stdout); 209 break; 210 #endif 211 231 212 case '%': 232 213 switch (*++fmt) { 233 case '%': /* Literal '%'. */ 234 putc('%', fp); 235 break; 214 #ifdef NOT_NEEDED_YET 215 /* Our format strings do not have these */ 216 /* and we do not take format str from user */ 217 default: 218 putc('%', stdout); 219 /*FALLTHROUGH*/ 220 case '%': 221 if (!*fmt) goto ret; 222 putc(*fmt, stdout); 223 break; 224 #endif 236 225 case 'C': /* The command that got timed. */ 237 fprintargv(fp,command, " ");226 printargv(command, " "); 238 227 break; 239 228 case 'D': /* Average unshared data size. */ 240 fprintf(fp,"%lu",241 MSEC_TO_TICKS(v) == 0 ? 0 :242 ptok((UL) resp->ru.ru_i drss) / MSEC_TO_TICKS(v) +243 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));244 break;245 case 'E': /* Elapsed real (wall clock) time. */246 if ( resp->elapsed.tv_sec>= 3600) /* One hour -> h:m:s. */247 fprintf(fp, "%ldh %ldm %02lds",248 resp->elapsed.tv_sec/ 3600,249 ( resp->elapsed.tv_sec% 3600) / 60,250 resp->elapsed.tv_sec% 60);229 printf("%lu", 230 ptok((UL) resp->ru.ru_idrss) / cpu_ticks + 231 ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 232 break; 233 case 'E': { /* Elapsed real (wall clock) time. */ 234 unsigned seconds = resp->elapsed_ms / 1000; 235 if (seconds >= 3600) /* One hour -> h:m:s. */ 236 printf("%uh %um %02us", 237 seconds / 3600, 238 (seconds % 3600) / 60, 239 seconds % 60); 251 240 else 252 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */ 253 resp->elapsed.tv_sec / 60, 254 resp->elapsed.tv_sec % 60, 255 resp->elapsed.tv_usec / 10000); 256 break; 241 printf("%um %u.%02us", /* -> m:s. */ 242 seconds / 60, 243 seconds % 60, 244 (unsigned)(resp->elapsed_ms / 10) % 100); 245 break; 246 } 257 247 case 'F': /* Major page faults. */ 258 fprintf(fp, "%ld", resp->ru.ru_majflt);248 printf("%lu", resp->ru.ru_majflt); 259 249 break; 260 250 case 'I': /* Inputs. */ 261 fprintf(fp, "%ld", resp->ru.ru_inblock);251 printf("%lu", resp->ru.ru_inblock); 262 252 break; 263 253 case 'K': /* Average mem usage == data+stack+text. */ 264 fprintf(fp, "%lu", 265 MSEC_TO_TICKS(v) == 0 ? 0 : 266 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + 267 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) + 268 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); 254 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); 269 258 break; 270 259 case 'M': /* Maximum resident set size. */ 271 fprintf(fp,"%lu", ptok((UL) resp->ru.ru_maxrss));260 printf("%lu", ptok((UL) resp->ru.ru_maxrss)); 272 261 break; 273 262 case 'O': /* Outputs. */ 274 fprintf(fp, "%ld", resp->ru.ru_oublock);263 printf("%lu", resp->ru.ru_oublock); 275 264 break; 276 265 case 'P': /* Percent of CPU this job got. */ 277 266 /* % cpu is (total cpu time)/(elapsed time). */ 278 if (r > 0)279 fprintf(fp, "%lu%%", (v * 100 / r));267 if (resp->elapsed_ms > 0) 268 printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms)); 280 269 else 281 fprintf(fp,"?%%");270 printf("?%%"); 282 271 break; 283 272 case 'R': /* Minor page faults (reclaims). */ 284 fprintf(fp, "%ld", resp->ru.ru_minflt);273 printf("%lu", resp->ru.ru_minflt); 285 274 break; 286 275 case 'S': /* System time. */ 287 fprintf(fp, "%ld.%02ld",288 resp->ru.ru_stime.tv_sec,289 resp->ru.ru_stime.TV_MSEC / 10);276 printf("%u.%02u", 277 (unsigned)resp->ru.ru_stime.tv_sec, 278 (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); 290 279 break; 291 280 case 'T': /* System time. */ 292 281 if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ 293 fprintf(fp, "%ldh %ldm %02lds",294 resp->ru.ru_stime.tv_sec / 3600,295 ( resp->ru.ru_stime.tv_sec % 3600) / 60,296 resp->ru.ru_stime.tv_sec % 60);282 printf("%uh %um %02us", 283 (unsigned)(resp->ru.ru_stime.tv_sec / 3600), 284 (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60, 285 (unsigned)(resp->ru.ru_stime.tv_sec % 60)); 297 286 else 298 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */299 resp->ru.ru_stime.tv_sec / 60,300 resp->ru.ru_stime.tv_sec % 60,301 resp->ru.ru_stime.tv_usec / 10000);287 printf("%um %u.%02us", /* -> m:s. */ 288 (unsigned)(resp->ru.ru_stime.tv_sec / 60), 289 (unsigned)(resp->ru.ru_stime.tv_sec % 60), 290 (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); 302 291 break; 303 292 case 'U': /* User time. */ 304 fprintf(fp, "%ld.%02ld",305 resp->ru.ru_utime.tv_sec,306 resp->ru.ru_utime.TV_MSEC / 10);293 printf("%u.%02u", 294 (unsigned)resp->ru.ru_utime.tv_sec, 295 (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); 307 296 break; 308 297 case 'u': /* User time. */ 309 298 if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ 310 fprintf(fp, "%ldh %ldm %02lds",311 resp->ru.ru_utime.tv_sec / 3600,312 ( resp->ru.ru_utime.tv_sec % 3600) / 60,313 resp->ru.ru_utime.tv_sec % 60);299 printf("%uh %um %02us", 300 (unsigned)(resp->ru.ru_utime.tv_sec / 3600), 301 (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60, 302 (unsigned)(resp->ru.ru_utime.tv_sec % 60)); 314 303 else 315 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */316 resp->ru.ru_utime.tv_sec / 60,317 resp->ru.ru_utime.tv_sec % 60,318 resp->ru.ru_utime.tv_usec / 10000);304 printf("%um %u.%02us", /* -> m:s. */ 305 (unsigned)(resp->ru.ru_utime.tv_sec / 60), 306 (unsigned)(resp->ru.ru_utime.tv_sec % 60), 307 (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); 319 308 break; 320 309 case 'W': /* Times swapped out. */ 321 fprintf(fp, "%ld", resp->ru.ru_nswap);310 printf("%lu", resp->ru.ru_nswap); 322 311 break; 323 312 case 'X': /* Average shared text size. */ 324 fprintf(fp, "%lu", 325 MSEC_TO_TICKS(v) == 0 ? 0 : 326 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); 313 printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks); 327 314 break; 328 315 case 'Z': /* Page size. */ 329 fprintf(fp, "%d", getpagesize());316 printf("%u", getpagesize()); 330 317 break; 331 318 case 'c': /* Involuntary context switches. */ 332 fprintf(fp, "%ld", resp->ru.ru_nivcsw);319 printf("%lu", resp->ru.ru_nivcsw); 333 320 break; 334 321 case 'e': /* Elapsed real time in seconds. */ 335 fprintf(fp, "%ld.%02ld", 336 resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000); 322 printf("%u.%02u", 323 (unsigned)resp->elapsed_ms / 1000, 324 (unsigned)(resp->elapsed_ms / 10) % 100); 337 325 break; 338 326 case 'k': /* Signals delivered. */ 339 fprintf(fp, "%ld", resp->ru.ru_nsignals);327 printf("%lu", resp->ru.ru_nsignals); 340 328 break; 341 329 case 'p': /* Average stack segment. */ 342 fprintf(fp, "%lu", 343 MSEC_TO_TICKS(v) == 0 ? 0 : 344 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); 330 printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 345 331 break; 346 332 case 'r': /* Incoming socket messages received. */ 347 fprintf(fp, "%ld", resp->ru.ru_msgrcv);333 printf("%lu", resp->ru.ru_msgrcv); 348 334 break; 349 335 case 's': /* Outgoing socket messages sent. */ 350 fprintf(fp, "%ld", resp->ru.ru_msgsnd);336 printf("%lu", resp->ru.ru_msgsnd); 351 337 break; 352 338 case 't': /* Average resident set size. */ 353 fprintf(fp, "%lu", 354 MSEC_TO_TICKS(v) == 0 ? 0 : 355 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v)); 339 printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks); 356 340 break; 357 341 case 'w': /* Voluntary context switches. */ 358 fprintf(fp, "%ld", resp->ru.ru_nvcsw);342 printf("%lu", resp->ru.ru_nvcsw); 359 343 break; 360 344 case 'x': /* Exit status. */ 361 fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus)); 362 break; 363 case '\0': 364 putc('?', fp); 365 return; 366 default: 367 putc('?', fp); 368 putc(*fmt, fp); 345 printf("%u", WEXITSTATUS(resp->waitstatus)); 346 break; 369 347 } 370 ++fmt;371 348 break; 372 349 350 #ifdef NOT_NEEDED_YET 373 351 case '\\': /* Format escape. */ 374 352 switch (*++fmt) { 353 default: 354 putc('\\', stdout); 355 /*FALLTHROUGH*/ 356 case '\\': 357 if (!*fmt) goto ret; 358 putc(*fmt, stdout); 359 break; 375 360 case 't': 376 putc('\t', fp);361 putc('\t', stdout); 377 362 break; 378 363 case 'n': 379 putc('\n', fp); 380 break; 381 case '\\': 382 putc('\\', fp); 383 break; 384 default: 385 putc('?', fp); 386 putc('\\', fp); 387 putc(*fmt, fp); 364 putc('\n', stdout); 365 break; 388 366 } 389 ++fmt;390 367 break; 391 392 default: 393 putc(*fmt++, fp); 368 #endif 394 369 } 395 396 if (ferror(fp)) 397 bb_error_msg_and_die(bb_msg_write_error); 398 } 399 putc('\n', fp); 400 401 if (ferror(fp)) 402 bb_error_msg_and_die(bb_msg_write_error); 370 ++fmt; 371 } 372 /* ret: */ 373 putc('\n', stdout); 403 374 } 404 375 … … 410 381 __sighandler_t interrupt_signal, quit_signal; 411 382 412 gettimeofday(&resp->start, (struct timezone *) 0);383 resp->elapsed_ms = monotonic_us() / 1000; 413 384 pid = vfork(); /* Run CMD as child process. */ 414 385 if (pid < 0) … … 417 388 /* Don't cast execvp arguments; that causes errors on some systems, 418 389 versus merely warnings if the cast is left off. */ 419 execvp(cmd[0], cmd);390 BB_EXECVP(cmd[0], cmd); 420 391 bb_error_msg("cannot run %s", cmd[0]); 421 392 _exit(errno == ENOENT ? 127 : 126); … … 434 405 } 435 406 407 int time_main(int argc, char **argv); 436 408 int time_main(int argc, char **argv) 437 409 { 438 int gotone;439 410 resource_t res; 440 411 const char *output_format = default_format; 441 442 argc--; 443 argv++;412 char c; 413 414 goto next; 444 415 /* Parse any options -- don't use getopt() here so we don't 445 416 * consume the args of our client application... */ 446 while (argc > 0 && **argv == '-') { 447 gotone = 0; 448 while (gotone == 0 && *++(*argv)) { 449 switch (**argv) { 417 while (argc > 0 && argv[0][0] == '-') { 418 while ((c = *++*argv)) { 419 switch (c) { 450 420 case 'v': 451 421 output_format = long_format; … … 457 427 bb_show_usage(); 458 428 } 459 argc--;460 argv++;461 gotone = 1;462 429 } 463 } 464 465 if (argv == NULL || *argv == NULL) 466 bb_show_usage(); 430 next: 431 argv++; 432 argc--; 433 if (!argc) 434 bb_show_usage(); 435 } 467 436 468 437 run_command(argv, &res); 469 summarize(stderr, output_format, argv, &res); 470 fflush(stderr); 438 439 /* Cheat. printf's are shorter :) */ 440 stdout = stderr; 441 dup2(2, 1); /* just in case libc does something silly :( */ 442 summarize(output_format, argv, &res); 471 443 472 444 if (WIFSTOPPED(res.waitstatus)) 473 exit(WSTOPSIG(res.waitstatus));474 elseif (WIFSIGNALED(res.waitstatus))475 exit(WTERMSIG(res.waitstatus));476 elseif (WIFEXITED(res.waitstatus))477 exit(WEXITSTATUS(res.waitstatus));478 return 0;479 } 445 return WSTOPSIG(res.waitstatus); 446 if (WIFSIGNALED(res.waitstatus)) 447 return WTERMSIG(res.waitstatus); 448 if (WIFEXITED(res.waitstatus)) 449 return WEXITSTATUS(res.waitstatus); 450 fflush_stdout_and_exit(0); 451 } -
branches/stable/mindi-busybox/miscutils/watchdog.c
r821 r1770 9 9 */ 10 10 11 #include "busybox.h" 12 #include <stdio.h> 13 #include <fcntl.h> 14 #include <unistd.h> 15 #include <stdlib.h> 16 #include <signal.h> 11 #include "libbb.h" 17 12 18 13 #define OPT_FOREGROUND 0x01 19 14 #define OPT_TIMER 0x02 20 15 21 /* Watchdog file descriptor */ 22 static int fd; 23 24 static void watchdog_shutdown(int ATTRIBUTE_UNUSED unused) 16 static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) ATTRIBUTE_NORETURN; 17 static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig) 25 18 { 26 write(fd, "V", 1); /* Magic, see watchdog-api.txt in kernel */ 27 close(fd); 19 write(3, "V", 1); /* Magic, see watchdog-api.txt in kernel */ 20 if (ENABLE_FEATURE_CLEAN_UP) 21 close(3); 28 22 exit(0); 29 23 } 30 24 25 int watchdog_main(int argc, char **argv); 31 26 int watchdog_main(int argc, char **argv) 32 27 { 33 unsigned longopts;34 unsigned longtimer_duration = 30; /* Userspace timer duration, in seconds */28 unsigned opts; 29 unsigned timer_duration = 30; /* Userspace timer duration, in seconds */ 35 30 char *t_arg; 36 31 37 opts = bb_getopt_ulflags(argc, argv, "Ft:", &t_arg); 32 opt_complementary = "=1"; /* must have 1 argument */ 33 opts = getopt32(argv, "Ft:", &t_arg); 38 34 39 35 if (opts & OPT_TIMER) 40 timer_duration = bb_xgetlarg(t_arg, 10, 0, INT_MAX);36 timer_duration = xatou(t_arg); 41 37 42 /* We're only interested in the watchdog device .. */ 43 if (optind < argc - 1 || argc == 1) 44 bb_show_usage(); 45 46 #ifdef BB_NOMMU 47 if (!(opts & OPT_FOREGROUND)) 48 vfork_daemon_rexec(0, 1, argc, argv, "-F"); 49 #else 50 bb_xdaemon(0, 1); 51 #endif 38 if (!(opts & OPT_FOREGROUND)) { 39 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 40 } 52 41 53 42 signal(SIGHUP, watchdog_shutdown); 54 43 signal(SIGINT, watchdog_shutdown); 55 44 56 fd = bb_xopen(argv[argc - 1], O_WRONLY); 45 /* Use known fd # - avoid needing global 'int fd' */ 46 xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3); 57 47 58 48 while (1) { … … 61 51 * is undefined at this point -- PFM 62 52 */ 63 write( fd, "\0", 1);53 write(3, "", 1); 64 54 sleep(timer_duration); 65 55 } 66 56 67 57 watchdog_shutdown(0); 68 69 return EXIT_SUCCESS; 58 /* return EXIT_SUCCESS; */ 70 59 }
Note:
See TracChangeset
for help on using the changeset viewer.