aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>1999-10-12 22:26:06 +0000
committerEric Andersen <andersen@codepoet.org>1999-10-12 22:26:06 +0000
commit3cf52d19581b2077480e7d2e63010baa1f5399c1 (patch)
treed91b0cb332ebc976126e36a394655dde7a15d8b1
parent2ce1edcf544ac675e6762c9861a6b918401ea716 (diff)
downloadbusybox-w32-3cf52d19581b2077480e7d2e63010baa1f5399c1.tar.gz
busybox-w32-3cf52d19581b2077480e7d2e63010baa1f5399c1.tar.bz2
busybox-w32-3cf52d19581b2077480e7d2e63010baa1f5399c1.zip
More stuff...
-rw-r--r--archival/tar.c1836
-rw-r--r--busybox.def.h8
-rw-r--r--cat.c28
-rw-r--r--coreutils/cat.c28
-rw-r--r--coreutils/dd.c425
-rw-r--r--coreutils/pwd.c3
-rw-r--r--coreutils/sleep.c21
-rw-r--r--dd.c425
-rw-r--r--dmesg.c127
-rw-r--r--dutmp.c61
-rw-r--r--findutils/grep.c144
-rw-r--r--grep.c144
-rw-r--r--init/reboot.c8
-rw-r--r--kill.c203
-rw-r--r--miscutils/dutmp.c61
-rw-r--r--more.c79
-rw-r--r--procps/kill.c203
-rw-r--r--pwd.c3
-rw-r--r--reboot.c8
-rw-r--r--sleep.c21
-rw-r--r--tar.c1836
-rw-r--r--util-linux/dmesg.c127
-rw-r--r--util-linux/more.c79
23 files changed, 2840 insertions, 3038 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 1a9f84217..a5a0fab64 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -7,7 +7,7 @@
7 * This allows creation, extraction, and listing of tar files. 7 * This allows creation, extraction, and listing of tar files.
8 * 8 *
9 * Permission to distribute this code under the GPL has been granted. 9 * Permission to distribute this code under the GPL has been granted.
10 * Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com> 10 * Modified for busybox by Erik Andersen <andersee@debian.org>
11 */ 11 */
12 12
13 13
@@ -15,11 +15,11 @@
15 15
16#ifdef BB_TAR 16#ifdef BB_TAR
17 17
18const char tar_usage[] = 18const char tar_usage[] =
19"Create, extract, or list files from a TAR file\n\n" 19 "Create, extract, or list files from a TAR file\n\n"
20"usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" 20 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n"
21"\tc=create, x=extract, t=list contents, v=verbose,\n" 21 "\tc=create, x=extract, t=list contents, v=verbose,\n"
22"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 22 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
23 23
24 24
25 25
@@ -42,24 +42,23 @@ const char tar_usage[] =
42 * This structure is always embedded in a TAR_BLOCK_SIZE sized block 42 * This structure is always embedded in a TAR_BLOCK_SIZE sized block
43 * with zero padding. We only process this information minimally. 43 * with zero padding. We only process this information minimally.
44 */ 44 */
45typedef struct 45typedef struct {
46{ 46 char name[TAR_NAME_SIZE];
47 char name[TAR_NAME_SIZE]; 47 char mode[8];
48 char mode[8]; 48 char uid[8];
49 char uid[8]; 49 char gid[8];
50 char gid[8]; 50 char size[12];
51 char size[12]; 51 char mtime[12];
52 char mtime[12]; 52 char checkSum[8];
53 char checkSum[8]; 53 char typeFlag;
54 char typeFlag; 54 char linkName[TAR_NAME_SIZE];
55 char linkName[TAR_NAME_SIZE]; 55 char magic[6];
56 char magic[6]; 56 char version[2];
57 char version[2]; 57 char uname[32];
58 char uname[32]; 58 char gname[32];
59 char gname[32]; 59 char devMajor[8];
60 char devMajor[8]; 60 char devMinor[8];
61 char devMinor[8]; 61 char prefix[155];
62 char prefix[155];
63} TarHeader; 62} TarHeader;
64 63
65#define TAR_MAGIC "ustar" 64#define TAR_MAGIC "ustar"
@@ -73,168 +72,162 @@ typedef struct
73/* 72/*
74 * Static data. 73 * Static data.
75 */ 74 */
76static int listFlag; 75static int listFlag;
77static int extractFlag; 76static int extractFlag;
78static int createFlag; 77static int createFlag;
79static int verboseFlag; 78static int verboseFlag;
80static int tostdoutFlag; 79static int tostdoutFlag;
81 80
82static int inHeader; 81static int inHeader;
83static int badHeader; 82static int badHeader;
84static int errorFlag; 83static int errorFlag;
85static int skipFileFlag; 84static int skipFileFlag;
86static int warnedRoot; 85static int warnedRoot;
87static int eofFlag; 86static int eofFlag;
88static long dataCc; 87static long dataCc;
89static int outFd; 88static int outFd;
90static char outName[TAR_NAME_SIZE]; 89static char outName[TAR_NAME_SIZE];
91 90
92 91
93/* 92/*
94 * Static data associated with the tar file. 93 * Static data associated with the tar file.
95 */ 94 */
96static const char * tarName; 95static const char *tarName;
97static int tarFd; 96static int tarFd;
98static dev_t tarDev; 97static dev_t tarDev;
99static ino_t tarInode; 98static ino_t tarInode;
100 99
101 100
102/* 101/*
103 * Local procedures to restore files from a tar file. 102 * Local procedures to restore files from a tar file.
104 */ 103 */
105static void readTarFile(int fileCount, char ** fileTable); 104static void readTarFile (int fileCount, char **fileTable);
106static void readData(const char * cp, int count); 105static void readData (const char *cp, int count);
107static void createPath(const char * name, int mode); 106static void createPath (const char *name, int mode);
108static long getOctal(const char * cp, int len); 107static long getOctal (const char *cp, int len);
109 108
110static void readHeader(const TarHeader * hp, 109static void readHeader (const TarHeader * hp,
111 int fileCount, char ** fileTable); 110 int fileCount, char **fileTable);
112 111
113 112
114/* 113/*
115 * Local procedures to save files into a tar file. 114 * Local procedures to save files into a tar file.
116 */ 115 */
117static void saveFile(const char * fileName, int seeLinks); 116static void saveFile (const char *fileName, int seeLinks);
118 117
119static void saveRegularFile(const char * fileName, 118static void saveRegularFile (const char *fileName,
120 const struct stat * statbuf); 119 const struct stat *statbuf);
121 120
122static void saveDirectory(const char * fileName, 121static void saveDirectory (const char *fileName,
123 const struct stat * statbuf); 122 const struct stat *statbuf);
124 123
125static int wantFileName(const char * fileName, 124static int wantFileName (const char *fileName,
126 int fileCount, char ** fileTable); 125 int fileCount, char **fileTable);
127 126
128static void writeHeader(const char * fileName, 127static void writeHeader (const char *fileName, const struct stat *statbuf);
129 const struct stat * statbuf);
130 128
131static void writeTarFile(int fileCount, char ** fileTable); 129static void writeTarFile (int fileCount, char **fileTable);
132static void writeTarBlock(const char * buf, int len); 130static void writeTarBlock (const char *buf, int len);
133static int putOctal(char * cp, int len, long value); 131static int putOctal (char *cp, int len, long value);
134 132
135 133
136extern int 134extern int tar_main (int argc, char **argv)
137tar_main(int argc, char ** argv)
138{ 135{
139 const char * options; 136 const char *options;
140 137
141 argc--; 138 argc--;
142 argv++; 139 argv++;
143 140
144 if (argc < 1) 141 if (argc < 1) {
145 { 142 fprintf (stderr, "%s", tar_usage);
146 fprintf(stderr, "%s", tar_usage); 143 exit (FALSE);
147 return 1; 144 }
148 } 145
149 146
150 147 errorFlag = FALSE;
151 errorFlag = FALSE; 148 extractFlag = FALSE;
152 extractFlag = FALSE; 149 createFlag = FALSE;
153 createFlag = FALSE; 150 listFlag = FALSE;
154 listFlag = FALSE; 151 verboseFlag = FALSE;
155 verboseFlag = FALSE; 152 tostdoutFlag = FALSE;
156 tostdoutFlag = FALSE; 153 tarName = NULL;
157 tarName = NULL; 154 tarDev = 0;
158 tarDev = 0; 155 tarInode = 0;
159 tarInode = 0; 156 tarFd = -1;
160 tarFd = -1; 157
161 158 /*
162 /* 159 * Parse the options.
163 * Parse the options. 160 */
164 */ 161 options = *argv++;
165 options = *argv++; 162 argc--;
166 argc--; 163
167 164 if (**argv == '-') {
168 if (**argv == '-') { 165 for (; *options; options++) {
169 for (; *options; options++) 166 switch (*options) {
170 { 167 case 'f':
171 switch (*options) 168 if (tarName != NULL) {
172 { 169 fprintf (stderr, "Only one 'f' option allowed\n");
173 case 'f': 170
174 if (tarName != NULL) 171 exit (FALSE);
175 { 172 }
176 fprintf(stderr, "Only one 'f' option allowed\n");
177
178 return 1;
179 }
180
181 tarName = *argv++;
182 argc--;
183
184 break;
185 173
186 case 't': 174 tarName = *argv++;
187 listFlag = TRUE; 175 argc--;
188 break;
189 176
190 case 'x': 177 break;
191 extractFlag = TRUE;
192 break;
193 178
194 case 'c': 179 case 't':
195 createFlag = TRUE; 180 listFlag = TRUE;
196 break; 181 break;
197 182
198 case 'v': 183 case 'x':
199 verboseFlag = TRUE; 184 extractFlag = TRUE;
200 break; 185 break;
201 186
202 case 'O': 187 case 'c':
203 tostdoutFlag = TRUE; 188 createFlag = TRUE;
204 break; 189 break;
205 190
206 case '-': 191 case 'v':
207 break; 192 verboseFlag = TRUE;
193 break;
208 194
209 default: 195 case 'O':
210 fprintf(stderr, "Unknown tar flag '%c'\n", *options); 196 tostdoutFlag = TRUE;
197 break;
211 198
212 return 1; 199 case '-':
213 } 200 break;
214 }
215 }
216 201
217 /* 202 default:
218 * Validate the options. 203 fprintf (stderr, "Unknown tar flag '%c'\n", *options);
219 */
220 if (extractFlag + listFlag + createFlag != 1)
221 {
222 fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n");
223 204
224 return 1; 205 exit (FALSE);
206 }
225 } 207 }
226 208 }
227 /* 209
228 * Do the correct type of action supplying the rest of the 210 /*
229 * command line arguments as the list of files to process. 211 * Validate the options.
230 */ 212 */
231 if (createFlag) 213 if (extractFlag + listFlag + createFlag != 1) {
232 writeTarFile(argc, argv); 214 fprintf (stderr,
233 else 215 "Exactly one of 'c', 'x' or 't' must be specified\n");
234 readTarFile(argc, argv); 216
235 if (errorFlag) 217 exit (FALSE);
236 fprintf(stderr, "\n"); 218 }
237 return( errorFlag); 219
220 /*
221 * Do the correct type of action supplying the rest of the
222 * command line arguments as the list of files to process.
223 */
224 if (createFlag)
225 writeTarFile (argc, argv);
226 else
227 readTarFile (argc, argv);
228 if (errorFlag)
229 fprintf (stderr, "\n");
230 exit (errorFlag);
238} 231}
239 232
240 233
@@ -242,128 +235,119 @@ tar_main(int argc, char ** argv)
242 * Read a tar file and extract or list the specified files within it. 235 * Read a tar file and extract or list the specified files within it.
243 * If the list is empty than all files are extracted or listed. 236 * If the list is empty than all files are extracted or listed.
244 */ 237 */
245static void 238static void readTarFile (int fileCount, char **fileTable)
246readTarFile(int fileCount, char ** fileTable)
247{ 239{
248 const char * cp; 240 const char *cp;
249 int cc; 241 int cc;
250 int inCc; 242 int inCc;
251 int blockSize; 243 int blockSize;
252 char buf[BUF_SIZE]; 244 char buf[BUF_SIZE];
253 245
254 skipFileFlag = FALSE; 246 skipFileFlag = FALSE;
255 badHeader = FALSE; 247 badHeader = FALSE;
256 warnedRoot = FALSE; 248 warnedRoot = FALSE;
257 eofFlag = FALSE; 249 eofFlag = FALSE;
258 inHeader = TRUE; 250 inHeader = TRUE;
259 inCc = 0; 251 inCc = 0;
260 dataCc = 0; 252 dataCc = 0;
261 outFd = -1; 253 outFd = -1;
262 blockSize = sizeof(buf); 254 blockSize = sizeof (buf);
263 cp = buf; 255 cp = buf;
264 256
265 /* 257 /*
266 * Open the tar file for reading. 258 * Open the tar file for reading.
259 */
260 if ((tarName == NULL) || !strcmp (tarName, "-")) {
261 tarFd = STDIN;
262 } else
263 tarFd = open (tarName, O_RDONLY);
264
265 if (tarFd < 0) {
266 perror (tarName);
267 errorFlag = TRUE;
268 return;
269 }
270
271 /*
272 * Read blocks from the file until an end of file header block
273 * has been seen. (A real end of file from a read is an error.)
274 */
275 while (!eofFlag) {
276 /*
277 * Read the next block of data if necessary.
278 * This will be a large block if possible, which we will
279 * then process in the small tar blocks.
267 */ 280 */
268 if ( (tarName==NULL) || !strcmp( tarName, "-") ) { 281 if (inCc <= 0) {
269 tarFd = STDIN; 282 cp = buf;
270 } 283 inCc = fullRead (tarFd, buf, blockSize);
271 else
272 tarFd = open(tarName, O_RDONLY);
273 284
274 if (tarFd < 0) 285 if (inCc < 0) {
275 { 286 perror (tarName);
276 perror(tarName);
277 errorFlag = TRUE; 287 errorFlag = TRUE;
278 return; 288 goto done;
289 }
290
291 if (inCc == 0) {
292 fprintf (stderr,
293 "Unexpected end of file from \"%s\"", tarName);
294 errorFlag = TRUE;
295 goto done;
296 }
279 } 297 }
280 298
281 /* 299 /*
282 * Read blocks from the file until an end of file header block 300 * If we are expecting a header block then examine it.
283 * has been seen. (A real end of file from a read is an error.)
284 */ 301 */
285 while (!eofFlag) 302 if (inHeader) {
286 { 303 readHeader ((const TarHeader *) cp, fileCount, fileTable);
287 /*
288 * Read the next block of data if necessary.
289 * This will be a large block if possible, which we will
290 * then process in the small tar blocks.
291 */
292 if (inCc <= 0)
293 {
294 cp = buf;
295 inCc = fullRead(tarFd, buf, blockSize);
296
297 if (inCc < 0)
298 {
299 perror(tarName);
300 errorFlag=TRUE;
301 goto done;
302 }
303
304 if (inCc == 0)
305 {
306 fprintf(stderr,
307 "Unexpected end of file from \"%s\"",
308 tarName);
309 errorFlag=TRUE;
310 goto done;
311 }
312 }
313 304
314 /* 305 cp += TAR_BLOCK_SIZE;
315 * If we are expecting a header block then examine it. 306 inCc -= TAR_BLOCK_SIZE;
316 */
317 if (inHeader)
318 {
319 readHeader((const TarHeader *) cp, fileCount, fileTable);
320 307
321 cp += TAR_BLOCK_SIZE; 308 continue;
322 inCc -= TAR_BLOCK_SIZE;
323
324 continue;
325 }
326
327 /*
328 * We are currently handling the data for a file.
329 * Process the minimum of the amount of data we have available
330 * and the amount left to be processed for the file.
331 */
332 cc = inCc;
333
334 if (cc > dataCc)
335 cc = dataCc;
336
337 readData(cp, cc);
338
339 /*
340 * If the amount left isn't an exact multiple of the tar block
341 * size then round it up to the next block boundary since there
342 * is padding at the end of the file.
343 */
344 if (cc % TAR_BLOCK_SIZE)
345 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
346
347 cp += cc;
348 inCc -= cc;
349 } 309 }
350 310
351done: 311 /*
352 /* 312 * We are currently handling the data for a file.
353 * Close the tar file if needed. 313 * Process the minimum of the amount of data we have available
314 * and the amount left to be processed for the file.
354 */ 315 */
355 if ((tarFd >= 0) && (close(tarFd) < 0)) 316 cc = inCc;
356 perror(tarName); 317
318 if (cc > dataCc)
319 cc = dataCc;
357 320
358 /* 321 readData (cp, cc);
359 * Close the output file if needed. 322
360 * This is only done here on a previous error and so no 323 /*
361 * message is required on errors. 324 * If the amount left isn't an exact multiple of the tar block
325 * size then round it up to the next block boundary since there
326 * is padding at the end of the file.
362 */ 327 */
363 if (tostdoutFlag==FALSE) { 328 if (cc % TAR_BLOCK_SIZE)
364 if (outFd >= 0) 329 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
365 (void) close(outFd); 330
366 } 331 cp += cc;
332 inCc -= cc;
333 }
334
335 done:
336 /*
337 * Close the tar file if needed.
338 */
339 if ((tarFd >= 0) && (close (tarFd) < 0))
340 perror (tarName);
341
342 /*
343 * Close the output file if needed.
344 * This is only done here on a previous error and so no
345 * message is required on errors.
346 */
347 if (tostdoutFlag == FALSE) {
348 if (outFd >= 0)
349 (void) close (outFd);
350 }
367} 351}
368 352
369 353
@@ -373,332 +357,307 @@ done:
373 * the end of the tar file. 357 * the end of the tar file.
374 */ 358 */
375static void 359static void
376readHeader(const TarHeader * hp, int fileCount, char ** fileTable) 360readHeader (const TarHeader * hp, int fileCount, char **fileTable)
377{ 361{
378 int mode; 362 int mode;
379 int uid; 363 int uid;
380 int gid; 364 int gid;
381 int checkSum; 365 int checkSum;
382 long size; 366 long size;
383 time_t mtime; 367 time_t mtime;
384 const char * name; 368 const char *name;
385 int cc; 369 int cc;
386 int hardLink; 370 int hardLink;
387 int softLink; 371 int softLink;
388 372
389 /* 373 /*
390 * If the block is completely empty, then this is the end of the 374 * If the block is completely empty, then this is the end of the
391 * archive file. If the name is null, then just skip this header. 375 * archive file. If the name is null, then just skip this header.
392 */ 376 */
393 name = hp->name; 377 name = hp->name;
394 378
395 if (*name == '\0') 379 if (*name == '\0') {
396 { 380 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
397 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) 381 if (*name++)
398 {
399 if (*name++)
400 return;
401 }
402
403 eofFlag = TRUE;
404
405 return; 382 return;
406 } 383 }
407 384
408 /* 385 eofFlag = TRUE;
409 * There is another file in the archive to examine.
410 * Extract the encoded information and check it.
411 */
412 mode = getOctal(hp->mode, sizeof(hp->mode));
413 uid = getOctal(hp->uid, sizeof(hp->uid));
414 gid = getOctal(hp->gid, sizeof(hp->gid));
415 size = getOctal(hp->size, sizeof(hp->size));
416 mtime = getOctal(hp->mtime, sizeof(hp->mtime));
417 checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum));
418 386
419 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) 387 return;
420 { 388 }
421 if (!badHeader)
422 fprintf(stderr, "Bad tar header, skipping\n");
423 389
424 badHeader = TRUE; 390 /*
391 * There is another file in the archive to examine.
392 * Extract the encoded information and check it.
393 */
394 mode = getOctal (hp->mode, sizeof (hp->mode));
395 uid = getOctal (hp->uid, sizeof (hp->uid));
396 gid = getOctal (hp->gid, sizeof (hp->gid));
397 size = getOctal (hp->size, sizeof (hp->size));
398 mtime = getOctal (hp->mtime, sizeof (hp->mtime));
399 checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum));
425 400
426 return; 401 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
427 } 402 if (!badHeader)
403 fprintf (stderr, "Bad tar header, skipping\n");
428 404
429 badHeader = FALSE; 405 badHeader = TRUE;
430 skipFileFlag = FALSE;
431 406
432 /* 407 return;
433 * Check for the file modes. 408 }
434 */ 409
435 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) || 410 badHeader = FALSE;
411 skipFileFlag = FALSE;
412
413 /*
414 * Check for the file modes.
415 */
416 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
436 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0')); 417 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
437 418
438 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) || 419 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
439 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0')); 420 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
440 421
441 /* 422 /*
442 * Check for a directory or a regular file. 423 * Check for a directory or a regular file.
443 */ 424 */
444 if (name[strlen(name) - 1] == '/') 425 if (name[strlen (name) - 1] == '/')
445 mode |= S_IFDIR; 426 mode |= S_IFDIR;
446 else if ((mode & S_IFMT) == 0) 427 else if ((mode & S_IFMT) == 0)
447 mode |= S_IFREG; 428 mode |= S_IFREG;
448 429
449 /* 430 /*
450 * Check for absolute paths in the file. 431 * Check for absolute paths in the file.
451 * If we find any, then warn the user and make them relative. 432 * If we find any, then warn the user and make them relative.
452 */ 433 */
453 if (*name == '/') 434 if (*name == '/') {
454 { 435 while (*name == '/')
455 while (*name == '/') 436 name++;
456 name++; 437
457 438 if (!warnedRoot) {
458 if (!warnedRoot) 439 fprintf (stderr,
459 { 440 "Absolute path detected, removing leading slashes\n");
460 fprintf(stderr,
461 "Absolute path detected, removing leading slashes\n");
462 }
463
464 warnedRoot = TRUE;
465 } 441 }
466 442
467 /* 443 warnedRoot = TRUE;
468 * See if we want this file to be restored. 444 }
469 * If not, then set up to skip it. 445
470 */ 446 /*
471 if (!wantFileName(name, fileCount, fileTable)) 447 * See if we want this file to be restored.
472 { 448 * If not, then set up to skip it.
473 if (!hardLink && !softLink && S_ISREG(mode)) 449 */
474 { 450 if (!wantFileName (name, fileCount, fileTable)) {
475 inHeader = (size == 0); 451 if (!hardLink && !softLink && S_ISREG (mode)) {
476 dataCc = size; 452 inHeader = (size == 0);
477 } 453 dataCc = size;
478
479 skipFileFlag = TRUE;
480
481 return;
482 } 454 }
483 455
484 /* 456 skipFileFlag = TRUE;
485 * This file is to be handled.
486 * If we aren't extracting then just list information about the file.
487 */
488 if (!extractFlag)
489 {
490 if (verboseFlag)
491 {
492 printf("%s %3d/%-d %9ld %s %s", modeString(mode),
493 uid, gid, size, timeString(mtime), name);
494 }
495 else
496 printf("%s", name);
497
498 if (hardLink)
499 printf(" (link to \"%s\")", hp->linkName);
500 else if (softLink)
501 printf(" (symlink to \"%s\")", hp->linkName);
502 else if (S_ISREG(mode))
503 {
504 inHeader = (size == 0);
505 dataCc = size;
506 }
507
508 printf("\n");
509 457
510 return; 458 return;
511 } 459 }
512 460
513 /* 461 /*
514 * We really want to extract the file. 462 * This file is to be handled.
515 */ 463 * If we aren't extracting then just list information about the file.
516 if (verboseFlag) 464 */
517 printf("x %s\n", name); 465 if (!extractFlag) {
466 if (verboseFlag) {
467 printf ("%s %3d/%-d %9ld %s %s", modeString (mode),
468 uid, gid, size, timeString (mtime), name);
469 } else
470 printf ("%s", name);
518 471
519 if (hardLink) 472 if (hardLink)
520 { 473 printf (" (link to \"%s\")", hp->linkName);
521 if (link(hp->linkName, name) < 0) 474 else if (softLink)
522 perror(name); 475 printf (" (symlink to \"%s\")", hp->linkName);
523 476 else if (S_ISREG (mode)) {
524 return; 477 inHeader = (size == 0);
525 } 478 dataCc = size;
526
527 if (softLink)
528 {
529#ifdef S_ISLNK
530 if (symlink(hp->linkName, name) < 0)
531 perror(name);
532#else
533 fprintf(stderr, "Cannot create symbolic links\n");
534#endif
535 return;
536 } 479 }
537 480
538 /* 481 printf ("\n");
539 * If the file is a directory, then just create the path.
540 */
541 if (S_ISDIR(mode))
542 {
543 createPath(name, mode);
544 482
545 return; 483 return;
546 } 484 }
547 485
548 /* 486 /*
549 * There is a file to write. 487 * We really want to extract the file.
550 * First create the path to it if necessary with a default permission. 488 */
551 */ 489 if (verboseFlag)
552 createPath(name, 0777); 490 printf ("x %s\n", name);
553 491
554 inHeader = (size == 0); 492 if (hardLink) {
555 dataCc = size; 493 if (link (hp->linkName, name) < 0)
494 perror (name);
556 495
557 /* 496 return;
558 * Start the output file. 497 }
559 */
560 if (tostdoutFlag==TRUE)
561 outFd = STDOUT;
562 else
563 outFd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);
564
565 if (outFd < 0)
566 {
567 perror(name);
568 skipFileFlag = TRUE;
569 return;
570 }
571 498
572 /* 499 if (softLink) {
573 * If the file is empty, then that's all we need to do. 500#ifdef S_ISLNK
574 */ 501 if (symlink (hp->linkName, name) < 0)
575 if (size == 0 && tostdoutFlag == FALSE) 502 perror (name);
576 { 503#else
577 (void) close(outFd); 504 fprintf (stderr, "Cannot create symbolic links\n");
578 outFd = -1; 505#endif
579 } 506 return;
507 }
508
509 /*
510 * If the file is a directory, then just create the path.
511 */
512 if (S_ISDIR (mode)) {
513 createPath (name, mode);
514
515 return;
516 }
517
518 /*
519 * There is a file to write.
520 * First create the path to it if necessary with a default permission.
521 */
522 createPath (name, 0777);
523
524 inHeader = (size == 0);
525 dataCc = size;
526
527 /*
528 * Start the output file.
529 */
530 if (tostdoutFlag == TRUE)
531 outFd = STDOUT;
532 else
533 outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode);
534
535 if (outFd < 0) {
536 perror (name);
537 skipFileFlag = TRUE;
538 return;
539 }
540
541 /*
542 * If the file is empty, then that's all we need to do.
543 */
544 if (size == 0 && tostdoutFlag == FALSE) {
545 (void) close (outFd);
546 outFd = -1;
547 }
580} 548}
581 549
582 550
583/* 551/*
584 * Handle a data block of some specified size that was read. 552 * Handle a data block of some specified size that was read.
585 */ 553 */
586static void 554static void readData (const char *cp, int count)
587readData(const char * cp, int count)
588{ 555{
589 /* 556 /*
590 * Reduce the amount of data left in this file. 557 * Reduce the amount of data left in this file.
591 * If there is no more data left, then we need to read 558 * If there is no more data left, then we need to read
592 * the header again. 559 * the header again.
593 */ 560 */
594 dataCc -= count; 561 dataCc -= count;
595 562
596 if (dataCc <= 0) 563 if (dataCc <= 0)
597 inHeader = TRUE; 564 inHeader = TRUE;
598
599 /*
600 * If we aren't extracting files or this file is being
601 * skipped then do nothing more.
602 */
603 if (!extractFlag || skipFileFlag)
604 return;
605 565
606 /* 566 /*
607 * Write the data to the output file. 567 * If we aren't extracting files or this file is being
608 */ 568 * skipped then do nothing more.
609 if (fullWrite(outFd, cp, count) < 0) 569 */
610 { 570 if (!extractFlag || skipFileFlag)
611 perror(outName); 571 return;
612 if (tostdoutFlag==FALSE) { 572
613 (void) close(outFd); 573 /*
614 outFd = -1; 574 * Write the data to the output file.
615 } 575 */
616 skipFileFlag = TRUE; 576 if (fullWrite (outFd, cp, count) < 0) {
617 return; 577 perror (outName);
578 if (tostdoutFlag == FALSE) {
579 (void) close (outFd);
580 outFd = -1;
618 } 581 }
582 skipFileFlag = TRUE;
583 return;
584 }
585
586 /*
587 * If the write failed, close the file and disable further
588 * writes to this file.
589 */
590 if (dataCc <= 0 && tostdoutFlag == FALSE) {
591 if (close (outFd))
592 perror (outName);
619 593
620 /* 594 outFd = -1;
621 * If the write failed, close the file and disable further 595 }
622 * writes to this file.
623 */
624 if (dataCc <= 0 && tostdoutFlag==FALSE)
625 {
626 if (close(outFd))
627 perror(outName);
628
629 outFd = -1;
630 }
631} 596}
632 597
633 598
634/* 599/*
635 * Write a tar file containing the specified files. 600 * Write a tar file containing the specified files.
636 */ 601 */
637static void 602static void writeTarFile (int fileCount, char **fileTable)
638writeTarFile(int fileCount, char ** fileTable)
639{ 603{
640 struct stat statbuf; 604 struct stat statbuf;
641 605
642 /* 606 /*
643 * Make sure there is at least one file specified. 607 * Make sure there is at least one file specified.
644 */ 608 */
645 if (fileCount <= 0) 609 if (fileCount <= 0) {
646 { 610 fprintf (stderr, "No files specified to be saved\n");
647 fprintf(stderr, "No files specified to be saved\n"); 611 errorFlag = TRUE;
648 errorFlag=TRUE; 612 }
649 } 613
650 614 /*
651 /* 615 * Create the tar file for writing.
652 * Create the tar file for writing. 616 */
653 */ 617 if ((tarName == NULL) || !strcmp (tarName, "-")) {
654 if ( (tarName==NULL) || !strcmp( tarName, "-") ) { 618 tostdoutFlag = TRUE;
655 tostdoutFlag = TRUE; 619 tarFd = STDOUT;
656 tarFd = STDOUT; 620 } else
657 } 621 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
658 else 622
659 tarFd = open(tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); 623 if (tarFd < 0) {
660 624 perror (tarName);
661 if (tarFd < 0) 625 errorFlag = TRUE;
662 { 626 return;
663 perror(tarName); 627 }
664 errorFlag=TRUE; 628
665 return; 629 /*
666 } 630 * Get the device and inode of the tar file for checking later.
667 631 */
668 /* 632 if (fstat (tarFd, &statbuf) < 0) {
669 * Get the device and inode of the tar file for checking later. 633 perror (tarName);
670 */ 634 errorFlag = TRUE;
671 if (fstat(tarFd, &statbuf) < 0) 635 goto done;
672 { 636 }
673 perror(tarName); 637
674 errorFlag = TRUE; 638 tarDev = statbuf.st_dev;
675 goto done; 639 tarInode = statbuf.st_ino;
676 } 640
677 641 /*
678 tarDev = statbuf.st_dev; 642 * Append each file name into the archive file.
679 tarInode = statbuf.st_ino; 643 * Follow symbolic links for these top level file names.
680 644 */
681 /* 645 while (!errorFlag && (fileCount-- > 0)) {
682 * Append each file name into the archive file. 646 saveFile (*fileTable++, FALSE);
683 * Follow symbolic links for these top level file names. 647 }
684 */ 648
685 while (!errorFlag && (fileCount-- > 0)) 649 /*
686 { 650 * Now write an empty block of zeroes to end the archive.
687 saveFile(*fileTable++, FALSE); 651 */
688 } 652 writeTarBlock ("", 1);
689 653
690 /* 654
691 * Now write an empty block of zeroes to end the archive. 655 done:
692 */ 656 /*
693 writeTarBlock("", 1); 657 * Close the tar file and check for errors if it was opened.
694 658 */
695 659 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0))
696done: 660 perror (tarName);
697 /*
698 * Close the tar file and check for errors if it was opened.
699 */
700 if ( (tostdoutFlag==FALSE) && (tarFd >= 0) && (close(tarFd) < 0))
701 perror(tarName);
702} 661}
703 662
704 663
@@ -709,76 +668,70 @@ done:
709 * flag indicates whether or not we want to see symbolic links as 668 * flag indicates whether or not we want to see symbolic links as
710 * they really are, instead of blindly following them. 669 * they really are, instead of blindly following them.
711 */ 670 */
712static void 671static void saveFile (const char *fileName, int seeLinks)
713saveFile(const char * fileName, int seeLinks)
714{ 672{
715 int status; 673 int status;
716 int mode; 674 int mode;
717 struct stat statbuf; 675 struct stat statbuf;
718 676
719 if (verboseFlag) 677 if (verboseFlag)
720 printf("a %s\n", fileName); 678 printf ("a %s\n", fileName);
721 679
722 /* 680 /*
723 * Check that the file name will fit in the header. 681 * Check that the file name will fit in the header.
724 */ 682 */
725 if (strlen(fileName) >= TAR_NAME_SIZE) 683 if (strlen (fileName) >= TAR_NAME_SIZE) {
726 { 684 fprintf (stderr, "%s: File name is too long\n", fileName);
727 fprintf(stderr, "%s: File name is too long\n", fileName);
728 685
729 return; 686 return;
730 } 687 }
731 688
732 /* 689 /*
733 * Find out about the file. 690 * Find out about the file.
734 */ 691 */
735#ifdef S_ISLNK 692#ifdef S_ISLNK
736 if (seeLinks) 693 if (seeLinks)
737 status = lstat(fileName, &statbuf); 694 status = lstat (fileName, &statbuf);
738 else 695 else
739#endif 696#endif
740 status = stat(fileName, &statbuf); 697 status = stat (fileName, &statbuf);
741 698
742 if (status < 0) 699 if (status < 0) {
743 { 700 perror (fileName);
744 perror(fileName);
745 701
746 return; 702 return;
747 } 703 }
748 704
749 /* 705 /*
750 * Make sure we aren't trying to save our file into itself. 706 * Make sure we aren't trying to save our file into itself.
751 */ 707 */
752 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) 708 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
753 { 709 fprintf (stderr, "Skipping saving of archive file itself\n");
754 fprintf(stderr, "Skipping saving of archive file itself\n");
755 710
756 return; 711 return;
757 } 712 }
758 713
759 /* 714 /*
760 * Check the type of file. 715 * Check the type of file.
761 */ 716 */
762 mode = statbuf.st_mode; 717 mode = statbuf.st_mode;
763 718
764 if (S_ISDIR(mode)) 719 if (S_ISDIR (mode)) {
765 { 720 saveDirectory (fileName, &statbuf);
766 saveDirectory(fileName, &statbuf);
767 721
768 return; 722 return;
769 } 723 }
770 724
771 if (S_ISREG(mode)) 725 if (S_ISREG (mode)) {
772 { 726 saveRegularFile (fileName, &statbuf);
773 saveRegularFile(fileName, &statbuf);
774 727
775 return; 728 return;
776 } 729 }
777 730
778 /* 731 /*
779 * The file is a strange type of file, ignore it. 732 * The file is a strange type of file, ignore it.
780 */ 733 */
781 fprintf(stderr, "%s: not a directory or regular file\n", fileName); 734 fprintf (stderr, "%s: not a directory or regular file\n", fileName);
782} 735}
783 736
784 737
@@ -786,183 +739,173 @@ saveFile(const char * fileName, int seeLinks)
786 * Save a regular file to the tar file. 739 * Save a regular file to the tar file.
787 */ 740 */
788static void 741static void
789saveRegularFile(const char * fileName, const struct stat * statbuf) 742saveRegularFile (const char *fileName, const struct stat *statbuf)
790{ 743{
791 int sawEof; 744 int sawEof;
792 int fileFd; 745 int fileFd;
793 int cc; 746 int cc;
794 int dataCount; 747 int dataCount;
795 long fullDataCount; 748 long fullDataCount;
796 char data[TAR_BLOCK_SIZE * 16]; 749 char data[TAR_BLOCK_SIZE * 16];
797 750
798 /* 751 /*
799 * Open the file for reading. 752 * Open the file for reading.
753 */
754 fileFd = open (fileName, O_RDONLY);
755
756 if (fileFd < 0) {
757 perror (fileName);
758
759 return;
760 }
761
762 /*
763 * Write out the header for the file.
764 */
765 writeHeader (fileName, statbuf);
766
767 /*
768 * Write the data blocks of the file.
769 * We must be careful to write the amount of data that the stat
770 * buffer indicated, even if the file has changed size. Otherwise
771 * the tar file will be incorrect.
772 */
773 fullDataCount = statbuf->st_size;
774 sawEof = FALSE;
775
776 while (fullDataCount > 0) {
777 /*
778 * Get the amount to write this iteration which is
779 * the minumum of the amount left to write and the
780 * buffer size.
800 */ 781 */
801 fileFd = open(fileName, O_RDONLY); 782 dataCount = sizeof (data);
802
803 if (fileFd < 0)
804 {
805 perror(fileName);
806 783
807 return; 784 if (dataCount > fullDataCount)
808 } 785 dataCount = (int) fullDataCount;
809 786
810 /* 787 /*
811 * Write out the header for the file. 788 * Read the data from the file if we haven't seen the
789 * end of file yet.
812 */ 790 */
813 writeHeader(fileName, statbuf); 791 cc = 0;
814 792
815 /* 793 if (!sawEof) {
816 * Write the data blocks of the file. 794 cc = fullRead (fileFd, data, dataCount);
817 * We must be careful to write the amount of data that the stat
818 * buffer indicated, even if the file has changed size. Otherwise
819 * the tar file will be incorrect.
820 */
821 fullDataCount = statbuf->st_size;
822 sawEof = FALSE;
823
824 while (fullDataCount > 0)
825 {
826 /*
827 * Get the amount to write this iteration which is
828 * the minumum of the amount left to write and the
829 * buffer size.
830 */
831 dataCount = sizeof(data);
832
833 if (dataCount > fullDataCount)
834 dataCount = (int) fullDataCount;
835
836 /*
837 * Read the data from the file if we haven't seen the
838 * end of file yet.
839 */
840 cc = 0;
841
842 if (!sawEof)
843 {
844 cc = fullRead(fileFd, data, dataCount);
845
846 if (cc < 0)
847 {
848 perror(fileName);
849
850 (void) close(fileFd);
851 errorFlag = TRUE;
852
853 return;
854 }
855
856 /*
857 * If the file ended too soon, complain and set
858 * a flag so we will zero fill the rest of it.
859 */
860 if (cc < dataCount)
861 {
862 fprintf(stderr,
863 "%s: Short read - zero filling",
864 fileName);
865
866 sawEof = TRUE;
867 }
868 }
869 795
870 /* 796 if (cc < 0) {
871 * Zero fill the rest of the data if necessary. 797 perror (fileName);
872 */
873 if (cc < dataCount)
874 memset(data + cc, 0, dataCount - cc);
875 798
876 /* 799 (void) close (fileFd);
877 * Write the buffer to the TAR file. 800 errorFlag = TRUE;
878 */
879 writeTarBlock(data, dataCount);
880 801
881 fullDataCount -= dataCount; 802 return;
803 }
804
805 /*
806 * If the file ended too soon, complain and set
807 * a flag so we will zero fill the rest of it.
808 */
809 if (cc < dataCount) {
810 fprintf (stderr,
811 "%s: Short read - zero filling", fileName);
812
813 sawEof = TRUE;
814 }
882 } 815 }
883 816
884 /* 817 /*
885 * Close the file. 818 * Zero fill the rest of the data if necessary.
819 */
820 if (cc < dataCount)
821 memset (data + cc, 0, dataCount - cc);
822
823 /*
824 * Write the buffer to the TAR file.
886 */ 825 */
887 if ( (tostdoutFlag==FALSE) && close(fileFd) < 0) 826 writeTarBlock (data, dataCount);
888 fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno)); 827
828 fullDataCount -= dataCount;
829 }
830
831 /*
832 * Close the file.
833 */
834 if ((tostdoutFlag == FALSE) && close (fileFd) < 0)
835 fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno));
889} 836}
890 837
891 838
892/* 839/*
893 * Save a directory and all of its files to the tar file. 840 * Save a directory and all of its files to the tar file.
894 */ 841 */
895static void 842static void saveDirectory (const char *dirName, const struct stat *statbuf)
896saveDirectory(const char * dirName, const struct stat * statbuf)
897{ 843{
898 DIR * dir; 844 DIR *dir;
899 struct dirent * entry; 845 struct dirent *entry;
900 int needSlash; 846 int needSlash;
901 char fullName[PATH_LEN]; 847 char fullName[PATH_LEN];
902 848
903 /* 849 /*
904 * Construct the directory name as used in the tar file by appending 850 * Construct the directory name as used in the tar file by appending
905 * a slash character to it. 851 * a slash character to it.
906 */ 852 */
907 strcpy(fullName, dirName); 853 strcpy (fullName, dirName);
908 strcat(fullName, "/"); 854 strcat (fullName, "/");
909 855
910 /* 856 /*
911 * Write out the header for the directory entry. 857 * Write out the header for the directory entry.
912 */ 858 */
913 writeHeader(fullName, statbuf); 859 writeHeader (fullName, statbuf);
914 860
915 /* 861 /*
916 * Open the directory. 862 * Open the directory.
917 */ 863 */
918 dir = opendir(dirName); 864 dir = opendir (dirName);
919 865
920 if (dir == NULL) 866 if (dir == NULL) {
921 { 867 fprintf (stderr, "Cannot read directory \"%s\": %s\n",
922 fprintf(stderr, "Cannot read directory \"%s\": %s\n", 868 dirName, strerror (errno));
923 dirName, strerror(errno)); 869
924 870 return;
925 return; 871 }
872
873 /*
874 * See if a slash is needed.
875 */
876 needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/'));
877
878 /*
879 * Read all of the directory entries and check them,
880 * except for the current and parent directory entries.
881 */
882 while (!errorFlag && ((entry = readdir (dir)) != NULL)) {
883 if ((strcmp (entry->d_name, ".") == 0) ||
884 (strcmp (entry->d_name, "..") == 0)) {
885 continue;
926 } 886 }
927 887
928 /* 888 /*
929 * See if a slash is needed. 889 * Build the full path name to the file.
930 */ 890 */
931 needSlash = (*dirName && (dirName[strlen(dirName) - 1] != '/')); 891 strcpy (fullName, dirName);
932 892
933 /* 893 if (needSlash)
934 * Read all of the directory entries and check them, 894 strcat (fullName, "/");
935 * except for the current and parent directory entries.
936 */
937 while (!errorFlag && ((entry = readdir(dir)) != NULL))
938 {
939 if ((strcmp(entry->d_name, ".") == 0) ||
940 (strcmp(entry->d_name, "..") == 0))
941 {
942 continue;
943 }
944
945 /*
946 * Build the full path name to the file.
947 */
948 strcpy(fullName, dirName);
949 895
950 if (needSlash) 896 strcat (fullName, entry->d_name);
951 strcat(fullName, "/");
952 897
953 strcat(fullName, entry->d_name); 898 /*
954 899 * Write this file to the tar file, noticing whether or not
955 /* 900 * the file is a symbolic link.
956 * Write this file to the tar file, noticing whether or not
957 * the file is a symbolic link.
958 */
959 saveFile(fullName, TRUE);
960 }
961
962 /*
963 * All done, close the directory.
964 */ 901 */
965 closedir(dir); 902 saveFile (fullName, TRUE);
903 }
904
905 /*
906 * All done, close the directory.
907 */
908 closedir (dir);
966} 909}
967 910
968 911
@@ -970,55 +913,54 @@ saveDirectory(const char * dirName, const struct stat * statbuf)
970 * Write a tar header for the specified file name and status. 913 * Write a tar header for the specified file name and status.
971 * It is assumed that the file name fits. 914 * It is assumed that the file name fits.
972 */ 915 */
973static void 916static void writeHeader (const char *fileName, const struct stat *statbuf)
974writeHeader(const char * fileName, const struct stat * statbuf)
975{ 917{
976 long checkSum; 918 long checkSum;
977 const unsigned char * cp; 919 const unsigned char *cp;
978 int len; 920 int len;
979 TarHeader header; 921 TarHeader header;
980 922
981 /* 923 /*
982 * Zero the header block in preparation for filling it in. 924 * Zero the header block in preparation for filling it in.
983 */ 925 */
984 memset((char *) &header, 0, sizeof(header)); 926 memset ((char *) &header, 0, sizeof (header));
985 927
986 /* 928 /*
987 * Fill in the header. 929 * Fill in the header.
988 */ 930 */
989 strcpy(header.name, fileName); 931 strcpy (header.name, fileName);
990 932
991 strncpy(header.magic, TAR_MAGIC, sizeof(header.magic)); 933 strncpy (header.magic, TAR_MAGIC, sizeof (header.magic));
992 strncpy(header.version, TAR_VERSION, sizeof(header.version)); 934 strncpy (header.version, TAR_VERSION, sizeof (header.version));
993 935
994 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); 936 putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777);
995 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 937 putOctal (header.uid, sizeof (header.uid), statbuf->st_uid);
996 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); 938 putOctal (header.gid, sizeof (header.gid), statbuf->st_gid);
997 putOctal(header.size, sizeof(header.size), statbuf->st_size); 939 putOctal (header.size, sizeof (header.size), statbuf->st_size);
998 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); 940 putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime);
999 941
1000 header.typeFlag = TAR_TYPE_REGULAR; 942 header.typeFlag = TAR_TYPE_REGULAR;
1001 943
1002 /* 944 /*
1003 * Calculate and store the checksum. 945 * Calculate and store the checksum.
1004 * This is the sum of all of the bytes of the header, 946 * This is the sum of all of the bytes of the header,
1005 * with the checksum field itself treated as blanks. 947 * with the checksum field itself treated as blanks.
1006 */ 948 */
1007 memset(header.checkSum, ' ', sizeof(header.checkSum)); 949 memset (header.checkSum, ' ', sizeof (header.checkSum));
1008 950
1009 cp = (const unsigned char *) &header; 951 cp = (const unsigned char *) &header;
1010 len = sizeof(header); 952 len = sizeof (header);
1011 checkSum = 0; 953 checkSum = 0;
1012 954
1013 while (len-- > 0) 955 while (len-- > 0)
1014 checkSum += *cp++; 956 checkSum += *cp++;
1015 957
1016 putOctal(header.checkSum, sizeof(header.checkSum), checkSum); 958 putOctal (header.checkSum, sizeof (header.checkSum), checkSum);
1017 959
1018 /* 960 /*
1019 * Write the tar header. 961 * Write the tar header.
1020 */ 962 */
1021 writeTarBlock((const char *) &header, sizeof(header)); 963 writeTarBlock ((const char *) &header, sizeof (header));
1022} 964}
1023 965
1024 966
@@ -1027,59 +969,56 @@ writeHeader(const char * fileName, const struct stat * statbuf)
1027 * The data is always padded out to a multiple of TAR_BLOCK_SIZE. 969 * The data is always padded out to a multiple of TAR_BLOCK_SIZE.
1028 * The errorFlag static variable is set on an error. 970 * The errorFlag static variable is set on an error.
1029 */ 971 */
1030static void 972static void writeTarBlock (const char *buf, int len)
1031writeTarBlock(const char * buf, int len)
1032{ 973{
1033 int partialLength; 974 int partialLength;
1034 int completeLength; 975 int completeLength;
1035 char fullBlock[TAR_BLOCK_SIZE]; 976 char fullBlock[TAR_BLOCK_SIZE];
1036 977
1037 /* 978 /*
1038 * If we had a write error before, then do nothing more. 979 * If we had a write error before, then do nothing more.
1039 */ 980 */
1040 if (errorFlag) 981 if (errorFlag)
1041 return; 982 return;
1042 983
1043 /* 984 /*
1044 * Get the amount of complete and partial blocks. 985 * Get the amount of complete and partial blocks.
1045 */ 986 */
1046 partialLength = len % TAR_BLOCK_SIZE; 987 partialLength = len % TAR_BLOCK_SIZE;
1047 completeLength = len - partialLength; 988 completeLength = len - partialLength;
1048 989
1049 /* 990 /*
1050 * Write all of the complete blocks. 991 * Write all of the complete blocks.
1051 */ 992 */
1052 if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) 993 if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) {
1053 { 994 perror (tarName);
1054 perror(tarName); 995
1055 996 errorFlag = TRUE;
1056 errorFlag = TRUE; 997
1057 998 return;
1058 return; 999 }
1059 } 1000
1060 1001 /*
1061 /* 1002 * If there are no partial blocks left, we are done.
1062 * If there are no partial blocks left, we are done. 1003 */
1063 */ 1004 if (partialLength == 0)
1064 if (partialLength == 0) 1005 return;
1065 return; 1006
1066 1007 /*
1067 /* 1008 * Copy the partial data into a complete block, and pad the rest
1068 * Copy the partial data into a complete block, and pad the rest 1009 * of it with zeroes.
1069 * of it with zeroes. 1010 */
1070 */ 1011 memcpy (fullBlock, buf + completeLength, partialLength);
1071 memcpy(fullBlock, buf + completeLength, partialLength); 1012 memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength);
1072 memset(fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); 1013
1073 1014 /*
1074 /* 1015 * Write the last complete block.
1075 * Write the last complete block. 1016 */
1076 */ 1017 if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) {
1077 if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) 1018 perror (tarName);
1078 { 1019
1079 perror(tarName); 1020 errorFlag = TRUE;
1080 1021 }
1081 errorFlag = TRUE;
1082 }
1083} 1022}
1084 1023
1085 1024
@@ -1089,29 +1028,27 @@ writeTarBlock(const char * buf, int len)
1089 * while all previous ones get default protections. Errors are not reported 1028 * while all previous ones get default protections. Errors are not reported
1090 * here, as failures to restore files can be reported later. 1029 * here, as failures to restore files can be reported later.
1091 */ 1030 */
1092static void 1031static void createPath (const char *name, int mode)
1093createPath(const char * name, int mode)
1094{ 1032{
1095 char * cp; 1033 char *cp;
1096 char * cpOld; 1034 char *cpOld;
1097 char buf[TAR_NAME_SIZE]; 1035 char buf[TAR_NAME_SIZE];
1098 1036
1099 strcpy(buf, name); 1037 strcpy (buf, name);
1100 1038
1101 cp = strchr(buf, '/'); 1039 cp = strchr (buf, '/');
1102 1040
1103 while (cp) 1041 while (cp) {
1104 { 1042 cpOld = cp;
1105 cpOld = cp; 1043 cp = strchr (cp + 1, '/');
1106 cp = strchr(cp + 1, '/');
1107 1044
1108 *cpOld = '\0'; 1045 *cpOld = '\0';
1109 1046
1110 if (mkdir(buf, cp ? 0777 : mode) == 0) 1047 if (mkdir (buf, cp ? 0777 : mode) == 0)
1111 printf("Directory \"%s\" created\n", buf); 1048 printf ("Directory \"%s\" created\n", buf);
1112 1049
1113 *cpOld = '/'; 1050 *cpOld = '/';
1114 } 1051 }
1115} 1052}
1116 1053
1117 1054
@@ -1120,38 +1057,34 @@ createPath(const char * name, int mode)
1120 * spaces on both sides of the number and with an optional null character 1057 * spaces on both sides of the number and with an optional null character
1121 * at the end. Returns -1 on an illegal format. 1058 * at the end. Returns -1 on an illegal format.
1122 */ 1059 */
1123static long 1060static long getOctal (const char *cp, int len)
1124getOctal(const char * cp, int len)
1125{ 1061{
1126 long val; 1062 long val;
1127 1063
1128 while ((len > 0) && (*cp == ' ')) 1064 while ((len > 0) && (*cp == ' ')) {
1129 { 1065 cp++;
1130 cp++; 1066 len--;
1131 len--; 1067 }
1132 }
1133 1068
1134 if ((len == 0) || !isOctal(*cp)) 1069 if ((len == 0) || !isOctal (*cp))
1135 return -1; 1070 return -1;
1136 1071
1137 val = 0; 1072 val = 0;
1138 1073
1139 while ((len > 0) && isOctal(*cp)) 1074 while ((len > 0) && isOctal (*cp)) {
1140 { 1075 val = val * 8 + *cp++ - '0';
1141 val = val * 8 + *cp++ - '0'; 1076 len--;
1142 len--; 1077 }
1143 }
1144 1078
1145 while ((len > 0) && (*cp == ' ')) 1079 while ((len > 0) && (*cp == ' ')) {
1146 { 1080 cp++;
1147 cp++; 1081 len--;
1148 len--; 1082 }
1149 }
1150 1083
1151 if ((len > 0) && *cp) 1084 if ((len > 0) && *cp)
1152 return -1; 1085 return -1;
1153 1086
1154 return val; 1087 return val;
1155} 1088}
1156 1089
1157 1090
@@ -1160,50 +1093,48 @@ getOctal(const char * cp, int len)
1160 * The number is zero and space padded and possibly null padded. 1093 * The number is zero and space padded and possibly null padded.
1161 * Returns TRUE if successful. 1094 * Returns TRUE if successful.
1162 */ 1095 */
1163static int 1096static int putOctal (char *cp, int len, long value)
1164putOctal(char * cp, int len, long value)
1165{ 1097{
1166 int tempLength; 1098 int tempLength;
1167 char * tempString; 1099 char *tempString;
1168 char tempBuffer[32]; 1100 char tempBuffer[32];
1169 1101
1170 /* 1102 /*
1171 * Create a string of the specified length with an initial space, 1103 * Create a string of the specified length with an initial space,
1172 * leading zeroes and the octal number, and a trailing null. 1104 * leading zeroes and the octal number, and a trailing null.
1173 */ 1105 */
1174 tempString = tempBuffer; 1106 tempString = tempBuffer;
1175 1107
1176 sprintf(tempString, " %0*lo", len - 2, value); 1108 sprintf (tempString, " %0*lo", len - 2, value);
1177 1109
1178 tempLength = strlen(tempString) + 1; 1110 tempLength = strlen (tempString) + 1;
1179 1111
1180 /* 1112 /*
1181 * If the string is too large, suppress the leading space. 1113 * If the string is too large, suppress the leading space.
1182 */ 1114 */
1183 if (tempLength > len) 1115 if (tempLength > len) {
1184 { 1116 tempLength--;
1185 tempLength--; 1117 tempString++;
1186 tempString++; 1118 }
1187 } 1119
1188 1120 /*
1189 /* 1121 * If the string is still too large, suppress the trailing null.
1190 * If the string is still too large, suppress the trailing null. 1122 */
1191 */ 1123 if (tempLength > len)
1192 if (tempLength > len) 1124 tempLength--;
1193 tempLength--; 1125
1126 /*
1127 * If the string is still too large, fail.
1128 */
1129 if (tempLength > len)
1130 return FALSE;
1194 1131
1195 /* 1132 /*
1196 * If the string is still too large, fail. 1133 * Copy the string to the field.
1197 */ 1134 */
1198 if (tempLength > len) 1135 memcpy (cp, tempString, len);
1199 return FALSE;
1200 1136
1201 /* 1137 return TRUE;
1202 * Copy the string to the field.
1203 */
1204 memcpy(cp, tempString, len);
1205
1206 return TRUE;
1207} 1138}
1208 1139
1209 1140
@@ -1213,48 +1144,43 @@ putOctal(char * cp, int len, long value)
1213 * Returns TRUE if the file is selected. 1144 * Returns TRUE if the file is selected.
1214 */ 1145 */
1215static int 1146static int
1216wantFileName(const char * fileName, int fileCount, char ** fileTable) 1147wantFileName (const char *fileName, int fileCount, char **fileTable)
1217{ 1148{
1218 const char * pathName; 1149 const char *pathName;
1219 int fileLength; 1150 int fileLength;
1220 int pathLength; 1151 int pathLength;
1221 1152
1222 /* 1153 /*
1223 * If there are no files in the list, then the file is wanted. 1154 * If there are no files in the list, then the file is wanted.
1224 */ 1155 */
1225 if (fileCount == 0) 1156 if (fileCount == 0)
1226 return TRUE; 1157 return TRUE;
1227 1158
1228 fileLength = strlen(fileName); 1159 fileLength = strlen (fileName);
1229 1160
1230 /* 1161 /*
1231 * Check each of the test paths. 1162 * Check each of the test paths.
1232 */ 1163 */
1233 while (fileCount-- > 0) 1164 while (fileCount-- > 0) {
1234 { 1165 pathName = *fileTable++;
1235 pathName = *fileTable++;
1236 1166
1237 pathLength = strlen(pathName); 1167 pathLength = strlen (pathName);
1238 1168
1239 if (fileLength < pathLength) 1169 if (fileLength < pathLength)
1240 continue; 1170 continue;
1241 1171
1242 if (memcmp(fileName, pathName, pathLength) != 0) 1172 if (memcmp (fileName, pathName, pathLength) != 0)
1243 continue; 1173 continue;
1244 1174
1245 if ((fileLength == pathLength) || 1175 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) {
1246 (fileName[pathLength] == '/')) 1176 return TRUE;
1247 {
1248 return TRUE;
1249 }
1250 } 1177 }
1178 }
1251 1179
1252 return FALSE; 1180 return FALSE;
1253} 1181}
1254 1182
1255 1183
1256 1184
1257#endif 1185#endif
1258/* END CODE */ 1186/* END CODE */
1259
1260
diff --git a/busybox.def.h b/busybox.def.h
index a5c5957a1..848783b9f 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -16,7 +16,7 @@
16//#define BB_DESCEND 16//#define BB_DESCEND
17#define BB_DF 17#define BB_DF
18#define BB_DMESG 18#define BB_DMESG
19//#define BB_DUTMP 19#define BB_DUTMP
20//#define BB_DYADIC 20//#define BB_DYADIC
21#define BB_FALSE 21#define BB_FALSE
22//#define BB_FDFLUSH 22//#define BB_FDFLUSH
@@ -24,7 +24,7 @@
24#define BB_GREP 24#define BB_GREP
25////#define BB_HALT 25////#define BB_HALT
26//#define BB_INIT 26//#define BB_INIT
27//#define BB_KILL 27#define BB_KILL
28////#define BB_LENGTH 28////#define BB_LENGTH
29//#define BB_LN 29//#define BB_LN
30//#define BB_LOADKMAP 30//#define BB_LOADKMAP
@@ -44,10 +44,10 @@
44//#define BB_POSTPROCESS 44//#define BB_POSTPROCESS
45//#define BB_PRINTF 45//#define BB_PRINTF
46#define BB_PWD 46#define BB_PWD
47//#define BB_REBOOT 47#define BB_REBOOT
48//#define BB_RM 48//#define BB_RM
49//#define BB_RMDIR 49//#define BB_RMDIR
50//#define BB_SLEEP 50#define BB_SLEEP
51////#define BB_SWAPOFF 51////#define BB_SWAPOFF
52//#define BB_SWAPON 52//#define BB_SWAPON
53//#define BB_SYNC 53//#define BB_SYNC
diff --git a/cat.c b/cat.c
index 8718c4d02..5c54c4941 100644
--- a/cat.c
+++ b/cat.c
@@ -22,15 +22,27 @@
22#include "internal.h" 22#include "internal.h"
23#include <stdio.h> 23#include <stdio.h>
24 24
25const char cat_usage[] = "[file ...]";
26 25
27extern int cat_more_main(int argc, char **argv) 26static void print_file( FILE *file)
28{ 27{
29 int c; 28 int c;
30 FILE *file = stdin; 29 while ((c = getc(file)) != EOF)
30 putc(c, stdout);
31 fclose(file);
32 fflush(stdout);
33}
34
35extern int cat_more_main(int argc, char **argv)
36{
37 FILE *file;
38
39 if (argc==1) {
40 print_file( stdin);
41 exit( TRUE);
42 }
31 43
32 if ( (argc < 2) || (**(argv+1) == '-') ) { 44 if ( **(argv+1) == '-' ) {
33 fprintf(stderr, "Usage: %s %s", *argv, cat_usage); 45 fprintf(stderr, "Usage: cat [file ...]\n");
34 exit(FALSE); 46 exit(FALSE);
35 } 47 }
36 argc--; 48 argc--;
@@ -42,11 +54,7 @@ extern int cat_more_main(int argc, char **argv)
42 perror(*argv); 54 perror(*argv);
43 exit(FALSE); 55 exit(FALSE);
44 } 56 }
45 while ((c = getc(file)) != EOF) 57 print_file( file);
46 putc(c, stdout);
47 fclose(file);
48 fflush(stdout);
49
50 argc--; 58 argc--;
51 argv++; 59 argv++;
52 } 60 }
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 8718c4d02..5c54c4941 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -22,15 +22,27 @@
22#include "internal.h" 22#include "internal.h"
23#include <stdio.h> 23#include <stdio.h>
24 24
25const char cat_usage[] = "[file ...]";
26 25
27extern int cat_more_main(int argc, char **argv) 26static void print_file( FILE *file)
28{ 27{
29 int c; 28 int c;
30 FILE *file = stdin; 29 while ((c = getc(file)) != EOF)
30 putc(c, stdout);
31 fclose(file);
32 fflush(stdout);
33}
34
35extern int cat_more_main(int argc, char **argv)
36{
37 FILE *file;
38
39 if (argc==1) {
40 print_file( stdin);
41 exit( TRUE);
42 }
31 43
32 if ( (argc < 2) || (**(argv+1) == '-') ) { 44 if ( **(argv+1) == '-' ) {
33 fprintf(stderr, "Usage: %s %s", *argv, cat_usage); 45 fprintf(stderr, "Usage: cat [file ...]\n");
34 exit(FALSE); 46 exit(FALSE);
35 } 47 }
36 argc--; 48 argc--;
@@ -42,11 +54,7 @@ extern int cat_more_main(int argc, char **argv)
42 perror(*argv); 54 perror(*argv);
43 exit(FALSE); 55 exit(FALSE);
44 } 56 }
45 while ((c = getc(file)) != EOF) 57 print_file( file);
46 putc(c, stdout);
47 fclose(file);
48 fflush(stdout);
49
50 argc--; 58 argc--;
51 argv++; 59 argv++;
52 } 60 }
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 07f092cc2..40288fd4d 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -6,302 +6,211 @@
6 * The "dd" command, originally taken from sash. 6 * The "dd" command, originally taken from sash.
7 * 7 *
8 * Permission to distribute this code under the GPL has been granted. 8 * Permission to distribute this code under the GPL has been granted.
9 * Majorly modified, and bugs fixed for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com> 9 * Mostly rewritten and bugs fixed for busybox by Erik Andersen <andersee@debian.org>
10 */ 10 */
11 11
12#include "internal.h" 12#include "internal.h"
13#ifdef BB_DD 13#include <stdio.h>
14#include <fcntl.h>
15#include <errno.h>
14 16
15const char dd_usage[] = 17const char dd_usage[] =
16"Copy a file, converting and formatting according to options\n\ 18 "Copy a file, converting and formatting according to options\n\
17\n\ 19\n\
18usage: [if=name] [of=name] [bs=n] [count=n]\n\ 20usage: [if=name] [of=name] [bs=n] [count=n]\n\
19\tif=FILE\tread from FILE instead of stdin\n\ 21\tif=FILE\tread from FILE instead of stdin\n\
20\tof=FILE\twrite to FILE instead of stout\n\ 22\tof=FILE\twrite to FILE instead of stout\n\
21\tbs=n\tread and write N bytes at a time\n\ 23\tbs=n\tread and write N bytes at a time\n\
22\tcount=n\tcopy only n input blocks\n\ 24\tcount=n\tcopy only n input blocks\n\
25\tskip=n\tskip n input blocks\n\
23\n\ 26\n\
24BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; 27BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
25 28
26 29
27#include <stdio.h>
28#include <dirent.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <signal.h>
32#include <time.h>
33
34
35#define PAR_NONE 0
36#define PAR_IF 1
37#define PAR_OF 2
38#define PAR_BS 3
39#define PAR_COUNT 4
40 30
41 31
42typedef struct 32/*
33 * Read a number with a possible multiplier.
34 * Returns -1 if the number format is illegal.
35 */
36static long getNum (const char *cp)
43{ 37{
44 const char * name; 38 long value;
45 int value;
46} PARAM;
47 39
40 if (!isDecimal (*cp))
41 return -1;
48 42
49static const PARAM params[] = 43 value = 0;
50{
51 {"if", PAR_IF},
52 {"of", PAR_OF},
53 {"bs", PAR_BS},
54 {"count", PAR_COUNT},
55 {NULL, PAR_NONE}
56};
57
58 44
59static long getNum(const char * cp); 45 while (isDecimal (*cp))
46 value = value * 10 + *cp++ - '0';
60 47
61extern int 48 switch (*cp++) {
62dd_main (int argc, char **argv) 49 case 'k':
63{ 50 value *= 1024;
64 const char * str; 51 break;
65 const PARAM * par;
66 const char * inFile;
67 const char * outFile;
68 char * cp;
69 int inFd;
70 int outFd;
71 int inCc=0;
72 int outCc;
73 int blockSize;
74 long count;
75 long intotal;
76 long outTotal;
77 unsigned char* buf;
78 unsigned char localBuf[BUF_SIZE];
79
80 inFile = NULL;
81 outFile = NULL;
82 blockSize = 512;
83 count = 1;
84
85
86 while (--argc > 0)
87 {
88 str = *++argv;
89 cp = strchr(str, '=');
90
91 if (cp == NULL)
92 {
93 fprintf(stderr, "Bad dd argument\n");
94 goto usage;
95 }
96
97 *cp++ = '\0';
98
99 for (par = params; par->name; par++)
100 {
101 if (strcmp(str, par->name) == 0)
102 break;
103 }
104
105 switch (par->value)
106 {
107 case PAR_IF:
108 if (inFile)
109 {
110 fprintf(stderr, "Multiple input files illegal\n");
111 goto usage;
112 }
113
114 //fprintf(stderr, "if=%s\n", cp);
115 inFile = cp;
116 break;
117
118 case PAR_OF:
119 if (outFile)
120 {
121 fprintf(stderr, "Multiple output files illegal\n");
122 goto usage;
123 }
124
125 //fprintf(stderr, "of=%s\n", cp);
126 outFile = cp;
127 break;
128
129 case PAR_BS:
130 blockSize = getNum(cp);
131 //fprintf(stderr, "bs=%d\n", blockSize);
132
133 if (blockSize <= 0)
134 {
135 fprintf(stderr, "Bad block size value\n");
136 goto usage;
137 }
138
139 break;
140
141 case PAR_COUNT:
142 count = getNum(cp);
143 //fprintf(stderr, "count=%ld\n", count);
144
145 if (count < 0)
146 {
147 fprintf(stderr, "Bad count value\n");
148 goto usage;
149 }
150
151 break;
152
153 default:
154 goto usage;
155 }
156 }
157 52
158 buf = localBuf; 53 case 'b':
54 value *= 512;
55 break;
159 56
160 if (blockSize > sizeof(localBuf)) 57 case 'w':
161 { 58 value *= 2;
162 buf = malloc(blockSize); 59 break;
163 60
164 if (buf == NULL) 61 case '\0':
165 { 62 return value;
166 fprintf(stderr, "Cannot allocate buffer\n");
167 return 1;
168 }
169 }
170 63
171 intotal = 0; 64 default:
172 outTotal = 0; 65 return -1;
66 }
173 67
174 if (inFile == NULL) 68 if (*cp)
175 inFd = STDIN; 69 return -1;
176 else
177 inFd = open(inFile, 0);
178 70
179 if (inFd < 0) 71 return value;
180 { 72}
181 perror(inFile);
182 73
183 if (buf != localBuf)
184 free(buf);
185 74
186 return 1; 75extern int dd_main (int argc, char **argv)
76{
77 const char *inFile;
78 const char *outFile;
79 char *cp;
80 int inFd;
81 int outFd;
82 int inCc = 0;
83 int outCc;
84 int skipBlocks;
85 int blockSize;
86 long count;
87 long intotal;
88 long outTotal;
89 unsigned char *buf;
90
91 inFile = NULL;
92 outFile = NULL;
93 blockSize = 512;
94 skipBlocks = 0;
95 count = 1;
96
97
98 argc--;
99 argv++;
100
101 /* Parse any options */
102 while (argc) {
103 if (inFile == NULL && (strncmp("if", *argv, 2) == 0))
104 inFile=*argv;
105 else if (outFile == NULL && (strncmp("of", *argv, 2) == 0))
106 outFile=*argv;
107 else if (strncmp("count", *argv, 5) == 0) {
108 count = getNum (*argv);
109 if (count <= 0) {
110 fprintf (stderr, "Bad count value %ld\n", count);
111 goto usage;
112 }
187 } 113 }
188 114 else if (strncmp("bs", *argv, 2) == 0) {
189 if (outFile == NULL) 115 blockSize = getNum(*argv);
190 outFd = STDOUT; 116 if (blockSize <= 0) {
191 else 117 fprintf (stderr, "Bad block size value %d\n", blockSize);
192 outFd = creat(outFile, 0666); 118 goto usage;
193 119 }
194 if (outFd < 0)
195 {
196 perror(outFile);
197 close(inFd);
198
199 if (buf != localBuf)
200 free(buf);
201
202 return 1;
203 } 120 }
121 else if (strncmp("skip", *argv, 4) == 0) {
122 skipBlocks = atoi( *argv);
123 if (skipBlocks <= 0) {
124 fprintf (stderr, "Bad skip value %d\n", skipBlocks);
125 goto usage;
126 }
204 127
205 while ( outTotal < count*blockSize )
206 {
207 inCc = read(inFd, buf, blockSize);
208 if (inCc < 0) {
209 perror(inFile);
210 goto cleanup;
211 }
212 //fprintf(stderr, "read in =%d\n", inCc);
213 intotal += inCc;
214 cp = buf;
215
216
217 while ( intotal > outTotal )
218 {
219 if (outTotal+inCc > count*blockSize)
220 inCc=count*blockSize-outTotal;
221 outCc = write(outFd, cp, inCc);
222 if (outCc < 0)
223 {
224 perror(outFile);
225 goto cleanup;
226 }
227 //fprintf(stderr, "wrote out =%d\n", outCc);
228
229 inCc -= outCc;
230 cp += outCc;
231 outTotal += outCc;
232 //fprintf(stderr, "outTotal=%ld\n", outTotal);
233 }
234 } 128 }
129 else {
130 fprintf (stderr, "Got here. argv=%s\n", *argv);
131 goto usage;
235 132
236 if (inCc < 0) 133 argc--;
237 perror(inFile); 134 argv++;
238 135 }
239cleanup: 136 }
240 close(inFd); 137 if ( inFile == NULL || outFile == NULL)
241 138 goto usage;
242 if (close(outFd) < 0) 139
243 perror(outFile); 140 buf = malloc (blockSize);
244 141 if (buf == NULL) {
245 if (buf != localBuf) 142 fprintf (stderr, "Cannot allocate buffer\n");
246 free(buf); 143 return( FALSE);
247 144 }
248 printf("%ld+%d records in\n", intotal / blockSize, 145
249 (intotal % blockSize) != 0); 146 intotal = 0;
250 147 outTotal = 0;
251 printf("%ld+%d records out\n", outTotal / blockSize, 148
252 (outTotal % blockSize) != 0); 149 if (!inFile)
253 return 0; 150 inFd = STDIN;
254usage: 151 else
255 152 inFd = open (inFile, 0);
256 fprintf(stderr, "%s", dd_usage); 153
257 return 1; 154 if (inFd < 0) {
258} 155 perror (inFile);
259 156 free (buf);
260 157 return( FALSE);
261/* 158 }
262 * Read a number with a possible multiplier. 159
263 * Returns -1 if the number format is illegal. 160 if (!outFile)
264 */ 161 outFd = STDOUT;
265static long 162 else
266getNum(const char * cp) 163 outFd = creat (outFile, 0666);
267{ 164
268 long value; 165 if (outFd < 0) {
269 166 perror (outFile);
270 if (!isDecimal(*cp)) 167 close (inFd);
271 return -1; 168 free (buf);
272 169 return( FALSE);
273 value = 0; 170 }
274 171
275 while (isDecimal(*cp)) 172 lseek(inFd, skipBlocks*blockSize, SEEK_SET);
276 value = value * 10 + *cp++ - '0'; 173 while (outTotal < count * blockSize) {
277 174 inCc = read (inFd, buf, blockSize);
278 switch (*cp++) 175 if (inCc < 0) {
279 { 176 perror (inFile);
280 case 'k': 177 goto cleanup;
281 value *= 1024; 178 }
282 break; 179 intotal += inCc;
283 180 cp = buf;
284 case 'b': 181
285 value *= 512; 182 while (intotal > outTotal) {
286 break; 183 if (outTotal + inCc > count * blockSize)
287 184 inCc = count * blockSize - outTotal;
288 case 'w': 185 outCc = write (outFd, cp, inCc);
289 value *= 2; 186 if (outCc < 0) {
290 break; 187 perror (outFile);
188 goto cleanup;
189 }
190
191 inCc -= outCc;
192 cp += outCc;
193 outTotal += outCc;
194 }
195 }
291 196
292 case '\0': 197 if (inCc < 0)
293 return value; 198 perror (inFile);
294 199
295 default: 200 cleanup:
296 return -1; 201 close (inFd);
297 } 202 close (outFd);
203 free (buf);
298 204
299 if (*cp) 205 printf ("%ld+%d records in\n", intotal / blockSize,
300 return -1; 206 (intotal % blockSize) != 0);
207 printf ("%ld+%d records out\n", outTotal / blockSize,
208 (outTotal % blockSize) != 0);
209 exit( TRUE);
210 usage:
301 211
302 return value; 212 fprintf (stderr, "%s", dd_usage);
213 exit( FALSE);
303} 214}
304 215
305#endif
306/* END CODE */
307 216
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
index 893ed1e15..2ad019d50 100644
--- a/coreutils/pwd.c
+++ b/coreutils/pwd.c
@@ -1,12 +1,13 @@
1#include "internal.h" 1#include "internal.h"
2#include <stdio.h> 2#include <stdio.h>
3#include <dirent.h>
3 4
4const char pwd_usage[] = "Print the current directory.\n"; 5const char pwd_usage[] = "Print the current directory.\n";
5 6
6extern int 7extern int
7pwd_main(int argc, char * * argv) 8pwd_main(int argc, char * * argv)
8{ 9{
9 char buf[1024]; 10 char buf[NAME_MAX];
10 11
11 if ( getcwd(buf, sizeof(buf)) == NULL ) { 12 if ( getcwd(buf, sizeof(buf)) == NULL ) {
12 perror("get working directory"); 13 perror("get working directory");
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index e48e14b2f..53fe5a0c2 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -1,15 +1,20 @@
1#include "internal.h" 1#include "internal.h"
2#include <stdio.h> 2#include <stdio.h>
3 3
4const char sleep_usage[] = "sleep seconds\n" 4const char sleep_usage[] = " NUMBER\n"
5"\n" 5"Pause for NUMBER seconds.\n";
6"\tPause program execution for the given number of seconds.\n";
7 6
8extern int 7extern int
9sleep_main(struct FileInfo * i, int argc, char * * argv) 8sleep_main(int argc, char * * argv)
10{ 9{
11 if ( sleep(atoi(argv[1])) != 0 ) 10 if ( (argc < 2) || (**(argv+1) == '-') ) {
12 return -1; 11 fprintf(stderr, "Usage: %s %s", *argv, sleep_usage);
13 else 12 exit(FALSE);
14 return 0; 13 }
14
15 if ( sleep(atoi(*(++argv))) != 0 ) {
16 perror( "sleep");
17 exit (FALSE);
18 } else
19 exit (TRUE);
15} 20}
diff --git a/dd.c b/dd.c
index 07f092cc2..40288fd4d 100644
--- a/dd.c
+++ b/dd.c
@@ -6,302 +6,211 @@
6 * The "dd" command, originally taken from sash. 6 * The "dd" command, originally taken from sash.
7 * 7 *
8 * Permission to distribute this code under the GPL has been granted. 8 * Permission to distribute this code under the GPL has been granted.
9 * Majorly modified, and bugs fixed for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com> 9 * Mostly rewritten and bugs fixed for busybox by Erik Andersen <andersee@debian.org>
10 */ 10 */
11 11
12#include "internal.h" 12#include "internal.h"
13#ifdef BB_DD 13#include <stdio.h>
14#include <fcntl.h>
15#include <errno.h>
14 16
15const char dd_usage[] = 17const char dd_usage[] =
16"Copy a file, converting and formatting according to options\n\ 18 "Copy a file, converting and formatting according to options\n\
17\n\ 19\n\
18usage: [if=name] [of=name] [bs=n] [count=n]\n\ 20usage: [if=name] [of=name] [bs=n] [count=n]\n\
19\tif=FILE\tread from FILE instead of stdin\n\ 21\tif=FILE\tread from FILE instead of stdin\n\
20\tof=FILE\twrite to FILE instead of stout\n\ 22\tof=FILE\twrite to FILE instead of stout\n\
21\tbs=n\tread and write N bytes at a time\n\ 23\tbs=n\tread and write N bytes at a time\n\
22\tcount=n\tcopy only n input blocks\n\ 24\tcount=n\tcopy only n input blocks\n\
25\tskip=n\tskip n input blocks\n\
23\n\ 26\n\
24BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; 27BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
25 28
26 29
27#include <stdio.h>
28#include <dirent.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <signal.h>
32#include <time.h>
33
34
35#define PAR_NONE 0
36#define PAR_IF 1
37#define PAR_OF 2
38#define PAR_BS 3
39#define PAR_COUNT 4
40 30
41 31
42typedef struct 32/*
33 * Read a number with a possible multiplier.
34 * Returns -1 if the number format is illegal.
35 */
36static long getNum (const char *cp)
43{ 37{
44 const char * name; 38 long value;
45 int value;
46} PARAM;
47 39
40 if (!isDecimal (*cp))
41 return -1;
48 42
49static const PARAM params[] = 43 value = 0;
50{
51 {"if", PAR_IF},
52 {"of", PAR_OF},
53 {"bs", PAR_BS},
54 {"count", PAR_COUNT},
55 {NULL, PAR_NONE}
56};
57
58 44
59static long getNum(const char * cp); 45 while (isDecimal (*cp))
46 value = value * 10 + *cp++ - '0';
60 47
61extern int 48 switch (*cp++) {
62dd_main (int argc, char **argv) 49 case 'k':
63{ 50 value *= 1024;
64 const char * str; 51 break;
65 const PARAM * par;
66 const char * inFile;
67 const char * outFile;
68 char * cp;
69 int inFd;
70 int outFd;
71 int inCc=0;
72 int outCc;
73 int blockSize;
74 long count;
75 long intotal;
76 long outTotal;
77 unsigned char* buf;
78 unsigned char localBuf[BUF_SIZE];
79
80 inFile = NULL;
81 outFile = NULL;
82 blockSize = 512;
83 count = 1;
84
85
86 while (--argc > 0)
87 {
88 str = *++argv;
89 cp = strchr(str, '=');
90
91 if (cp == NULL)
92 {
93 fprintf(stderr, "Bad dd argument\n");
94 goto usage;
95 }
96
97 *cp++ = '\0';
98
99 for (par = params; par->name; par++)
100 {
101 if (strcmp(str, par->name) == 0)
102 break;
103 }
104
105 switch (par->value)
106 {
107 case PAR_IF:
108 if (inFile)
109 {
110 fprintf(stderr, "Multiple input files illegal\n");
111 goto usage;
112 }
113
114 //fprintf(stderr, "if=%s\n", cp);
115 inFile = cp;
116 break;
117
118 case PAR_OF:
119 if (outFile)
120 {
121 fprintf(stderr, "Multiple output files illegal\n");
122 goto usage;
123 }
124
125 //fprintf(stderr, "of=%s\n", cp);
126 outFile = cp;
127 break;
128
129 case PAR_BS:
130 blockSize = getNum(cp);
131 //fprintf(stderr, "bs=%d\n", blockSize);
132
133 if (blockSize <= 0)
134 {
135 fprintf(stderr, "Bad block size value\n");
136 goto usage;
137 }
138
139 break;
140
141 case PAR_COUNT:
142 count = getNum(cp);
143 //fprintf(stderr, "count=%ld\n", count);
144
145 if (count < 0)
146 {
147 fprintf(stderr, "Bad count value\n");
148 goto usage;
149 }
150
151 break;
152
153 default:
154 goto usage;
155 }
156 }
157 52
158 buf = localBuf; 53 case 'b':
54 value *= 512;
55 break;
159 56
160 if (blockSize > sizeof(localBuf)) 57 case 'w':
161 { 58 value *= 2;
162 buf = malloc(blockSize); 59 break;
163 60
164 if (buf == NULL) 61 case '\0':
165 { 62 return value;
166 fprintf(stderr, "Cannot allocate buffer\n");
167 return 1;
168 }
169 }
170 63
171 intotal = 0; 64 default:
172 outTotal = 0; 65 return -1;
66 }
173 67
174 if (inFile == NULL) 68 if (*cp)
175 inFd = STDIN; 69 return -1;
176 else
177 inFd = open(inFile, 0);
178 70
179 if (inFd < 0) 71 return value;
180 { 72}
181 perror(inFile);
182 73
183 if (buf != localBuf)
184 free(buf);
185 74
186 return 1; 75extern int dd_main (int argc, char **argv)
76{
77 const char *inFile;
78 const char *outFile;
79 char *cp;
80 int inFd;
81 int outFd;
82 int inCc = 0;
83 int outCc;
84 int skipBlocks;
85 int blockSize;
86 long count;
87 long intotal;
88 long outTotal;
89 unsigned char *buf;
90
91 inFile = NULL;
92 outFile = NULL;
93 blockSize = 512;
94 skipBlocks = 0;
95 count = 1;
96
97
98 argc--;
99 argv++;
100
101 /* Parse any options */
102 while (argc) {
103 if (inFile == NULL && (strncmp("if", *argv, 2) == 0))
104 inFile=*argv;
105 else if (outFile == NULL && (strncmp("of", *argv, 2) == 0))
106 outFile=*argv;
107 else if (strncmp("count", *argv, 5) == 0) {
108 count = getNum (*argv);
109 if (count <= 0) {
110 fprintf (stderr, "Bad count value %ld\n", count);
111 goto usage;
112 }
187 } 113 }
188 114 else if (strncmp("bs", *argv, 2) == 0) {
189 if (outFile == NULL) 115 blockSize = getNum(*argv);
190 outFd = STDOUT; 116 if (blockSize <= 0) {
191 else 117 fprintf (stderr, "Bad block size value %d\n", blockSize);
192 outFd = creat(outFile, 0666); 118 goto usage;
193 119 }
194 if (outFd < 0)
195 {
196 perror(outFile);
197 close(inFd);
198
199 if (buf != localBuf)
200 free(buf);
201
202 return 1;
203 } 120 }
121 else if (strncmp("skip", *argv, 4) == 0) {
122 skipBlocks = atoi( *argv);
123 if (skipBlocks <= 0) {
124 fprintf (stderr, "Bad skip value %d\n", skipBlocks);
125 goto usage;
126 }
204 127
205 while ( outTotal < count*blockSize )
206 {
207 inCc = read(inFd, buf, blockSize);
208 if (inCc < 0) {
209 perror(inFile);
210 goto cleanup;
211 }
212 //fprintf(stderr, "read in =%d\n", inCc);
213 intotal += inCc;
214 cp = buf;
215
216
217 while ( intotal > outTotal )
218 {
219 if (outTotal+inCc > count*blockSize)
220 inCc=count*blockSize-outTotal;
221 outCc = write(outFd, cp, inCc);
222 if (outCc < 0)
223 {
224 perror(outFile);
225 goto cleanup;
226 }
227 //fprintf(stderr, "wrote out =%d\n", outCc);
228
229 inCc -= outCc;
230 cp += outCc;
231 outTotal += outCc;
232 //fprintf(stderr, "outTotal=%ld\n", outTotal);
233 }
234 } 128 }
129 else {
130 fprintf (stderr, "Got here. argv=%s\n", *argv);
131 goto usage;
235 132
236 if (inCc < 0) 133 argc--;
237 perror(inFile); 134 argv++;
238 135 }
239cleanup: 136 }
240 close(inFd); 137 if ( inFile == NULL || outFile == NULL)
241 138 goto usage;
242 if (close(outFd) < 0) 139
243 perror(outFile); 140 buf = malloc (blockSize);
244 141 if (buf == NULL) {
245 if (buf != localBuf) 142 fprintf (stderr, "Cannot allocate buffer\n");
246 free(buf); 143 return( FALSE);
247 144 }
248 printf("%ld+%d records in\n", intotal / blockSize, 145
249 (intotal % blockSize) != 0); 146 intotal = 0;
250 147 outTotal = 0;
251 printf("%ld+%d records out\n", outTotal / blockSize, 148
252 (outTotal % blockSize) != 0); 149 if (!inFile)
253 return 0; 150 inFd = STDIN;
254usage: 151 else
255 152 inFd = open (inFile, 0);
256 fprintf(stderr, "%s", dd_usage); 153
257 return 1; 154 if (inFd < 0) {
258} 155 perror (inFile);
259 156 free (buf);
260 157 return( FALSE);
261/* 158 }
262 * Read a number with a possible multiplier. 159
263 * Returns -1 if the number format is illegal. 160 if (!outFile)
264 */ 161 outFd = STDOUT;
265static long 162 else
266getNum(const char * cp) 163 outFd = creat (outFile, 0666);
267{ 164
268 long value; 165 if (outFd < 0) {
269 166 perror (outFile);
270 if (!isDecimal(*cp)) 167 close (inFd);
271 return -1; 168 free (buf);
272 169 return( FALSE);
273 value = 0; 170 }
274 171
275 while (isDecimal(*cp)) 172 lseek(inFd, skipBlocks*blockSize, SEEK_SET);
276 value = value * 10 + *cp++ - '0'; 173 while (outTotal < count * blockSize) {
277 174 inCc = read (inFd, buf, blockSize);
278 switch (*cp++) 175 if (inCc < 0) {
279 { 176 perror (inFile);
280 case 'k': 177 goto cleanup;
281 value *= 1024; 178 }
282 break; 179 intotal += inCc;
283 180 cp = buf;
284 case 'b': 181
285 value *= 512; 182 while (intotal > outTotal) {
286 break; 183 if (outTotal + inCc > count * blockSize)
287 184 inCc = count * blockSize - outTotal;
288 case 'w': 185 outCc = write (outFd, cp, inCc);
289 value *= 2; 186 if (outCc < 0) {
290 break; 187 perror (outFile);
188 goto cleanup;
189 }
190
191 inCc -= outCc;
192 cp += outCc;
193 outTotal += outCc;
194 }
195 }
291 196
292 case '\0': 197 if (inCc < 0)
293 return value; 198 perror (inFile);
294 199
295 default: 200 cleanup:
296 return -1; 201 close (inFd);
297 } 202 close (outFd);
203 free (buf);
298 204
299 if (*cp) 205 printf ("%ld+%d records in\n", intotal / blockSize,
300 return -1; 206 (intotal % blockSize) != 0);
207 printf ("%ld+%d records out\n", outTotal / blockSize,
208 (outTotal % blockSize) != 0);
209 exit( TRUE);
210 usage:
301 211
302 return value; 212 fprintf (stderr, "%s", dd_usage);
213 exit( FALSE);
303} 214}
304 215
305#endif
306/* END CODE */
307 216
diff --git a/dmesg.c b/dmesg.c
index 9096621b0..64265b473 100644
--- a/dmesg.c
+++ b/dmesg.c
@@ -14,7 +14,6 @@
14 14
15#include <linux/unistd.h> 15#include <linux/unistd.h>
16#include <stdio.h> 16#include <stdio.h>
17#include <getopt.h>
18 17
19#define __NR_klog __NR_syslog 18#define __NR_klog __NR_syslog
20 19
@@ -22,74 +21,78 @@
22#include <sys/klog.h> 21#include <sys/klog.h>
23#define klog klogctl 22#define klog klogctl
24#else 23#else
25static inline _syscall3(int,klog,int,type,char *,b,int,len) 24static inline _syscall3 (int, klog, int, type, char *, b, int, len)
26#endif /* __GLIBC__ */ 25#endif /* __GLIBC__ */
27 26
28const char dmesg_usage[] = "dmesg";
29 27
30int 28
31dmesg_main(int argc, char * * argv) 29static const char dmesg_usage[] = "dmesg [-c] [-n level]\n";
30
31int dmesg_main (int argc, char **argv)
32{ 32{
33 33
34 char buf[4096]; 34 char buf[4096];
35 int i; 35 int i;
36 int n; 36 int n;
37 int c; 37 int level = 0;
38 int level = 0; 38 int lastc;
39 int lastc; 39 int cmd = 3;
40 int cmd = 3;
41 40
42 while ((c = getopt( argc, argv, "cn:" )) != EOF) { 41 argc--;
43 switch (c) { 42 argv++;
44 case 'c':
45 cmd = 4;
46 break;
47 case 'n':
48 cmd = 8;
49 level = atoi(optarg);
50 break;
51 case '?':
52 default:
53 fprintf(stderr, "%s\n", dmesg_usage);
54 exit(1);
55 }
56 }
57 argc -= optind;
58 argv += optind;
59
60 if (argc > 1) {
61 fprintf(stderr, "%s\n", dmesg_usage);
62 exit(1);
63 }
64 43
65 if (cmd == 8) { 44 /* Parse any options */
66 n = klog( cmd, NULL, level ); 45 while (argc && **argv == '-') {
67 if (n < 0) { 46 while (*++(*argv))
68 perror( "klog" ); 47 switch (**argv) {
69 exit( 1 ); 48 case 'c':
70 } 49 cmd = 4;
71 exit( 0 ); 50 break;
72 } 51 case 'n':
52 cmd = 8;
53 if (--argc == 0)
54 goto end;
55 level = atoi (*(++argv));
56 --argc;
57 ++argv;
58 break;
59 default:
60 goto end;
61 }
62 }
73 63
74 n = klog( cmd, buf, sizeof( buf ) ); 64 if (cmd == 8) {
75 if (n < 0) { 65 n = klog (cmd, NULL, level);
76 perror( "klog" ); 66 if (n < 0) {
77 exit( 1 ); 67 perror ("klog");
78 } 68 exit (FALSE);
69 }
70 exit (TRUE);
71 }
79 72
80 lastc = '\n'; 73 n = klog (cmd, buf, sizeof (buf));
81 for (i = 0; i < n; i++) { 74 if (n < 0) {
82 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 75 perror ("klog");
83 i++; 76 exit (FALSE);
84 while (buf[i] >= '0' && buf[i] <= '9') 77 }
85 i++; 78
86 if (buf[i] == '>') 79 lastc = '\n';
80 for (i = 0; i < n; i++) {
81 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
87 i++; 82 i++;
88 } 83 while (buf[i] >= '0' && buf[i] <= '9')
89 lastc = buf[i]; 84 i++;
90 putchar( lastc ); 85 if (buf[i] == '>')
91 } 86 i++;
92 if (lastc != '\n') 87 }
93 putchar( '\n' ); 88 lastc = buf[i];
94 return 0; 89 putchar (lastc);
90 }
91 if (lastc != '\n')
92 putchar ('\n');
93 exit (TRUE);
94
95 end:
96 fprintf (stderr, "Usage: %s\n", dmesg_usage);
97 exit (FALSE);
95} 98}
diff --git a/dutmp.c b/dutmp.c
index e92b6700f..2dad7d4a5 100644
--- a/dutmp.c
+++ b/dutmp.c
@@ -9,39 +9,44 @@
9 * 9 *
10 * made against libc6 10 * made against libc6
11 */ 11 */
12 12
13#include "internal.h" 13#include "internal.h"
14#include <stdio.h> 14#include <stdio.h>
15#include <utmp.h> 15#include <utmp.h>
16 16
17const char dutmp_usage[] = "dutmp\n" 17const char dutmp_usage[] = "dutmp\n"
18"\n" 18 "\n"
19"\tDump file or stdin utmp file format to stdout, pipe delimited.\n" 19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20"\tdutmp /var/run/utmp\n"; 20 "\tdutmp /var/run/utmp\n";
21 21
22extern int 22extern int dutmp_fn (int argc, char **argv)
23dutmp_fn(const struct FileInfo * i)
24{ 23{
25 24
26FILE * f = stdin; 25 FILE *f = stdin;
27struct utmp * ut = (struct utmp *) malloc(sizeof(struct utmp) ); 26 struct utmp ut;
28 27
29 if ( i ) 28 if ((argc < 2) || (**(argv + 1) == '-')) {
30 if (! (f = fopen(i->source, "r"))) { 29 fprintf (stderr, "Usage: %s %s\n", *argv, dutmp_usage);
31 name_and_error(i->source); 30 exit (FALSE);
32 return 1; 31 }
33 } 32
34 33 if ( **(++argv) == 0 ) {
35 while (fread (ut, 1, sizeof(struct utmp), f)) { 34 f = fopen (*(++argv), "r");
36 //printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n", 35 if (f < 0 ) {
37 printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n", 36 perror (*argv);
38 ut->ut_type, ut->ut_pid, ut->ut_line, 37 exit (FALSE);
39 ut->ut_id, ut->ut_user, ut->ut_host, 38 }
40 ut->ut_exit.e_termination, ut->ut_exit.e_exit, 39 }
41 ut->ut_session, 40
42 ut->ut_tv.tv_sec, ut->ut_tv.tv_usec, 41 while (fread (&ut, 1, sizeof (struct utmp), f)) {
43 ut->ut_addr); 42 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
44 } 43 printf ("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
45 44 ut.ut_type, ut.ut_pid, ut.ut_line,
46return 0; 45 ut.ut_id, ut.ut_user, ut.ut_host,
46 ut.ut_exit.e_termination, ut.ut_exit.e_exit,
47 ut.ut_session,
48 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr);
49 }
50
51 exit (TRUE);
47} 52}
diff --git a/findutils/grep.c b/findutils/grep.c
index 52ef6c0fe..657bb2570 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -11,7 +11,6 @@
11 */ 11 */
12 12
13#include "internal.h" 13#include "internal.h"
14#ifdef BB_GREP
15 14
16#include <stdio.h> 15#include <stdio.h>
17#include <dirent.h> 16#include <dirent.h>
@@ -31,7 +30,76 @@ const char grep_usage[] =
31 30
32 31
33 32
34static int search (const char *string, const char *word, int ignoreCase); 33/*
34 * See if the specified word is found in the specified string.
35 */
36static int search (const char *string, const char *word, int ignoreCase)
37{
38 const char *cp1;
39 const char *cp2;
40 int len;
41 int lowFirst;
42 int ch1;
43 int ch2;
44
45 len = strlen (word);
46
47 if (!ignoreCase) {
48 while (TRUE) {
49 string = strchr (string, word[0]);
50
51 if (string == NULL)
52 return FALSE;
53
54 if (memcmp (string, word, len) == 0)
55 return TRUE;
56
57 string++;
58 }
59 }
60
61 /*
62 * Here if we need to check case independence.
63 * Do the search by lower casing both strings.
64 */
65 lowFirst = *word;
66
67 if (isupper (lowFirst))
68 lowFirst = tolower (lowFirst);
69
70 while (TRUE) {
71 while (*string && (*string != lowFirst) &&
72 (!isupper (*string) || (tolower (*string) != lowFirst))) {
73 string++;
74 }
75
76 if (*string == '\0')
77 return FALSE;
78
79 cp1 = string;
80 cp2 = word;
81
82 do {
83 if (*cp2 == '\0')
84 return TRUE;
85
86 ch1 = *cp1++;
87
88 if (isupper (ch1))
89 ch1 = tolower (ch1);
90
91 ch2 = *cp2++;
92
93 if (isupper (ch2))
94 ch2 = tolower (ch2);
95
96 }
97 while (ch1 == ch2);
98
99 string++;
100 }
101 return (TRUE);
102}
35 103
36 104
37extern int grep_main (int argc, char **argv) 105extern int grep_main (int argc, char **argv)
@@ -122,76 +190,6 @@ extern int grep_main (int argc, char **argv)
122} 190}
123 191
124 192
125/* 193/* END CODE */
126 * See if the specified word is found in the specified string.
127 */
128static int search (const char *string, const char *word, int ignoreCase)
129{
130 const char *cp1;
131 const char *cp2;
132 int len;
133 int lowFirst;
134 int ch1;
135 int ch2;
136
137 len = strlen (word);
138
139 if (!ignoreCase) {
140 while (TRUE) {
141 string = strchr (string, word[0]);
142
143 if (string == NULL)
144 return FALSE;
145
146 if (memcmp (string, word, len) == 0)
147 return TRUE;
148
149 string++;
150 }
151 }
152
153 /*
154 * Here if we need to check case independence.
155 * Do the search by lower casing both strings.
156 */
157 lowFirst = *word;
158
159 if (isupper (lowFirst))
160 lowFirst = tolower (lowFirst);
161
162 while (TRUE) {
163 while (*string && (*string != lowFirst) &&
164 (!isupper (*string) || (tolower (*string) != lowFirst))) {
165 string++;
166 }
167
168 if (*string == '\0')
169 return FALSE;
170
171 cp1 = string;
172 cp2 = word;
173
174 do {
175 if (*cp2 == '\0')
176 return TRUE;
177
178 ch1 = *cp1++;
179
180 if (isupper (ch1))
181 ch1 = tolower (ch1);
182
183 ch2 = *cp2++;
184
185 if (isupper (ch2))
186 ch2 = tolower (ch2);
187
188 }
189 while (ch1 == ch2);
190 194
191 string++;
192 }
193 return (TRUE);
194}
195 195
196#endif
197/* END CODE */
diff --git a/grep.c b/grep.c
index 52ef6c0fe..657bb2570 100644
--- a/grep.c
+++ b/grep.c
@@ -11,7 +11,6 @@
11 */ 11 */
12 12
13#include "internal.h" 13#include "internal.h"
14#ifdef BB_GREP
15 14
16#include <stdio.h> 15#include <stdio.h>
17#include <dirent.h> 16#include <dirent.h>
@@ -31,7 +30,76 @@ const char grep_usage[] =
31 30
32 31
33 32
34static int search (const char *string, const char *word, int ignoreCase); 33/*
34 * See if the specified word is found in the specified string.
35 */
36static int search (const char *string, const char *word, int ignoreCase)
37{
38 const char *cp1;
39 const char *cp2;
40 int len;
41 int lowFirst;
42 int ch1;
43 int ch2;
44
45 len = strlen (word);
46
47 if (!ignoreCase) {
48 while (TRUE) {
49 string = strchr (string, word[0]);
50
51 if (string == NULL)
52 return FALSE;
53
54 if (memcmp (string, word, len) == 0)
55 return TRUE;
56
57 string++;
58 }
59 }
60
61 /*
62 * Here if we need to check case independence.
63 * Do the search by lower casing both strings.
64 */
65 lowFirst = *word;
66
67 if (isupper (lowFirst))
68 lowFirst = tolower (lowFirst);
69
70 while (TRUE) {
71 while (*string && (*string != lowFirst) &&
72 (!isupper (*string) || (tolower (*string) != lowFirst))) {
73 string++;
74 }
75
76 if (*string == '\0')
77 return FALSE;
78
79 cp1 = string;
80 cp2 = word;
81
82 do {
83 if (*cp2 == '\0')
84 return TRUE;
85
86 ch1 = *cp1++;
87
88 if (isupper (ch1))
89 ch1 = tolower (ch1);
90
91 ch2 = *cp2++;
92
93 if (isupper (ch2))
94 ch2 = tolower (ch2);
95
96 }
97 while (ch1 == ch2);
98
99 string++;
100 }
101 return (TRUE);
102}
35 103
36 104
37extern int grep_main (int argc, char **argv) 105extern int grep_main (int argc, char **argv)
@@ -122,76 +190,6 @@ extern int grep_main (int argc, char **argv)
122} 190}
123 191
124 192
125/* 193/* END CODE */
126 * See if the specified word is found in the specified string.
127 */
128static int search (const char *string, const char *word, int ignoreCase)
129{
130 const char *cp1;
131 const char *cp2;
132 int len;
133 int lowFirst;
134 int ch1;
135 int ch2;
136
137 len = strlen (word);
138
139 if (!ignoreCase) {
140 while (TRUE) {
141 string = strchr (string, word[0]);
142
143 if (string == NULL)
144 return FALSE;
145
146 if (memcmp (string, word, len) == 0)
147 return TRUE;
148
149 string++;
150 }
151 }
152
153 /*
154 * Here if we need to check case independence.
155 * Do the search by lower casing both strings.
156 */
157 lowFirst = *word;
158
159 if (isupper (lowFirst))
160 lowFirst = tolower (lowFirst);
161
162 while (TRUE) {
163 while (*string && (*string != lowFirst) &&
164 (!isupper (*string) || (tolower (*string) != lowFirst))) {
165 string++;
166 }
167
168 if (*string == '\0')
169 return FALSE;
170
171 cp1 = string;
172 cp2 = word;
173
174 do {
175 if (*cp2 == '\0')
176 return TRUE;
177
178 ch1 = *cp1++;
179
180 if (isupper (ch1))
181 ch1 = tolower (ch1);
182
183 ch2 = *cp2++;
184
185 if (isupper (ch2))
186 ch2 = tolower (ch2);
187
188 }
189 while (ch1 == ch2);
190 194
191 string++;
192 }
193 return (TRUE);
194}
195 195
196#endif
197/* END CODE */
diff --git a/init/reboot.c b/init/reboot.c
index 0388fbce7..f915205ea 100644
--- a/init/reboot.c
+++ b/init/reboot.c
@@ -1,12 +1,8 @@
1#include "internal.h" 1#include "internal.h"
2#include <signal.h> 2#include <signal.h>
3 3
4const char reboot_usage[] = "reboot\n"
5"\n\t"
6"\treboot the system.\n";
7
8extern int 4extern int
9reboot_main(struct FileInfo * i, int argc, char * * argv) 5reboot_main(int argc, char ** argv)
10{ 6{
11 return kill(1, SIGUSR2); 7 exit( kill(1, SIGUSR2));
12} 8}
diff --git a/kill.c b/kill.c
index da025fafc..58dc8a986 100644
--- a/kill.c
+++ b/kill.c
@@ -4,137 +4,134 @@
4#include <unistd.h> 4#include <unistd.h>
5#include <signal.h> 5#include <signal.h>
6 6
7const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n"; 7const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n";
8 8
9struct signal_name { 9struct signal_name {
10 const char * name; 10 const char *name;
11 int number; 11 int number;
12}; 12};
13 13
14const struct signal_name signames[] = { 14const struct signal_name signames[] = {
15 { "HUP", SIGHUP }, 15 {"HUP", SIGHUP},
16 { "INT", SIGINT }, 16 {"INT", SIGINT},
17 { "QUIT", SIGQUIT }, 17 {"QUIT", SIGQUIT},
18 { "ILL", SIGILL }, 18 {"ILL", SIGILL},
19 { "TRAP", SIGTRAP }, 19 {"TRAP", SIGTRAP},
20 { "ABRT", SIGABRT }, 20 {"ABRT", SIGABRT},
21#ifndef __alpha__ 21#ifndef __alpha__
22 { "IOT", SIGIOT }, 22 {"IOT", SIGIOT},
23#endif 23#endif
24#if defined(sparc) || defined(__alpha__) 24#if defined(sparc) || defined(__alpha__)
25 { "EMT", SIGEMT }, 25 {"EMT", SIGEMT},
26#else 26#else
27 { "BUS", SIGBUS }, 27 {"BUS", SIGBUS},
28#endif 28#endif
29 { "FPE", SIGFPE }, 29 {"FPE", SIGFPE},
30 { "KILL", SIGKILL }, 30 {"KILL", SIGKILL},
31#if defined(sparc) || defined(__alpha__) 31#if defined(sparc) || defined(__alpha__)
32 { "BUS", SIGBUS }, 32 {"BUS", SIGBUS},
33#else 33#else
34 { "USR1", SIGUSR1 }, 34 {"USR1", SIGUSR1},
35#endif 35#endif
36 { "SEGV", SIGSEGV }, 36 {"SEGV", SIGSEGV},
37#if defined(sparc) || defined(__alpha__) 37#if defined(sparc) || defined(__alpha__)
38 { "SYS", SIGSYS }, 38 {"SYS", SIGSYS},
39#else 39#else
40 { "USR2", SIGUSR2 }, 40 {"USR2", SIGUSR2},
41#endif 41#endif
42 { "PIPE", SIGPIPE }, 42 {"PIPE", SIGPIPE},
43 { "ALRM", SIGALRM }, 43 {"ALRM", SIGALRM},
44 { "TERM", SIGTERM }, 44 {"TERM", SIGTERM},
45#if defined(sparc) || defined(__alpha__) 45#if defined(sparc) || defined(__alpha__)
46 { "URG", SIGURG }, 46 {"URG", SIGURG},
47 { "STOP", SIGSTOP }, 47 {"STOP", SIGSTOP},
48 { "TSTP", SIGTSTP }, 48 {"TSTP", SIGTSTP},
49 { "CONT", SIGCONT }, 49 {"CONT", SIGCONT},
50 { "CHLD", SIGCHLD }, 50 {"CHLD", SIGCHLD},
51 { "TTIN", SIGTTIN }, 51 {"TTIN", SIGTTIN},
52 { "TTOU", SIGTTOU }, 52 {"TTOU", SIGTTOU},
53 { "IO", SIGIO }, 53 {"IO", SIGIO},
54# ifndef __alpha__ 54# ifndef __alpha__
55 { "POLL", SIGIO }, 55 {"POLL", SIGIO},
56# endif 56# endif
57 { "XCPU", SIGXCPU }, 57 {"XCPU", SIGXCPU},
58 { "XFSZ", SIGXFSZ }, 58 {"XFSZ", SIGXFSZ},
59 { "VTALRM", SIGVTALRM }, 59 {"VTALRM", SIGVTALRM},
60 { "PROF", SIGPROF }, 60 {"PROF", SIGPROF},
61 { "WINCH", SIGWINCH }, 61 {"WINCH", SIGWINCH},
62# ifdef __alpha__ 62# ifdef __alpha__
63 { "INFO", SIGINFO }, 63 {"INFO", SIGINFO},
64# else 64# else
65 { "LOST", SIGLOST }, 65 {"LOST", SIGLOST},
66# endif 66# endif
67 { "USR1", SIGUSR1 }, 67 {"USR1", SIGUSR1},
68 { "USR2", SIGUSR2 }, 68 {"USR2", SIGUSR2},
69#else 69#else
70 { "STKFLT", SIGSTKFLT }, 70 {"STKFLT", SIGSTKFLT},
71 { "CHLD", SIGCHLD }, 71 {"CHLD", SIGCHLD},
72 { "CONT", SIGCONT }, 72 {"CONT", SIGCONT},
73 { "STOP", SIGSTOP }, 73 {"STOP", SIGSTOP},
74 { "TSTP", SIGTSTP }, 74 {"TSTP", SIGTSTP},
75 { "TTIN", SIGTTIN }, 75 {"TTIN", SIGTTIN},
76 { "TTOU", SIGTTOU }, 76 {"TTOU", SIGTTOU},
77 { "URG", SIGURG }, 77 {"URG", SIGURG},
78 { "XCPU", SIGXCPU }, 78 {"XCPU", SIGXCPU},
79 { "XFSZ", SIGXFSZ }, 79 {"XFSZ", SIGXFSZ},
80 { "VTALRM", SIGVTALRM }, 80 {"VTALRM", SIGVTALRM},
81 { "PROF", SIGPROF }, 81 {"PROF", SIGPROF},
82 { "WINCH", SIGWINCH }, 82 {"WINCH", SIGWINCH},
83 { "IO", SIGIO }, 83 {"IO", SIGIO},
84 { "POLL", SIGPOLL }, 84 {"POLL", SIGPOLL},
85 { "PWR", SIGPWR }, 85 {"PWR", SIGPWR},
86 { "UNUSED", SIGUNUSED }, 86 {"UNUSED", SIGUNUSED},
87#endif 87#endif
88 { 0, 0 } 88 {0, 0}
89}; 89};
90 90
91extern int 91extern int kill_main (int argc, char **argv)
92kill_main(struct FileInfo * i, int argc, char * * argv)
93{ 92{
94 int had_error = 0; 93 int had_error = 0;
95 int sig = SIGTERM; 94 int sig = SIGTERM;
96 if ( argv[1][0] == '-' ) {
97 if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
98 sig = atoi(&argv[1][1]);
99 if ( sig < 0 || sig >= NSIG ) {
100 usage(kill_usage);
101 exit(-1);
102 }
103 }
104 else {
105 const struct signal_name * s = signames;
106 for ( ; ; ) {
107 if ( strcmp(s->name, &argv[1][1]) == 0 ) {
108 sig = s->number;
109 break;
110 }
111 s++;
112 if ( s->name == 0 ) {
113 usage(kill_usage);
114 exit(-1);
115 }
116 }
117 }
118 argv++;
119 argc--;
120 95
121 } 96
122 while ( argc > 1 ) { 97
123 int pid; 98 if (argv[1][0] == '-') {
124 if ( argv[1][0] < '0' || argv[1][0] > '9' ) { 99 if (argv[1][1] >= '0' && argv[1][1] <= '9') {
125 usage(kill_usage); 100 sig = atoi (&argv[1][1]);
126 exit(-1); 101 if (sig < 0 || sig >= NSIG)
127 } 102 goto end;
128 pid = atoi(argv[1]); 103 } else {
129 if ( kill(pid, sig) != 0 ) { 104 const struct signal_name *s = signames;
130 had_error = 1; 105 for (;;) {
131 perror(argv[1]); 106 if (strcmp (s->name, &argv[1][1]) == 0) {
107 sig = s->number;
108 break;
132 } 109 }
133 argv++; 110 s++;
134 argc--; 111 if (s->name == 0)
112 goto end;
113 }
114 }
115 argv++;
116 argc--;
117
118 }
119 while (argc > 1) {
120 int pid;
121 if (argv[1][0] < '0' || argv[1][0] > '9')
122 goto end;
123 pid = atoi (argv[1]);
124 if (kill (pid, sig) != 0) {
125 had_error = 1;
126 perror (argv[1]);
135 } 127 }
136 if ( had_error ) 128 argv++;
137 return -1; 129 argc--;
138 else 130 }
139 return 0; 131 if (had_error) {
132end:
133 fprintf(stderr, "Usage: %s\n", kill_usage);
134 exit ( FALSE);
135 }
136 exit (TRUE);
140} 137}
diff --git a/miscutils/dutmp.c b/miscutils/dutmp.c
index e92b6700f..2dad7d4a5 100644
--- a/miscutils/dutmp.c
+++ b/miscutils/dutmp.c
@@ -9,39 +9,44 @@
9 * 9 *
10 * made against libc6 10 * made against libc6
11 */ 11 */
12 12
13#include "internal.h" 13#include "internal.h"
14#include <stdio.h> 14#include <stdio.h>
15#include <utmp.h> 15#include <utmp.h>
16 16
17const char dutmp_usage[] = "dutmp\n" 17const char dutmp_usage[] = "dutmp\n"
18"\n" 18 "\n"
19"\tDump file or stdin utmp file format to stdout, pipe delimited.\n" 19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20"\tdutmp /var/run/utmp\n"; 20 "\tdutmp /var/run/utmp\n";
21 21
22extern int 22extern int dutmp_fn (int argc, char **argv)
23dutmp_fn(const struct FileInfo * i)
24{ 23{
25 24
26FILE * f = stdin; 25 FILE *f = stdin;
27struct utmp * ut = (struct utmp *) malloc(sizeof(struct utmp) ); 26 struct utmp ut;
28 27
29 if ( i ) 28 if ((argc < 2) || (**(argv + 1) == '-')) {
30 if (! (f = fopen(i->source, "r"))) { 29 fprintf (stderr, "Usage: %s %s\n", *argv, dutmp_usage);
31 name_and_error(i->source); 30 exit (FALSE);
32 return 1; 31 }
33 } 32
34 33 if ( **(++argv) == 0 ) {
35 while (fread (ut, 1, sizeof(struct utmp), f)) { 34 f = fopen (*(++argv), "r");
36 //printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n", 35 if (f < 0 ) {
37 printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n", 36 perror (*argv);
38 ut->ut_type, ut->ut_pid, ut->ut_line, 37 exit (FALSE);
39 ut->ut_id, ut->ut_user, ut->ut_host, 38 }
40 ut->ut_exit.e_termination, ut->ut_exit.e_exit, 39 }
41 ut->ut_session, 40
42 ut->ut_tv.tv_sec, ut->ut_tv.tv_usec, 41 while (fread (&ut, 1, sizeof (struct utmp), f)) {
43 ut->ut_addr); 42 // printf("%d:%d:%s:%s:%s:%s:%d:%d:%ld:%ld:%ld:%x\n",
44 } 43 printf ("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n",
45 44 ut.ut_type, ut.ut_pid, ut.ut_line,
46return 0; 45 ut.ut_id, ut.ut_user, ut.ut_host,
46 ut.ut_exit.e_termination, ut.ut_exit.e_exit,
47 ut.ut_session,
48 ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, ut.ut_addr);
49 }
50
51 exit (TRUE);
47} 52}
diff --git a/more.c b/more.c
index 6ac553e6b..f89387436 100644
--- a/more.c
+++ b/more.c
@@ -19,27 +19,48 @@
19 * 19 *
20 */ 20 */
21 21
22
23/* Turning this off makes things a bit smaller (and less pretty) */
24#define BB_MORE_TERM
25
26
27
22#include "internal.h" 28#include "internal.h"
23#include <stdio.h> 29#include <stdio.h>
24#include <signal.h> 30#include <signal.h>
25 31
32
26const char more_usage[] = "[file ...]"; 33const char more_usage[] = "[file ...]";
27 34
28//#define ERASE_STUFF 35
36#ifdef BB_MORE_TERM
37 #include <termios.h>
38 #include <signal.h>
39 #include <sys/ioctl.h>
40
41 FILE *cin;
42 struct termios initial_settings, new_settings;
43
44 void gotsig(int sig) {
45 tcsetattr(fileno(cin), TCSANOW, &initial_settings);
46 exit( TRUE);
47 }
48#endif
29 49
30extern int more_main(int argc, char **argv) 50extern int more_main(int argc, char **argv)
31{ 51{
32 int c, lines=0; 52 int c, lines=0, input;
33 int next_page=0, rows = 24; 53 int next_page=0, rows = 24;
34#ifdef ERASE_STUFF 54#ifdef BB_MORE_TERM
35 int cols=79; 55 int cols;
56 struct winsize win;
36#endif 57#endif
37 struct stat st; 58 struct stat st;
38 FILE *file = stdin; 59 FILE *file = stdin;
39 60
40 if ( strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0 ) { 61 if ( strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0 ) {
41 fprintf(stderr, "Usage: %s %s", *argv, more_usage); 62 fprintf(stderr, "Usage: %s %s", *argv, more_usage);
42 return(FALSE); 63 exit(FALSE);
43 } 64 }
44 argc--; 65 argc--;
45 argv++; 66 argv++;
@@ -48,23 +69,47 @@ extern int more_main(int argc, char **argv)
48 file = fopen(*argv, "r"); 69 file = fopen(*argv, "r");
49 if (file == NULL) { 70 if (file == NULL) {
50 perror("Can't open file"); 71 perror("Can't open file");
51 return(FALSE); 72 exit(FALSE);
52 } 73 }
53 fstat(fileno(file), &st); 74 fstat(fileno(file), &st);
54 fprintf(stderr, "hi\n"); 75 fprintf(stderr, "hi\n");
55 76
77#ifdef BB_MORE_TERM
78 cin = fopen("/dev/tty", "r");
79 tcgetattr(fileno(cin),&initial_settings);
80 new_settings = initial_settings;
81 new_settings.c_lflag &= ~ICANON;
82 new_settings.c_lflag &= ~ECHO;
83 tcsetattr(fileno(cin), TCSANOW, &new_settings);
84
85 (void) signal(SIGINT, gotsig);
86
87 ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
88 if (win.ws_row > 4) rows = win.ws_row - 2;
89 if (win.ws_col > 0) cols = win.ws_col - 1;
90
91
92#endif
56 while ((c = getc(file)) != EOF) { 93 while ((c = getc(file)) != EOF) {
57 if ( next_page ) { 94 if ( next_page ) {
58 int len=0; 95 int len=0;
59 next_page = 0; 96 next_page = 0;
60 lines=0; 97 lines=0;
61 len = fprintf(stdout, "--More-- (%d%% of %ld bytes)", 98 len = fprintf(stdout, "--More-- (%d%% of %ld bytes)%s",
62 (int) (100*( (double) ftell(file) / (double) st.st_size )), 99 (int) (100*( (double) ftell(file) / (double) st.st_size )),
63 st.st_size); 100 st.st_size,
101#ifdef BB_MORE_TERM
102 ""
103#else
104 "\n"
105#endif
106 );
107
64 fflush(stdout); 108 fflush(stdout);
65 getc( stdin); 109 input = getc( stdin);
66#ifdef ERASE_STUFF 110
67 /* Try to erase the "More" message */ 111#ifdef BB_MORE_TERM
112 /* Erase the "More" message */
68 while(len-- > 0) 113 while(len-- > 0)
69 putc('\b', stdout); 114 putc('\b', stdout);
70 while(len++ < cols) 115 while(len++ < cols)
@@ -73,7 +118,12 @@ extern int more_main(int argc, char **argv)
73 putc('\b', stdout); 118 putc('\b', stdout);
74 fflush(stdout); 119 fflush(stdout);
75#endif 120#endif
121
76 } 122 }
123 if (input=='q')
124 goto end;
125 if (input==' ' && c == '\n' )
126 next_page = 1;
77 if ( c == '\n' && ++lines == (rows + 1) ) 127 if ( c == '\n' && ++lines == (rows + 1) )
78 next_page = 1; 128 next_page = 1;
79 putc(c, stdout); 129 putc(c, stdout);
@@ -84,7 +134,10 @@ extern int more_main(int argc, char **argv)
84 argc--; 134 argc--;
85 argv++; 135 argv++;
86 } 136 }
87 return(TRUE); 137end:
138#ifdef BB_MORE_TERM
139 gotsig(0);
140#endif
141 exit(TRUE);
88} 142}
89 143
90
diff --git a/procps/kill.c b/procps/kill.c
index da025fafc..58dc8a986 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -4,137 +4,134 @@
4#include <unistd.h> 4#include <unistd.h>
5#include <signal.h> 5#include <signal.h>
6 6
7const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n"; 7const char kill_usage[] = "kill [-signal] process-id [process-id ...]\n";
8 8
9struct signal_name { 9struct signal_name {
10 const char * name; 10 const char *name;
11 int number; 11 int number;
12}; 12};
13 13
14const struct signal_name signames[] = { 14const struct signal_name signames[] = {
15 { "HUP", SIGHUP }, 15 {"HUP", SIGHUP},
16 { "INT", SIGINT }, 16 {"INT", SIGINT},
17 { "QUIT", SIGQUIT }, 17 {"QUIT", SIGQUIT},
18 { "ILL", SIGILL }, 18 {"ILL", SIGILL},
19 { "TRAP", SIGTRAP }, 19 {"TRAP", SIGTRAP},
20 { "ABRT", SIGABRT }, 20 {"ABRT", SIGABRT},
21#ifndef __alpha__ 21#ifndef __alpha__
22 { "IOT", SIGIOT }, 22 {"IOT", SIGIOT},
23#endif 23#endif
24#if defined(sparc) || defined(__alpha__) 24#if defined(sparc) || defined(__alpha__)
25 { "EMT", SIGEMT }, 25 {"EMT", SIGEMT},
26#else 26#else
27 { "BUS", SIGBUS }, 27 {"BUS", SIGBUS},
28#endif 28#endif
29 { "FPE", SIGFPE }, 29 {"FPE", SIGFPE},
30 { "KILL", SIGKILL }, 30 {"KILL", SIGKILL},
31#if defined(sparc) || defined(__alpha__) 31#if defined(sparc) || defined(__alpha__)
32 { "BUS", SIGBUS }, 32 {"BUS", SIGBUS},
33#else 33#else
34 { "USR1", SIGUSR1 }, 34 {"USR1", SIGUSR1},
35#endif 35#endif
36 { "SEGV", SIGSEGV }, 36 {"SEGV", SIGSEGV},
37#if defined(sparc) || defined(__alpha__) 37#if defined(sparc) || defined(__alpha__)
38 { "SYS", SIGSYS }, 38 {"SYS", SIGSYS},
39#else 39#else
40 { "USR2", SIGUSR2 }, 40 {"USR2", SIGUSR2},
41#endif 41#endif
42 { "PIPE", SIGPIPE }, 42 {"PIPE", SIGPIPE},
43 { "ALRM", SIGALRM }, 43 {"ALRM", SIGALRM},
44 { "TERM", SIGTERM }, 44 {"TERM", SIGTERM},
45#if defined(sparc) || defined(__alpha__) 45#if defined(sparc) || defined(__alpha__)
46 { "URG", SIGURG }, 46 {"URG", SIGURG},
47 { "STOP", SIGSTOP }, 47 {"STOP", SIGSTOP},
48 { "TSTP", SIGTSTP }, 48 {"TSTP", SIGTSTP},
49 { "CONT", SIGCONT }, 49 {"CONT", SIGCONT},
50 { "CHLD", SIGCHLD }, 50 {"CHLD", SIGCHLD},
51 { "TTIN", SIGTTIN }, 51 {"TTIN", SIGTTIN},
52 { "TTOU", SIGTTOU }, 52 {"TTOU", SIGTTOU},
53 { "IO", SIGIO }, 53 {"IO", SIGIO},
54# ifndef __alpha__ 54# ifndef __alpha__
55 { "POLL", SIGIO }, 55 {"POLL", SIGIO},
56# endif 56# endif
57 { "XCPU", SIGXCPU }, 57 {"XCPU", SIGXCPU},
58 { "XFSZ", SIGXFSZ }, 58 {"XFSZ", SIGXFSZ},
59 { "VTALRM", SIGVTALRM }, 59 {"VTALRM", SIGVTALRM},
60 { "PROF", SIGPROF }, 60 {"PROF", SIGPROF},
61 { "WINCH", SIGWINCH }, 61 {"WINCH", SIGWINCH},
62# ifdef __alpha__ 62# ifdef __alpha__
63 { "INFO", SIGINFO }, 63 {"INFO", SIGINFO},
64# else 64# else
65 { "LOST", SIGLOST }, 65 {"LOST", SIGLOST},
66# endif 66# endif
67 { "USR1", SIGUSR1 }, 67 {"USR1", SIGUSR1},
68 { "USR2", SIGUSR2 }, 68 {"USR2", SIGUSR2},
69#else 69#else
70 { "STKFLT", SIGSTKFLT }, 70 {"STKFLT", SIGSTKFLT},
71 { "CHLD", SIGCHLD }, 71 {"CHLD", SIGCHLD},
72 { "CONT", SIGCONT }, 72 {"CONT", SIGCONT},
73 { "STOP", SIGSTOP }, 73 {"STOP", SIGSTOP},
74 { "TSTP", SIGTSTP }, 74 {"TSTP", SIGTSTP},
75 { "TTIN", SIGTTIN }, 75 {"TTIN", SIGTTIN},
76 { "TTOU", SIGTTOU }, 76 {"TTOU", SIGTTOU},
77 { "URG", SIGURG }, 77 {"URG", SIGURG},
78 { "XCPU", SIGXCPU }, 78 {"XCPU", SIGXCPU},
79 { "XFSZ", SIGXFSZ }, 79 {"XFSZ", SIGXFSZ},
80 { "VTALRM", SIGVTALRM }, 80 {"VTALRM", SIGVTALRM},
81 { "PROF", SIGPROF }, 81 {"PROF", SIGPROF},
82 { "WINCH", SIGWINCH }, 82 {"WINCH", SIGWINCH},
83 { "IO", SIGIO }, 83 {"IO", SIGIO},
84 { "POLL", SIGPOLL }, 84 {"POLL", SIGPOLL},
85 { "PWR", SIGPWR }, 85 {"PWR", SIGPWR},
86 { "UNUSED", SIGUNUSED }, 86 {"UNUSED", SIGUNUSED},
87#endif 87#endif
88 { 0, 0 } 88 {0, 0}
89}; 89};
90 90
91extern int 91extern int kill_main (int argc, char **argv)
92kill_main(struct FileInfo * i, int argc, char * * argv)
93{ 92{
94 int had_error = 0; 93 int had_error = 0;
95 int sig = SIGTERM; 94 int sig = SIGTERM;
96 if ( argv[1][0] == '-' ) {
97 if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
98 sig = atoi(&argv[1][1]);
99 if ( sig < 0 || sig >= NSIG ) {
100 usage(kill_usage);
101 exit(-1);
102 }
103 }
104 else {
105 const struct signal_name * s = signames;
106 for ( ; ; ) {
107 if ( strcmp(s->name, &argv[1][1]) == 0 ) {
108 sig = s->number;
109 break;
110 }
111 s++;
112 if ( s->name == 0 ) {
113 usage(kill_usage);
114 exit(-1);
115 }
116 }
117 }
118 argv++;
119 argc--;
120 95
121 } 96
122 while ( argc > 1 ) { 97
123 int pid; 98 if (argv[1][0] == '-') {
124 if ( argv[1][0] < '0' || argv[1][0] > '9' ) { 99 if (argv[1][1] >= '0' && argv[1][1] <= '9') {
125 usage(kill_usage); 100 sig = atoi (&argv[1][1]);
126 exit(-1); 101 if (sig < 0 || sig >= NSIG)
127 } 102 goto end;
128 pid = atoi(argv[1]); 103 } else {
129 if ( kill(pid, sig) != 0 ) { 104 const struct signal_name *s = signames;
130 had_error = 1; 105 for (;;) {
131 perror(argv[1]); 106 if (strcmp (s->name, &argv[1][1]) == 0) {
107 sig = s->number;
108 break;
132 } 109 }
133 argv++; 110 s++;
134 argc--; 111 if (s->name == 0)
112 goto end;
113 }
114 }
115 argv++;
116 argc--;
117
118 }
119 while (argc > 1) {
120 int pid;
121 if (argv[1][0] < '0' || argv[1][0] > '9')
122 goto end;
123 pid = atoi (argv[1]);
124 if (kill (pid, sig) != 0) {
125 had_error = 1;
126 perror (argv[1]);
135 } 127 }
136 if ( had_error ) 128 argv++;
137 return -1; 129 argc--;
138 else 130 }
139 return 0; 131 if (had_error) {
132end:
133 fprintf(stderr, "Usage: %s\n", kill_usage);
134 exit ( FALSE);
135 }
136 exit (TRUE);
140} 137}
diff --git a/pwd.c b/pwd.c
index 893ed1e15..2ad019d50 100644
--- a/pwd.c
+++ b/pwd.c
@@ -1,12 +1,13 @@
1#include "internal.h" 1#include "internal.h"
2#include <stdio.h> 2#include <stdio.h>
3#include <dirent.h>
3 4
4const char pwd_usage[] = "Print the current directory.\n"; 5const char pwd_usage[] = "Print the current directory.\n";
5 6
6extern int 7extern int
7pwd_main(int argc, char * * argv) 8pwd_main(int argc, char * * argv)
8{ 9{
9 char buf[1024]; 10 char buf[NAME_MAX];
10 11
11 if ( getcwd(buf, sizeof(buf)) == NULL ) { 12 if ( getcwd(buf, sizeof(buf)) == NULL ) {
12 perror("get working directory"); 13 perror("get working directory");
diff --git a/reboot.c b/reboot.c
index 0388fbce7..f915205ea 100644
--- a/reboot.c
+++ b/reboot.c
@@ -1,12 +1,8 @@
1#include "internal.h" 1#include "internal.h"
2#include <signal.h> 2#include <signal.h>
3 3
4const char reboot_usage[] = "reboot\n"
5"\n\t"
6"\treboot the system.\n";
7
8extern int 4extern int
9reboot_main(struct FileInfo * i, int argc, char * * argv) 5reboot_main(int argc, char ** argv)
10{ 6{
11 return kill(1, SIGUSR2); 7 exit( kill(1, SIGUSR2));
12} 8}
diff --git a/sleep.c b/sleep.c
index e48e14b2f..53fe5a0c2 100644
--- a/sleep.c
+++ b/sleep.c
@@ -1,15 +1,20 @@
1#include "internal.h" 1#include "internal.h"
2#include <stdio.h> 2#include <stdio.h>
3 3
4const char sleep_usage[] = "sleep seconds\n" 4const char sleep_usage[] = " NUMBER\n"
5"\n" 5"Pause for NUMBER seconds.\n";
6"\tPause program execution for the given number of seconds.\n";
7 6
8extern int 7extern int
9sleep_main(struct FileInfo * i, int argc, char * * argv) 8sleep_main(int argc, char * * argv)
10{ 9{
11 if ( sleep(atoi(argv[1])) != 0 ) 10 if ( (argc < 2) || (**(argv+1) == '-') ) {
12 return -1; 11 fprintf(stderr, "Usage: %s %s", *argv, sleep_usage);
13 else 12 exit(FALSE);
14 return 0; 13 }
14
15 if ( sleep(atoi(*(++argv))) != 0 ) {
16 perror( "sleep");
17 exit (FALSE);
18 } else
19 exit (TRUE);
15} 20}
diff --git a/tar.c b/tar.c
index 1a9f84217..a5a0fab64 100644
--- a/tar.c
+++ b/tar.c
@@ -7,7 +7,7 @@
7 * This allows creation, extraction, and listing of tar files. 7 * This allows creation, extraction, and listing of tar files.
8 * 8 *
9 * Permission to distribute this code under the GPL has been granted. 9 * Permission to distribute this code under the GPL has been granted.
10 * Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com> 10 * Modified for busybox by Erik Andersen <andersee@debian.org>
11 */ 11 */
12 12
13 13
@@ -15,11 +15,11 @@
15 15
16#ifdef BB_TAR 16#ifdef BB_TAR
17 17
18const char tar_usage[] = 18const char tar_usage[] =
19"Create, extract, or list files from a TAR file\n\n" 19 "Create, extract, or list files from a TAR file\n\n"
20"usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" 20 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n"
21"\tc=create, x=extract, t=list contents, v=verbose,\n" 21 "\tc=create, x=extract, t=list contents, v=verbose,\n"
22"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; 22 "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
23 23
24 24
25 25
@@ -42,24 +42,23 @@ const char tar_usage[] =
42 * This structure is always embedded in a TAR_BLOCK_SIZE sized block 42 * This structure is always embedded in a TAR_BLOCK_SIZE sized block
43 * with zero padding. We only process this information minimally. 43 * with zero padding. We only process this information minimally.
44 */ 44 */
45typedef struct 45typedef struct {
46{ 46 char name[TAR_NAME_SIZE];
47 char name[TAR_NAME_SIZE]; 47 char mode[8];
48 char mode[8]; 48 char uid[8];
49 char uid[8]; 49 char gid[8];
50 char gid[8]; 50 char size[12];
51 char size[12]; 51 char mtime[12];
52 char mtime[12]; 52 char checkSum[8];
53 char checkSum[8]; 53 char typeFlag;
54 char typeFlag; 54 char linkName[TAR_NAME_SIZE];
55 char linkName[TAR_NAME_SIZE]; 55 char magic[6];
56 char magic[6]; 56 char version[2];
57 char version[2]; 57 char uname[32];
58 char uname[32]; 58 char gname[32];
59 char gname[32]; 59 char devMajor[8];
60 char devMajor[8]; 60 char devMinor[8];
61 char devMinor[8]; 61 char prefix[155];
62 char prefix[155];
63} TarHeader; 62} TarHeader;
64 63
65#define TAR_MAGIC "ustar" 64#define TAR_MAGIC "ustar"
@@ -73,168 +72,162 @@ typedef struct
73/* 72/*
74 * Static data. 73 * Static data.
75 */ 74 */
76static int listFlag; 75static int listFlag;
77static int extractFlag; 76static int extractFlag;
78static int createFlag; 77static int createFlag;
79static int verboseFlag; 78static int verboseFlag;
80static int tostdoutFlag; 79static int tostdoutFlag;
81 80
82static int inHeader; 81static int inHeader;
83static int badHeader; 82static int badHeader;
84static int errorFlag; 83static int errorFlag;
85static int skipFileFlag; 84static int skipFileFlag;
86static int warnedRoot; 85static int warnedRoot;
87static int eofFlag; 86static int eofFlag;
88static long dataCc; 87static long dataCc;
89static int outFd; 88static int outFd;
90static char outName[TAR_NAME_SIZE]; 89static char outName[TAR_NAME_SIZE];
91 90
92 91
93/* 92/*
94 * Static data associated with the tar file. 93 * Static data associated with the tar file.
95 */ 94 */
96static const char * tarName; 95static const char *tarName;
97static int tarFd; 96static int tarFd;
98static dev_t tarDev; 97static dev_t tarDev;
99static ino_t tarInode; 98static ino_t tarInode;
100 99
101 100
102/* 101/*
103 * Local procedures to restore files from a tar file. 102 * Local procedures to restore files from a tar file.
104 */ 103 */
105static void readTarFile(int fileCount, char ** fileTable); 104static void readTarFile (int fileCount, char **fileTable);
106static void readData(const char * cp, int count); 105static void readData (const char *cp, int count);
107static void createPath(const char * name, int mode); 106static void createPath (const char *name, int mode);
108static long getOctal(const char * cp, int len); 107static long getOctal (const char *cp, int len);
109 108
110static void readHeader(const TarHeader * hp, 109static void readHeader (const TarHeader * hp,
111 int fileCount, char ** fileTable); 110 int fileCount, char **fileTable);
112 111
113 112
114/* 113/*
115 * Local procedures to save files into a tar file. 114 * Local procedures to save files into a tar file.
116 */ 115 */
117static void saveFile(const char * fileName, int seeLinks); 116static void saveFile (const char *fileName, int seeLinks);
118 117
119static void saveRegularFile(const char * fileName, 118static void saveRegularFile (const char *fileName,
120 const struct stat * statbuf); 119 const struct stat *statbuf);
121 120
122static void saveDirectory(const char * fileName, 121static void saveDirectory (const char *fileName,
123 const struct stat * statbuf); 122 const struct stat *statbuf);
124 123
125static int wantFileName(const char * fileName, 124static int wantFileName (const char *fileName,
126 int fileCount, char ** fileTable); 125 int fileCount, char **fileTable);
127 126
128static void writeHeader(const char * fileName, 127static void writeHeader (const char *fileName, const struct stat *statbuf);
129 const struct stat * statbuf);
130 128
131static void writeTarFile(int fileCount, char ** fileTable); 129static void writeTarFile (int fileCount, char **fileTable);
132static void writeTarBlock(const char * buf, int len); 130static void writeTarBlock (const char *buf, int len);
133static int putOctal(char * cp, int len, long value); 131static int putOctal (char *cp, int len, long value);
134 132
135 133
136extern int 134extern int tar_main (int argc, char **argv)
137tar_main(int argc, char ** argv)
138{ 135{
139 const char * options; 136 const char *options;
140 137
141 argc--; 138 argc--;
142 argv++; 139 argv++;
143 140
144 if (argc < 1) 141 if (argc < 1) {
145 { 142 fprintf (stderr, "%s", tar_usage);
146 fprintf(stderr, "%s", tar_usage); 143 exit (FALSE);
147 return 1; 144 }
148 } 145
149 146
150 147 errorFlag = FALSE;
151 errorFlag = FALSE; 148 extractFlag = FALSE;
152 extractFlag = FALSE; 149 createFlag = FALSE;
153 createFlag = FALSE; 150 listFlag = FALSE;
154 listFlag = FALSE; 151 verboseFlag = FALSE;
155 verboseFlag = FALSE; 152 tostdoutFlag = FALSE;
156 tostdoutFlag = FALSE; 153 tarName = NULL;
157 tarName = NULL; 154 tarDev = 0;
158 tarDev = 0; 155 tarInode = 0;
159 tarInode = 0; 156 tarFd = -1;
160 tarFd = -1; 157
161 158 /*
162 /* 159 * Parse the options.
163 * Parse the options. 160 */
164 */ 161 options = *argv++;
165 options = *argv++; 162 argc--;
166 argc--; 163
167 164 if (**argv == '-') {
168 if (**argv == '-') { 165 for (; *options; options++) {
169 for (; *options; options++) 166 switch (*options) {
170 { 167 case 'f':
171 switch (*options) 168 if (tarName != NULL) {
172 { 169 fprintf (stderr, "Only one 'f' option allowed\n");
173 case 'f': 170
174 if (tarName != NULL) 171 exit (FALSE);
175 { 172 }
176 fprintf(stderr, "Only one 'f' option allowed\n");
177
178 return 1;
179 }
180
181 tarName = *argv++;
182 argc--;
183
184 break;
185 173
186 case 't': 174 tarName = *argv++;
187 listFlag = TRUE; 175 argc--;
188 break;
189 176
190 case 'x': 177 break;
191 extractFlag = TRUE;
192 break;
193 178
194 case 'c': 179 case 't':
195 createFlag = TRUE; 180 listFlag = TRUE;
196 break; 181 break;
197 182
198 case 'v': 183 case 'x':
199 verboseFlag = TRUE; 184 extractFlag = TRUE;
200 break; 185 break;
201 186
202 case 'O': 187 case 'c':
203 tostdoutFlag = TRUE; 188 createFlag = TRUE;
204 break; 189 break;
205 190
206 case '-': 191 case 'v':
207 break; 192 verboseFlag = TRUE;
193 break;
208 194
209 default: 195 case 'O':
210 fprintf(stderr, "Unknown tar flag '%c'\n", *options); 196 tostdoutFlag = TRUE;
197 break;
211 198
212 return 1; 199 case '-':
213 } 200 break;
214 }
215 }
216 201
217 /* 202 default:
218 * Validate the options. 203 fprintf (stderr, "Unknown tar flag '%c'\n", *options);
219 */
220 if (extractFlag + listFlag + createFlag != 1)
221 {
222 fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n");
223 204
224 return 1; 205 exit (FALSE);
206 }
225 } 207 }
226 208 }
227 /* 209
228 * Do the correct type of action supplying the rest of the 210 /*
229 * command line arguments as the list of files to process. 211 * Validate the options.
230 */ 212 */
231 if (createFlag) 213 if (extractFlag + listFlag + createFlag != 1) {
232 writeTarFile(argc, argv); 214 fprintf (stderr,
233 else 215 "Exactly one of 'c', 'x' or 't' must be specified\n");
234 readTarFile(argc, argv); 216
235 if (errorFlag) 217 exit (FALSE);
236 fprintf(stderr, "\n"); 218 }
237 return( errorFlag); 219
220 /*
221 * Do the correct type of action supplying the rest of the
222 * command line arguments as the list of files to process.
223 */
224 if (createFlag)
225 writeTarFile (argc, argv);
226 else
227 readTarFile (argc, argv);
228 if (errorFlag)
229 fprintf (stderr, "\n");
230 exit (errorFlag);
238} 231}
239 232
240 233
@@ -242,128 +235,119 @@ tar_main(int argc, char ** argv)
242 * Read a tar file and extract or list the specified files within it. 235 * Read a tar file and extract or list the specified files within it.
243 * If the list is empty than all files are extracted or listed. 236 * If the list is empty than all files are extracted or listed.
244 */ 237 */
245static void 238static void readTarFile (int fileCount, char **fileTable)
246readTarFile(int fileCount, char ** fileTable)
247{ 239{
248 const char * cp; 240 const char *cp;
249 int cc; 241 int cc;
250 int inCc; 242 int inCc;
251 int blockSize; 243 int blockSize;
252 char buf[BUF_SIZE]; 244 char buf[BUF_SIZE];
253 245
254 skipFileFlag = FALSE; 246 skipFileFlag = FALSE;
255 badHeader = FALSE; 247 badHeader = FALSE;
256 warnedRoot = FALSE; 248 warnedRoot = FALSE;
257 eofFlag = FALSE; 249 eofFlag = FALSE;
258 inHeader = TRUE; 250 inHeader = TRUE;
259 inCc = 0; 251 inCc = 0;
260 dataCc = 0; 252 dataCc = 0;
261 outFd = -1; 253 outFd = -1;
262 blockSize = sizeof(buf); 254 blockSize = sizeof (buf);
263 cp = buf; 255 cp = buf;
264 256
265 /* 257 /*
266 * Open the tar file for reading. 258 * Open the tar file for reading.
259 */
260 if ((tarName == NULL) || !strcmp (tarName, "-")) {
261 tarFd = STDIN;
262 } else
263 tarFd = open (tarName, O_RDONLY);
264
265 if (tarFd < 0) {
266 perror (tarName);
267 errorFlag = TRUE;
268 return;
269 }
270
271 /*
272 * Read blocks from the file until an end of file header block
273 * has been seen. (A real end of file from a read is an error.)
274 */
275 while (!eofFlag) {
276 /*
277 * Read the next block of data if necessary.
278 * This will be a large block if possible, which we will
279 * then process in the small tar blocks.
267 */ 280 */
268 if ( (tarName==NULL) || !strcmp( tarName, "-") ) { 281 if (inCc <= 0) {
269 tarFd = STDIN; 282 cp = buf;
270 } 283 inCc = fullRead (tarFd, buf, blockSize);
271 else
272 tarFd = open(tarName, O_RDONLY);
273 284
274 if (tarFd < 0) 285 if (inCc < 0) {
275 { 286 perror (tarName);
276 perror(tarName);
277 errorFlag = TRUE; 287 errorFlag = TRUE;
278 return; 288 goto done;
289 }
290
291 if (inCc == 0) {
292 fprintf (stderr,
293 "Unexpected end of file from \"%s\"", tarName);
294 errorFlag = TRUE;
295 goto done;
296 }
279 } 297 }
280 298
281 /* 299 /*
282 * Read blocks from the file until an end of file header block 300 * If we are expecting a header block then examine it.
283 * has been seen. (A real end of file from a read is an error.)
284 */ 301 */
285 while (!eofFlag) 302 if (inHeader) {
286 { 303 readHeader ((const TarHeader *) cp, fileCount, fileTable);
287 /*
288 * Read the next block of data if necessary.
289 * This will be a large block if possible, which we will
290 * then process in the small tar blocks.
291 */
292 if (inCc <= 0)
293 {
294 cp = buf;
295 inCc = fullRead(tarFd, buf, blockSize);
296
297 if (inCc < 0)
298 {
299 perror(tarName);
300 errorFlag=TRUE;
301 goto done;
302 }
303
304 if (inCc == 0)
305 {
306 fprintf(stderr,
307 "Unexpected end of file from \"%s\"",
308 tarName);
309 errorFlag=TRUE;
310 goto done;
311 }
312 }
313 304
314 /* 305 cp += TAR_BLOCK_SIZE;
315 * If we are expecting a header block then examine it. 306 inCc -= TAR_BLOCK_SIZE;
316 */
317 if (inHeader)
318 {
319 readHeader((const TarHeader *) cp, fileCount, fileTable);
320 307
321 cp += TAR_BLOCK_SIZE; 308 continue;
322 inCc -= TAR_BLOCK_SIZE;
323
324 continue;
325 }
326
327 /*
328 * We are currently handling the data for a file.
329 * Process the minimum of the amount of data we have available
330 * and the amount left to be processed for the file.
331 */
332 cc = inCc;
333
334 if (cc > dataCc)
335 cc = dataCc;
336
337 readData(cp, cc);
338
339 /*
340 * If the amount left isn't an exact multiple of the tar block
341 * size then round it up to the next block boundary since there
342 * is padding at the end of the file.
343 */
344 if (cc % TAR_BLOCK_SIZE)
345 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
346
347 cp += cc;
348 inCc -= cc;
349 } 309 }
350 310
351done: 311 /*
352 /* 312 * We are currently handling the data for a file.
353 * Close the tar file if needed. 313 * Process the minimum of the amount of data we have available
314 * and the amount left to be processed for the file.
354 */ 315 */
355 if ((tarFd >= 0) && (close(tarFd) < 0)) 316 cc = inCc;
356 perror(tarName); 317
318 if (cc > dataCc)
319 cc = dataCc;
357 320
358 /* 321 readData (cp, cc);
359 * Close the output file if needed. 322
360 * This is only done here on a previous error and so no 323 /*
361 * message is required on errors. 324 * If the amount left isn't an exact multiple of the tar block
325 * size then round it up to the next block boundary since there
326 * is padding at the end of the file.
362 */ 327 */
363 if (tostdoutFlag==FALSE) { 328 if (cc % TAR_BLOCK_SIZE)
364 if (outFd >= 0) 329 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
365 (void) close(outFd); 330
366 } 331 cp += cc;
332 inCc -= cc;
333 }
334
335 done:
336 /*
337 * Close the tar file if needed.
338 */
339 if ((tarFd >= 0) && (close (tarFd) < 0))
340 perror (tarName);
341
342 /*
343 * Close the output file if needed.
344 * This is only done here on a previous error and so no
345 * message is required on errors.
346 */
347 if (tostdoutFlag == FALSE) {
348 if (outFd >= 0)
349 (void) close (outFd);
350 }
367} 351}
368 352
369 353
@@ -373,332 +357,307 @@ done:
373 * the end of the tar file. 357 * the end of the tar file.
374 */ 358 */
375static void 359static void
376readHeader(const TarHeader * hp, int fileCount, char ** fileTable) 360readHeader (const TarHeader * hp, int fileCount, char **fileTable)
377{ 361{
378 int mode; 362 int mode;
379 int uid; 363 int uid;
380 int gid; 364 int gid;
381 int checkSum; 365 int checkSum;
382 long size; 366 long size;
383 time_t mtime; 367 time_t mtime;
384 const char * name; 368 const char *name;
385 int cc; 369 int cc;
386 int hardLink; 370 int hardLink;
387 int softLink; 371 int softLink;
388 372
389 /* 373 /*
390 * If the block is completely empty, then this is the end of the 374 * If the block is completely empty, then this is the end of the
391 * archive file. If the name is null, then just skip this header. 375 * archive file. If the name is null, then just skip this header.
392 */ 376 */
393 name = hp->name; 377 name = hp->name;
394 378
395 if (*name == '\0') 379 if (*name == '\0') {
396 { 380 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
397 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) 381 if (*name++)
398 {
399 if (*name++)
400 return;
401 }
402
403 eofFlag = TRUE;
404
405 return; 382 return;
406 } 383 }
407 384
408 /* 385 eofFlag = TRUE;
409 * There is another file in the archive to examine.
410 * Extract the encoded information and check it.
411 */
412 mode = getOctal(hp->mode, sizeof(hp->mode));
413 uid = getOctal(hp->uid, sizeof(hp->uid));
414 gid = getOctal(hp->gid, sizeof(hp->gid));
415 size = getOctal(hp->size, sizeof(hp->size));
416 mtime = getOctal(hp->mtime, sizeof(hp->mtime));
417 checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum));
418 386
419 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) 387 return;
420 { 388 }
421 if (!badHeader)
422 fprintf(stderr, "Bad tar header, skipping\n");
423 389
424 badHeader = TRUE; 390 /*
391 * There is another file in the archive to examine.
392 * Extract the encoded information and check it.
393 */
394 mode = getOctal (hp->mode, sizeof (hp->mode));
395 uid = getOctal (hp->uid, sizeof (hp->uid));
396 gid = getOctal (hp->gid, sizeof (hp->gid));
397 size = getOctal (hp->size, sizeof (hp->size));
398 mtime = getOctal (hp->mtime, sizeof (hp->mtime));
399 checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum));
425 400
426 return; 401 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
427 } 402 if (!badHeader)
403 fprintf (stderr, "Bad tar header, skipping\n");
428 404
429 badHeader = FALSE; 405 badHeader = TRUE;
430 skipFileFlag = FALSE;
431 406
432 /* 407 return;
433 * Check for the file modes. 408 }
434 */ 409
435 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) || 410 badHeader = FALSE;
411 skipFileFlag = FALSE;
412
413 /*
414 * Check for the file modes.
415 */
416 hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
436 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0')); 417 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
437 418
438 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) || 419 softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
439 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0')); 420 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
440 421
441 /* 422 /*
442 * Check for a directory or a regular file. 423 * Check for a directory or a regular file.
443 */ 424 */
444 if (name[strlen(name) - 1] == '/') 425 if (name[strlen (name) - 1] == '/')
445 mode |= S_IFDIR; 426 mode |= S_IFDIR;
446 else if ((mode & S_IFMT) == 0) 427 else if ((mode & S_IFMT) == 0)
447 mode |= S_IFREG; 428 mode |= S_IFREG;
448 429
449 /* 430 /*
450 * Check for absolute paths in the file. 431 * Check for absolute paths in the file.
451 * If we find any, then warn the user and make them relative. 432 * If we find any, then warn the user and make them relative.
452 */ 433 */
453 if (*name == '/') 434 if (*name == '/') {
454 { 435 while (*name == '/')
455 while (*name == '/') 436 name++;
456 name++; 437
457 438 if (!warnedRoot) {
458 if (!warnedRoot) 439 fprintf (stderr,
459 { 440 "Absolute path detected, removing leading slashes\n");
460 fprintf(stderr,
461 "Absolute path detected, removing leading slashes\n");
462 }
463
464 warnedRoot = TRUE;
465 } 441 }
466 442
467 /* 443 warnedRoot = TRUE;
468 * See if we want this file to be restored. 444 }
469 * If not, then set up to skip it. 445
470 */ 446 /*
471 if (!wantFileName(name, fileCount, fileTable)) 447 * See if we want this file to be restored.
472 { 448 * If not, then set up to skip it.
473 if (!hardLink && !softLink && S_ISREG(mode)) 449 */
474 { 450 if (!wantFileName (name, fileCount, fileTable)) {
475 inHeader = (size == 0); 451 if (!hardLink && !softLink && S_ISREG (mode)) {
476 dataCc = size; 452 inHeader = (size == 0);
477 } 453 dataCc = size;
478
479 skipFileFlag = TRUE;
480
481 return;
482 } 454 }
483 455
484 /* 456 skipFileFlag = TRUE;
485 * This file is to be handled.
486 * If we aren't extracting then just list information about the file.
487 */
488 if (!extractFlag)
489 {
490 if (verboseFlag)
491 {
492 printf("%s %3d/%-d %9ld %s %s", modeString(mode),
493 uid, gid, size, timeString(mtime), name);
494 }
495 else
496 printf("%s", name);
497
498 if (hardLink)
499 printf(" (link to \"%s\")", hp->linkName);
500 else if (softLink)
501 printf(" (symlink to \"%s\")", hp->linkName);
502 else if (S_ISREG(mode))
503 {
504 inHeader = (size == 0);
505 dataCc = size;
506 }
507
508 printf("\n");
509 457
510 return; 458 return;
511 } 459 }
512 460
513 /* 461 /*
514 * We really want to extract the file. 462 * This file is to be handled.
515 */ 463 * If we aren't extracting then just list information about the file.
516 if (verboseFlag) 464 */
517 printf("x %s\n", name); 465 if (!extractFlag) {
466 if (verboseFlag) {
467 printf ("%s %3d/%-d %9ld %s %s", modeString (mode),
468 uid, gid, size, timeString (mtime), name);
469 } else
470 printf ("%s", name);
518 471
519 if (hardLink) 472 if (hardLink)
520 { 473 printf (" (link to \"%s\")", hp->linkName);
521 if (link(hp->linkName, name) < 0) 474 else if (softLink)
522 perror(name); 475 printf (" (symlink to \"%s\")", hp->linkName);
523 476 else if (S_ISREG (mode)) {
524 return; 477 inHeader = (size == 0);
525 } 478 dataCc = size;
526
527 if (softLink)
528 {
529#ifdef S_ISLNK
530 if (symlink(hp->linkName, name) < 0)
531 perror(name);
532#else
533 fprintf(stderr, "Cannot create symbolic links\n");
534#endif
535 return;
536 } 479 }
537 480
538 /* 481 printf ("\n");
539 * If the file is a directory, then just create the path.
540 */
541 if (S_ISDIR(mode))
542 {
543 createPath(name, mode);
544 482
545 return; 483 return;
546 } 484 }
547 485
548 /* 486 /*
549 * There is a file to write. 487 * We really want to extract the file.
550 * First create the path to it if necessary with a default permission. 488 */
551 */ 489 if (verboseFlag)
552 createPath(name, 0777); 490 printf ("x %s\n", name);
553 491
554 inHeader = (size == 0); 492 if (hardLink) {
555 dataCc = size; 493 if (link (hp->linkName, name) < 0)
494 perror (name);
556 495
557 /* 496 return;
558 * Start the output file. 497 }
559 */
560 if (tostdoutFlag==TRUE)
561 outFd = STDOUT;
562 else
563 outFd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);
564
565 if (outFd < 0)
566 {
567 perror(name);
568 skipFileFlag = TRUE;
569 return;
570 }
571 498
572 /* 499 if (softLink) {
573 * If the file is empty, then that's all we need to do. 500#ifdef S_ISLNK
574 */ 501 if (symlink (hp->linkName, name) < 0)
575 if (size == 0 && tostdoutFlag == FALSE) 502 perror (name);
576 { 503#else
577 (void) close(outFd); 504 fprintf (stderr, "Cannot create symbolic links\n");
578 outFd = -1; 505#endif
579 } 506 return;
507 }
508
509 /*
510 * If the file is a directory, then just create the path.
511 */
512 if (S_ISDIR (mode)) {
513 createPath (name, mode);
514
515 return;
516 }
517
518 /*
519 * There is a file to write.
520 * First create the path to it if necessary with a default permission.
521 */
522 createPath (name, 0777);
523
524 inHeader = (size == 0);
525 dataCc = size;
526
527 /*
528 * Start the output file.
529 */
530 if (tostdoutFlag == TRUE)
531 outFd = STDOUT;
532 else
533 outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode);
534
535 if (outFd < 0) {
536 perror (name);
537 skipFileFlag = TRUE;
538 return;
539 }
540
541 /*
542 * If the file is empty, then that's all we need to do.
543 */
544 if (size == 0 && tostdoutFlag == FALSE) {
545 (void) close (outFd);
546 outFd = -1;
547 }
580} 548}
581 549
582 550
583/* 551/*
584 * Handle a data block of some specified size that was read. 552 * Handle a data block of some specified size that was read.
585 */ 553 */
586static void 554static void readData (const char *cp, int count)
587readData(const char * cp, int count)
588{ 555{
589 /* 556 /*
590 * Reduce the amount of data left in this file. 557 * Reduce the amount of data left in this file.
591 * If there is no more data left, then we need to read 558 * If there is no more data left, then we need to read
592 * the header again. 559 * the header again.
593 */ 560 */
594 dataCc -= count; 561 dataCc -= count;
595 562
596 if (dataCc <= 0) 563 if (dataCc <= 0)
597 inHeader = TRUE; 564 inHeader = TRUE;
598
599 /*
600 * If we aren't extracting files or this file is being
601 * skipped then do nothing more.
602 */
603 if (!extractFlag || skipFileFlag)
604 return;
605 565
606 /* 566 /*
607 * Write the data to the output file. 567 * If we aren't extracting files or this file is being
608 */ 568 * skipped then do nothing more.
609 if (fullWrite(outFd, cp, count) < 0) 569 */
610 { 570 if (!extractFlag || skipFileFlag)
611 perror(outName); 571 return;
612 if (tostdoutFlag==FALSE) { 572
613 (void) close(outFd); 573 /*
614 outFd = -1; 574 * Write the data to the output file.
615 } 575 */
616 skipFileFlag = TRUE; 576 if (fullWrite (outFd, cp, count) < 0) {
617 return; 577 perror (outName);
578 if (tostdoutFlag == FALSE) {
579 (void) close (outFd);
580 outFd = -1;
618 } 581 }
582 skipFileFlag = TRUE;
583 return;
584 }
585
586 /*
587 * If the write failed, close the file and disable further
588 * writes to this file.
589 */
590 if (dataCc <= 0 && tostdoutFlag == FALSE) {
591 if (close (outFd))
592 perror (outName);
619 593
620 /* 594 outFd = -1;
621 * If the write failed, close the file and disable further 595 }
622 * writes to this file.
623 */
624 if (dataCc <= 0 && tostdoutFlag==FALSE)
625 {
626 if (close(outFd))
627 perror(outName);
628
629 outFd = -1;
630 }
631} 596}
632 597
633 598
634/* 599/*
635 * Write a tar file containing the specified files. 600 * Write a tar file containing the specified files.
636 */ 601 */
637static void 602static void writeTarFile (int fileCount, char **fileTable)
638writeTarFile(int fileCount, char ** fileTable)
639{ 603{
640 struct stat statbuf; 604 struct stat statbuf;
641 605
642 /* 606 /*
643 * Make sure there is at least one file specified. 607 * Make sure there is at least one file specified.
644 */ 608 */
645 if (fileCount <= 0) 609 if (fileCount <= 0) {
646 { 610 fprintf (stderr, "No files specified to be saved\n");
647 fprintf(stderr, "No files specified to be saved\n"); 611 errorFlag = TRUE;
648 errorFlag=TRUE; 612 }
649 } 613
650 614 /*
651 /* 615 * Create the tar file for writing.
652 * Create the tar file for writing. 616 */
653 */ 617 if ((tarName == NULL) || !strcmp (tarName, "-")) {
654 if ( (tarName==NULL) || !strcmp( tarName, "-") ) { 618 tostdoutFlag = TRUE;
655 tostdoutFlag = TRUE; 619 tarFd = STDOUT;
656 tarFd = STDOUT; 620 } else
657 } 621 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
658 else 622
659 tarFd = open(tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); 623 if (tarFd < 0) {
660 624 perror (tarName);
661 if (tarFd < 0) 625 errorFlag = TRUE;
662 { 626 return;
663 perror(tarName); 627 }
664 errorFlag=TRUE; 628
665 return; 629 /*
666 } 630 * Get the device and inode of the tar file for checking later.
667 631 */
668 /* 632 if (fstat (tarFd, &statbuf) < 0) {
669 * Get the device and inode of the tar file for checking later. 633 perror (tarName);
670 */ 634 errorFlag = TRUE;
671 if (fstat(tarFd, &statbuf) < 0) 635 goto done;
672 { 636 }
673 perror(tarName); 637
674 errorFlag = TRUE; 638 tarDev = statbuf.st_dev;
675 goto done; 639 tarInode = statbuf.st_ino;
676 } 640
677 641 /*
678 tarDev = statbuf.st_dev; 642 * Append each file name into the archive file.
679 tarInode = statbuf.st_ino; 643 * Follow symbolic links for these top level file names.
680 644 */
681 /* 645 while (!errorFlag && (fileCount-- > 0)) {
682 * Append each file name into the archive file. 646 saveFile (*fileTable++, FALSE);
683 * Follow symbolic links for these top level file names. 647 }
684 */ 648
685 while (!errorFlag && (fileCount-- > 0)) 649 /*
686 { 650 * Now write an empty block of zeroes to end the archive.
687 saveFile(*fileTable++, FALSE); 651 */
688 } 652 writeTarBlock ("", 1);
689 653
690 /* 654
691 * Now write an empty block of zeroes to end the archive. 655 done:
692 */ 656 /*
693 writeTarBlock("", 1); 657 * Close the tar file and check for errors if it was opened.
694 658 */
695 659 if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0))
696done: 660 perror (tarName);
697 /*
698 * Close the tar file and check for errors if it was opened.
699 */
700 if ( (tostdoutFlag==FALSE) && (tarFd >= 0) && (close(tarFd) < 0))
701 perror(tarName);
702} 661}
703 662
704 663
@@ -709,76 +668,70 @@ done:
709 * flag indicates whether or not we want to see symbolic links as 668 * flag indicates whether or not we want to see symbolic links as
710 * they really are, instead of blindly following them. 669 * they really are, instead of blindly following them.
711 */ 670 */
712static void 671static void saveFile (const char *fileName, int seeLinks)
713saveFile(const char * fileName, int seeLinks)
714{ 672{
715 int status; 673 int status;
716 int mode; 674 int mode;
717 struct stat statbuf; 675 struct stat statbuf;
718 676
719 if (verboseFlag) 677 if (verboseFlag)
720 printf("a %s\n", fileName); 678 printf ("a %s\n", fileName);
721 679
722 /* 680 /*
723 * Check that the file name will fit in the header. 681 * Check that the file name will fit in the header.
724 */ 682 */
725 if (strlen(fileName) >= TAR_NAME_SIZE) 683 if (strlen (fileName) >= TAR_NAME_SIZE) {
726 { 684 fprintf (stderr, "%s: File name is too long\n", fileName);
727 fprintf(stderr, "%s: File name is too long\n", fileName);
728 685
729 return; 686 return;
730 } 687 }
731 688
732 /* 689 /*
733 * Find out about the file. 690 * Find out about the file.
734 */ 691 */
735#ifdef S_ISLNK 692#ifdef S_ISLNK
736 if (seeLinks) 693 if (seeLinks)
737 status = lstat(fileName, &statbuf); 694 status = lstat (fileName, &statbuf);
738 else 695 else
739#endif 696#endif
740 status = stat(fileName, &statbuf); 697 status = stat (fileName, &statbuf);
741 698
742 if (status < 0) 699 if (status < 0) {
743 { 700 perror (fileName);
744 perror(fileName);
745 701
746 return; 702 return;
747 } 703 }
748 704
749 /* 705 /*
750 * Make sure we aren't trying to save our file into itself. 706 * Make sure we aren't trying to save our file into itself.
751 */ 707 */
752 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) 708 if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
753 { 709 fprintf (stderr, "Skipping saving of archive file itself\n");
754 fprintf(stderr, "Skipping saving of archive file itself\n");
755 710
756 return; 711 return;
757 } 712 }
758 713
759 /* 714 /*
760 * Check the type of file. 715 * Check the type of file.
761 */ 716 */
762 mode = statbuf.st_mode; 717 mode = statbuf.st_mode;
763 718
764 if (S_ISDIR(mode)) 719 if (S_ISDIR (mode)) {
765 { 720 saveDirectory (fileName, &statbuf);
766 saveDirectory(fileName, &statbuf);
767 721
768 return; 722 return;
769 } 723 }
770 724
771 if (S_ISREG(mode)) 725 if (S_ISREG (mode)) {
772 { 726 saveRegularFile (fileName, &statbuf);
773 saveRegularFile(fileName, &statbuf);
774 727
775 return; 728 return;
776 } 729 }
777 730
778 /* 731 /*
779 * The file is a strange type of file, ignore it. 732 * The file is a strange type of file, ignore it.
780 */ 733 */
781 fprintf(stderr, "%s: not a directory or regular file\n", fileName); 734 fprintf (stderr, "%s: not a directory or regular file\n", fileName);
782} 735}
783 736
784 737
@@ -786,183 +739,173 @@ saveFile(const char * fileName, int seeLinks)
786 * Save a regular file to the tar file. 739 * Save a regular file to the tar file.
787 */ 740 */
788static void 741static void
789saveRegularFile(const char * fileName, const struct stat * statbuf) 742saveRegularFile (const char *fileName, const struct stat *statbuf)
790{ 743{
791 int sawEof; 744 int sawEof;
792 int fileFd; 745 int fileFd;
793 int cc; 746 int cc;
794 int dataCount; 747 int dataCount;
795 long fullDataCount; 748 long fullDataCount;
796 char data[TAR_BLOCK_SIZE * 16]; 749 char data[TAR_BLOCK_SIZE * 16];
797 750
798 /* 751 /*
799 * Open the file for reading. 752 * Open the file for reading.
753 */
754 fileFd = open (fileName, O_RDONLY);
755
756 if (fileFd < 0) {
757 perror (fileName);
758
759 return;
760 }
761
762 /*
763 * Write out the header for the file.
764 */
765 writeHeader (fileName, statbuf);
766
767 /*
768 * Write the data blocks of the file.
769 * We must be careful to write the amount of data that the stat
770 * buffer indicated, even if the file has changed size. Otherwise
771 * the tar file will be incorrect.
772 */
773 fullDataCount = statbuf->st_size;
774 sawEof = FALSE;
775
776 while (fullDataCount > 0) {
777 /*
778 * Get the amount to write this iteration which is
779 * the minumum of the amount left to write and the
780 * buffer size.
800 */ 781 */
801 fileFd = open(fileName, O_RDONLY); 782 dataCount = sizeof (data);
802
803 if (fileFd < 0)
804 {
805 perror(fileName);
806 783
807 return; 784 if (dataCount > fullDataCount)
808 } 785 dataCount = (int) fullDataCount;
809 786
810 /* 787 /*
811 * Write out the header for the file. 788 * Read the data from the file if we haven't seen the
789 * end of file yet.
812 */ 790 */
813 writeHeader(fileName, statbuf); 791 cc = 0;
814 792
815 /* 793 if (!sawEof) {
816 * Write the data blocks of the file. 794 cc = fullRead (fileFd, data, dataCount);
817 * We must be careful to write the amount of data that the stat
818 * buffer indicated, even if the file has changed size. Otherwise
819 * the tar file will be incorrect.
820 */
821 fullDataCount = statbuf->st_size;
822 sawEof = FALSE;
823
824 while (fullDataCount > 0)
825 {
826 /*
827 * Get the amount to write this iteration which is
828 * the minumum of the amount left to write and the
829 * buffer size.
830 */
831 dataCount = sizeof(data);
832
833 if (dataCount > fullDataCount)
834 dataCount = (int) fullDataCount;
835
836 /*
837 * Read the data from the file if we haven't seen the
838 * end of file yet.
839 */
840 cc = 0;
841
842 if (!sawEof)
843 {
844 cc = fullRead(fileFd, data, dataCount);
845
846 if (cc < 0)
847 {
848 perror(fileName);
849
850 (void) close(fileFd);
851 errorFlag = TRUE;
852
853 return;
854 }
855
856 /*
857 * If the file ended too soon, complain and set
858 * a flag so we will zero fill the rest of it.
859 */
860 if (cc < dataCount)
861 {
862 fprintf(stderr,
863 "%s: Short read - zero filling",
864 fileName);
865
866 sawEof = TRUE;
867 }
868 }
869 795
870 /* 796 if (cc < 0) {
871 * Zero fill the rest of the data if necessary. 797 perror (fileName);
872 */
873 if (cc < dataCount)
874 memset(data + cc, 0, dataCount - cc);
875 798
876 /* 799 (void) close (fileFd);
877 * Write the buffer to the TAR file. 800 errorFlag = TRUE;
878 */
879 writeTarBlock(data, dataCount);
880 801
881 fullDataCount -= dataCount; 802 return;
803 }
804
805 /*
806 * If the file ended too soon, complain and set
807 * a flag so we will zero fill the rest of it.
808 */
809 if (cc < dataCount) {
810 fprintf (stderr,
811 "%s: Short read - zero filling", fileName);
812
813 sawEof = TRUE;
814 }
882 } 815 }
883 816
884 /* 817 /*
885 * Close the file. 818 * Zero fill the rest of the data if necessary.
819 */
820 if (cc < dataCount)
821 memset (data + cc, 0, dataCount - cc);
822
823 /*
824 * Write the buffer to the TAR file.
886 */ 825 */
887 if ( (tostdoutFlag==FALSE) && close(fileFd) < 0) 826 writeTarBlock (data, dataCount);
888 fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno)); 827
828 fullDataCount -= dataCount;
829 }
830
831 /*
832 * Close the file.
833 */
834 if ((tostdoutFlag == FALSE) && close (fileFd) < 0)
835 fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno));
889} 836}
890 837
891 838
892/* 839/*
893 * Save a directory and all of its files to the tar file. 840 * Save a directory and all of its files to the tar file.
894 */ 841 */
895static void 842static void saveDirectory (const char *dirName, const struct stat *statbuf)
896saveDirectory(const char * dirName, const struct stat * statbuf)
897{ 843{
898 DIR * dir; 844 DIR *dir;
899 struct dirent * entry; 845 struct dirent *entry;
900 int needSlash; 846 int needSlash;
901 char fullName[PATH_LEN]; 847 char fullName[PATH_LEN];
902 848
903 /* 849 /*
904 * Construct the directory name as used in the tar file by appending 850 * Construct the directory name as used in the tar file by appending
905 * a slash character to it. 851 * a slash character to it.
906 */ 852 */
907 strcpy(fullName, dirName); 853 strcpy (fullName, dirName);
908 strcat(fullName, "/"); 854 strcat (fullName, "/");
909 855
910 /* 856 /*
911 * Write out the header for the directory entry. 857 * Write out the header for the directory entry.
912 */ 858 */
913 writeHeader(fullName, statbuf); 859 writeHeader (fullName, statbuf);
914 860
915 /* 861 /*
916 * Open the directory. 862 * Open the directory.
917 */ 863 */
918 dir = opendir(dirName); 864 dir = opendir (dirName);
919 865
920 if (dir == NULL) 866 if (dir == NULL) {
921 { 867 fprintf (stderr, "Cannot read directory \"%s\": %s\n",
922 fprintf(stderr, "Cannot read directory \"%s\": %s\n", 868 dirName, strerror (errno));
923 dirName, strerror(errno)); 869
924 870 return;
925 return; 871 }
872
873 /*
874 * See if a slash is needed.
875 */
876 needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/'));
877
878 /*
879 * Read all of the directory entries and check them,
880 * except for the current and parent directory entries.
881 */
882 while (!errorFlag && ((entry = readdir (dir)) != NULL)) {
883 if ((strcmp (entry->d_name, ".") == 0) ||
884 (strcmp (entry->d_name, "..") == 0)) {
885 continue;
926 } 886 }
927 887
928 /* 888 /*
929 * See if a slash is needed. 889 * Build the full path name to the file.
930 */ 890 */
931 needSlash = (*dirName && (dirName[strlen(dirName) - 1] != '/')); 891 strcpy (fullName, dirName);
932 892
933 /* 893 if (needSlash)
934 * Read all of the directory entries and check them, 894 strcat (fullName, "/");
935 * except for the current and parent directory entries.
936 */
937 while (!errorFlag && ((entry = readdir(dir)) != NULL))
938 {
939 if ((strcmp(entry->d_name, ".") == 0) ||
940 (strcmp(entry->d_name, "..") == 0))
941 {
942 continue;
943 }
944
945 /*
946 * Build the full path name to the file.
947 */
948 strcpy(fullName, dirName);
949 895
950 if (needSlash) 896 strcat (fullName, entry->d_name);
951 strcat(fullName, "/");
952 897
953 strcat(fullName, entry->d_name); 898 /*
954 899 * Write this file to the tar file, noticing whether or not
955 /* 900 * the file is a symbolic link.
956 * Write this file to the tar file, noticing whether or not
957 * the file is a symbolic link.
958 */
959 saveFile(fullName, TRUE);
960 }
961
962 /*
963 * All done, close the directory.
964 */ 901 */
965 closedir(dir); 902 saveFile (fullName, TRUE);
903 }
904
905 /*
906 * All done, close the directory.
907 */
908 closedir (dir);
966} 909}
967 910
968 911
@@ -970,55 +913,54 @@ saveDirectory(const char * dirName, const struct stat * statbuf)
970 * Write a tar header for the specified file name and status. 913 * Write a tar header for the specified file name and status.
971 * It is assumed that the file name fits. 914 * It is assumed that the file name fits.
972 */ 915 */
973static void 916static void writeHeader (const char *fileName, const struct stat *statbuf)
974writeHeader(const char * fileName, const struct stat * statbuf)
975{ 917{
976 long checkSum; 918 long checkSum;
977 const unsigned char * cp; 919 const unsigned char *cp;
978 int len; 920 int len;
979 TarHeader header; 921 TarHeader header;
980 922
981 /* 923 /*
982 * Zero the header block in preparation for filling it in. 924 * Zero the header block in preparation for filling it in.
983 */ 925 */
984 memset((char *) &header, 0, sizeof(header)); 926 memset ((char *) &header, 0, sizeof (header));
985 927
986 /* 928 /*
987 * Fill in the header. 929 * Fill in the header.
988 */ 930 */
989 strcpy(header.name, fileName); 931 strcpy (header.name, fileName);
990 932
991 strncpy(header.magic, TAR_MAGIC, sizeof(header.magic)); 933 strncpy (header.magic, TAR_MAGIC, sizeof (header.magic));
992 strncpy(header.version, TAR_VERSION, sizeof(header.version)); 934 strncpy (header.version, TAR_VERSION, sizeof (header.version));
993 935
994 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); 936 putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777);
995 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 937 putOctal (header.uid, sizeof (header.uid), statbuf->st_uid);
996 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); 938 putOctal (header.gid, sizeof (header.gid), statbuf->st_gid);
997 putOctal(header.size, sizeof(header.size), statbuf->st_size); 939 putOctal (header.size, sizeof (header.size), statbuf->st_size);
998 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); 940 putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime);
999 941
1000 header.typeFlag = TAR_TYPE_REGULAR; 942 header.typeFlag = TAR_TYPE_REGULAR;
1001 943
1002 /* 944 /*
1003 * Calculate and store the checksum. 945 * Calculate and store the checksum.
1004 * This is the sum of all of the bytes of the header, 946 * This is the sum of all of the bytes of the header,
1005 * with the checksum field itself treated as blanks. 947 * with the checksum field itself treated as blanks.
1006 */ 948 */
1007 memset(header.checkSum, ' ', sizeof(header.checkSum)); 949 memset (header.checkSum, ' ', sizeof (header.checkSum));
1008 950
1009 cp = (const unsigned char *) &header; 951 cp = (const unsigned char *) &header;
1010 len = sizeof(header); 952 len = sizeof (header);
1011 checkSum = 0; 953 checkSum = 0;
1012 954
1013 while (len-- > 0) 955 while (len-- > 0)
1014 checkSum += *cp++; 956 checkSum += *cp++;
1015 957
1016 putOctal(header.checkSum, sizeof(header.checkSum), checkSum); 958 putOctal (header.checkSum, sizeof (header.checkSum), checkSum);
1017 959
1018 /* 960 /*
1019 * Write the tar header. 961 * Write the tar header.
1020 */ 962 */
1021 writeTarBlock((const char *) &header, sizeof(header)); 963 writeTarBlock ((const char *) &header, sizeof (header));
1022} 964}
1023 965
1024 966
@@ -1027,59 +969,56 @@ writeHeader(const char * fileName, const struct stat * statbuf)
1027 * The data is always padded out to a multiple of TAR_BLOCK_SIZE. 969 * The data is always padded out to a multiple of TAR_BLOCK_SIZE.
1028 * The errorFlag static variable is set on an error. 970 * The errorFlag static variable is set on an error.
1029 */ 971 */
1030static void 972static void writeTarBlock (const char *buf, int len)
1031writeTarBlock(const char * buf, int len)
1032{ 973{
1033 int partialLength; 974 int partialLength;
1034 int completeLength; 975 int completeLength;
1035 char fullBlock[TAR_BLOCK_SIZE]; 976 char fullBlock[TAR_BLOCK_SIZE];
1036 977
1037 /* 978 /*
1038 * If we had a write error before, then do nothing more. 979 * If we had a write error before, then do nothing more.
1039 */ 980 */
1040 if (errorFlag) 981 if (errorFlag)
1041 return; 982 return;
1042 983
1043 /* 984 /*
1044 * Get the amount of complete and partial blocks. 985 * Get the amount of complete and partial blocks.
1045 */ 986 */
1046 partialLength = len % TAR_BLOCK_SIZE; 987 partialLength = len % TAR_BLOCK_SIZE;
1047 completeLength = len - partialLength; 988 completeLength = len - partialLength;
1048 989
1049 /* 990 /*
1050 * Write all of the complete blocks. 991 * Write all of the complete blocks.
1051 */ 992 */
1052 if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) 993 if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) {
1053 { 994 perror (tarName);
1054 perror(tarName); 995
1055 996 errorFlag = TRUE;
1056 errorFlag = TRUE; 997
1057 998 return;
1058 return; 999 }
1059 } 1000
1060 1001 /*
1061 /* 1002 * If there are no partial blocks left, we are done.
1062 * If there are no partial blocks left, we are done. 1003 */
1063 */ 1004 if (partialLength == 0)
1064 if (partialLength == 0) 1005 return;
1065 return; 1006
1066 1007 /*
1067 /* 1008 * Copy the partial data into a complete block, and pad the rest
1068 * Copy the partial data into a complete block, and pad the rest 1009 * of it with zeroes.
1069 * of it with zeroes. 1010 */
1070 */ 1011 memcpy (fullBlock, buf + completeLength, partialLength);
1071 memcpy(fullBlock, buf + completeLength, partialLength); 1012 memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength);
1072 memset(fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); 1013
1073 1014 /*
1074 /* 1015 * Write the last complete block.
1075 * Write the last complete block. 1016 */
1076 */ 1017 if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) {
1077 if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) 1018 perror (tarName);
1078 { 1019
1079 perror(tarName); 1020 errorFlag = TRUE;
1080 1021 }
1081 errorFlag = TRUE;
1082 }
1083} 1022}
1084 1023
1085 1024
@@ -1089,29 +1028,27 @@ writeTarBlock(const char * buf, int len)
1089 * while all previous ones get default protections. Errors are not reported 1028 * while all previous ones get default protections. Errors are not reported
1090 * here, as failures to restore files can be reported later. 1029 * here, as failures to restore files can be reported later.
1091 */ 1030 */
1092static void 1031static void createPath (const char *name, int mode)
1093createPath(const char * name, int mode)
1094{ 1032{
1095 char * cp; 1033 char *cp;
1096 char * cpOld; 1034 char *cpOld;
1097 char buf[TAR_NAME_SIZE]; 1035 char buf[TAR_NAME_SIZE];
1098 1036
1099 strcpy(buf, name); 1037 strcpy (buf, name);
1100 1038
1101 cp = strchr(buf, '/'); 1039 cp = strchr (buf, '/');
1102 1040
1103 while (cp) 1041 while (cp) {
1104 { 1042 cpOld = cp;
1105 cpOld = cp; 1043 cp = strchr (cp + 1, '/');
1106 cp = strchr(cp + 1, '/');
1107 1044
1108 *cpOld = '\0'; 1045 *cpOld = '\0';
1109 1046
1110 if (mkdir(buf, cp ? 0777 : mode) == 0) 1047 if (mkdir (buf, cp ? 0777 : mode) == 0)
1111 printf("Directory \"%s\" created\n", buf); 1048 printf ("Directory \"%s\" created\n", buf);
1112 1049
1113 *cpOld = '/'; 1050 *cpOld = '/';
1114 } 1051 }
1115} 1052}
1116 1053
1117 1054
@@ -1120,38 +1057,34 @@ createPath(const char * name, int mode)
1120 * spaces on both sides of the number and with an optional null character 1057 * spaces on both sides of the number and with an optional null character
1121 * at the end. Returns -1 on an illegal format. 1058 * at the end. Returns -1 on an illegal format.
1122 */ 1059 */
1123static long 1060static long getOctal (const char *cp, int len)
1124getOctal(const char * cp, int len)
1125{ 1061{
1126 long val; 1062 long val;
1127 1063
1128 while ((len > 0) && (*cp == ' ')) 1064 while ((len > 0) && (*cp == ' ')) {
1129 { 1065 cp++;
1130 cp++; 1066 len--;
1131 len--; 1067 }
1132 }
1133 1068
1134 if ((len == 0) || !isOctal(*cp)) 1069 if ((len == 0) || !isOctal (*cp))
1135 return -1; 1070 return -1;
1136 1071
1137 val = 0; 1072 val = 0;
1138 1073
1139 while ((len > 0) && isOctal(*cp)) 1074 while ((len > 0) && isOctal (*cp)) {
1140 { 1075 val = val * 8 + *cp++ - '0';
1141 val = val * 8 + *cp++ - '0'; 1076 len--;
1142 len--; 1077 }
1143 }
1144 1078
1145 while ((len > 0) && (*cp == ' ')) 1079 while ((len > 0) && (*cp == ' ')) {
1146 { 1080 cp++;
1147 cp++; 1081 len--;
1148 len--; 1082 }
1149 }
1150 1083
1151 if ((len > 0) && *cp) 1084 if ((len > 0) && *cp)
1152 return -1; 1085 return -1;
1153 1086
1154 return val; 1087 return val;
1155} 1088}
1156 1089
1157 1090
@@ -1160,50 +1093,48 @@ getOctal(const char * cp, int len)
1160 * The number is zero and space padded and possibly null padded. 1093 * The number is zero and space padded and possibly null padded.
1161 * Returns TRUE if successful. 1094 * Returns TRUE if successful.
1162 */ 1095 */
1163static int 1096static int putOctal (char *cp, int len, long value)
1164putOctal(char * cp, int len, long value)
1165{ 1097{
1166 int tempLength; 1098 int tempLength;
1167 char * tempString; 1099 char *tempString;
1168 char tempBuffer[32]; 1100 char tempBuffer[32];
1169 1101
1170 /* 1102 /*
1171 * Create a string of the specified length with an initial space, 1103 * Create a string of the specified length with an initial space,
1172 * leading zeroes and the octal number, and a trailing null. 1104 * leading zeroes and the octal number, and a trailing null.
1173 */ 1105 */
1174 tempString = tempBuffer; 1106 tempString = tempBuffer;
1175 1107
1176 sprintf(tempString, " %0*lo", len - 2, value); 1108 sprintf (tempString, " %0*lo", len - 2, value);
1177 1109
1178 tempLength = strlen(tempString) + 1; 1110 tempLength = strlen (tempString) + 1;
1179 1111
1180 /* 1112 /*
1181 * If the string is too large, suppress the leading space. 1113 * If the string is too large, suppress the leading space.
1182 */ 1114 */
1183 if (tempLength > len) 1115 if (tempLength > len) {
1184 { 1116 tempLength--;
1185 tempLength--; 1117 tempString++;
1186 tempString++; 1118 }
1187 } 1119
1188 1120 /*
1189 /* 1121 * If the string is still too large, suppress the trailing null.
1190 * If the string is still too large, suppress the trailing null. 1122 */
1191 */ 1123 if (tempLength > len)
1192 if (tempLength > len) 1124 tempLength--;
1193 tempLength--; 1125
1126 /*
1127 * If the string is still too large, fail.
1128 */
1129 if (tempLength > len)
1130 return FALSE;
1194 1131
1195 /* 1132 /*
1196 * If the string is still too large, fail. 1133 * Copy the string to the field.
1197 */ 1134 */
1198 if (tempLength > len) 1135 memcpy (cp, tempString, len);
1199 return FALSE;
1200 1136
1201 /* 1137 return TRUE;
1202 * Copy the string to the field.
1203 */
1204 memcpy(cp, tempString, len);
1205
1206 return TRUE;
1207} 1138}
1208 1139
1209 1140
@@ -1213,48 +1144,43 @@ putOctal(char * cp, int len, long value)
1213 * Returns TRUE if the file is selected. 1144 * Returns TRUE if the file is selected.
1214 */ 1145 */
1215static int 1146static int
1216wantFileName(const char * fileName, int fileCount, char ** fileTable) 1147wantFileName (const char *fileName, int fileCount, char **fileTable)
1217{ 1148{
1218 const char * pathName; 1149 const char *pathName;
1219 int fileLength; 1150 int fileLength;
1220 int pathLength; 1151 int pathLength;
1221 1152
1222 /* 1153 /*
1223 * If there are no files in the list, then the file is wanted. 1154 * If there are no files in the list, then the file is wanted.
1224 */ 1155 */
1225 if (fileCount == 0) 1156 if (fileCount == 0)
1226 return TRUE; 1157 return TRUE;
1227 1158
1228 fileLength = strlen(fileName); 1159 fileLength = strlen (fileName);
1229 1160
1230 /* 1161 /*
1231 * Check each of the test paths. 1162 * Check each of the test paths.
1232 */ 1163 */
1233 while (fileCount-- > 0) 1164 while (fileCount-- > 0) {
1234 { 1165 pathName = *fileTable++;
1235 pathName = *fileTable++;
1236 1166
1237 pathLength = strlen(pathName); 1167 pathLength = strlen (pathName);
1238 1168
1239 if (fileLength < pathLength) 1169 if (fileLength < pathLength)
1240 continue; 1170 continue;
1241 1171
1242 if (memcmp(fileName, pathName, pathLength) != 0) 1172 if (memcmp (fileName, pathName, pathLength) != 0)
1243 continue; 1173 continue;
1244 1174
1245 if ((fileLength == pathLength) || 1175 if ((fileLength == pathLength) || (fileName[pathLength] == '/')) {
1246 (fileName[pathLength] == '/')) 1176 return TRUE;
1247 {
1248 return TRUE;
1249 }
1250 } 1177 }
1178 }
1251 1179
1252 return FALSE; 1180 return FALSE;
1253} 1181}
1254 1182
1255 1183
1256 1184
1257#endif 1185#endif
1258/* END CODE */ 1186/* END CODE */
1259
1260
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index 9096621b0..64265b473 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -14,7 +14,6 @@
14 14
15#include <linux/unistd.h> 15#include <linux/unistd.h>
16#include <stdio.h> 16#include <stdio.h>
17#include <getopt.h>
18 17
19#define __NR_klog __NR_syslog 18#define __NR_klog __NR_syslog
20 19
@@ -22,74 +21,78 @@
22#include <sys/klog.h> 21#include <sys/klog.h>
23#define klog klogctl 22#define klog klogctl
24#else 23#else
25static inline _syscall3(int,klog,int,type,char *,b,int,len) 24static inline _syscall3 (int, klog, int, type, char *, b, int, len)
26#endif /* __GLIBC__ */ 25#endif /* __GLIBC__ */
27 26
28const char dmesg_usage[] = "dmesg";
29 27
30int 28
31dmesg_main(int argc, char * * argv) 29static const char dmesg_usage[] = "dmesg [-c] [-n level]\n";
30
31int dmesg_main (int argc, char **argv)
32{ 32{
33 33
34 char buf[4096]; 34 char buf[4096];
35 int i; 35 int i;
36 int n; 36 int n;
37 int c; 37 int level = 0;
38 int level = 0; 38 int lastc;
39 int lastc; 39 int cmd = 3;
40 int cmd = 3;
41 40
42 while ((c = getopt( argc, argv, "cn:" )) != EOF) { 41 argc--;
43 switch (c) { 42 argv++;
44 case 'c':
45 cmd = 4;
46 break;
47 case 'n':
48 cmd = 8;
49 level = atoi(optarg);
50 break;
51 case '?':
52 default:
53 fprintf(stderr, "%s\n", dmesg_usage);
54 exit(1);
55 }
56 }
57 argc -= optind;
58 argv += optind;
59
60 if (argc > 1) {
61 fprintf(stderr, "%s\n", dmesg_usage);
62 exit(1);
63 }
64 43
65 if (cmd == 8) { 44 /* Parse any options */
66 n = klog( cmd, NULL, level ); 45 while (argc && **argv == '-') {
67 if (n < 0) { 46 while (*++(*argv))
68 perror( "klog" ); 47 switch (**argv) {
69 exit( 1 ); 48 case 'c':
70 } 49 cmd = 4;
71 exit( 0 ); 50 break;
72 } 51 case 'n':
52 cmd = 8;
53 if (--argc == 0)
54 goto end;
55 level = atoi (*(++argv));
56 --argc;
57 ++argv;
58 break;
59 default:
60 goto end;
61 }
62 }
73 63
74 n = klog( cmd, buf, sizeof( buf ) ); 64 if (cmd == 8) {
75 if (n < 0) { 65 n = klog (cmd, NULL, level);
76 perror( "klog" ); 66 if (n < 0) {
77 exit( 1 ); 67 perror ("klog");
78 } 68 exit (FALSE);
69 }
70 exit (TRUE);
71 }
79 72
80 lastc = '\n'; 73 n = klog (cmd, buf, sizeof (buf));
81 for (i = 0; i < n; i++) { 74 if (n < 0) {
82 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 75 perror ("klog");
83 i++; 76 exit (FALSE);
84 while (buf[i] >= '0' && buf[i] <= '9') 77 }
85 i++; 78
86 if (buf[i] == '>') 79 lastc = '\n';
80 for (i = 0; i < n; i++) {
81 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
87 i++; 82 i++;
88 } 83 while (buf[i] >= '0' && buf[i] <= '9')
89 lastc = buf[i]; 84 i++;
90 putchar( lastc ); 85 if (buf[i] == '>')
91 } 86 i++;
92 if (lastc != '\n') 87 }
93 putchar( '\n' ); 88 lastc = buf[i];
94 return 0; 89 putchar (lastc);
90 }
91 if (lastc != '\n')
92 putchar ('\n');
93 exit (TRUE);
94
95 end:
96 fprintf (stderr, "Usage: %s\n", dmesg_usage);
97 exit (FALSE);
95} 98}
diff --git a/util-linux/more.c b/util-linux/more.c
index 6ac553e6b..f89387436 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -19,27 +19,48 @@
19 * 19 *
20 */ 20 */
21 21
22
23/* Turning this off makes things a bit smaller (and less pretty) */
24#define BB_MORE_TERM
25
26
27
22#include "internal.h" 28#include "internal.h"
23#include <stdio.h> 29#include <stdio.h>
24#include <signal.h> 30#include <signal.h>
25 31
32
26const char more_usage[] = "[file ...]"; 33const char more_usage[] = "[file ...]";
27 34
28//#define ERASE_STUFF 35
36#ifdef BB_MORE_TERM
37 #include <termios.h>
38 #include <signal.h>
39 #include <sys/ioctl.h>
40
41 FILE *cin;
42 struct termios initial_settings, new_settings;
43
44 void gotsig(int sig) {
45 tcsetattr(fileno(cin), TCSANOW, &initial_settings);
46 exit( TRUE);
47 }
48#endif
29 49
30extern int more_main(int argc, char **argv) 50extern int more_main(int argc, char **argv)
31{ 51{
32 int c, lines=0; 52 int c, lines=0, input;
33 int next_page=0, rows = 24; 53 int next_page=0, rows = 24;
34#ifdef ERASE_STUFF 54#ifdef BB_MORE_TERM
35 int cols=79; 55 int cols;
56 struct winsize win;
36#endif 57#endif
37 struct stat st; 58 struct stat st;
38 FILE *file = stdin; 59 FILE *file = stdin;
39 60
40 if ( strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0 ) { 61 if ( strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0 ) {
41 fprintf(stderr, "Usage: %s %s", *argv, more_usage); 62 fprintf(stderr, "Usage: %s %s", *argv, more_usage);
42 return(FALSE); 63 exit(FALSE);
43 } 64 }
44 argc--; 65 argc--;
45 argv++; 66 argv++;
@@ -48,23 +69,47 @@ extern int more_main(int argc, char **argv)
48 file = fopen(*argv, "r"); 69 file = fopen(*argv, "r");
49 if (file == NULL) { 70 if (file == NULL) {
50 perror("Can't open file"); 71 perror("Can't open file");
51 return(FALSE); 72 exit(FALSE);
52 } 73 }
53 fstat(fileno(file), &st); 74 fstat(fileno(file), &st);
54 fprintf(stderr, "hi\n"); 75 fprintf(stderr, "hi\n");
55 76
77#ifdef BB_MORE_TERM
78 cin = fopen("/dev/tty", "r");
79 tcgetattr(fileno(cin),&initial_settings);
80 new_settings = initial_settings;
81 new_settings.c_lflag &= ~ICANON;
82 new_settings.c_lflag &= ~ECHO;
83 tcsetattr(fileno(cin), TCSANOW, &new_settings);
84
85 (void) signal(SIGINT, gotsig);
86
87 ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
88 if (win.ws_row > 4) rows = win.ws_row - 2;
89 if (win.ws_col > 0) cols = win.ws_col - 1;
90
91
92#endif
56 while ((c = getc(file)) != EOF) { 93 while ((c = getc(file)) != EOF) {
57 if ( next_page ) { 94 if ( next_page ) {
58 int len=0; 95 int len=0;
59 next_page = 0; 96 next_page = 0;
60 lines=0; 97 lines=0;
61 len = fprintf(stdout, "--More-- (%d%% of %ld bytes)", 98 len = fprintf(stdout, "--More-- (%d%% of %ld bytes)%s",
62 (int) (100*( (double) ftell(file) / (double) st.st_size )), 99 (int) (100*( (double) ftell(file) / (double) st.st_size )),
63 st.st_size); 100 st.st_size,
101#ifdef BB_MORE_TERM
102 ""
103#else
104 "\n"
105#endif
106 );
107
64 fflush(stdout); 108 fflush(stdout);
65 getc( stdin); 109 input = getc( stdin);
66#ifdef ERASE_STUFF 110
67 /* Try to erase the "More" message */ 111#ifdef BB_MORE_TERM
112 /* Erase the "More" message */
68 while(len-- > 0) 113 while(len-- > 0)
69 putc('\b', stdout); 114 putc('\b', stdout);
70 while(len++ < cols) 115 while(len++ < cols)
@@ -73,7 +118,12 @@ extern int more_main(int argc, char **argv)
73 putc('\b', stdout); 118 putc('\b', stdout);
74 fflush(stdout); 119 fflush(stdout);
75#endif 120#endif
121
76 } 122 }
123 if (input=='q')
124 goto end;
125 if (input==' ' && c == '\n' )
126 next_page = 1;
77 if ( c == '\n' && ++lines == (rows + 1) ) 127 if ( c == '\n' && ++lines == (rows + 1) )
78 next_page = 1; 128 next_page = 1;
79 putc(c, stdout); 129 putc(c, stdout);
@@ -84,7 +134,10 @@ extern int more_main(int argc, char **argv)
84 argc--; 134 argc--;
85 argv++; 135 argv++;
86 } 136 }
87 return(TRUE); 137end:
138#ifdef BB_MORE_TERM
139 gotsig(0);
140#endif
141 exit(TRUE);
88} 142}
89 143
90