diff options
author | Rob Landley <rob@landley.net> | 2012-11-13 17:14:08 -0600 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2012-11-13 17:14:08 -0600 |
commit | 7aa651a6a4496d848f86de9b1e6b3a003256a01f (patch) | |
tree | 6995fb4b7cc2e90a6706b0239ebaf95d9dbab530 /toys | |
parent | 571b0706cce45716126776d0ad0f6ac65f4586e3 (diff) | |
download | toybox-7aa651a6a4496d848f86de9b1e6b3a003256a01f.tar.gz |
Reindent to two spaces per level. Remove vi: directives that haven't worked right in years (ubuntu broke its' vim implementation). Remove trailing spaces. Add/remove blank lines. Re-wordwrap in places. Update documentation with new coding style.
The actual code should be the same afterward, this is just cosmetic refactoring.
Diffstat (limited to 'toys')
96 files changed, 6103 insertions, 6302 deletions
diff --git a/toys/e2fs.h b/toys/e2fs.h index 13474804..43594114 100644 --- a/toys/e2fs.h +++ b/toys/e2fs.h @@ -1,6 +1,4 @@ -/* vi: set ts=4: - * - * mke2fs.h - Headers for ext2 +/* mke2fs.h - Headers for ext2 * * Copyright 2006 Rob Landley <rob@landley.net> */ @@ -10,103 +8,103 @@ #define EXT2_SUPER_MAGIC 0xEF53 struct ext2_superblock { - uint32_t inodes_count; // Inodes count - uint32_t blocks_count; // Blocks count - uint32_t r_blocks_count; // Reserved blocks count - uint32_t free_blocks_count; // Free blocks count - uint32_t free_inodes_count; // Free inodes count - uint32_t first_data_block; // First Data Block - uint32_t log_block_size; // Block size - uint32_t log_frag_size; // Fragment size - uint32_t blocks_per_group; // Blocks per group - uint32_t frags_per_group; // Fragments per group - uint32_t inodes_per_group; // Inodes per group - uint32_t mtime; // Mount time - uint32_t wtime; // Write time - uint16_t mnt_count; // Mount count - uint16_t max_mnt_count; // Maximal mount count - uint16_t magic; // Magic signature - uint16_t state; // File system state - uint16_t errors; // Behaviour when detecting errors - uint16_t minor_rev_level; // minor revision level - uint32_t lastcheck; // time of last check - uint32_t checkinterval; // max. time between checks - uint32_t creator_os; // OS - uint32_t rev_level; // Revision level - uint16_t def_resuid; // Default uid for reserved blocks - uint16_t def_resgid; // Default gid for reserved blocks - uint32_t first_ino; // First non-reserved inode - uint16_t inode_size; // size of inode structure - uint16_t block_group_nr; // block group # of this superblock - uint32_t feature_compat; // compatible feature set - uint32_t feature_incompat; // incompatible feature set - uint32_t feature_ro_compat; // readonly-compatible feature set - char uuid[16]; // 128-bit uuid for volume - char volume_name[16]; // volume name - char last_mounted[64]; // directory where last mounted - uint32_t alg_usage_bitmap; // For compression - // For EXT2_COMPAT_PREALLOC - uint8_t prealloc_blocks; // Nr of blocks to try to preallocate - uint8_t prealloc_dir_blocks; //Nr to preallocate for dirs - uint16_t padding1; - // For EXT3_FEATURE_COMPAT_HAS_JOURNAL - uint8_t journal_uuid[16]; // uuid of journal superblock - uint32_t journal_inum; // inode number of journal file - uint32_t journal_dev; // device number of journal file - uint32_t last_orphan; // start of list of inodes to delete - uint32_t hash_seed[4]; // HTREE hash seed - uint8_t def_hash_version; // Default hash version to use - uint8_t padding2[3]; - uint32_t default_mount_opts; - uint32_t first_meta_bg; // First metablock block group - uint32_t mkfs_time; // Creation timestamp - uint32_t jnl_blocks[17]; // Backup of journal inode - // uint32_t reserved[172]; // Padding to the end of the block + uint32_t inodes_count; // Inodes count + uint32_t blocks_count; // Blocks count + uint32_t r_blocks_count; // Reserved blocks count + uint32_t free_blocks_count; // Free blocks count + uint32_t free_inodes_count; // Free inodes count + uint32_t first_data_block; // First Data Block + uint32_t log_block_size; // Block size + uint32_t log_frag_size; // Fragment size + uint32_t blocks_per_group; // Blocks per group + uint32_t frags_per_group; // Fragments per group + uint32_t inodes_per_group; // Inodes per group + uint32_t mtime; // Mount time + uint32_t wtime; // Write time + uint16_t mnt_count; // Mount count + uint16_t max_mnt_count; // Maximal mount count + uint16_t magic; // Magic signature + uint16_t state; // File system state + uint16_t errors; // Behaviour when detecting errors + uint16_t minor_rev_level; // minor revision level + uint32_t lastcheck; // time of last check + uint32_t checkinterval; // max. time between checks + uint32_t creator_os; // OS + uint32_t rev_level; // Revision level + uint16_t def_resuid; // Default uid for reserved blocks + uint16_t def_resgid; // Default gid for reserved blocks + uint32_t first_ino; // First non-reserved inode + uint16_t inode_size; // size of inode structure + uint16_t block_group_nr; // block group # of this superblock + uint32_t feature_compat; // compatible feature set + uint32_t feature_incompat; // incompatible feature set + uint32_t feature_ro_compat; // readonly-compatible feature set + char uuid[16]; // 128-bit uuid for volume + char volume_name[16]; // volume name + char last_mounted[64]; // directory where last mounted + uint32_t alg_usage_bitmap; // For compression + // For EXT2_COMPAT_PREALLOC + uint8_t prealloc_blocks; // Nr of blocks to try to preallocate + uint8_t prealloc_dir_blocks; //Nr to preallocate for dirs + uint16_t padding1; + // For EXT3_FEATURE_COMPAT_HAS_JOURNAL + uint8_t journal_uuid[16]; // uuid of journal superblock + uint32_t journal_inum; // inode number of journal file + uint32_t journal_dev; // device number of journal file + uint32_t last_orphan; // start of list of inodes to delete + uint32_t hash_seed[4]; // HTREE hash seed + uint8_t def_hash_version; // Default hash version to use + uint8_t padding2[3]; + uint32_t default_mount_opts; + uint32_t first_meta_bg; // First metablock block group + uint32_t mkfs_time; // Creation timestamp + uint32_t jnl_blocks[17]; // Backup of journal inode + // uint32_t reserved[172]; // Padding to the end of the block }; struct ext2_group { - uint32_t block_bitmap; // Block number of block bitmap - uint32_t inode_bitmap; // Block number of inode bitmap - uint32_t inode_table; // Block number of inode table - uint16_t free_blocks_count; // How many free blocks in this group? - uint16_t free_inodes_count; // How many free inodes in this group? - uint16_t used_dirs_count; // How many directories? - uint16_t reserved[7]; // pad to 32 bytes + uint32_t block_bitmap; // Block number of block bitmap + uint32_t inode_bitmap; // Block number of inode bitmap + uint32_t inode_table; // Block number of inode table + uint16_t free_blocks_count; // How many free blocks in this group? + uint16_t free_inodes_count; // How many free inodes in this group? + uint16_t used_dirs_count; // How many directories? + uint16_t reserved[7]; // pad to 32 bytes }; struct ext2_dentry { - uint32_t inode; // Inode number - uint16_t rec_len; // Directory entry length - uint8_t name_len; // Name length - uint8_t file_type; - char name[0]; // File name + uint32_t inode; // Inode number + uint16_t rec_len; // Directory entry length + uint8_t name_len; // Name length + uint8_t file_type; + char name[0]; // File name }; struct ext2_inode { - uint16_t mode; // File mode - uint16_t uid; // Low 16 bits of Owner Uid - uint32_t size; // Size in bytes - uint32_t atime; // Access time - uint32_t ctime; // Creation time - uint32_t mtime; // Modification time - uint32_t dtime; // Deletion Time - uint16_t gid; // Low 16 bits of Group Id - uint16_t links_count; // Links count - uint32_t blocks; // Blocks count - uint32_t flags; // File flags - uint32_t reserved1; - uint32_t block[15]; // Pointers to blocks - uint32_t generation; // File version (for NFS) - uint32_t file_acl; // File ACL - uint32_t dir_acl; // Directory ACL (or top bits of file length) - uint32_t faddr; // Last block in file - uint8_t frag; // Fragment number - uint8_t fsize; // Fragment size - uint16_t pad1; - uint16_t uid_high; // High bits of uid - uint16_t gid_high; // High bits of gid - uint32_t reserved2; + uint16_t mode; // File mode + uint16_t uid; // Low 16 bits of Owner Uid + uint32_t size; // Size in bytes + uint32_t atime; // Access time + uint32_t ctime; // Creation time + uint32_t mtime; // Modification time + uint32_t dtime; // Deletion Time + uint16_t gid; // Low 16 bits of Group Id + uint16_t links_count; // Links count + uint32_t blocks; // Blocks count + uint32_t flags; // File flags + uint32_t reserved1; + uint32_t block[15]; // Pointers to blocks + uint32_t generation; // File version (for NFS) + uint32_t file_acl; // File ACL + uint32_t dir_acl; // Directory ACL (or top bits of file length) + uint32_t faddr; // Last block in file + uint8_t frag; // Fragment number + uint8_t fsize; // Fragment size + uint16_t pad1; + uint16_t uid_high; // High bits of uid + uint16_t gid_high; // High bits of gid + uint32_t reserved2; }; #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 @@ -132,13 +130,13 @@ struct ext2_inode { // other bits are reserved for now. enum { - EXT2_FT_UNKNOWN, - EXT2_FT_REG_FILE, - EXT2_FT_DIR, - EXT2_FT_CHRDEV, - EXT2_FT_BLKDEV, - EXT2_FT_FIFO, - EXT2_FT_SOCK, - EXT2_FT_SYMLINK, - EXT2_FT_MAX + EXT2_FT_UNKNOWN, + EXT2_FT_REG_FILE, + EXT2_FT_DIR, + EXT2_FT_CHRDEV, + EXT2_FT_BLKDEV, + EXT2_FT_FIFO, + EXT2_FT_SOCK, + EXT2_FT_SYMLINK, + EXT2_FT_MAX }; diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c index 8d73513b..10032562 100644 --- a/toys/lsb/dmesg.c +++ b/toys/lsb/dmesg.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dmesg.c - display/control kernel ring buffer. +/* dmesg.c - display/control kernel ring buffer. * * Copyright 2006, 2007 Rob Landley <rob@landley.net> * @@ -9,16 +7,16 @@ USE_DMESG(NEWTOY(dmesg, "s#n#c", TOYFLAG_BIN)) config DMESG - bool "dmesg" - default y - help - usage: dmesg [-n level] [-s bufsize] | -c + bool "dmesg" + default y + help + usage: dmesg [-n level] [-s bufsize] | -c - Print or control the kernel ring buffer. + Print or control the kernel ring buffer. - -n Set kernel logging level (1-9). - -s Size of buffer to read (in bytes), default 16384. - -c Clear the ring buffer after printing. + -n Set kernel logging level (1-9). + -s Size of buffer to read (in bytes), default 16384. + -c Clear the ring buffer after printing. */ #define FOR_dmesg @@ -26,33 +24,32 @@ config DMESG #include <sys/klog.h> GLOBALS( - long level; - long size; + long level; + long size; ) void dmesg_main(void) { - // For -n just tell kernel to which messages to keep. - if (toys.optflags & 2) { - if (klogctl(8, NULL, TT.level)) - error_exit("klogctl"); - } else { - int size, i, last = '\n'; - char *data; - - // Figure out how much data we need, and fetch it. - size = TT.size; - if (size<2) size = 16384; - data = xmalloc(size); - size = klogctl(3 + (toys.optflags&1), data, size); - if (size < 0) error_exit("klogctl"); - - // Display data, filtering out level markers. - for (i=0; i<size; ) { - if (last=='\n' && data[i]=='<') i += 3; - else xputc(last = data[i++]); - } - if (last!='\n') xputc('\n'); - if (CFG_TOYBOX_FREE) free(data); - } + // For -n just tell kernel to which messages to keep. + if (toys.optflags & 2) { + if (klogctl(8, NULL, TT.level)) error_exit("klogctl"); + } else { + int size, i, last = '\n'; + char *data; + + // Figure out how much data we need, and fetch it. + size = TT.size; + if (size<2) size = 16384; + data = xmalloc(size); + size = klogctl(3 + (toys.optflags&1), data, size); + if (size < 0) error_exit("klogctl"); + + // Display data, filtering out level markers. + for (i=0; i<size; ) { + if (last=='\n' && data[i]=='<') i += 3; + else xputc(last = data[i++]); + } + if (last!='\n') xputc('\n'); + if (CFG_TOYBOX_FREE) free(data); + } } diff --git a/toys/lsb/hostname.c b/toys/lsb/hostname.c index ca436833..23467fb3 100644 --- a/toys/lsb/hostname.c +++ b/toys/lsb/hostname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * hostname.c - Get/Set the hostname +/* hostname.c - Get/Set the hostname * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * @@ -9,12 +7,12 @@ USE_HOSTNAME(NEWTOY(hostname, NULL, TOYFLAG_BIN)) config HOSTNAME - bool "hostname" - default y - help - usage: hostname [newname] + bool "hostname" + default y + help + usage: hostname [newname] - Get/Set the current hostname + Get/Set the current hostname */ #define FOR_hostname @@ -22,13 +20,12 @@ config HOSTNAME void hostname_main(void) { - const char *hostname = toys.optargs[0]; - if (hostname) { - if (sethostname(hostname, strlen(hostname))) - perror_exit("set failed '%s'", hostname); - } else { - if (gethostname(toybuf, sizeof(toybuf))) - perror_exit("get failed"); - xputs(toybuf); - } + const char *hostname = toys.optargs[0]; + if (hostname) { + if (sethostname(hostname, strlen(hostname))) + perror_exit("set failed '%s'", hostname); + } else { + if (gethostname(toybuf, sizeof(toybuf))) perror_exit("get failed"); + xputs(toybuf); + } } diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c index ec9df62e..7883c53d 100644 --- a/toys/lsb/killall.c +++ b/toys/lsb/killall.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * killall.c - Send signal (default: TERM) to all processes with given names. +/* killall.c - Send signal (default: TERM) to all processes with given names. * * Copyright 2012 Andreas Heck <aheck@gmx.de> * @@ -9,68 +7,67 @@ USE_KILLALL(NEWTOY(killall, "<1?lq", TOYFLAG_USR|TOYFLAG_BIN)) config KILLALL - bool "killall" - default y - help - usage: killall [-l] [-q] [-SIG] PROCESS_NAME... + bool "killall" + default y + help + usage: killall [-l] [-q] [-SIG] PROCESS_NAME... - Send a signal (default: TERM) to all processes with the given names. + Send a signal (default: TERM) to all processes with the given names. - -l print list of all available signals - -q don't print any warnings or error messages + -l print list of all available signals + -q don't print any warnings or error messages */ #define FOR_killall #include "toys.h" GLOBALS( - int signum; + int signum; ) static void kill_process(pid_t pid) { - int ret; + int ret; - toys.exitval = 0; - ret = kill(pid, TT.signum); + toys.exitval = 0; + ret = kill(pid, TT.signum); - if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill"); + if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill"); } void killall_main(void) { - char **names; + char **names; - if (toys.optflags & FLAG_l) { - sig_to_num(NULL); - return; - } + if (toys.optflags & FLAG_l) { + sig_to_num(NULL); + return; + } - TT.signum = SIGTERM; - toys.exitval++; + TT.signum = SIGTERM; + toys.exitval++; - if (!*toys.optargs) { - toys.exithelp = 1; - error_exit("Process name missing!"); - } + if (!*toys.optargs) { + toys.exithelp = 1; + error_exit("Process name missing!"); + } - names = toys.optargs; + names = toys.optargs; - if (**names == '-') { - if (0 > (TT.signum = sig_to_num((*names)+1))) { - if (toys.optflags & FLAG_q) exit(1); - error_exit("Invalid signal"); - } - names++; + if (**names == '-') { + if (0 > (TT.signum = sig_to_num((*names)+1))) { + if (toys.optflags & FLAG_q) exit(1); + error_exit("Invalid signal"); + } + names++; - if (!*names) { - toys.exithelp++; - error_exit("Process name missing!"); - } - } + if (!*names) { + toys.exithelp++; + error_exit("Process name missing!"); + } + } - for_each_pid_with_name_in(names, kill_process); + for_each_pid_with_name_in(names, kill_process); - if (toys.exitval && !(toys.optflags & FLAG_q)) - error_exit("No such process"); + if (toys.exitval && !(toys.optflags & FLAG_q)) error_exit("No such process"); } diff --git a/toys/lsb/md5sum.c b/toys/lsb/md5sum.c index b0b35419..3b5571bb 100644 --- a/toys/lsb/md5sum.c +++ b/toys/lsb/md5sum.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * md5sum.c - Calculate RFC 1321 md5 hash and sha1 hash. +/* md5sum.c - Calculate RFC 1321 md5 hash and sha1 hash. * * Copyright 2012 Rob Landley <rob@landley.net> * @@ -219,8 +217,7 @@ static void do_hash(int fd, char *name) buf = 0; } while ((TT.count & 63) != 56); if (sha1) count=bswap_64(count); - for (i = 0; i < 8; i++) - TT.buffer.c[56+i] = count >> (8*i); + for (i = 0; i < 8; i++) TT.buffer.c[56+i] = count >> (8*i); transform(); if (sha1) diff --git a/toys/lsb/mknod.c b/toys/lsb/mknod.c index c1d78b10..bf9288ae 100644 --- a/toys/lsb/mknod.c +++ b/toys/lsb/mknod.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mknod.c - make block or character special file +/* mknod.c - make block or character special file * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -9,15 +7,15 @@ USE_MKNOD(NEWTOY(mknod, "<2>4", TOYFLAG_BIN)) config MKNOD - bool "mknod" - default y - help - usage: mknod NAME TYPE [MAJOR MINOR] - - Create a special file NAME with a given type, possible types are - b block device - c or u character device - p named pipe (ignores MAJOR/MINOR) + bool "mknod" + default y + help + usage: mknod NAME TYPE [MAJOR MINOR] + + Create a special file NAME with a given type, possible types are + b block device + c or u character device + p named pipe (ignores MAJOR/MINOR) */ #define FOR_mknod @@ -25,20 +23,19 @@ config MKNOD void mknod_main(void) { - mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK}; - int major=0, minor=0, type; - int mode = 0660; - - type = stridx("pcub", *toys.optargs[1]); - if (type == -1) perror_exit("bad type '%c'", *toys.optargs[1]); - if (type) { - if (toys.optc != 4) perror_exit("need major/minor"); + mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK}; + int major=0, minor=0, type; + int mode = 0660; - major = atoi(toys.optargs[2]); - minor = atoi(toys.optargs[3]); - } + type = stridx("pcub", *toys.optargs[1]); + if (type == -1) perror_exit("bad type '%c'", *toys.optargs[1]); + if (type) { + if (toys.optc != 4) perror_exit("need major/minor"); - if (mknod(toys.optargs[0], mode | modes[type], makedev(major, minor))) - perror_exit("mknod %s failed", toys.optargs[0]); + major = atoi(toys.optargs[2]); + minor = atoi(toys.optargs[3]); + } + if (mknod(toys.optargs[0], mode | modes[type], makedev(major, minor))) + perror_exit("mknod %s failed", toys.optargs[0]); } diff --git a/toys/lsb/mktemp.c b/toys/lsb/mktemp.c index 1b2222c0..86c2033e 100644 --- a/toys/lsb/mktemp.c +++ b/toys/lsb/mktemp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mktemp.c - Create a temporary file or directory. +/* mktemp.c - Create a temporary file or directory. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -9,46 +7,46 @@ USE_MKTEMP(NEWTOY(mktemp, ">1q(directory)d(tmpdir)p:", TOYFLAG_BIN)) config MKTEMP - bool "mktemp" - default y - help - usage: mktemp [-dq] [-p DIR] [TEMPLATE] + bool "mktemp" + default y + help + usage: mktemp [-dq] [-p DIR] [TEMPLATE] - Safely create new file and print its name. Default TEMPLATE is - /tmp/tmp.XXXXXX and each trailing X is replaced with random char. + Safely create new file and print its name. Default TEMPLATE is + /tmp/tmp.XXXXXX and each trailing X is replaced with random char. - -d, --directory Create directory instead of file - -p DIR, --tmpdir=DIR Put new file in DIR - -q Quiet + -d, --directory Create directory instead of file + -p DIR, --tmpdir=DIR Put new file in DIR + -q Quiet */ #define FOR_mktemp #include "toys.h" GLOBALS( - char * tmpdir; + char * tmpdir; ) void mktemp_main(void) { - int d_flag = toys.optflags & FLAG_d; - char *tmp; + int d_flag = toys.optflags & FLAG_d; + char *tmp; - tmp = *toys.optargs; + tmp = *toys.optargs; - if (!tmp) { - if (!TT.tmpdir) TT.tmpdir = "/tmp"; - tmp = "tmp.xxxxxx"; - } - if (TT.tmpdir) tmp = xmsprintf("%s/%s", TT.tmpdir ? TT.tmpdir : "/tmp", - *toys.optargs ? *toys.optargs : "tmp.XXXXXX"); + if (!tmp) { + if (!TT.tmpdir) TT.tmpdir = "/tmp"; + tmp = "tmp.xxxxxx"; + } + if (TT.tmpdir) tmp = xmsprintf("%s/%s", TT.tmpdir ? TT.tmpdir : "/tmp", + *toys.optargs ? *toys.optargs : "tmp.XXXXXX"); - if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1) - if (toys.optflags & FLAG_q) - perror_exit("Failed to create temporary %s", - d_flag ? "directory" : "file"); + if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1) + if (toys.optflags & FLAG_q) + perror_exit("Failed to create temporary %s", + d_flag ? "directory" : "file"); - xputs(tmp); + xputs(tmp); - if (CFG_TOYBOX_FREE && TT.tmpdir) free(tmp); + if (CFG_TOYBOX_FREE && TT.tmpdir) free(tmp); } diff --git a/toys/lsb/passwd.c b/toys/lsb/passwd.c index ef119c5d..ff109f14 100644 --- a/toys/lsb/passwd.c +++ b/toys/lsb/passwd.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * passwd.c - Program to upadte user password. +/* passwd.c - Program to update user password. * * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com> * Modified 2012 Jason Kyungwan Han <asura321@gmail.com> @@ -10,18 +8,17 @@ USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN)) config PASSWD - bool "passwd" - default y - help - usage: passwd [-a ALGO] [-d] [-l] [-u] <account name> - - update user’s authentication tokens. Default : current user + bool "passwd" + default y + help + usage: passwd [-a ALGO] [-d] [-l] [-u] <account name> - -a ALGO Encryption method (des, md5, sha256, sha512) default: des - -d Set password to '' - -l Lock (disable) account - -u Unlock (enable) account + update user’s authentication tokens. Default : current user + -a ALGO Encryption method (des, md5, sha256, sha512) default: des + -d Set password to '' + -l Lock (disable) account + -u Unlock (enable) account */ #define FOR_passwd @@ -29,7 +26,7 @@ config PASSWD #include <time.h> GLOBALS( - char *algo; + char *algo; ) #define MAX_SALT_LEN 20 //3 for id, 16 for key, 1 for '\0' @@ -41,227 +38,225 @@ char *strcasestr(const char *haystack, const char *needle); unsigned int random_number_generator(int fd) { - unsigned int randnum; - xreadall(fd, &randnum, sizeof(randnum)); - return randnum; + unsigned int randnum; + xreadall(fd, &randnum, sizeof(randnum)); + return randnum; } - - char inttoc(int i) { - // salt value uses 64 chracters in "./0-9a-zA-Z" - const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - i &= 0x3f; // masking for using 10 bits only - return character_set[i]; + // salt value uses 64 chracters in "./0-9a-zA-Z" + const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + i &= 0x3f; // masking for using 10 bits only + return character_set[i]; } int get_salt(char *salt) -{ - int i, salt_length = 0; - int randfd; - if(!strncmp(TT.algo,"des",3)){ - // 2 bytes salt value is used in des - salt_length = 2; - } else { - *salt++ = '$'; - if(!strncmp(TT.algo,"md5",3)){ - *salt++ = '1'; - // 8 bytes salt value is used in md5 - salt_length = 8; - } else if(!strncmp(TT.algo,"sha256",6)){ - *salt++ = '5'; - // 16 bytes salt value is used in sha256 - salt_length = 16; - } else if(!strncmp(TT.algo,"sha512",6)){ - *salt++ = '6'; - // 16 bytes salt value is used in sha512 - salt_length = 16; - } else return 1; - - *salt++ = '$'; - } - - randfd = xopen(URANDOM_PATH, O_RDONLY); - for(i=0; i<salt_length; i++) - salt[i] = inttoc(random_number_generator(randfd)); - salt[salt_length+1] = '\0'; - xclose(randfd); - - return 0; +{ + int i, salt_length = 0; + int randfd; + if(!strncmp(TT.algo,"des",3)){ + // 2 bytes salt value is used in des + salt_length = 2; + } else { + *salt++ = '$'; + if(!strncmp(TT.algo,"md5",3)){ + *salt++ = '1'; + // 8 bytes salt value is used in md5 + salt_length = 8; + } else if(!strncmp(TT.algo,"sha256",6)){ + *salt++ = '5'; + // 16 bytes salt value is used in sha256 + salt_length = 16; + } else if(!strncmp(TT.algo,"sha512",6)){ + *salt++ = '6'; + // 16 bytes salt value is used in sha512 + salt_length = 16; + } else return 1; + + *salt++ = '$'; + } + + randfd = xopen(URANDOM_PATH, O_RDONLY); + for(i=0; i<salt_length; i++) + salt[i] = inttoc(random_number_generator(randfd)); + salt[salt_length+1] = '\0'; + xclose(randfd); + + return 0; } static int str_check(char *s, char *p) { - if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL)) - return 1; - return 0; + if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL)) + return 1; + return 0; } static void strength_check(char *newp, char *oldp, char *user) { - char *msg = NULL; - if(strlen(newp) < 6) { //Min passwd len - msg = "too short"; - xprintf("BAD PASSWORD: %s\n",msg); - } - if(!newp[0]) - return; //passwd is empty - - if(str_check(newp, user)) { - msg = "user based password"; - xprintf("BAD PASSWORD: %s\n",msg); - } - - if(oldp[0] && str_check(newp, oldp)) { - msg = "based on old passwd"; - xprintf("BAD PASSWORD: %s\n",msg); - } + char *msg = NULL; + if(strlen(newp) < 6) { //Min passwd len + msg = "too short"; + xprintf("BAD PASSWORD: %s\n",msg); + } + if(!newp[0]) + return; //passwd is empty + + if(str_check(newp, user)) { + msg = "user based password"; + xprintf("BAD PASSWORD: %s\n",msg); + } + + if(oldp[0] && str_check(newp, oldp)) { + msg = "based on old passwd"; + xprintf("BAD PASSWORD: %s\n",msg); + } } static int verify_passwd(char * pwd) -{ - char * pass; +{ + char * pass; - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; - pass = crypt(toybuf, pwd); - if (pass != NULL && strcmp(pass, pwd)==0) - return 0; + pass = crypt(toybuf, pwd); + if (pass != NULL && strcmp(pass, pwd)==0) + return 0; - return 1; + return 1; } static char *new_password(char *oldp, char *user) { - char *newp = NULL; - - if(read_password(toybuf, sizeof(toybuf), "New password:")) - return NULL; //may be due to Ctrl-C + char *newp = NULL; - newp = xstrdup(toybuf); - strength_check(newp, oldp, user); - if(read_password(toybuf, sizeof(toybuf), "Retype password:")) { - free(newp); - return NULL; //may be due to Ctrl-C - } + if(read_password(toybuf, sizeof(toybuf), "New password:")) + return NULL; //may be due to Ctrl-C - if(strcmp(newp, toybuf) == 0) - return newp; - else error_msg("Passwords do not match.\n"); - /*Failure Case */ + newp = xstrdup(toybuf); + strength_check(newp, oldp, user); + if(read_password(toybuf, sizeof(toybuf), "Retype password:")) { free(newp); - return NULL; + return NULL; //may be due to Ctrl-C + } + + if(strcmp(newp, toybuf) == 0) + return newp; + else error_msg("Passwords do not match.\n"); + /*Failure Case */ + free(newp); + return NULL; } void passwd_main(void) { - uid_t myuid; - struct passwd *pw; - struct spwd *sp; - char *name = NULL; - char *pass = NULL, *encrypted = NULL, *newp = NULL; - char *orig = (char *)""; - char salt[MAX_SALT_LEN]; - int ret = -1; - - myuid = getuid(); - if((myuid != 0) && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) - error_exit("You need to be root to do these actions\n"); - - pw = getpwuid(myuid); - - if(!pw) - error_exit("Unknown uid '%u'",myuid); - - if(toys.optargs[0]) - name = toys.optargs[0]; - else - name = xstrdup(pw->pw_name); - - pw = getpwnam(name); - if(!pw) error_exit("Unknown user '%s'",name); - - if(myuid != 0 && (myuid != pw->pw_uid)) - error_exit("You need to be root to change '%s' password\n", name); - - pass = pw->pw_passwd; - if(pw->pw_passwd[0] == 'x') { - /*get shadow passwd */ - sp = getspnam(name); - if(sp) - pass = sp->sp_pwdp; + uid_t myuid; + struct passwd *pw; + struct spwd *sp; + char *name = NULL; + char *pass = NULL, *encrypted = NULL, *newp = NULL; + char *orig = (char *)""; + char salt[MAX_SALT_LEN]; + int ret = -1; + + myuid = getuid(); + if((myuid != 0) && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) + error_exit("You need to be root to do these actions\n"); + + pw = getpwuid(myuid); + + if(!pw) + error_exit("Unknown uid '%u'",myuid); + + if(toys.optargs[0]) + name = toys.optargs[0]; + else + name = xstrdup(pw->pw_name); + + pw = getpwnam(name); + if(!pw) error_exit("Unknown user '%s'",name); + + if(myuid != 0 && (myuid != pw->pw_uid)) + error_exit("You need to be root to change '%s' password\n", name); + + pass = pw->pw_passwd; + if(pw->pw_passwd[0] == 'x') { + /*get shadow passwd */ + sp = getspnam(name); + if(sp) + pass = sp->sp_pwdp; + } + + + if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { + printf("Changing password for %s\n",name); + if(pass[0] == '!') + error_exit("Can't change, password is locked for %s",name); + if(myuid != 0) { + /*Validate user */ + + if(read_password(toybuf, sizeof(toybuf), "Origial password:")) { + if(!toys.optargs[0]) free(name); + return; + } + orig = toybuf; + if(verify_passwd(pass)) + error_exit("Authentication failed\n"); } + orig = xstrdup(orig); - if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { - printf("Changing password for %s\n",name); - if(pass[0] == '!') - error_exit("Can't change, password is locked for %s",name); - if(myuid != 0) { - /*Validate user */ - - if(read_password(toybuf, sizeof(toybuf), "Origial password:")) { - if(!toys.optargs[0]) free(name); - return; - } - orig = toybuf; - if(verify_passwd(pass)) - error_exit("Authentication failed\n"); - } - - orig = xstrdup(orig); - - /*Get new password */ - newp = new_password(orig, name); - if(!newp) { - free(orig); - if(!toys.optargs[0]) free(name); - return; //new password is not set well. - } - - /*Encrypt the passwd */ - if(!(toys.optflags & FLAG_a)) TT.algo = "des"; - - if(get_salt(salt)) - error_exit("Error: Unkown encryption algorithm\n"); - - encrypted = crypt(newp, salt); - free(newp); - free(orig); + /*Get new password */ + newp = new_password(orig, name); + if(!newp) { + free(orig); + if(!toys.optargs[0]) free(name); + return; //new password is not set well. } - else if(toys.optflags & FLAG_l) { - if(pass[0] == '!') - error_exit("password is already locked for %s",name); - printf("Locking password for %s\n",name); - encrypted = xmsprintf("!%s",pass); - } - else if(toys.optflags & FLAG_u) { - if(pass[0] != '!') - error_exit("password is already unlocked for %s",name); - printf("Unlocking password for %s\n",name); - encrypted = xstrdup(&pass[1]); - } - else if(toys.optflags & FLAG_d) { - printf("Deleting password for %s\n",name); - encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0' - } + /*Encrypt the passwd */ + if(!(toys.optflags & FLAG_a)) TT.algo = "des"; - /*Update the passwd */ - if(pw->pw_passwd[0] == 'x') - ret = update_password("/etc/shadow", name, encrypted); - else - ret = update_password("/etc/passwd", name, encrypted); + if(get_salt(salt)) + error_exit("Error: Unkown encryption algorithm\n"); - if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) - free(encrypted); - - if(!toys.optargs[0]) free(name); - if(!ret) - error_msg("Success"); - else - error_msg("Failure"); + encrypted = crypt(newp, salt); + free(newp); + free(orig); + } + else if(toys.optflags & FLAG_l) { + if(pass[0] == '!') + error_exit("password is already locked for %s",name); + printf("Locking password for %s\n",name); + encrypted = xmsprintf("!%s",pass); + } + else if(toys.optflags & FLAG_u) { + if(pass[0] != '!') + error_exit("password is already unlocked for %s",name); + + printf("Unlocking password for %s\n",name); + encrypted = xstrdup(&pass[1]); + } + else if(toys.optflags & FLAG_d) { + printf("Deleting password for %s\n",name); + encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0' + } + + /*Update the passwd */ + if(pw->pw_passwd[0] == 'x') + ret = update_password("/etc/shadow", name, encrypted); + else + ret = update_password("/etc/passwd", name, encrypted); + + if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) + free(encrypted); + + if(!toys.optargs[0]) free(name); + if(!ret) + error_msg("Success"); + else + error_msg("Failure"); } diff --git a/toys/lsb/pidof.c b/toys/lsb/pidof.c index 45c398b4..03643015 100644 --- a/toys/lsb/pidof.c +++ b/toys/lsb/pidof.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * pidof.c - Print the PIDs of all processes with the given names. +/* pidof.c - Print the Process IDs of all processes with the given names. * * Copyright 2012 Andreas Heck <aheck@gmx.de> * @@ -9,24 +7,25 @@ USE_PIDOF(NEWTOY(pidof, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config PIDOF - bool "pidof" - default y - help - usage: pidof [NAME]... + bool "pidof" + default y + help + usage: pidof [NAME]... - Print the PIDs of all processes with the given names. + Print the PIDs of all processes with the given names. */ #include "toys.h" -static void print_pid(pid_t pid) { - xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid); - toys.exitval = 0; +static void print_pid(pid_t pid) +{ + xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid); + toys.exitval = 0; } void pidof_main(void) { - toys.exitval = 1; - for_each_pid_with_name_in(toys.optargs, print_pid); - if (!toys.exitval) xputc('\n'); + toys.exitval = 1; + for_each_pid_with_name_in(toys.optargs, print_pid); + if (!toys.exitval) xputc('\n'); } diff --git a/toys/lsb/seq.c b/toys/lsb/seq.c index 2f8538cf..22e45dde 100644 --- a/toys/lsb/seq.c +++ b/toys/lsb/seq.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * seq.c - Count from first to last, by increment. +/* seq.c - Count from first to last, by increment. * * Copyright 2006 Rob Landley <rob@landley.net> * @@ -9,40 +7,40 @@ USE_SEQ(NEWTOY(seq, "<1>3?", TOYFLAG_USR|TOYFLAG_BIN)) config SEQ - bool "seq" - depends on TOYBOX_FLOAT - default y - help - usage: seq [first] [increment] last + bool "seq" + depends on TOYBOX_FLOAT + default y + help + usage: seq [first] [increment] last - Count from first to last, by increment. Omitted arguments default - to 1. Two arguments are used as first and last. Arguments can be - negative or floating point. + Count from first to last, by increment. Omitted arguments default + to 1. Two arguments are used as first and last. Arguments can be + negative or floating point. */ #include "toys.h" void seq_main(void) { - double first, increment, last, dd; + double first, increment, last, dd; - // Parse command line arguments, with appropriate defaults. - // Note that any non-numeric arguments are treated as zero. - first = increment = 1; - switch (toys.optc) { - case 3: - increment = atof(toys.optargs[1]); - case 2: - first = atof(*toys.optargs); - default: - last = atof(toys.optargs[toys.optc-1]); - } + // Parse command line arguments, with appropriate defaults. + // Note that any non-numeric arguments are treated as zero. + first = increment = 1; + switch (toys.optc) { + case 3: + increment = atof(toys.optargs[1]); + case 2: + first = atof(*toys.optargs); + default: + last = atof(toys.optargs[toys.optc-1]); + } - // Yes, we're looping on a double. Yes rounding errors can accumulate if - // you use a non-integer increment. Deal with it. - for (dd=first; (increment>0 && dd<=last) || (increment <0 && dd>=last); - dd+=increment) - { - printf("%g\n", dd); - } + // Yes, we're looping on a double. Yes rounding errors can accumulate if + // you use a non-integer increment. Deal with it. + for (dd=first; (increment>0 && dd<=last) || (increment<0 && dd>=last); + dd+=increment) + { + printf("%g\n", dd); + } } diff --git a/toys/lsb/sync.c b/toys/lsb/sync.c index 0d167147..b12a8cca 100644 --- a/toys/lsb/sync.c +++ b/toys/lsb/sync.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sync.c - Write all pending data to disk. +/* sync.c - Write all pending data to disk. * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -9,17 +7,17 @@ USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN)) config SYNC - bool "sync" - default y - help - usage: sync + bool "sync" + default y + help + usage: sync - Write pending cached data to disk (synchronize), blocking until done. + Write pending cached data to disk (synchronize), blocking until done. */ #include "toys.h" void sync_main(void) { - sync(); + sync(); } diff --git a/toys/other/bzcat.c b/toys/other/bzcat.c index c0c2b96a..8266484c 100644 --- a/toys/other/bzcat.c +++ b/toys/other/bzcat.c @@ -1,28 +1,26 @@ -/* vi: set sw=4 ts=4: - * - * bzcat.c - decompress stdin to stdout using bunzip2. +/* bzcat.c - decompress stdin to stdout using bunzip2. * * Copyright 2007 Rob Landley <rob@landley.net> USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config BZCAT - bool "bzcat" - default y - help - usage: bzcat [filename...] + bool "bzcat" + default y + help + usage: bzcat [filename...] - Decompress listed files to stdout. Use stdin if no files listed. + Decompress listed files to stdout. Use stdin if no files listed. */ #include "toys.h" static void do_bzcat(int fd, char *name) { - bunzipStream(fd, 1); + bunzipStream(fd, 1); } void bzcat_main(void) { - loopfiles(toys.optargs, do_bzcat); + loopfiles(toys.optargs, do_bzcat); } diff --git a/toys/other/catv.c b/toys/other/catv.c index a0790a9b..62520c41 100644 --- a/toys/other/catv.c +++ b/toys/other/catv.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cat -v implementation for toybox +/* cat -v implementation for toybox * * Copyright (C) 2006, 2007 Rob Landley <rob@landley.net> * @@ -10,17 +8,17 @@ USE_CATV(NEWTOY(catv, "vte", TOYFLAG_USR|TOYFLAG_BIN)) config CATV - bool "catv" - default y - help - usage: catv [-evt] [filename...] + bool "catv" + default y + help + usage: catv [-evt] [filename...] - Display nonprinting characters as escape sequences. Use M-x for - high ascii characters (>127), and ^x for other nonprinting chars. + Display nonprinting characters as escape sequences. Use M-x for + high ascii characters (>127), and ^x for other nonprinting chars. - -e Mark each newline with $ - -t Show tabs as ^I - -v Don't use ^x or M-x escapes. + -e Mark each newline with $ + -t Show tabs as ^I + -v Don't use ^x or M-x escapes. */ #define FOR_catv @@ -30,40 +28,40 @@ config CATV static void do_catv(int fd, char *name) { - for(;;) { - int i, len; + for(;;) { + int i, len; - len = read(fd, toybuf, sizeof(toybuf)); - if (len < 0) toys.exitval = EXIT_FAILURE; - if (len < 1) break; - for (i=0; i<len; i++) { - char c=toybuf[i]; + len = read(fd, toybuf, sizeof(toybuf)); + if (len < 0) toys.exitval = EXIT_FAILURE; + if (len < 1) break; + for (i=0; i<len; i++) { + char c=toybuf[i]; - if (c > 126 && (toys.optflags & FLAG_v)) { - if (c > 127) { - printf("M-"); - c -= 128; - } - if (c == 127) { - printf("^?"); - continue; - } - } - if (c < 32) { - if (c == 10) { - if (toys.optflags & FLAG_e) xputc('$'); - } else if (toys.optflags & (c==9 ? FLAG_t : FLAG_v)) { - printf("^%c", c+'@'); - continue; - } - } - xputc(c); - } - } + if (c > 126 && (toys.optflags & FLAG_v)) { + if (c > 127) { + printf("M-"); + c -= 128; + } + if (c == 127) { + printf("^?"); + continue; + } + } + if (c < 32) { + if (c == 10) { + if (toys.optflags & FLAG_e) xputc('$'); + } else if (toys.optflags & (c==9 ? FLAG_t : FLAG_v)) { + printf("^%c", c+'@'); + continue; + } + } + xputc(c); + } + } } void catv_main(void) { - toys.optflags ^= FLAG_v; - loopfiles(toys.optargs, do_catv); + toys.optflags ^= FLAG_v; + loopfiles(toys.optargs, do_catv); } diff --git a/toys/other/chroot.c b/toys/other/chroot.c index 003ed072..c9ff10c7 100644 --- a/toys/other/chroot.c +++ b/toys/other/chroot.c @@ -1,26 +1,23 @@ -/* vi: set sw=4 ts=4: - * - * chroot.c - Run command in new root directory. +/* chroot.c - Run command in new root directory. * * Copyright 2007 Rob Landley <rob@landley.net> USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN)) config CHROOT - bool "chroot" - default y - help - usage: chroot NEWPATH [commandline...] + bool "chroot" + default y + help + usage: chroot NEWPATH [commandline...] - Run command within a new root directory. If no command, run /bin/sh. + Run command within a new root directory. If no command, run /bin/sh. */ #include "toys.h" void chroot_main(void) { - char *binsh[] = {"/bin/sh", "-i", 0}; - if (chdir(*toys.optargs) || chroot(".")) - perror_exit("%s", *toys.optargs); - xexec(toys.optargs[1] ? toys.optargs+1 : binsh); + char *binsh[] = {"/bin/sh", "-i", 0}; + if (chdir(*toys.optargs) || chroot(".")) perror_exit("%s", *toys.optargs); + xexec(toys.optargs[1] ? toys.optargs+1 : binsh); } diff --git a/toys/other/chvt.c b/toys/other/chvt.c index 80eeadc4..7a0119c9 100644 --- a/toys/other/chvt.c +++ b/toys/other/chvt.c @@ -1,22 +1,20 @@ -/* vi: set sw=4 ts=4: - * - * chvt.c - switch virtual terminals +/* chvt.c - switch virtual terminals * * Copyright (C) 2008 David Anders <danders@amltd.com> USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_SBIN)) config CHVT - bool "chvt" - default y - help - usage: chvt N + bool "chvt" + default y + help + usage: chvt N - Change to virtual terminal number N. (This only works in text mode.) + Change to virtual terminal number N. (This only works in text mode.) - Virtual terminals are the Linux VGA text mode displays, ordinarily - switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch - from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back. + Virtual terminals are the Linux VGA text mode displays, ordinarily + switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch + from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back. */ #include "toys.h" @@ -24,26 +22,26 @@ config CHVT /* Note: get_console_fb() will need to be moved into a seperate lib section */ int get_console_fd() { - int fd; - char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc; + int fd; + char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc; - cc = consoles; - while (*cc) { - fd = open(*cc++, O_RDWR); - if (fd >= 0) return fd; - } + cc = consoles; + while (*cc) { + fd = open(*cc++, O_RDWR); + if (fd >= 0) return fd; + } - return -1; + return -1; } void chvt_main(void) { - int vtnum, fd; + int vtnum, fd; - vtnum=atoi(*toys.optargs); + vtnum=atoi(*toys.optargs); - fd=get_console_fd(); - // These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h - if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum)) - perror_exit(NULL); + fd=get_console_fd(); + // These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h + if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum)) + perror_exit(NULL); } diff --git a/toys/other/clear.c b/toys/other/clear.c index 7647f669..2515f735 100644 --- a/toys/other/clear.c +++ b/toys/other/clear.c @@ -1,21 +1,19 @@ -/* vi: set sw=4 ts=4: - * - * clear.c - clear the screen +/* clear.c - clear the screen * * Copyright 2012 Rob Landley <rob@landley.net> USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config CLEAR - bool "clear" - default y - help - Clear the screen. + bool "clear" + default y + help + Clear the screen. */ #include "toys.h" void clear_main(void) { - write(1, "\e[2J\e[H", 7); + write(1, "\e[2J\e[H", 7); } diff --git a/toys/other/count.c b/toys/other/count.c index 22a06a1c..f3b6f821 100644 --- a/toys/other/count.c +++ b/toys/other/count.c @@ -1,34 +1,32 @@ -/* vi: set sw=4 ts=4: - * - * count.c - Progress indicator from stdin to stdout +/* count.c - Progress indicator from stdin to stdout * * Copyright 2002 Rob Landley <rob@landley.net> USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config COUNT - bool "count" - default y - help - usage: count + bool "count" + default y + help + usage: count - Copy stdin to stdout, displaying simple progress indicator to stderr. + Copy stdin to stdout, displaying simple progress indicator to stderr. */ #include "toys.h" void count_main(void) { - uint64_t size = 0; - int len; - char buf[32]; + uint64_t size = 0; + int len; + char buf[32]; - for (;;) { - len = xread(0, toybuf, sizeof(toybuf)); - if (!len) break; - size += len; - xwrite(1, toybuf, len); - xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size)); - } - xwrite(2, "\n", 1); + for (;;) { + len = xread(0, toybuf, sizeof(toybuf)); + if (!len) break; + size += len; + xwrite(1, toybuf, len); + xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size)); + } + xwrite(2, "\n", 1); } diff --git a/toys/other/dos2unix.c b/toys/other/dos2unix.c index 15cc1706..59cd6a53 100644 --- a/toys/other/dos2unix.c +++ b/toys/other/dos2unix.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dos2unix.c - convert newline format +/* dos2unix.c - convert newline format * * Copyright 2012 Rob Landley <rob@landley.net> @@ -8,60 +6,60 @@ USE_DOS2UNIX(NEWTOY(dos2unix, NULL, TOYFLAG_BIN)) USE_DOS2UNIX(OLDTOY(unix2dos, dos2unix, NULL, TOYFLAG_BIN)) config DOS2UNIX - bool "dos2unix/unix2dos" - default y - help - usage: dos2unix/unix2dos [file...] + bool "dos2unix/unix2dos" + default y + help + usage: dos2unix/unix2dos [file...] - Convert newline format between dos (\r\n) and unix (just \n) - If no files listed copy from stdin, "-" is a synonym for stdin. + Convert newline format between dos (\r\n) and unix (just \n) + If no files listed copy from stdin, "-" is a synonym for stdin. */ #define FOR_dos2unix #include "toys.h" GLOBALS( - char *tempfile; + char *tempfile; ) static void do_dos2unix(int fd, char *name) { - char c = toys.which->name[0]; - int outfd = 1, catch = 0; + char c = toys.which->name[0]; + int outfd = 1, catch = 0; - if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile); + if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile); - for (;;) { - int len, in, out; + for (;;) { + int len, in, out; - len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2); - if (len<0) { - perror_msg("%s",name); - toys.exitval = 1; - } - if (len<1) break; + len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2); + if (len<0) { + perror_msg("%s",name); + toys.exitval = 1; + } + if (len<1) break; - for (in = out = 0; in < len; in++) { - char x = toybuf[in+sizeof(toybuf)/2]; + for (in = out = 0; in < len; in++) { + char x = toybuf[in+sizeof(toybuf)/2]; - // Drop \r only if followed by \n in dos2unix mode - if (catch) { - if (c == 'u' || x != '\n') toybuf[out++] = '\r'; - catch = 0; - // Add \r only if \n not after \r in unix2dos mode - } else if (c == 'u' && x == '\n') toybuf[out++] = '\r'; + // Drop \r only if followed by \n in dos2unix mode + if (catch) { + if (c == 'u' || x != '\n') toybuf[out++] = '\r'; + catch = 0; + // Add \r only if \n not after \r in unix2dos mode + } else if (c == 'u' && x == '\n') toybuf[out++] = '\r'; - if (x == '\r') catch++; - else toybuf[out++] = x; - } - xwrite(outfd, toybuf, out); - } - if (catch) xwrite(outfd, "\r", 1); + if (x == '\r') catch++; + else toybuf[out++] = x; + } + xwrite(outfd, toybuf, out); + } + if (catch) xwrite(outfd, "\r", 1); - if (fd) replace_tempfile(-1, outfd, &TT.tempfile); + if (fd) replace_tempfile(-1, outfd, &TT.tempfile); } void dos2unix_main(void) { - loopfiles(toys.optargs, do_dos2unix); + loopfiles(toys.optargs, do_dos2unix); } diff --git a/toys/other/free.c b/toys/other/free.c index aa344928..3281d79b 100644 --- a/toys/other/free.c +++ b/toys/other/free.c @@ -1,59 +1,57 @@ -/* vi: set sw=4 ts=4: - * - * free.c - Display amount of free and used memory in the system. +/* free.c - Display amount of free and used memory in the system. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_FREE(NEWTOY(free, "gmkb", TOYFLAG_USR|TOYFLAG_BIN)) config FREE - bool "free" - default y - help - usage: free [-bkmg] + bool "free" + default y + help + usage: free [-bkmg] - Display the total, free and used amount of physical memory and - swap space. + Display the total, free and used amount of physical memory and + swap space. - -bkmg Output in bytes (default), KB, MB or GB + -bkmg Output in bytes (default), KB, MB or GB */ #define FOR_free #include "toys.h" static unsigned long long convert(unsigned long d, unsigned int iscale, - unsigned int oscale) + unsigned int oscale) { - return ((unsigned long long)d*iscale)>>oscale; + return ((unsigned long long)d*iscale)>>oscale; } void free_main(void) { - struct sysinfo info; - unsigned int iscale = 1; - unsigned int oscale = 0; - - sysinfo(&info); - if (info.mem_unit) iscale = info.mem_unit; - if (toys.optflags & FLAG_b) oscale = 0; - if (toys.optflags & FLAG_k) oscale = 10; - if (toys.optflags & FLAG_m) oscale = 20; - if (toys.optflags & FLAG_g) oscale = 30; - - xprintf("\t\ttotal used free shared buffers\n"); - xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n", - convert(info.totalram, iscale, oscale), - convert(info.totalram-info.freeram, iscale, oscale), - convert(info.freeram, iscale, oscale), - convert(info.sharedram, iscale, oscale), - convert(info.bufferram, iscale, oscale)); - - xprintf("-/+ buffers/cache:%15llu%12llu\n", - convert(info.totalram - info.freeram - info.bufferram, iscale, oscale), - convert(info.freeram + info.bufferram, iscale, oscale)); - - xprintf("Swap:%16llu%12llu%12llu\n", - convert(info.totalswap, iscale, oscale), - convert(info.totalswap - info.freeswap, iscale, oscale), - convert(info.freeswap, iscale, oscale)); + struct sysinfo info; + unsigned int iscale = 1; + unsigned int oscale = 0; + + sysinfo(&info); + if (info.mem_unit) iscale = info.mem_unit; + if (toys.optflags & FLAG_b) oscale = 0; + if (toys.optflags & FLAG_k) oscale = 10; + if (toys.optflags & FLAG_m) oscale = 20; + if (toys.optflags & FLAG_g) oscale = 30; + + xprintf("\t\ttotal used free shared buffers\n"); + xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n", + convert(info.totalram, iscale, oscale), + convert(info.totalram-info.freeram, iscale, oscale), + convert(info.freeram, iscale, oscale), + convert(info.sharedram, iscale, oscale), + convert(info.bufferram, iscale, oscale)); + + xprintf("-/+ buffers/cache:%15llu%12llu\n", + convert(info.totalram - info.freeram - info.bufferram, iscale, oscale), + convert(info.freeram + info.bufferram, iscale, oscale)); + + xprintf("Swap:%16llu%12llu%12llu\n", + convert(info.totalswap, iscale, oscale), + convert(info.totalswap - info.freeswap, iscale, oscale), + convert(info.freeswap, iscale, oscale)); } diff --git a/toys/other/hello.c b/toys/other/hello.c index 2b469591..aa256155 100644 --- a/toys/other/hello.c +++ b/toys/other/hello.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * hello.c - A hello world program. (Template for new commands.) +/* hello.c - A hello world program. (Template for new commands.) * * Copyright 2012 Rob Landley <rob@landley.net> * @@ -10,15 +8,15 @@ USE_HELLO(NEWTOY(hello, "e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN)) config HELLO - bool "hello" - default n - help - usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...] + bool "hello" + default n + help + usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...] - A hello world program. You don't need this. + A hello world program. You don't need this. - Mostly used as an example/skeleton file for adding new commands, - occasionally nice to test kernel booting via "init=/bin/hello". + Mostly used as an example/skeleton file for adding new commands, + occasionally nice to test kernel booting via "init=/bin/hello". */ #define FOR_hello @@ -27,26 +25,26 @@ config HELLO // Hello doesn't use these globals, they're here for example/skeleton purposes. GLOBALS( - char *b_string; - long c_number; - struct arg_list *d_list; - long e_count; + char *b_string; + long c_number; + struct arg_list *d_list; + long e_count; - int more_globals; + int more_globals; ) void hello_main(void) { - printf("Hello world\n"); - - if (toys.optflags & FLAG_a) printf("Saw a\n"); - if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string); - if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number); - while (TT.d_list) { - printf("d=%s\n", TT.d_list->arg); - TT.d_list = TT.d_list->next; - } - if (TT.e_count) printf("e was seen %ld times", TT.e_count); - - while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++)); + printf("Hello world\n"); + + if (toys.optflags & FLAG_a) printf("Saw a\n"); + if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string); + if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number); + while (TT.d_list) { + printf("d=%s\n", TT.d_list->arg); + TT.d_list = TT.d_list->next; + } + if (TT.e_count) printf("e was seen %ld times", TT.e_count); + + while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++)); } diff --git a/toys/other/help.c b/toys/other/help.c index 2c175552..68bc3aab 100644 --- a/toys/other/help.c +++ b/toys/other/help.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * help.c - Show help for toybox commands +/* help.c - Show help for toybox commands * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -9,15 +7,15 @@ USE_HELP(NEWTOY(help, "<1", TOYFLAG_BIN)) config HELP - bool "help" - default y - help - usage: help [command] + bool "help" + default y + help + usage: help [command] - Show usage information for toybox commands. - Run "toybox" with no arguments for a list of available commands. + Show usage information for toybox commands. + Run "toybox" with no arguments for a list of available commands. */ - + #include "toys.h" #include "generated/help.h" @@ -32,17 +30,17 @@ static char *help_data = void help_main(void) { - struct toy_list *t = toy_find(*toys.optargs); - int i = t-toy_list; - char *s = help_data; - - if (!t) error_exit("Unknown command '%s'", *toys.optargs); - for (;;) { - while (i--) s += strlen(s) + 1; - if (*s != 255) break; - i = toy_find(++s)-toy_list; - s = help_data; - } - - fprintf(toys.exithelp ? stderr : stdout, "%s", s); + struct toy_list *t = toy_find(*toys.optargs); + int i = t-toy_list; + char *s = help_data; + + if (!t) error_exit("Unknown command '%s'", *toys.optargs); + for (;;) { + while (i--) s += strlen(s) + 1; + if (*s != 255) break; + i = toy_find(++s)-toy_list; + s = help_data; + } + + fprintf(toys.exithelp ? stderr : stdout, "%s", s); } diff --git a/toys/other/insmod.c b/toys/other/insmod.c index 3eae538a..8aa959a9 100644 --- a/toys/other/insmod.c +++ b/toys/other/insmod.c @@ -1,18 +1,16 @@ -/* vi: set sw=4 ts=4: - * - * insmod.c - Load a module into the Linux kernel. +/* insmod.c - Load a module into the Linux kernel. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config INSMOD - bool "insmod" - default y - help - usage: insmod MODULE [MODULE_OPTIONS] + bool "insmod" + default y + help + usage: insmod MODULE [MODULE_OPTIONS] - Load the module named MODULE passing options if given. + Load the module named MODULE passing options if given. */ #include "toys.h" @@ -22,24 +20,23 @@ config INSMOD void insmod_main(void) { - char * buf = NULL; - int len, res, i; - int fd = xopen(toys.optargs[0], O_RDONLY); - - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); - - i = 1; - while(toys.optargs[i] && - strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) { - strcat(toybuf, toys.optargs[i++]); - strcat(toybuf, " "); - } - - res = init_module(buf, len, toybuf); - if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); - - if (res) - perror_exit("failed to load %s", toys.optargs[0]); + char * buf = NULL; + int len, res, i; + int fd = xopen(toys.optargs[0], O_RDONLY); + + len = fdlength(fd); + buf = xmalloc(len); + xreadall(fd, buf, len); + + i = 1; + while(toys.optargs[i] && + strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) { + strcat(toybuf, toys.optargs[i++]); + strcat(toybuf, " "); + } + + res = init_module(buf, len, toybuf); + if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); + + if (res) perror_exit("failed to load %s", toys.optargs[0]); } diff --git a/toys/other/login.c b/toys/other/login.c index a9e7562c..72d7063e 100644 --- a/toys/other/login.c +++ b/toys/other/login.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * login.c - Start a session on the system. +/* login.c - Start a session on the system. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -10,15 +8,15 @@ USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN)) config LOGIN - bool "login" - default y - help - usage: login [-p] [-h host] [[-f] username] - - Establish a new session with the system. - -p Preserve environment - -h The name of the remote host for this login - -f Do not perform authentication + bool "login" + default y + help + usage: login [-p] [-h host] [[-f] username] + + Establish a new session with the system. + -p Preserve environment + -h The name of the remote host for this login + -f Do not perform authentication */ #define FOR_login @@ -30,215 +28,199 @@ config LOGIN #define HOSTNAME_SIZE 32 GLOBALS( - char *hostname; + char *hostname; ) static void login_timeout_handler(int sig __attribute__((unused))) { - printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); - exit(0); + printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); + exit(0); } static char *forbid[] = { - "BASH_ENV", - "ENV", - "HOME", - "IFS", - "LD_LIBRARY_PATH", - "LD_PRELOAD", - "LD_TRACE_LOADED_OBJECTS", - "LD_BIND_NOW", - "LD_AOUT_LIBRARY_PATH", - "LD_AOUT_PRELOAD", - "LD_NOWARN", - "LD_KEEPDIR", - "SHELL", - NULL + "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", + "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL }; int verify_password(char * pwd) { - char *pass; + char *pass; - if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; + if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; - pass = crypt(toybuf, pwd); - if (pass && !strcmp(pass, pwd)) return 0; + pass = crypt(toybuf, pwd); + if (pass && !strcmp(pass, pwd)) return 0; - return 1; + return 1; } void read_user(char * buff, int size) { - char hostname[HOSTNAME_SIZE+1]; - int i = 0; - hostname[HOSTNAME_SIZE] = 0; - if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); - - fputs(" login: ", stdout); - fflush(stdout); - - do { - buff[0] = getchar(); - if (buff[0] == EOF) - exit(EXIT_FAILURE); - } while (isblank(buff[0])); - - if (buff[0] != '\n') - if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) - _exit(1); - - while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; - buff[i] = 0; + char hostname[HOSTNAME_SIZE+1]; + int i = 0; + hostname[HOSTNAME_SIZE] = 0; + if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); + + fputs(" login: ", stdout); + fflush(stdout); + + do { + buff[0] = getchar(); + if (buff[0] == EOF) exit(EXIT_FAILURE); + } while (isblank(buff[0])); + + if (buff[0] != '\n') if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) _exit(1); + + while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; + buff[i] = 0; } void handle_nologin(void) { - int fd = open("/etc/nologin", O_RDONLY); - int size; - if (fd == -1) return; - - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - if (!size) puts("System closed for routine maintenance\n"); - else puts(toybuf); - - close(fd); - fflush(stdout); - exit(EXIT_FAILURE); + int fd = open("/etc/nologin", O_RDONLY); + int size; + if (fd == -1) return; + + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + if (!size) puts("System closed for routine maintenance\n"); + else puts(toybuf); + + close(fd); + fflush(stdout); + exit(EXIT_FAILURE); } void handle_motd(void) { - int fd = open("/etc/motd", O_RDONLY); - int size; - if (fd == -1) return; + int fd = open("/etc/motd", O_RDONLY); + int size; + if (fd == -1) return; - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - puts(toybuf); + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + puts(toybuf); - close(fd); - fflush(stdout); + close(fd); + fflush(stdout); } int change_identity(const struct passwd *pwd) { - if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; - if (setgid(pwd->pw_uid)) return 1; - if (setuid(pwd->pw_uid)) return 1; + if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; + if (setgid(pwd->pw_uid)) return 1; + if (setuid(pwd->pw_uid)) return 1; - return 0; + return 0; } void spawn_shell(const char *shell) { - const char * exec_name = strrchr(shell,'/'); - if (exec_name) exec_name++; - else exec_name = shell; + const char * exec_name = strrchr(shell,'/'); + if (exec_name) exec_name++; + else exec_name = shell; - snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); - execl(shell, toybuf, NULL); - error_exit("Failed to spawn shell"); + snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); + execl(shell, toybuf, NULL); + error_exit("Failed to spawn shell"); } void setup_environment(const struct passwd *pwd, int clear_env) { - if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); - - if (clear_env) { - const char * term = getenv("TERM"); - clearenv(); - if (term) setenv("TERM", term, 1); - } - - setenv("USER", pwd->pw_name, 1); - setenv("LOGNAME", pwd->pw_name, 1); - setenv("HOME", pwd->pw_dir, 1); - setenv("SHELL", pwd->pw_shell, 1); + if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); + + if (clear_env) { + const char * term = getenv("TERM"); + clearenv(); + if (term) setenv("TERM", term, 1); + } + + setenv("USER", pwd->pw_name, 1); + setenv("LOGNAME", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + setenv("SHELL", pwd->pw_shell, 1); } void login_main(void) { - int f_flag = toys.optflags & FLAG_f; - int h_flag = toys.optflags & FLAG_h; - char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; - struct passwd * pwd = NULL; - struct spwd * spwd = NULL; - int auth_fail_cnt = 0; + int f_flag = toys.optflags & FLAG_f; + int h_flag = toys.optflags & FLAG_h; + char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; + struct passwd * pwd = NULL; + struct spwd * spwd = NULL; + int auth_fail_cnt = 0; - if (f_flag && toys.optc != 1) - error_exit("-f requires username"); + if (f_flag && toys.optc != 1) error_exit("-f requires username"); - if (geteuid()) error_exit("not root"); + if (geteuid()) error_exit("not root"); - if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); + if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); - openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); - signal(SIGALRM, login_timeout_handler); - alarm(LOGIN_TIMEOUT); + openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); + signal(SIGALRM, login_timeout_handler); + alarm(LOGIN_TIMEOUT); - for (ss = forbid; *ss; ss++) unsetenv(*ss); + for (ss = forbid; *ss; ss++) unsetenv(*ss); - while (1) { - tcflush(0, TCIFLUSH); + while (1) { + tcflush(0, TCIFLUSH); - username[USER_NAME_MAX_SIZE] = 0; - if (toys.optargs[0]) - strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); - else { - read_user(username, USER_NAME_MAX_SIZE+1); - if (username[0] == 0) continue; - } + username[USER_NAME_MAX_SIZE] = 0; + if (toys.optargs[0]) strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); + else { + read_user(username, USER_NAME_MAX_SIZE+1); + if (username[0] == 0) continue; + } - pwd = getpwnam(username); - if (!pwd) goto query_pass; // Non-existing user + pwd = getpwnam(username); + if (!pwd) goto query_pass; // Non-existing user - if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') - goto query_pass; // Locked account + if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') + goto query_pass; // Locked account - if (f_flag) break; // Pre-authenticated + if (f_flag) break; // Pre-authenticated - if (!pwd->pw_passwd[0]) break; // Password-less account + if (!pwd->pw_passwd[0]) break; // Password-less account - pass = pwd->pw_passwd; - if (pwd->pw_passwd[0] == 'x') { - spwd = getspnam (username); - if (spwd) pass = spwd->sp_pwdp; - } + pass = pwd->pw_passwd; + if (pwd->pw_passwd[0] == 'x') { + spwd = getspnam (username); + if (spwd) pass = spwd->sp_pwdp; + } query_pass: - if (!verify_password(pass)) break; + if (!verify_password(pass)) break; - f_flag = 0; - syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + f_flag = 0; + syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - sleep(LOGIN_FAIL_TIMEOUT); - puts("Login incorrect"); + sleep(LOGIN_FAIL_TIMEOUT); + puts("Login incorrect"); - if (++auth_fail_cnt == 3) - error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); + if (++auth_fail_cnt == 3) + error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); - username[0] = 0; - pwd = NULL; - spwd = NULL; - } + username[0] = 0; + pwd = NULL; + spwd = NULL; + } - alarm(0); + alarm(0); - if (pwd->pw_uid) handle_nologin(); + if (pwd->pw_uid) handle_nologin(); - if (change_identity(pwd)) error_exit("Failed to change identity"); + if (change_identity(pwd)) error_exit("Failed to change identity"); - setup_environment(pwd, !(toys.optflags & FLAG_p)); + setup_environment(pwd, !(toys.optflags & FLAG_p)); - handle_motd(); + handle_motd(); - syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - spawn_shell(pwd->pw_shell); + spawn_shell(pwd->pw_shell); } diff --git a/toys/other/lsmod.c b/toys/other/lsmod.c index 821243b8..b8f5d820 100644 --- a/toys/other/lsmod.c +++ b/toys/other/lsmod.c @@ -1,40 +1,36 @@ -/* vi: set sw=4 ts=4: - * - * lsmod.c - Show the status of modules in the kernel +/* lsmod.c - Show the status of modules in the kernel * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_BIN)) config LSMOD - bool "lsmod" - default y - help - usage: lsmod + bool "lsmod" + default y + help + usage: lsmod - Display the currently loaded modules, their sizes and their - dependencies. + Display the currently loaded modules, their sizes and their dependencies. */ #include "toys.h" void lsmod_main(void) { - char *modfile = "/proc/modules"; - FILE * file = xfopen(modfile, "r"); - - xprintf("%-23s Size Used by\n", "Module"); - - while (fgets(toybuf, sizeof(toybuf), file)) { - char *name = strtok(toybuf, " "), *size = strtok(NULL, " "), - *refcnt = strtok(NULL, " "), *users = strtok(NULL, " "); - - if(users) { - int len = strlen(users)-1; - if (users[len] == ',' || users[len] == '-') - users[len] = 0; - xprintf("%-19s %8s %s %s\n", name, size, refcnt, users); - } else perror_exit("bad %s", modfile); - } - fclose(file); + char *modfile = "/proc/modules"; + FILE * file = xfopen(modfile, "r"); + + xprintf("%-23s Size Used by\n", "Module"); + + while (fgets(toybuf, sizeof(toybuf), file)) { + char *name = strtok(toybuf, " "), *size = strtok(NULL, " "), + *refcnt = strtok(NULL, " "), *users = strtok(NULL, " "); + + if(users) { + int len = strlen(users)-1; + if (users[len] == ',' || users[len] == '-') users[len] = 0; + xprintf("%-19s %8s %s %s\n", name, size, refcnt, users); + } else perror_exit("bad %s", modfile); + } + fclose(file); } diff --git a/toys/other/mdev.c b/toys/other/mdev.c index 6d030d14..b89ac2ca 100644 --- a/toys/other/mdev.c +++ b/toys/other/mdev.c @@ -1,6 +1,4 @@ -/* vi:set ts=4: - * - * mdev.c - Populate /dev directory and handle hotplug events +/* mdev.c - Populate /dev directory and handle hotplug events * * Copyright 2005, 2008 Rob Landley <rob@landley.net> * Copyright 2005 Frank Sorenson <frank@tuxrocks.com> @@ -8,27 +6,27 @@ USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK)) config MDEV - bool "mdev" - default n - help - usage: mdev [-s] + bool "mdev" + default n + help + usage: mdev [-s] - Create devices in /dev using information from /sys. + Create devices in /dev using information from /sys. - -s Scan all entries in /sys to populate /dev. + -s Scan all entries in /sys to populate /dev. config MDEV_CONF - bool "Configuration file for mdev" - default y - depends on MDEV - help - The mdev config file (/etc/mdev.conf) contains lines that look like: - hd[a-z][0-9]* 0:3 660 - - Each line must contain three whitespace separated fields. The first - field is a regular expression matching one or more device names, and - the second and third fields are uid:gid and file permissions for - matching devies. + bool "Configuration file for mdev" + default y + depends on MDEV + help + The mdev config file (/etc/mdev.conf) contains lines that look like: + hd[a-z][0-9]* 0:3 660 + + Each line must contain three whitespace separated fields. The first + field is a regular expression matching one or more device names, and + the second and third fields are uid:gid and file permissions for + matching devies. */ #include "toys.h" @@ -39,173 +37,173 @@ config MDEV_CONF // mknod in /dev based on a path like "/sys/block/hda/hda1" static void make_device(char *path) { - char *device_name, *s, *temp; - int major, minor, type, len, fd; - int mode = 0660; - uid_t uid = 0; - gid_t gid = 0; - - // Try to read major/minor string - - temp = strrchr(path, '/'); - fd = open(path, O_RDONLY); - *temp=0; - temp = toybuf; - len = read(fd, temp, 64); - close(fd); - if (len<1) return; - temp[len] = 0; - - // Determine device name, type, major and minor - - device_name = strrchr(path, '/') + 1; - type = path[5]=='c' ? S_IFCHR : S_IFBLK; - major = minor = 0; - sscanf(temp, "%u:%u", &major, &minor); - - // If we have a config file, look up permissions for this device - - if (CFG_MDEV_CONF) { - char *conf, *pos, *end; - - // mmap the config file - if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) { - len = fdlength(fd); - conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); - if (conf) { - int line = 0; - - // Loop through lines in mmaped file - for (pos = conf; pos-conf<len;) { - int field; - char *end2; - - line++; - // find end of this line - for(end = pos; end-conf<len && *end!='\n'; end++); - - // Three fields: regex, uid:gid, mode - for (field = 3; field; field--) { - // Skip whitespace - while (pos<end && isspace(*pos)) pos++; - if (pos==end || *pos=='#') break; - for (end2 = pos; - end2<end && !isspace(*end2) && *end2!='#'; end2++); - switch(field) { - // Regex to match this device - case 3: - { - char *regex = strndup(pos, end2-pos); - regex_t match; - regmatch_t off; - int result; - - // Is this it? - xregcomp(&match, regex, REG_EXTENDED); - result=regexec(&match, device_name, 1, &off, 0); - regfree(&match); - free(regex); - - // If not this device, skip rest of line - if (result || off.rm_so - || off.rm_eo!=strlen(device_name)) - goto end_line; - - break; - } - // uid:gid - case 2: - { - char *s2; - - // Find : - for(s = pos; s<end2 && *s!=':'; s++); - if (s==end2) goto end_line; - - // Parse UID - uid = strtoul(pos,&s2,10); - if (s!=s2) { - struct passwd *pass; - char *str = strndup(pos, s-pos); - pass = getpwnam(str); - free(str); - if (!pass) goto end_line; - uid = pass->pw_uid; - } - s++; - // parse GID - gid = strtoul(s,&s2,10); - if (end2!=s2) { - struct group *grp; - char *str = strndup(s, end2-s); - grp = getgrnam(str); - free(str); - if (!grp) goto end_line; - gid = grp->gr_gid; - } - break; - } - // mode - case 1: - { - mode = strtoul(pos, &pos, 8); - if (pos!=end2) goto end_line; - goto found_device; - } - } - pos=end2; - } + char *device_name, *s, *temp; + int major, minor, type, len, fd; + int mode = 0660; + uid_t uid = 0; + gid_t gid = 0; + + // Try to read major/minor string + + temp = strrchr(path, '/'); + fd = open(path, O_RDONLY); + *temp=0; + temp = toybuf; + len = read(fd, temp, 64); + close(fd); + if (len<1) return; + temp[len] = 0; + + // Determine device name, type, major and minor + + device_name = strrchr(path, '/') + 1; + type = path[5]=='c' ? S_IFCHR : S_IFBLK; + major = minor = 0; + sscanf(temp, "%u:%u", &major, &minor); + + // If we have a config file, look up permissions for this device + + if (CFG_MDEV_CONF) { + char *conf, *pos, *end; + + // mmap the config file + if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) { + len = fdlength(fd); + conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (conf) { + int line = 0; + + // Loop through lines in mmaped file + for (pos = conf; pos-conf<len;) { + int field; + char *end2; + + line++; + // find end of this line + for(end = pos; end-conf<len && *end!='\n'; end++); + + // Three fields: regex, uid:gid, mode + for (field = 3; field; field--) { + // Skip whitespace + while (pos<end && isspace(*pos)) pos++; + if (pos==end || *pos=='#') break; + for (end2 = pos; + end2<end && !isspace(*end2) && *end2!='#'; end2++); + switch(field) { + // Regex to match this device + case 3: + { + char *regex = strndup(pos, end2-pos); + regex_t match; + regmatch_t off; + int result; + + // Is this it? + xregcomp(&match, regex, REG_EXTENDED); + result=regexec(&match, device_name, 1, &off, 0); + regfree(&match); + free(regex); + + // If not this device, skip rest of line + if (result || off.rm_so + || off.rm_eo!=strlen(device_name)) + goto end_line; + + break; + } + // uid:gid + case 2: + { + char *s2; + + // Find : + for(s = pos; s<end2 && *s!=':'; s++); + if (s==end2) goto end_line; + + // Parse UID + uid = strtoul(pos,&s2,10); + if (s!=s2) { + struct passwd *pass; + char *str = strndup(pos, s-pos); + pass = getpwnam(str); + free(str); + if (!pass) goto end_line; + uid = pass->pw_uid; + } + s++; + // parse GID + gid = strtoul(s,&s2,10); + if (end2!=s2) { + struct group *grp; + char *str = strndup(s, end2-s); + grp = getgrnam(str); + free(str); + if (!grp) goto end_line; + gid = grp->gr_gid; + } + break; + } + // mode + case 1: + { + mode = strtoul(pos, &pos, 8); + if (pos!=end2) goto end_line; + goto found_device; + } + } + pos=end2; + } end_line: - // Did everything parse happily? - if (field && field!=3) error_exit("Bad line %d", line); + // Did everything parse happily? + if (field && field!=3) error_exit("Bad line %d", line); - // Next line - pos = ++end; - } + // Next line + pos = ++end; + } found_device: - munmap(conf, len); - } - close(fd); - } - } + munmap(conf, len); + } + close(fd); + } + } - sprintf(temp, "/dev/%s", device_name); - if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) - perror_exit("mknod %s failed", temp); + sprintf(temp, "/dev/%s", device_name); + if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) + perror_exit("mknod %s failed", temp); - if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); + if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); } static int callback(struct dirtree *node) { - // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll - // get block devices out of /sys/block.) - if(!strcmp(node->name, "block")) return 0; - - // Does this directory have a "dev" entry in it? - // This is path based because the hotplug callbacks are - if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) { - int len=4; - char *dev = dirtree_path(node, &len); - strcpy(dev+len, "/dev"); - if (!access(dev, R_OK)) make_device(dev); - free(dev); - } - - // Circa 2.6.25 the entries more than 2 deep are all either redundant - // (mouse#, event#) or unnamed (every usb_* entry is called "device"). - - return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE; + // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll + // get block devices out of /sys/block.) + if(!strcmp(node->name, "block")) return 0; + + // Does this directory have a "dev" entry in it? + // This is path based because the hotplug callbacks are + if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) { + int len=4; + char *dev = dirtree_path(node, &len); + strcpy(dev+len, "/dev"); + if (!access(dev, R_OK)) make_device(dev); + free(dev); + } + + // Circa 2.6.25 the entries more than 2 deep are all either redundant + // (mouse#, event#) or unnamed (every usb_* entry is called "device"). + + return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE; } void mdev_main(void) { - // Handle -s + // Handle -s - if (toys.optflags) { - dirtree_read("/sys/class", callback); - dirtree_read("/sys/block", callback); - } + if (toys.optflags) { + dirtree_read("/sys/class", callback); + dirtree_read("/sys/block", callback); + } - // hotplug support goes here + // hotplug support goes here } diff --git a/toys/other/mke2fs.c b/toys/other/mke2fs.c index 5745d519..1a83e4f6 100644 --- a/toys/other/mke2fs.c +++ b/toys/other/mke2fs.c @@ -1,6 +1,4 @@ -/* vi: set ts=4: - * - * mke2fs.c - Create an ext2 filesystem image. +/* mke2fs.c - Create an ext2 filesystem image. * * Copyright 2006, 2007 Rob Landley <rob@landley.net> @@ -8,155 +6,155 @@ USE_MKE2FS(NEWTOY(mke2fs, "<1>2g:Fnqm#N#i#b#", TOYFLAG_SBIN)) config MKE2FS - bool "mke2fs (unfinished and broken by dirtree changes)" - default n - help - usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device + bool "mke2fs (unfinished and broken by dirtree changes)" + default n + help + usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device - Create an ext2 filesystem on a block device or filesystem image. + Create an ext2 filesystem on a block device or filesystem image. - -F Force to run on a mounted device - -n Don't write to device - -q Quiet (no output) - -b size Block size (1024, 2048, or 4096) - -N inodes Allocate this many inodes - -i bytes Allocate one inode for every XXX bytes of device - -m percent Reserve this percent of filesystem space for root user + -F Force to run on a mounted device + -n Don't write to device + -q Quiet (no output) + -b size Block size (1024, 2048, or 4096) + -N inodes Allocate this many inodes + -i bytes Allocate one inode for every XXX bytes of device + -m percent Reserve this percent of filesystem space for root user config MKE2FS_JOURNAL - bool "Journaling support (ext3)" - default n - depends on MKE2FS - help - usage: [-j] [-J size=###,device=XXX] + bool "Journaling support (ext3)" + default n + depends on MKE2FS + help + usage: [-j] [-J size=###,device=XXX] - -j Create journal (ext3) - -J Journal options - size: Number of blocks (1024-102400) - device: Specify an external journal + -j Create journal (ext3) + -J Journal options + size: Number of blocks (1024-102400) + device: Specify an external journal config MKE2FS_GEN - bool "Generate (gene2fs)" - default n - depends on MKE2FS - help - usage: gene2fs [options] device filename + bool "Generate (gene2fs)" + default n + depends on MKE2FS + help + usage: gene2fs [options] device filename - The [options] are the same as mke2fs. + The [options] are the same as mke2fs. config MKE2FS_LABEL - bool "Label support" - default n - depends on MKE2FS - help - usage: mke2fs [-L label] [-M path] [-o string] + bool "Label support" + default n + depends on MKE2FS + help + usage: mke2fs [-L label] [-M path] [-o string] - -L Volume label - -M Path to mount point - -o Created by + -L Volume label + -M Path to mount point + -o Created by config MKE2FS_EXTENDED - bool "Extended options" - default n - depends on MKE2FS - help - usage: mke2fs [-E stride=###] [-O option[,option]] - - -E stride= Set RAID stripe size (in blocks) - -O [opts] Specify fewer ext2 option flags (for old kernels) - All of these are on by default (as appropriate) - none Clear default options (all but journaling) - dir_index Use htree indexes for large directories - filetype Store file type info in directory entry - has_journal Set by -j - journal_dev Set by -J device=XXX - sparse_super Don't allocate huge numbers of redundant superblocks + bool "Extended options" + default n + depends on MKE2FS + help + usage: mke2fs [-E stride=###] [-O option[,option]] + + -E stride= Set RAID stripe size (in blocks) + -O [opts] Specify fewer ext2 option flags (for old kernels) + All of these are on by default (as appropriate) + none Clear default options (all but journaling) + dir_index Use htree indexes for large directories + filetype Store file type info in directory entry + has_journal Set by -j + journal_dev Set by -J device=XXX + sparse_super Don't allocate huge numbers of redundant superblocks */ #define FOR_mke2fs #include "toys.h" GLOBALS( - // Command line arguments. - long blocksize; - long bytes_per_inode; - long inodes; // Total inodes in filesystem. - long reserved_percent; // Integer precent of space to reserve for root. - char *gendir; // Where to read dirtree from. - - // Internal data. - struct dirtree *dt; // Tree of files to copy into the new filesystem. - unsigned treeblocks; // Blocks used by dt - unsigned treeinodes; // Inodes used by dt - - unsigned blocks; // Total blocks in the filesystem. - unsigned freeblocks; // Free blocks in the filesystem. - unsigned inodespg; // Inodes per group - unsigned groups; // Total number of block groups. - unsigned blockbits; // Bits per block. (Also blocks per group.) - - // For gene2fs - unsigned nextblock; // Next data block to allocate - unsigned nextgroup; // Next group we'll be allocating from - int fsfd; // File descriptor of filesystem (to output to). - - struct ext2_superblock sb; + // Command line arguments. + long blocksize; + long bytes_per_inode; + long inodes; // Total inodes in filesystem. + long reserved_percent; // Integer precent of space to reserve for root. + char *gendir; // Where to read dirtree from. + + // Internal data. + struct dirtree *dt; // Tree of files to copy into the new filesystem. + unsigned treeblocks; // Blocks used by dt + unsigned treeinodes; // Inodes used by dt + + unsigned blocks; // Total blocks in the filesystem. + unsigned freeblocks; // Free blocks in the filesystem. + unsigned inodespg; // Inodes per group + unsigned groups; // Total number of block groups. + unsigned blockbits; // Bits per block. (Also blocks per group.) + + // For gene2fs + unsigned nextblock; // Next data block to allocate + unsigned nextgroup; // Next group we'll be allocating from + int fsfd; // File descriptor of filesystem (to output to). + + struct ext2_superblock sb; ) #define INODES_RESERVED 10 static uint32_t div_round_up(uint32_t a, uint32_t b) { - uint32_t c = a/b; + uint32_t c = a/b; - if (a%b) c++; - return c; + if (a%b) c++; + return c; } // Calculate data blocks plus index blocks needed to hold a file. static uint32_t file_blocks_used(uint64_t size, uint32_t *blocklist) { - uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize); - uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0; + uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize); + uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0; - // Fill out index blocks in inode. + // Fill out index blocks in inode. - if (blocklist) { - int i; + if (blocklist) { + int i; - // Direct index blocks - for (i=0; i<13 && i<dblocks; i++) blocklist[i] = i; - // Singly indirect index blocks - if (dblocks > 13+idx) blocklist[13] = 13+idx; - // Doubly indirect index blocks - idx = 13 + idx + (idx*idx); - if (dblocks > idx) blocklist[14] = idx; + // Direct index blocks + for (i=0; i<13 && i<dblocks; i++) blocklist[i] = i; + // Singly indirect index blocks + if (dblocks > 13+idx) blocklist[13] = 13+idx; + // Doubly indirect index blocks + idx = 13 + idx + (idx*idx); + if (dblocks > idx) blocklist[14] = idx; - return 0; - } + return 0; + } - // Account for direct, singly, doubly, and triply indirect index blocks + // Account for direct, singly, doubly, and triply indirect index blocks - if (dblocks > 12) { - iblocks = ((dblocks-13)/idx)+1; - if (iblocks > 1) { - diblocks = ((iblocks-2)/idx)+1; - if (diblocks > 1) - tiblocks = ((diblocks-2)/idx)+1; - } - } + if (dblocks > 12) { + iblocks = ((dblocks-13)/idx)+1; + if (iblocks > 1) { + diblocks = ((iblocks-2)/idx)+1; + if (diblocks > 1) + tiblocks = ((diblocks-2)/idx)+1; + } + } - return dblocks + iblocks + diblocks + tiblocks; + return dblocks + iblocks + diblocks + tiblocks; } // Use the parent pointer to iterate through the tree non-recursively. static struct dirtree *treenext(struct dirtree *this) { - while (this && !this->next) this = this->parent; - if (this) this = this->next; + while (this && !this->next) this = this->parent; + if (this) this = this->next; - return this; + return this; } // Recursively calculate the number of blocks used by each inode in the tree. @@ -165,27 +163,27 @@ static struct dirtree *treenext(struct dirtree *this) static long check_treesize(struct dirtree *that, off_t *size) { - long blocks; - - while (that) { - *size += sizeof(struct ext2_dentry) + strlen(that->name); - - if (that->child) - that->st.st_blocks = check_treesize(that->child, &that->st.st_size); - else if (S_ISREG(that->st.st_mode)) { - that->st.st_blocks = file_blocks_used(that->st.st_size, 0); - TT.treeblocks += that->st.st_blocks; - } - that = that->next; - } - TT.treeblocks += blocks = file_blocks_used(*size, 0); - TT.treeinodes++; - - return blocks; + long blocks; + + while (that) { + *size += sizeof(struct ext2_dentry) + strlen(that->name); + + if (that->child) + that->st.st_blocks = check_treesize(that->child, &that->st.st_size); + else if (S_ISREG(that->st.st_mode)) { + that->st.st_blocks = file_blocks_used(that->st.st_size, 0); + TT.treeblocks += that->st.st_blocks; + } + that = that->next; + } + TT.treeblocks += blocks = file_blocks_used(*size, 0); + TT.treeinodes++; + + return blocks; } // Calculate inode numbers and link counts. -// +// // To do this right I need to copy the tree and sort it, but here's a really // ugly n^2 way of dealing with the problem that doesn't scale well to large // numbers of files (> 100,000) but can be done in very little code. @@ -193,32 +191,32 @@ static long check_treesize(struct dirtree *that, off_t *size) static void check_treelinks(struct dirtree *tree) { - struct dirtree *current=tree, *that; - long inode = INODES_RESERVED; - - while (current) { - ++inode; - // Since we can't hardlink to directories, we know their link count. - if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2; - else { - dev_t new = current->st.st_dev; - - if (!new) continue; - - // Look for other copies of current node - current->st.st_nlink = 0; - for (that = tree; that; that = treenext(that)) { - if (current->st.st_ino == that->st.st_ino && - current->st.st_dev == that->st.st_dev) - { - current->st.st_nlink++; - current->st.st_ino = inode; - } - } - } - current->st.st_ino = inode; - current = treenext(current); - } + struct dirtree *current=tree, *that; + long inode = INODES_RESERVED; + + while (current) { + ++inode; + // Since we can't hardlink to directories, we know their link count. + if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2; + else { + dev_t new = current->st.st_dev; + + if (!new) continue; + + // Look for other copies of current node + current->st.st_nlink = 0; + for (that = tree; that; that = treenext(that)) { + if (current->st.st_ino == that->st.st_ino && + current->st.st_dev == that->st.st_dev) + { + current->st.st_nlink++; + current->st.st_ino = inode; + } + } + } + current->st.st_ino = inode; + current = treenext(current); + } } // According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm @@ -231,202 +229,202 @@ static void check_treelinks(struct dirtree *tree) static void create_uuid(char *uuid) { - // Read 128 random bits - int fd = xopen("/dev/urandom", O_RDONLY); - xreadall(fd, uuid, 16); - close(fd); - - // Claim to be a DCE format UUID. - uuid[6] = (uuid[6] & 0x0F) | 0x40; - uuid[8] = (uuid[8] & 0x3F) | 0x80; - - // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should - // set bit 1 of the node ID, which is the mac multicast bit. This means we - // should never collide with anybody actually using a macaddr. - uuid[11] = uuid[11] | 128; + // Read 128 random bits + int fd = xopen("/dev/urandom", O_RDONLY); + xreadall(fd, uuid, 16); + close(fd); + + // Claim to be a DCE format UUID. + uuid[6] = (uuid[6] & 0x0F) | 0x40; + uuid[8] = (uuid[8] & 0x3F) | 0x80; + + // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should + // set bit 1 of the node ID, which is the mac multicast bit. This means we + // should never collide with anybody actually using a macaddr. + uuid[11] = uuid[11] | 128; } // Calculate inodes per group from total inodes. static uint32_t get_inodespg(uint32_t inodes) { - uint32_t temp; + uint32_t temp; - // Round up to fill complete inode blocks. - temp = (inodes + TT.groups - 1) / TT.groups; - inodes = TT.blocksize/sizeof(struct ext2_inode); - return ((temp + inodes - 1)/inodes)*inodes; + // Round up to fill complete inode blocks. + temp = (inodes + TT.groups - 1) / TT.groups; + inodes = TT.blocksize/sizeof(struct ext2_inode); + return ((temp + inodes - 1)/inodes)*inodes; } // Fill out superblock and TT structures. static void init_superblock(struct ext2_superblock *sb) { - uint32_t temp; + uint32_t temp; - // Set log_block_size and log_frag_size. + // Set log_block_size and log_frag_size. - for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<<temp) break; - if (temp==4) error_exit("bad blocksize"); - sb->log_block_size = sb->log_frag_size = SWAP_LE32(temp); + for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<<temp) break; + if (temp==4) error_exit("bad blocksize"); + sb->log_block_size = sb->log_frag_size = SWAP_LE32(temp); - // Fill out blocks_count, r_blocks_count, first_data_block + // Fill out blocks_count, r_blocks_count, first_data_block - sb->blocks_count = SWAP_LE32(TT.blocks); - sb->free_blocks_count = SWAP_LE32(TT.freeblocks); - temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100; - sb->r_blocks_count = SWAP_LE32(temp); + sb->blocks_count = SWAP_LE32(TT.blocks); + sb->free_blocks_count = SWAP_LE32(TT.freeblocks); + temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100; + sb->r_blocks_count = SWAP_LE32(temp); - sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0); + sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0); - // Set blocks_per_group and frags_per_group, which is the size of an - // allocation bitmap that fits in one block (I.E. how many bits per block)? + // Set blocks_per_group and frags_per_group, which is the size of an + // allocation bitmap that fits in one block (I.E. how many bits per block)? - sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits); + sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits); - // Set inodes_per_group and total inodes_count - sb->inodes_per_group = SWAP_LE32(TT.inodespg); - sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups); + // Set inodes_per_group and total inodes_count + sb->inodes_per_group = SWAP_LE32(TT.inodespg); + sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups); - // Determine free inodes. - temp = TT.inodespg*TT.groups - INODES_RESERVED; - if (temp < TT.treeinodes) error_exit("Not enough inodes.\n"); - sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes); + // Determine free inodes. + temp = TT.inodespg*TT.groups - INODES_RESERVED; + if (temp < TT.treeinodes) error_exit("Not enough inodes.\n"); + sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes); - // Fill out the rest of the superblock. - sb->max_mnt_count=0xFFFF; - sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL)); - sb->magic = SWAP_LE32(0xEF53); - sb->state = sb->errors = SWAP_LE16(1); + // Fill out the rest of the superblock. + sb->max_mnt_count=0xFFFF; + sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL)); + sb->magic = SWAP_LE32(0xEF53); + sb->state = sb->errors = SWAP_LE16(1); - sb->rev_level = SWAP_LE32(1); - sb->first_ino = SWAP_LE32(INODES_RESERVED+1); - sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode)); - sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE); - sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); + sb->rev_level = SWAP_LE32(1); + sb->first_ino = SWAP_LE32(INODES_RESERVED+1); + sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode)); + sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE); + sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); - create_uuid(sb->uuid); - - // TODO If we're called as mke3fs or mkfs.ext3, do a journal. + create_uuid(sb->uuid); - //if (strchr(toys.which->name,'3')) - // sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL); + // TODO If we're called as mke3fs or mkfs.ext3, do a journal. + + //if (strchr(toys.which->name,'3')) + // sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL); } // Does this group contain a superblock backup (and group descriptor table)? static int is_sb_group(uint32_t group) { - int i; - - // Superblock backups are on groups 0, 1, and powers of 3, 5, and 7. - if(!group || group==1) return 1; - for (i=3; i<9; i+=2) { - int j = i; - while (j<group) j*=i; - if (j==group) return 1; - } - return 0; + int i; + + // Superblock backups are on groups 0, 1, and powers of 3, 5, and 7. + if(!group || group==1) return 1; + for (i=3; i<9; i+=2) { + int j = i; + while (j<group) j*=i; + if (j==group) return 1; + } + return 0; } - + // Number of blocks used in group by optional superblock/group list backup. static int group_superblock_overhead(uint32_t group) { - int used; + int used; - if (!is_sb_group(group)) return 0; + if (!is_sb_group(group)) return 0; - // How many blocks does the group descriptor table take up? - used = TT.groups * sizeof(struct ext2_group); - used += TT.blocksize - 1; - used /= TT.blocksize; - // Plus the superblock itself. - used++; - // And a corner case. - if (!group && TT.blocksize == 1024) used++; + // How many blocks does the group descriptor table take up? + used = TT.groups * sizeof(struct ext2_group); + used += TT.blocksize - 1; + used /= TT.blocksize; + // Plus the superblock itself. + used++; + // And a corner case. + if (!group && TT.blocksize == 1024) used++; - return used; + return used; } // Number of blocks used in group to store superblock/group/inode list static int group_overhead(uint32_t group) { - // Return superblock backup overhead (if any), plus block/inode - // allocation bitmaps, plus inode tables. - return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg) - / (TT.blocksize/sizeof(struct ext2_inode)); + // Return superblock backup overhead (if any), plus block/inode + // allocation bitmaps, plus inode tables. + return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg) + / (TT.blocksize/sizeof(struct ext2_inode)); } // In bitmap "array" set "len" bits starting at position "start" (from 0). static void bits_set(char *array, int start, int len) { - while(len) { - if ((start&7) || len<8) { - array[start/8]|=(1<<(start&7)); - start++; - len--; - } else { - array[start/8]=255; - start+=8; - len-=8; - } - } + while(len) { + if ((start&7) || len<8) { + array[start/8]|=(1<<(start&7)); + start++; + len--; + } else { + array[start/8]=255; + start+=8; + len-=8; + } + } } // Seek past len bytes (to maintain sparse file), or write zeroes if output // not seekable static void put_zeroes(int len) { - if(-1 == lseek(TT.fsfd, len, SEEK_SET)) { - memset(toybuf, 0, sizeof(toybuf)); - while (len) { - int out = len > sizeof(toybuf) ? sizeof(toybuf) : len; - xwrite(TT.fsfd, toybuf, out); - len -= out; - } - } + if(-1 == lseek(TT.fsfd, len, SEEK_SET)) { + memset(toybuf, 0, sizeof(toybuf)); + while (len) { + int out = len > sizeof(toybuf) ? sizeof(toybuf) : len; + xwrite(TT.fsfd, toybuf, out); + len -= out; + } + } } // Fill out an inode structure from struct stat info in dirtree. static void fill_inode(struct ext2_inode *in, struct dirtree *that) { - uint32_t fbu[15]; - int temp; - - file_blocks_used(that->st.st_size, fbu); - - // If that inode needs data blocks allocated to it. - if (that->st.st_size) { - int i, group = TT.nextblock/TT.blockbits; - - // TODO: teach this about indirect blocks. - for (i=0; i<15; i++) { - // If we just jumped into a new group, skip group overhead blocks. - while (group >= TT.nextgroup) - TT.nextblock += group_overhead(TT.nextgroup++); - } - } - // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m) - in->mode = SWAP_LE32(that->st.st_mode); - - in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF); - in->uid_high = SWAP_LE16(that->st.st_uid >> 16); - in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF); - in->gid_high = SWAP_LE16(that->st.st_gid >> 16); - in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF); - - // Contortions to make the compiler not generate a warning for x>>32 - // when x is 32 bits. The optimizer should clean this up. - if (sizeof(that->st.st_size) > 4) temp = 32; - else temp = 0; - if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp); - - in->atime = SWAP_LE32(that->st.st_atime); - in->ctime = SWAP_LE32(that->st.st_ctime); - in->mtime = SWAP_LE32(that->st.st_mtime); - - in->links_count = SWAP_LE16(that->st.st_nlink); - in->blocks = SWAP_LE32(that->st.st_blocks); - // in->faddr + uint32_t fbu[15]; + int temp; + + file_blocks_used(that->st.st_size, fbu); + + // If that inode needs data blocks allocated to it. + if (that->st.st_size) { + int i, group = TT.nextblock/TT.blockbits; + + // TODO: teach this about indirect blocks. + for (i=0; i<15; i++) { + // If we just jumped into a new group, skip group overhead blocks. + while (group >= TT.nextgroup) + TT.nextblock += group_overhead(TT.nextgroup++); + } + } + // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m) + in->mode = SWAP_LE32(that->st.st_mode); + + in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF); + in->uid_high = SWAP_LE16(that->st.st_uid >> 16); + in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF); + in->gid_high = SWAP_LE16(that->st.st_gid >> 16); + in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF); + + // Contortions to make the compiler not generate a warning for x>>32 + // when x is 32 bits. The optimizer should clean this up. + if (sizeof(that->st.st_size) > 4) temp = 32; + else temp = 0; + if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp); + + in->atime = SWAP_LE32(that->st.st_atime); + in->ctime = SWAP_LE32(that->st.st_ctime); + in->mtime = SWAP_LE32(that->st.st_mtime); + + in->links_count = SWAP_LE16(that->st.st_nlink); + in->blocks = SWAP_LE32(that->st.st_blocks); + // in->faddr } // Works like an archiver. @@ -435,224 +433,224 @@ static void fill_inode(struct ext2_inode *in, struct dirtree *that) void mke2fs_main(void) { - int i, temp; - off_t length; - uint32_t usedblocks, usedinodes, dtiblk, dtbblk; - struct dirtree *dti, *dtb; - - // Handle command line arguments. - - if (toys.optargs[1]) { - sscanf(toys.optargs[1], "%u", &TT.blocks); - temp = O_RDWR|O_CREAT; - } else temp = O_RDWR; - if (!TT.reserved_percent) TT.reserved_percent = 5; - - // TODO: Check if filesystem is mounted here - - // For mke?fs, open file. For gene?fs, create file. - TT.fsfd = xcreate(*toys.optargs, temp, 0777); - - // Determine appropriate block size and block count from file length. - // (If no length, default to 4k. They can override it on the cmdline.) - - length = fdlength(TT.fsfd); - if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096; - TT.blockbits = 8*TT.blocksize; - if (!TT.blocks) TT.blocks = length/TT.blocksize; - - // Collect gene2fs list or lost+found, calculate requirements. - - if (TT.gendir) { - strncpy(toybuf, TT.gendir, sizeof(toybuf)); - dti = dirtree_read(toybuf, NULL, NULL); - } else { - dti = xzalloc(sizeof(struct dirtree)+11); - strcpy(dti->name, "lost+found"); - dti->st.st_mode = S_IFDIR|0755; - dti->st.st_ctime = dti->st.st_mtime = time(NULL); - } - - // Add root directory inode. This is iterated through for when finding - // blocks, but not when finding inodes. The tree's parent pointers don't - // point back into this. - - dtb = xzalloc(sizeof(struct dirtree)+1); - dtb->st.st_mode = S_IFDIR|0755; - dtb->st.st_ctime = dtb->st.st_mtime = time(NULL); - dtb->child = dti; - - // Figure out how much space is used by preset files - length = check_treesize(dtb, &(dtb->st.st_size)); - check_treelinks(dtb); - - // Figure out how many total inodes we need. - - if (!TT.inodes) { - if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192; - TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode; - } - - // If we're generating a filesystem and have no idea how many blocks it - // needs, start with a minimal guess, find the overhead of that many - // groups, and loop until this is enough groups to store this many blocks. - if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1; - else TT.groups = div_round_up(TT.blocks, TT.blockbits); - - for (;;) { - temp = TT.treeblocks; - - for (i = 0; i<TT.groups; i++) temp += group_overhead(i); - - if (TT.blocks) { - if (TT.blocks < temp) error_exit("Not enough space.\n"); - break; - } - if (temp <= TT.groups * TT.blockbits) { - TT.blocks = temp; - break; - } - TT.groups++; - } - TT.freeblocks = TT.blocks - temp; - - // Now we know all the TT data, initialize superblock structure. - - init_superblock(&TT.sb); - - // Start writing. Skip the first 1k to avoid the boot sector (if any). - put_zeroes(1024); - - // Loop through block groups, write out each one. - dtiblk = dtbblk = usedblocks = usedinodes = 0; - for (i=0; i<TT.groups; i++) { - struct ext2_inode *in = (struct ext2_inode *)toybuf; - uint32_t start, itable, used, end; - int j, slot; - - // Where does this group end? - end = TT.blockbits; - if ((i+1)*TT.blockbits > TT.blocks) end = TT.blocks & (TT.blockbits-1); - - // Blocks used by inode table - itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize; - - // If a superblock goes here, write it out. - start = group_superblock_overhead(i); - if (start) { - struct ext2_group *bg = (struct ext2_group *)toybuf; - int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes; - - TT.sb.block_group_nr = SWAP_LE16(i); - - // Write superblock and pad it up to block size - xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock)); - temp = TT.blocksize - sizeof(struct ext2_superblock); - if (!i && TT.blocksize > 1024) temp -= 1024; - memset(toybuf, 0, TT.blocksize); - xwrite(TT.fsfd, toybuf, temp); - - // Loop through groups to write group descriptor table. - for(j=0; j<TT.groups; j++) { - - // Figure out what sector this group starts in. - used = group_superblock_overhead(j); - - // Find next array slot in this block (flush block if full). - slot = j % (TT.blocksize/sizeof(struct ext2_group)); - if (!slot) { - if (j) xwrite(TT.fsfd, bg, TT.blocksize); - memset(bg, 0, TT.blocksize); - } - - // How many free inodes in this group? - temp = TT.inodespg; - if (!i) temp -= INODES_RESERVED; - if (temp > treeinodes) { - treeinodes -= temp; - temp = 0; - } else { - temp -= treeinodes; - treeinodes = 0; - } - bg[slot].free_inodes_count = SWAP_LE16(temp); - - // How many free blocks in this group? - temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2; - temp = end-used-temp; - if (temp > treeblocks) { - treeblocks -= temp; - temp = 0; - } else { - temp -= treeblocks; - treeblocks = 0; - } - bg[slot].free_blocks_count = SWAP_LE32(temp); - - // Fill out rest of group structure - used += j*TT.blockbits; - bg[slot].block_bitmap = SWAP_LE32(used++); - bg[slot].inode_bitmap = SWAP_LE32(used++); - bg[slot].inode_table = SWAP_LE32(used); - bg[slot].used_dirs_count = 0; // (TODO) - } - xwrite(TT.fsfd, bg, TT.blocksize); - } - - // Now write out stuff that every block group has. - - // Write block usage bitmap - - start += 2 + itable; - memset(toybuf, 0, TT.blocksize); - bits_set(toybuf, 0, start); - bits_set(toybuf, end, TT.blockbits-end); - temp = TT.treeblocks - usedblocks; - if (temp) { - if (end-start > temp) temp = end-start; - bits_set(toybuf, start, temp); - } - xwrite(TT.fsfd, toybuf, TT.blocksize); - - // Write inode bitmap - memset(toybuf, 0, TT.blocksize); - j = 0; - if (!i) bits_set(toybuf, 0, j = INODES_RESERVED); - bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg); - temp = TT.treeinodes - usedinodes; - if (temp) { - if (slot-j > temp) temp = slot-j; - bits_set(toybuf, j, temp); - } - xwrite(TT.fsfd, toybuf, TT.blocksize); - - // Write inode table for this group (TODO) - for (j = 0; j<TT.inodespg; j++) { - slot = j % (TT.blocksize/sizeof(struct ext2_inode)); - if (!slot) { - if (j) xwrite(TT.fsfd, in, TT.blocksize); - memset(in, 0, TT.blocksize); - } - if (!i && j<INODES_RESERVED) { - // Write root inode - if (j == 2) fill_inode(in+slot, dtb); - } else if (dti) { - fill_inode(in+slot, dti); - dti = treenext(dti); - } - } - xwrite(TT.fsfd, in, TT.blocksize); - - while (dtb) { - // TODO write index data block - // TODO write root directory data block - // TODO write directory data block - // TODO write file data block - put_zeroes(TT.blocksize); - start++; - if (start == end) break; - } - // Write data blocks (TODO) - put_zeroes((end-start) * TT.blocksize); - } + int i, temp; + off_t length; + uint32_t usedblocks, usedinodes, dtiblk, dtbblk; + struct dirtree *dti, *dtb; + + // Handle command line arguments. + + if (toys.optargs[1]) { + sscanf(toys.optargs[1], "%u", &TT.blocks); + temp = O_RDWR|O_CREAT; + } else temp = O_RDWR; + if (!TT.reserved_percent) TT.reserved_percent = 5; + + // TODO: Check if filesystem is mounted here + + // For mke?fs, open file. For gene?fs, create file. + TT.fsfd = xcreate(*toys.optargs, temp, 0777); + + // Determine appropriate block size and block count from file length. + // (If no length, default to 4k. They can override it on the cmdline.) + + length = fdlength(TT.fsfd); + if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096; + TT.blockbits = 8*TT.blocksize; + if (!TT.blocks) TT.blocks = length/TT.blocksize; + + // Collect gene2fs list or lost+found, calculate requirements. + + if (TT.gendir) { + strncpy(toybuf, TT.gendir, sizeof(toybuf)); + dti = dirtree_read(toybuf, NULL, NULL); + } else { + dti = xzalloc(sizeof(struct dirtree)+11); + strcpy(dti->name, "lost+found"); + dti->st.st_mode = S_IFDIR|0755; + dti->st.st_ctime = dti->st.st_mtime = time(NULL); + } + + // Add root directory inode. This is iterated through for when finding + // blocks, but not when finding inodes. The tree's parent pointers don't + // point back into this. + + dtb = xzalloc(sizeof(struct dirtree)+1); + dtb->st.st_mode = S_IFDIR|0755; + dtb->st.st_ctime = dtb->st.st_mtime = time(NULL); + dtb->child = dti; + + // Figure out how much space is used by preset files + length = check_treesize(dtb, &(dtb->st.st_size)); + check_treelinks(dtb); + + // Figure out how many total inodes we need. + + if (!TT.inodes) { + if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192; + TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode; + } + + // If we're generating a filesystem and have no idea how many blocks it + // needs, start with a minimal guess, find the overhead of that many + // groups, and loop until this is enough groups to store this many blocks. + if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1; + else TT.groups = div_round_up(TT.blocks, TT.blockbits); + + for (;;) { + temp = TT.treeblocks; + + for (i = 0; i<TT.groups; i++) temp += group_overhead(i); + + if (TT.blocks) { + if (TT.blocks < temp) error_exit("Not enough space.\n"); + break; + } + if (temp <= TT.groups * TT.blockbits) { + TT.blocks = temp; + break; + } + TT.groups++; + } + TT.freeblocks = TT.blocks - temp; + + // Now we know all the TT data, initialize superblock structure. + + init_superblock(&TT.sb); + + // Start writing. Skip the first 1k to avoid the boot sector (if any). + put_zeroes(1024); + + // Loop through block groups, write out each one. + dtiblk = dtbblk = usedblocks = usedinodes = 0; + for (i=0; i<TT.groups; i++) { + struct ext2_inode *in = (struct ext2_inode *)toybuf; + uint32_t start, itable, used, end; + int j, slot; + + // Where does this group end? + end = TT.blockbits; + if ((i+1)*TT.blockbits > TT.blocks) end = TT.blocks & (TT.blockbits-1); + + // Blocks used by inode table + itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize; + + // If a superblock goes here, write it out. + start = group_superblock_overhead(i); + if (start) { + struct ext2_group *bg = (struct ext2_group *)toybuf; + int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes; + + TT.sb.block_group_nr = SWAP_LE16(i); + + // Write superblock and pad it up to block size + xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock)); + temp = TT.blocksize - sizeof(struct ext2_superblock); + if (!i && TT.blocksize > 1024) temp -= 1024; + memset(toybuf, 0, TT.blocksize); + xwrite(TT.fsfd, toybuf, temp); + + // Loop through groups to write group descriptor table. + for(j=0; j<TT.groups; j++) { + + // Figure out what sector this group starts in. + used = group_superblock_overhead(j); + + // Find next array slot in this block (flush block if full). + slot = j % (TT.blocksize/sizeof(struct ext2_group)); + if (!slot) { + if (j) xwrite(TT.fsfd, bg, TT.blocksize); + memset(bg, 0, TT.blocksize); + } + + // How many free inodes in this group? + temp = TT.inodespg; + if (!i) temp -= INODES_RESERVED; + if (temp > treeinodes) { + treeinodes -= temp; + temp = 0; + } else { + temp -= treeinodes; + treeinodes = 0; + } + bg[slot].free_inodes_count = SWAP_LE16(temp); + + // How many free blocks in this group? + temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2; + temp = end-used-temp; + if (temp > treeblocks) { + treeblocks -= temp; + temp = 0; + } else { + temp -= treeblocks; + treeblocks = 0; + } + bg[slot].free_blocks_count = SWAP_LE32(temp); + + // Fill out rest of group structure + used += j*TT.blockbits; + bg[slot].block_bitmap = SWAP_LE32(used++); + bg[slot].inode_bitmap = SWAP_LE32(used++); + bg[slot].inode_table = SWAP_LE32(used); + bg[slot].used_dirs_count = 0; // (TODO) + } + xwrite(TT.fsfd, bg, TT.blocksize); + } + + // Now write out stuff that every block group has. + + // Write block usage bitmap + + start += 2 + itable; + memset(toybuf, 0, TT.blocksize); + bits_set(toybuf, 0, start); + bits_set(toybuf, end, TT.blockbits-end); + temp = TT.treeblocks - usedblocks; + if (temp) { + if (end-start > temp) temp = end-start; + bits_set(toybuf, start, temp); + } + xwrite(TT.fsfd, toybuf, TT.blocksize); + + // Write inode bitmap + memset(toybuf, 0, TT.blocksize); + j = 0; + if (!i) bits_set(toybuf, 0, j = INODES_RESERVED); + bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg); + temp = TT.treeinodes - usedinodes; + if (temp) { + if (slot-j > temp) temp = slot-j; + bits_set(toybuf, j, temp); + } + xwrite(TT.fsfd, toybuf, TT.blocksize); + + // Write inode table for this group (TODO) + for (j = 0; j<TT.inodespg; j++) { + slot = j % (TT.blocksize/sizeof(struct ext2_inode)); + if (!slot) { + if (j) xwrite(TT.fsfd, in, TT.blocksize); + memset(in, 0, TT.blocksize); + } + if (!i && j<INODES_RESERVED) { + // Write root inode + if (j == 2) fill_inode(in+slot, dtb); + } else if (dti) { + fill_inode(in+slot, dti); + dti = treenext(dti); + } + } + xwrite(TT.fsfd, in, TT.blocksize); + + while (dtb) { + // TODO write index data block + // TODO write root directory data block + // TODO write directory data block + // TODO write file data block + put_zeroes(TT.blocksize); + start++; + if (start == end) break; + } + // Write data blocks (TODO) + put_zeroes((end-start) * TT.blocksize); + } } diff --git a/toys/other/mkswap.c b/toys/other/mkswap.c index 1e96c196..ff864244 100644 --- a/toys/other/mkswap.c +++ b/toys/other/mkswap.c @@ -1,40 +1,38 @@ -/* vi: set sw=4 ts=4: - * - * mkswap.c - Format swap device. +/* mkswap.c - Format swap device. * * Copyright 2009 Rob Landley <rob@landley.net> USE_MKSWAP(NEWTOY(mkswap, "<1>1", TOYFLAG_SBIN)) config MKSWAP - bool "mkswap" - default y - help - usage: mkswap DEVICE + bool "mkswap" + default y + help + usage: mkswap DEVICE - Sets up a Linux swap area on a device or file. + Sets up a Linux swap area on a device or file. */ #include "toys.h" void mkswap_main(void) { - int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); - off_t len = fdlength(fd); - unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf; + int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); + off_t len = fdlength(fd); + unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf; - // Write header. Note that older kernel versions checked signature - // on disk (not in cache) during swapon, so sync after writing. + // Write header. Note that older kernel versions checked signature + // on disk (not in cache) during swapon, so sync after writing. - swap[0] = 1; - swap[1] = pages; - xlseek(fd, 1024, SEEK_SET); - xwrite(fd, swap, 129*sizeof(unsigned int)); - xlseek(fd, pagesize-10, SEEK_SET); - xwrite(fd, "SWAPSPACE2", 10); - fsync(fd); + swap[0] = 1; + swap[1] = pages; + xlseek(fd, 1024, SEEK_SET); + xwrite(fd, swap, 129*sizeof(unsigned int)); + xlseek(fd, pagesize-10, SEEK_SET); + xwrite(fd, "SWAPSPACE2", 10); + fsync(fd); - if (CFG_TOYBOX_FREE) close(fd); + if (CFG_TOYBOX_FREE) close(fd); - printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024)); + printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024)); } diff --git a/toys/other/modinfo.c b/toys/other/modinfo.c index 0c5f177f..36a38382 100644 --- a/toys/other/modinfo.c +++ b/toys/other/modinfo.c @@ -1,101 +1,92 @@ -/* vi: set sw=4 ts=4: - * - * modinfo.c - Display module info +/* modinfo.c - Display module info * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> - * USE_MODINFO(NEWTOY(modinfo, "<1F:0", TOYFLAG_BIN)) config MODINFO - bool "modinfo" - default y - help - usage: modinfo [-0] [-F field] [modulename...] + bool "modinfo" + default y + help + usage: modinfo [-0] [-F field] [modulename...] */ #define FOR_modinfo #include "toys.h" GLOBALS( - char *field; + char *field; ) static const char *modinfo_tags[] = { - "alias", "license", "description", "author", "vermagic", - "srcversion", "intree", "parm", "depends", + "alias", "license", "description", "author", "vermagic", + "srcversion", "intree", "parm", "depends", }; static void output_field(const char *field, const char *value) { - int len; - - if (TT.field && strcmp(TT.field, field) != 0) - return; - - len = strlen(field); - - if (TT.field) - xprintf("%s", value); - else - xprintf("%s:%*s%s", - field, 15 - len, "", value); - if (toys.optflags & FLAG_0) - xwrite(fileno(stdout), "\0", 1); - else - xputs(""); + int len; + + if (TT.field && strcmp(TT.field, field) != 0) return; + + len = strlen(field); + + if (TT.field) xprintf("%s", value); + else xprintf("%s:%*s%s", field, 15 - len, "", value); + if (toys.optflags & FLAG_0) xwrite(fileno(stdout), "\0", 1); + else xputs(""); } static void modinfo_file(struct dirtree *dir) { - int fd, len, i; - char *buf, *pos; - char *full_name; - - full_name = dirtree_path(dir, NULL); - - output_field("filename", full_name); - fd = xopen(full_name, O_RDONLY); - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); - - for (pos = buf; pos < buf + len + 10; pos++) { - if (*pos) - continue; - - for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) { - const char *str = modinfo_tags[i]; - int len = strlen(str); - if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=') - output_field(str, &pos[len + 2]); - } + int fd, len, i; + char *buf, *pos; + char *full_name; + + full_name = dirtree_path(dir, NULL); + + output_field("filename", full_name); + fd = xopen(full_name, O_RDONLY); + len = fdlength(fd); + buf = xmalloc(len); + xreadall(fd, buf, len); + + for (pos = buf; pos < buf + len + 10; pos++) { + if (*pos) continue; + + for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) { + const char *str = modinfo_tags[i]; + int len = strlen(str); + if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=') + output_field(str, &pos[len + 2]); } + } - free(full_name); - free(buf); - close(fd); + free(full_name); + free(buf); + close(fd); } static int check_module(struct dirtree *new) { - if (S_ISREG(new->st.st_mode)) { - char **s; - for (s = toys.optargs; *s; s++) { - int len = strlen(*s); - if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko")) - modinfo_file(new); - } + if (S_ISREG(new->st.st_mode)) { + char **s; + for (s = toys.optargs; *s; s++) { + int len = strlen(*s); + if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko")) + modinfo_file(new); } + } - return dirtree_notdotdot(new); + return dirtree_notdotdot(new); } void modinfo_main(void) { - struct utsname uts; - if (uname(&uts) < 0) perror_exit("bad uname"); - sprintf(toybuf, "/lib/modules/%s", uts.release); - dirtree_read(toybuf, check_module); + struct utsname uts; + + if (uname(&uts) < 0) perror_exit("bad uname"); + sprintf(toybuf, "/lib/modules/%s", uts.release); + dirtree_read(toybuf, check_module); } diff --git a/toys/other/mountpoint.c b/toys/other/mountpoint.c index fe63b725..29b8ae67 100644 --- a/toys/other/mountpoint.c +++ b/toys/other/mountpoint.c @@ -1,20 +1,19 @@ -/* vi: set sw=4 ts=4: - * - * mountpoint.c - Check if a directory is a mountpoint. +/* mountpoint.c - Check if a directory is a mountpoint. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx", TOYFLAG_BIN)) config MOUNTPOINT - bool "mountpoint" - default y - help - usage: mountpoint [-q] [-d] directory - mountpoint [-q] [-x] device - -q Be quiet, return zero if directory is a mountpoint - -d Print major/minor device number of the directory - -x Print major/minor device number of the block device + bool "mountpoint" + default y + help + usage: mountpoint [-q] [-d] directory + mountpoint [-q] [-x] device + + -q Be quiet, return zero if directory is a mountpoint + -d Print major/minor device number of the directory + -x Print major/minor device number of the block device */ #define FOR_mountpoint @@ -22,34 +21,34 @@ config MOUNTPOINT void mountpoint_main(void) { - struct stat st1, st2; - int res = 0; - int quiet = toys.optflags & FLAG_q; - toys.exitval = 1; // be pessimistic - strncpy(toybuf, toys.optargs[0], sizeof(toybuf)); - if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) - perror_exit("%s", toybuf); + struct stat st1, st2; + int res = 0; + int quiet = toys.optflags & FLAG_q; + toys.exitval = 1; // be pessimistic + strncpy(toybuf, toys.optargs[0], sizeof(toybuf)); + if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) + perror_exit("%s", toybuf); - if (toys.optflags & FLAG_x){ - if (S_ISBLK(st1.st_mode)) { - if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev)); - toys.exitval = 0; - return; - } - if (!quiet) printf("%s: not a block device\n", toybuf); - return; - } + if (toys.optflags & FLAG_x){ + if (S_ISBLK(st1.st_mode)) { + if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev)); + toys.exitval = 0; + return; + } + if (!quiet) printf("%s: not a block device\n", toybuf); + return; + } - if(!S_ISDIR(st1.st_mode)){ - if (!quiet) printf("%s: not a directory\n", toybuf); - return; - } - strncat(toybuf, "/..", sizeof(toybuf)); - stat(toybuf, &st2); - res = (st1.st_dev != st2.st_dev) || - (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); - if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not "); - if (toys.optflags & FLAG_d) - printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev)); - toys.exitval = res ? 0 : 1; + if(!S_ISDIR(st1.st_mode)){ + if (!quiet) printf("%s: not a directory\n", toybuf); + return; + } + strncat(toybuf, "/..", sizeof(toybuf)); + stat(toybuf, &st2); + res = (st1.st_dev != st2.st_dev) || + (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); + if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not "); + if (toys.optflags & FLAG_d) + printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev)); + toys.exitval = res ? 0 : 1; } diff --git a/toys/other/netcat.c b/toys/other/netcat.c index 2e90737d..0173e6db 100644 --- a/toys/other/netcat.c +++ b/toys/other/netcat.c @@ -1,46 +1,42 @@ -/* vi: set sw=4 ts=4: - * - * netcat.c - Forward stdin/stdout to a file or network connection. +/* netcat.c - Forward stdin/stdout to a file or network connection. * * Copyright 2007 Rob Landley <rob@landley.net> * * TODO: udp, ipv6, genericize for telnet/microcom/tail-f - USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) config NETCAT - bool "netcat" - default y - help - usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND] - - -w SECONDS timeout for connection - -p local port number - -s local ipv4 address - -q SECONDS quit this many seconds after EOF on stdin. - -f use FILENAME (ala /dev/ttyS0) instead of network + bool "netcat" + default y + help + usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND] - Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with - netcat -f to connect to a serial port. + -w SECONDS timeout for connection + -p local port number + -s local ipv4 address + -q SECONDS quit this many seconds after EOF on stdin. + -f use FILENAME (ala /dev/ttyS0) instead of network + Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with + netcat -f to connect to a serial port. config NETCAT_LISTEN - bool "netcat server options (-let)" - default y - depends on NETCAT - help - -t allocate tty (must come before -l or -L) - -l listen for one incoming connection. - -L listen for multiple incoming connections (server mode). - - Any additional command line arguments after -l or -L are executed - to handle each incoming connection. If none, the connection is - forwarded to stdin/stdout. - - For a quick-and-dirty server, try something like: - netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l + bool "netcat server options (-let)" + default y + depends on NETCAT + help + -t allocate tty (must come before -l or -L) + -l listen for one incoming connection. + -L listen for multiple incoming connections (server mode). + + Any additional command line arguments after -l or -L are executed + to handle each incoming connection. If none, the connection is + forwarded to stdin/stdout. + + For a quick-and-dirty server, try something like: + netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l */ #define FOR_netcat @@ -48,33 +44,33 @@ config NETCAT_LISTEN #include "toynet.h" GLOBALS( - char *filename; // -f read from filename instead of network - long quit_delay; // -q Exit after EOF from stdin after # seconds. - char *source_address; // -s Bind to a specific source address. - long port; // -p Bind to a specific source port. - long wait; // -w Wait # seconds for a connection. + char *filename; // -f read from filename instead of network + long quit_delay; // -q Exit after EOF from stdin after # seconds. + char *source_address; // -s Bind to a specific source address. + long port; // -p Bind to a specific source port. + long wait; // -w Wait # seconds for a connection. ) static void timeout(int signum) { - if (TT.wait) error_exit("Timeout"); - exit(0); + if (TT.wait) error_exit("Timeout"); + exit(0); } static void set_alarm(int seconds) { - signal(SIGALRM, seconds ? timeout : SIG_DFL); - alarm(seconds); + signal(SIGALRM, seconds ? timeout : SIG_DFL); + alarm(seconds); } // Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name. static void lookup_name(char *name, uint32_t *result) { - struct hostent *hostbyname; + struct hostent *hostbyname; - hostbyname = gethostbyname(name); - if (!hostbyname) error_exit("no host '%s'", name); - *result = *(uint32_t *)*hostbyname->h_addr_list; + hostbyname = gethostbyname(name); + if (!hostbyname) error_exit("no host '%s'", name); + *result = *(uint32_t *)*hostbyname->h_addr_list; } // Worry about a fancy lookup later. @@ -85,143 +81,142 @@ static void lookup_port(char *str, uint16_t *port) void netcat_main(void) { - int sockfd=-1, pollcount=2; - struct pollfd pollfds[2]; - - memset(pollfds, 0, 2*sizeof(struct pollfd)); - pollfds[0].events = pollfds[1].events = POLLIN; - set_alarm(TT.wait); - - // The argument parsing logic can't make "<2" conditional on other - // arguments like -f and -l, so we do it by hand here. - if (toys.optflags&FLAG_f) { - if (toys.optc) toys.exithelp++; - } else if (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2) toys.exithelp++; - - if (toys.exithelp) error_exit("Argument count wrong"); - - if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR); - else { - int temp; - struct sockaddr_in address; - - // Setup socket - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (-1 == sockfd) perror_exit("socket"); - fcntl(sockfd, F_SETFD, FD_CLOEXEC); - temp = 1; - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp)); - memset(&address, 0, sizeof(address)); - address.sin_family = AF_INET; - if (TT.source_address || TT.port) { - address.sin_port = SWAP_BE16(TT.port); - if (TT.source_address) - lookup_name(TT.source_address, (uint32_t *)&address.sin_addr); - if (bind(sockfd, (struct sockaddr *)&address, sizeof(address))) - perror_exit("bind"); - } - - // Dial out - - if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) { - // Figure out where to dial out to. - lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr); - lookup_port(toys.optargs[1], &address.sin_port); - temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); - if (temp<0) perror_exit("connect"); - pollfds[0].fd = sockfd; - - // Listen for incoming connections - - } else { - socklen_t len = sizeof(address); - - if (listen(sockfd, 5)) error_exit("listen"); - if (!TT.port) { - getsockname(sockfd, (struct sockaddr *)&address, &len); - printf("%d\n", SWAP_BE16(address.sin_port)); - fflush(stdout); - } - // Do we need to return immediately because -l has arguments? - - if ((toys.optflags&FLAG_l) && toys.optc) { - if (fork()) goto cleanup; - close(0); - close(1); - close(2); - } - - for (;;) { - pid_t child = 0; - - // For -l, call accept from the _new_ thread. - - pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address, - &len); - if (pollfds[0].fd<0) perror_exit("accept"); - - // Do we need a tty? - - if (toys.optflags&FLAG_t) - child = forkpty(&(pollfds[1].fd), NULL, NULL, NULL); - - // Do we need to fork and/or redirect for exec? - - else { - if (toys.optflags&FLAG_L) child = fork(); - if (!child && toys.optc) { - int fd = pollfds[0].fd; - - if (!temp) close(sockfd); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - if (fd>2) close(fd); - } - } - - if (child<0) error_msg("Fork failed\n"); - if (child<1) break; - close(pollfds[0].fd); - } - } - } - - // We have a connection. Disarm timeout. - // (Does not play well with -L, but what _should_ that do?) - set_alarm(0); - - if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) { - execvp(*toys.optargs, toys.optargs); - error_exit("Exec failed"); - } - - // Poll loop copying stdin->socket and socket->stdout. - for (;;) { - int i; - - if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); - - for (i=0; i<pollcount; i++) { - if (pollfds[i].revents & POLLIN) { - int len = read(pollfds[i].fd, toybuf, sizeof(toybuf)); - if (len<1) goto dohupnow; - xwrite(i ? pollfds[0].fd : 1, toybuf, len); - } else if (pollfds[i].revents & POLLHUP) { + int sockfd=-1, pollcount=2; + struct pollfd pollfds[2]; + + memset(pollfds, 0, 2*sizeof(struct pollfd)); + pollfds[0].events = pollfds[1].events = POLLIN; + set_alarm(TT.wait); + + // The argument parsing logic can't make "<2" conditional on other + // arguments like -f and -l, so we do it by hand here. + if (toys.optflags&FLAG_f) { + if (toys.optc) toys.exithelp++; + } else if (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2) toys.exithelp++; + + if (toys.exithelp) error_exit("Argument count wrong"); + + if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR); + else { + int temp; + struct sockaddr_in address; + + // Setup socket + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (-1 == sockfd) perror_exit("socket"); + fcntl(sockfd, F_SETFD, FD_CLOEXEC); + temp = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp)); + memset(&address, 0, sizeof(address)); + address.sin_family = AF_INET; + if (TT.source_address || TT.port) { + address.sin_port = SWAP_BE16(TT.port); + if (TT.source_address) + lookup_name(TT.source_address, (uint32_t *)&address.sin_addr); + if (bind(sockfd, (struct sockaddr *)&address, sizeof(address))) + perror_exit("bind"); + } + + // Dial out + + if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) { + // Figure out where to dial out to. + lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr); + lookup_port(toys.optargs[1], &address.sin_port); + temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); + if (temp<0) perror_exit("connect"); + pollfds[0].fd = sockfd; + + // Listen for incoming connections + + } else { + socklen_t len = sizeof(address); + + if (listen(sockfd, 5)) error_exit("listen"); + if (!TT.port) { + getsockname(sockfd, (struct sockaddr *)&address, &len); + printf("%d\n", SWAP_BE16(address.sin_port)); + fflush(stdout); + } + // Do we need to return immediately because -l has arguments? + + if ((toys.optflags&FLAG_l) && toys.optc) { + if (fork()) goto cleanup; + close(0); + close(1); + close(2); + } + + for (;;) { + pid_t child = 0; + + // For -l, call accept from the _new_ thread. + + pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address, &len); + if (pollfds[0].fd<0) perror_exit("accept"); + + // Do we need a tty? + + if (toys.optflags&FLAG_t) + child = forkpty(&(pollfds[1].fd), NULL, NULL, NULL); + + // Do we need to fork and/or redirect for exec? + + else { + if (toys.optflags&FLAG_L) child = fork(); + if (!child && toys.optc) { + int fd = pollfds[0].fd; + + if (!temp) close(sockfd); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + if (fd>2) close(fd); + } + } + + if (child<0) error_msg("Fork failed\n"); + if (child<1) break; + close(pollfds[0].fd); + } + } + } + + // We have a connection. Disarm timeout. + // (Does not play well with -L, but what _should_ that do?) + set_alarm(0); + + if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) { + execvp(*toys.optargs, toys.optargs); + error_exit("Exec failed"); + } + + // Poll loop copying stdin->socket and socket->stdout. + for (;;) { + int i; + + if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); + + for (i=0; i<pollcount; i++) { + if (pollfds[i].revents & POLLIN) { + int len = read(pollfds[i].fd, toybuf, sizeof(toybuf)); + if (len<1) goto dohupnow; + xwrite(i ? pollfds[0].fd : 1, toybuf, len); + } else if (pollfds[i].revents & POLLHUP) { dohupnow: - // Close half-connection. This is needed for things like - // "echo GET / | netcat landley.net 80" - if (i) { - shutdown(pollfds[0].fd, SHUT_WR); - pollcount--; - set_alarm(TT.quit_delay); - } else goto cleanup; - } - } - } + // Close half-connection. This is needed for things like + // "echo GET / | netcat landley.net 80" + if (i) { + shutdown(pollfds[0].fd, SHUT_WR); + pollcount--; + set_alarm(TT.quit_delay); + } else goto cleanup; + } + } + } cleanup: - if (CFG_TOYBOX_FREE) { - close(pollfds[0].fd); - close(sockfd); - } + if (CFG_TOYBOX_FREE) { + close(pollfds[0].fd); + close(sockfd); + } } diff --git a/toys/other/oneit.c b/toys/other/oneit.c index 8bb482da..5bf4e941 100644 --- a/toys/other/oneit.c +++ b/toys/other/oneit.c @@ -1,27 +1,25 @@ -/* vi: set sw=4 ts=4: - * - * oneit.c - tiny init replacement to launch a single child process. +/* oneit.c - tiny init replacement to launch a single child process. * * Copyright 2005, 2007 by Rob Landley <rob@landley.net>. USE_ONEIT(NEWTOY(oneit, "^<1c:p", TOYFLAG_SBIN)) config ONEIT - bool "oneit" - default y - help - usage: oneit [-p] [-c /dev/tty0] command [...] + bool "oneit" + default y + help + usage: oneit [-p] [-c /dev/tty0] command [...] - A simple init program that runs a single supplied command line with a - controlling tty (so CTRL-C can kill it). + A simple init program that runs a single supplied command line with a + controlling tty (so CTRL-C can kill it). - -p Power off instead of rebooting when command exits. - -c Which console device to use. + -p Power off instead of rebooting when command exits. + -c Which console device to use. - The oneit command runs the supplied command line as a child process - (because PID 1 has signals blocked), attached to /dev/tty0, in its - own session. Then oneit reaps zombies until the child exits, at - which point it reboots (or with -p, powers off) the system. + The oneit command runs the supplied command line as a child process + (because PID 1 has signals blocked), attached to /dev/tty0, in its + own session. Then oneit reaps zombies until the child exits, at + which point it reboots (or with -p, powers off) the system. */ #define FOR_oneit @@ -29,7 +27,7 @@ config ONEIT #include <sys/reboot.h> GLOBALS( - char *console; + char *console; ) // The minimum amount of work necessary to get ctrl-c and such to work is: @@ -53,22 +51,21 @@ void oneit_main(void) if (pid) { // pid 1 just reaps zombies until it gets its child, then halts the system. - while (pid!=wait(&i)); + while (pid != wait(&i)); sync(); - // PID 1 can't call reboot() because it kills the task that calls it, - // which causes the kernel to panic before the actual reboot happens. - if (!vfork()) - reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT); - sleep(5); - _exit(1); + // PID 1 can't call reboot() because it kills the task that calls it, + // which causes the kernel to panic before the actual reboot happens. + if (!vfork()) reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT); + sleep(5); + _exit(1); } // Redirect stdio to /dev/tty0, with new session ID, so ctrl-c works. setsid(); for (i=0; i<3; i++) { close(i); - xopen(TT.console ? TT.console : "/dev/tty0",O_RDWR); + xopen(TT.console ? TT.console : "/dev/tty0", O_RDWR); } // Can't xexec() here, because we vforked so we don't want to error_exit(). diff --git a/toys/other/printenv.c b/toys/other/printenv.c index d5177468..e8bcf29b 100644 --- a/toys/other/printenv.c +++ b/toys/other/printenv.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * printenv.c - Print environment variables. +/* printenv.c - Print environment variables. * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> USE_PRINTENV(NEWTOY(printenv, "0(null)", TOYFLAG_USR|TOYFLAG_BIN)) config PRINTENV - bool "printenv" - default y - help - usage: printenv [-0] [env_var...] + bool "printenv" + default y + help + usage: printenv [-0] [env_var...] - Print environment variables. + Print environment variables. - -0 Use \0 as delimiter instead of \n + -0 Use \0 as delimiter instead of \n */ #include "toys.h" @@ -23,24 +21,23 @@ extern char **environ; void printenv_main(void) { - char **env, **var = toys.optargs; - char delim = '\n'; - - if (toys.optflags) delim = 0; - - do { - int catch = 0, len = *var ? strlen(*var) : 0; - - for (env = environ; *env; env++) { - char *out = *env; - if (*var) { - if (!strncmp(out, *var, len) && out[len] == '=') - out += len +1; - else continue; - } - xprintf("%s%c", out, delim); - catch++; - } - if (*var && !catch) toys.exitval = 1; - } while (*var && *(++var)); + char **env, **var = toys.optargs; + char delim = '\n'; + + if (toys.optflags) delim = 0; + + do { + int catch = 0, len = *var ? strlen(*var) : 0; + + for (env = environ; *env; env++) { + char *out = *env; + if (*var) { + if (!strncmp(out, *var, len) && out[len] == '=') out += len +1; + else continue; + } + xprintf("%s%c", out, delim); + catch++; + } + if (*var && !catch) toys.exitval = 1; + } while (*var && *(++var)); } diff --git a/toys/other/readlink.c b/toys/other/readlink.c index c579635c..b7f77f91 100644 --- a/toys/other/readlink.c +++ b/toys/other/readlink.c @@ -1,43 +1,41 @@ -/* vi: set sw=4 ts=4: - * - * readlink.c - Return string representation of a symbolic link. +/* readlink.c - Return string representation of a symbolic link. * * Copyright 2007 Rob Landley <rob@landley.net> USE_READLINK(NEWTOY(readlink, "<1f", TOYFLAG_BIN)) config READLINK - bool "readlink" - default n - help - usage: readlink + bool "readlink" + default n + help + usage: readlink - Show what a symbolic link points to. + Show what a symbolic link points to. config READLINK_F - bool "readlink -f" - default n - depends on READLINK - help - usage: readlink [-f] - - -f Show full cannonical path, with no symlinks in it. Returns - nonzero if nothing could currently exist at this location. + bool "readlink -f" + default n + depends on READLINK + help + usage: readlink [-f] + + -f Show full cannonical path, with no symlinks in it. Returns + nonzero if nothing could currently exist at this location. */ #include "toys.h" void readlink_main(void) { - char *s; + char *s; - // Calculating full cannonical path? + // Calculating full cannonical path? - if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs); - else s = xreadlink(*toys.optargs); + if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs); + else s = xreadlink(*toys.optargs); - if (s) { - xputs(s); - if (CFG_TOYBOX_FREE) free(s); - } else toys.exitval = 1; + if (s) { + xputs(s); + if (CFG_TOYBOX_FREE) free(s); + } else toys.exitval = 1; } diff --git a/toys/other/realpath.c b/toys/other/realpath.c index 1503c455..dc75840b 100644 --- a/toys/other/realpath.c +++ b/toys/other/realpath.c @@ -1,29 +1,28 @@ -/* vi: set sw=4 ts=4: - * - * realpath.c - Return the canonical version of a pathname +/* realpath.c - Return the canonical version of a pathname * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> USE_REALPATH(NEWTOY(realpath, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config REALPATH - bool "realpath" - default y - help - usage: realpath FILE... + bool "realpath" + default y + help + usage: realpath FILE... - Display the canonical absolute pathname + Display the canonical absolute pathname */ #include "toys.h" void realpath_main(void) { - char **s = toys.optargs; - for (s = toys.optargs; *s; s++) { - if (!realpath(*s, toybuf)) { - perror_msg("cannot access '%s'", *s); - toys.exitval = 1; - } else xputs(toybuf); - } + char **s = toys.optargs; + + for (s = toys.optargs; *s; s++) { + if (!realpath(*s, toybuf)) { + perror_msg("cannot access '%s'", *s); + toys.exitval = 1; + } else xputs(toybuf); + } } diff --git a/toys/other/rmmod.c b/toys/other/rmmod.c index 18ace3fa..093eb8a1 100644 --- a/toys/other/rmmod.c +++ b/toys/other/rmmod.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * rmmod.c - Remove a module from the Linux kernel. +/* rmmod.c - Remove a module from the Linux kernel. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config RMMOD - bool "rmmod" - default y - help - usage: rmmod [-wf] [MODULE] + bool "rmmod" + default y + help + usage: rmmod [-wf] [MODULE] - Unload the module named MODULE from the Linux kernel. - -f Force unload of a module - -w Wait until the module is no longer used. + Unload the module named MODULE from the Linux kernel. + -f Force unload of a module + -w Wait until the module is no longer used. */ @@ -26,25 +24,22 @@ config RMMOD void rmmod_main(void) { - unsigned int flags = O_NONBLOCK|O_EXCL; - char * mod_name; - int len; - - // Basename - mod_name = strrchr(toys.optargs[0],'/'); - if (mod_name) - mod_name++; - else - mod_name = toys.optargs[0]; - - // Remove .ko if present - len = strlen(mod_name); - if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) - mod_name[len-3] = 0; - - if (toys.optflags & FLAG_f) flags |= O_TRUNC; - if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; - - if (delete_module(mod_name, flags)) - perror_exit("failed to unload %s", mod_name); + unsigned int flags = O_NONBLOCK|O_EXCL; + char * mod_name; + int len; + + // Basename + mod_name = strrchr(toys.optargs[0],'/'); + if (mod_name) mod_name++; + else mod_name = toys.optargs[0]; + + // Remove .ko if present + len = strlen(mod_name); + if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) mod_name[len-3] = 0; + + if (toys.optflags & FLAG_f) flags |= O_TRUNC; + if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; + + if (delete_module(mod_name, flags)) + perror_exit("failed to unload %s", mod_name); } diff --git a/toys/other/setsid.c b/toys/other/setsid.c index 0f08cc03..59a1d78f 100644 --- a/toys/other/setsid.c +++ b/toys/other/setsid.c @@ -1,31 +1,28 @@ -/* vi: set sw=4 ts=4: - * - * setsid.c - Run program in a new session ID. +/* setsid.c - Run program in a new session ID. * * Copyright 2006 Rob Landley <rob@landley.net> USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN)) config SETSID - bool "setsid" - default y - help - usage: setsid [-t] command [args...] + bool "setsid" + default y + help + usage: setsid [-t] command [args...] - Run process in a new session. + Run process in a new session. - -t Grab tty (become foreground process, receiving keyboard signals) + -t Grab tty (become foreground process, receiving keyboard signals) */ #include "toys.h" void setsid_main(void) { - while (setsid()<0) - if (vfork()) _exit(0); - if (toys.optflags) { - setpgid(0,0); - tcsetpgrp(0, getpid()); - } - xexec(toys.optargs); + while (setsid()<0) if (vfork()) _exit(0); + if (toys.optflags) { + setpgid(0,0); + tcsetpgrp(0, getpid()); + } + xexec(toys.optargs); } diff --git a/toys/other/swapoff.c b/toys/other/swapoff.c index cac15732..b89e915c 100644 --- a/toys/other/swapoff.c +++ b/toys/other/swapoff.c @@ -1,24 +1,21 @@ -/* vi: set sw=4 ts=4: - * - * swapoff.c - Disable region for swapping +/* swapoff.c - Disable region for swapping * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config SWAPOFF - bool "swapoff" - default y - help - usage: swapoff swapregion + bool "swapoff" + default y + help + usage: swapoff swapregion - Disable swapping on a given swapregion. + Disable swapping on a given swapregion. */ #include "toys.h" void swapoff_main(void) { - if (swapoff(toys.optargs[0])) - perror_exit("failed to remove swaparea"); + if (swapoff(toys.optargs[0])) perror_exit("failed to remove swaparea"); } diff --git a/toys/other/swapon.c b/toys/other/swapon.c index db7c45b0..49f12499 100644 --- a/toys/other/swapon.c +++ b/toys/other/swapon.c @@ -1,34 +1,32 @@ -/* vi: set sw=4 ts=4: - * - * swapon.c - Enable region for swapping +/* swapon.c - Enable region for swapping * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config SWAPON - bool "swapon" - default y - help - usage: swapon [-p priority] filename + bool "swapon" + default y + help + usage: swapon [-p priority] filename - Enable swapping on a given device/file. + Enable swapping on a given device/file. */ #define FOR_swapon #include "toys.h" GLOBALS( - long priority; + long priority; ) void swapon_main(void) { - int flags = 0; + int flags = 0; - if (toys.optflags) - flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); + if (toys.optflags) + flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); - if (swapon(*toys.optargs, flags)) - perror_exit("Couldn't swapon '%s'", *toys.optargs); + if (swapon(*toys.optargs, flags)) + perror_exit("Couldn't swapon '%s'", *toys.optargs); } diff --git a/toys/other/switch_root.c b/toys/other/switch_root.c index 6451ec15..1dfa20de 100644 --- a/toys/other/switch_root.c +++ b/toys/other/switch_root.c @@ -5,16 +5,16 @@ USE_SWITCH_ROOT(NEWTOY(switch_root, "<2c:h", TOYFLAG_SBIN)) config SWITCH_ROOT - bool "switch_root" - default y - help - usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT... + bool "switch_root" + default y + help + usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT... - Use from PID 1 under initramfs to free initramfs, chroot to NEW_ROOT, - and exec NEW_INIT. + Use from PID 1 under initramfs to free initramfs, chroot to NEW_ROOT, + and exec NEW_INIT. - -c Redirect console to device in NEW_ROOT - -h Hang instead of exiting on failure (avoids kernel panic) + -c Redirect console to device in NEW_ROOT + -h Hang instead of exiting on failure (avoids kernel panic) */ #define FOR_switch_root @@ -22,72 +22,72 @@ config SWITCH_ROOT #include <sys/vfs.h> GLOBALS( - char *console; + char *console; - dev_t rootdev; + dev_t rootdev; ) static int del_node(struct dirtree *node) { - if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) { - int flag = 0; - if (S_ISDIR(node->st.st_mode)) { - if (node->data != -1) return DIRTREE_COMEAGAIN; - flag = AT_REMOVEDIR; - } - unlinkat(dirtree_parentfd(node), node->name, flag); - } - - return 0; + if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) { + int flag = 0; + if (S_ISDIR(node->st.st_mode)) { + if (node->data != -1) return DIRTREE_COMEAGAIN; + flag = AT_REMOVEDIR; + } + unlinkat(dirtree_parentfd(node), node->name, flag); + } + + return 0; } void switch_root_main(void) { - char *newroot = *toys.optargs, **cmdline = toys.optargs+1; - struct stat st1, st2; - struct statfs stfs; - int console = console; // gcc's "may be used" warnings are broken. - - if (getpid() != 1) error_exit("not pid 1"); - - // Root filesystem we're leaving must be ramfs or tmpfs - if (statfs("/", &stfs) || - (stfs.f_type != 0x858458f6 && stfs.f_type != 0x01021994)) - { - error_msg("not ramfs"); - goto panic; - } - - // New directory must be different filesystem instance - if (chdir(newroot) || stat(".", &st1) || stat("/", &st2) || - st1.st_dev == st2.st_dev) - { - error_msg("bad newroot '%s'", newroot); - goto panic; - } - TT.rootdev=st2.st_dev; - - // init program must exist and be an executable file - if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { - error_msg("bad init"); - goto panic; - } - - if (TT.console && -1 == (console = open(TT.console, O_RDWR))) { - perror_msg("bad console '%s'", TT.console); - goto panic; - } + char *newroot = *toys.optargs, **cmdline = toys.optargs+1; + struct stat st1, st2; + struct statfs stfs; + int console = console; // gcc's "may be used" warnings are broken. + + if (getpid() != 1) error_exit("not pid 1"); + + // Root filesystem we're leaving must be ramfs or tmpfs + if (statfs("/", &stfs) || + (stfs.f_type != 0x858458f6 && stfs.f_type != 0x01021994)) + { + error_msg("not ramfs"); + goto panic; + } + + // New directory must be different filesystem instance + if (chdir(newroot) || stat(".", &st1) || stat("/", &st2) || + st1.st_dev == st2.st_dev) + { + error_msg("bad newroot '%s'", newroot); + goto panic; + } + TT.rootdev=st2.st_dev; + + // init program must exist and be an executable file + if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { + error_msg("bad init"); + goto panic; + } + + if (TT.console && -1 == (console = open(TT.console, O_RDWR))) { + perror_msg("bad console '%s'", TT.console); + goto panic; + } - // Ok, enough safety checks: wipe root partition. - dirtree_read("/", del_node); - - if (TT.console) { - int i; - for (i=0; i<3; i++) if (console != i) dup2(console, i); - if (console>2) close(console); - } - execv(*cmdline, cmdline); - perror_msg("Failed to exec '%s'", *cmdline); + // Ok, enough safety checks: wipe root partition. + dirtree_read("/", del_node); + + if (TT.console) { + int i; + for (i=0; i<3; i++) if (console != i) dup2(console, i); + if (console>2) close(console); + } + execv(*cmdline, cmdline); + perror_msg("Failed to exec '%s'", *cmdline); panic: - if (toys.optflags & FLAG_h) for (;;) wait(NULL); + if (toys.optflags & FLAG_h) for (;;) wait(NULL); } diff --git a/toys/other/tac.c b/toys/other/tac.c index 7a8bb4ae..78b22866 100644 --- a/toys/other/tac.c +++ b/toys/other/tac.c @@ -1,53 +1,51 @@ -/* vi: set sw=4 ts=4: - * - * tac.c - output lines in reverse order +/* tac.c - output lines in reverse order * * Copyright 2012 Rob Landley <rob@landley.net> USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config TAC - bool "tac" - default y - help - usage: tac [FILE...] + bool "tac" + default y + help + usage: tac [FILE...] - Output lines in reverse order. + Output lines in reverse order. */ #include "toys.h" void do_tac(int fd, char *name) { - struct arg_list *list = NULL; - char *c; - - // Read in lines - for (;;) { - struct arg_list *temp; - int len; - - if (!(c = get_line(fd))) break; - - len = strlen(c); - if (len && c[len-1]=='\n') c[len-1] = 0; - temp = xmalloc(sizeof(struct arg_list)); - temp->next = list; - temp->arg = c; - list = temp; - } - - // Play them back. - while (list) { - struct arg_list *temp = list->next; - xputs(list->arg); - free(list->arg); - free(list); - list = temp; - } + struct arg_list *list = NULL; + char *c; + + // Read in lines + for (;;) { + struct arg_list *temp; + int len; + + if (!(c = get_line(fd))) break; + + len = strlen(c); + if (len && c[len-1]=='\n') c[len-1] = 0; + temp = xmalloc(sizeof(struct arg_list)); + temp->next = list; + temp->arg = c; + list = temp; + } + + // Play them back. + while (list) { + struct arg_list *temp = list->next; + xputs(list->arg); + free(list->arg); + free(list); + list = temp; + } } void tac_main(void) { - loopfiles(toys.optargs, do_tac); + loopfiles(toys.optargs, do_tac); } diff --git a/toys/other/taskset.c b/toys/other/taskset.c index 74cbfffa..967bf70f 100644 --- a/toys/other/taskset.c +++ b/toys/other/taskset.c @@ -1,25 +1,23 @@ -/* vi: set sw=4 ts=4: - * - * taskset.c - Retrieve or set the CPU affinity of a process. +/* taskset.c - Retrieve or set the CPU affinity of a process. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_BIN|TOYFLAG_STAYROOT)) config TASKSET - bool "taskset" - default y - help - usage: taskset [-ap] [mask] [PID | cmd [args...]] + bool "taskset" + default y + help + usage: taskset [-ap] [mask] [PID | cmd [args...]] - Launch a new task which may only run on certain processors, or change - the processor affinity of an exisitng PID. + Launch a new task which may only run on certain processors, or change + the processor affinity of an exisitng PID. - Mask is a hex string where each bit represents a processor the process - is allowed to run on. PID without a mask displays existing affinity. + Mask is a hex string where each bit represents a processor the process + is allowed to run on. PID without a mask displays existing affinity. - -p Set/get the affinity of given PID instead of a new command. - -a Set/get the affinity of all threads of the PID. + -p Set/get the affinity of given PID instead of a new command. + -a Set/get the affinity of all threads of the PID. */ #define FOR_taskset @@ -34,73 +32,73 @@ int sched_getaffinity(pid_t pid, size_t size, void *cpuset); static void do_taskset(pid_t pid, int quiet) { - unsigned long *mask = (unsigned long *)toybuf; - char *s = *toys.optargs, *failed = "failed to %s %d's affinity"; - int i, j, k; - - for (i=0; ; i++) { - if (!quiet) { - int j = sizeof(toybuf), flag = 0; - - if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask)) - perror_exit(failed, "get", pid); - - printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current"); - - while (j--) { - int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1)))); - - if (flag) printf("%02x", x); - else if (x) { - flag++; - printf("%x", x); - } - } - putchar('\n'); - } - - if (i || toys.optc < 2) return; - - memset(toybuf, 0, sizeof(toybuf)); - k = strlen(s = *toys.optargs); - s += k; - for (j = 0; j<k; j++) { - unsigned long digit = *(--s) - '0'; - - if (digit > 9) digit = 10 + tolower(*s)-'a'; - if (digit > 15) error_exit("bad mask '%s'", *toys.optargs); - mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1)); - } - - if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask)) - perror_exit(failed, "set", pid); - } + unsigned long *mask = (unsigned long *)toybuf; + char *s = *toys.optargs, *failed = "failed to %s %d's affinity"; + int i, j, k; + + for (i=0; ; i++) { + if (!quiet) { + int j = sizeof(toybuf), flag = 0; + + if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask)) + perror_exit(failed, "get", pid); + + printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current"); + + while (j--) { + int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1)))); + + if (flag) printf("%02x", x); + else if (x) { + flag++; + printf("%x", x); + } + } + putchar('\n'); + } + + if (i || toys.optc < 2) return; + + memset(toybuf, 0, sizeof(toybuf)); + k = strlen(s = *toys.optargs); + s += k; + for (j = 0; j<k; j++) { + unsigned long digit = *(--s) - '0'; + + if (digit > 9) digit = 10 + tolower(*s)-'a'; + if (digit > 15) error_exit("bad mask '%s'", *toys.optargs); + mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1)); + } + + if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask)) + perror_exit(failed, "set", pid); + } } static int task_callback(struct dirtree *new) { - if (!new->parent) return DIRTREE_RECURSE; - if (isdigit(*new->name)) do_taskset(atoi(new->name), 0); + if (!new->parent) return DIRTREE_RECURSE; + if (isdigit(*new->name)) do_taskset(atoi(new->name), 0); - return 0; + return 0; } void taskset_main(void) { - if (!(toys.optflags & FLAG_p)) { - if (toys.optc < 2) error_exit("Needs 2 args"); - do_taskset(getpid(), 1); - xexec(toys.optargs+1); - } else { - char *c; - pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10); - - if (*c) error_exit("Not int %s", toys.optargs[1]); - - if (toys.optflags & FLAG_a) { - char buf[33]; - sprintf(buf, "/proc/%ld/task/", (long)pid); - dirtree_read(buf, task_callback); - } else do_taskset(pid, 0); - } + if (!(toys.optflags & FLAG_p)) { + if (toys.optc < 2) error_exit("Needs 2 args"); + do_taskset(getpid(), 1); + xexec(toys.optargs+1); + } else { + char *c; + pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10); + + if (*c) error_exit("Not int %s", toys.optargs[1]); + + if (toys.optflags & FLAG_a) { + char buf[33]; + sprintf(buf, "/proc/%ld/task/", (long)pid); + dirtree_read(buf, task_callback); + } else do_taskset(pid, 0); + } } diff --git a/toys/other/truncate.c b/toys/other/truncate.c index 47b07583..5ed9f61b 100644 --- a/toys/other/truncate.c +++ b/toys/other/truncate.c @@ -1,44 +1,43 @@ -/* vi: set sw=4 ts=4: - * - * truncate.c - set file length, extending sparsely if necessary +/* truncate.c - set file length, extending sparsely if necessary * * Copyright 2011 Rob Landley <rob@landley.net> USE_TRUNCATE(NEWTOY(truncate, "<1s#|c", TOYFLAG_BIN)) config TRUNCATE - bool "truncate" - default y - help - usage: truncate [-c] -s file... - Set length of file(s), extending sparsely if necessary. - - -c Don't create file if it doesn't exist. - -s New size + bool "truncate" + default y + help + usage: truncate [-c] -s file... + + Set length of file(s), extending sparsely if necessary. + + -c Don't create file if it doesn't exist. + -s New size */ #define FOR_truncate #include "toys.h" GLOBALS( - long size; + long size; ) static void do_truncate(int fd, char *name) { - if (fd<0) return; - if (ftruncate(fd, TT.size)) { - perror_msg("failed to set '%s' to '%ld'", name, TT.size); - toys.exitval = EXIT_FAILURE; - } + if (fd<0) return; + if (ftruncate(fd, TT.size)) { + perror_msg("failed to set '%s' to '%ld'", name, TT.size); + toys.exitval = EXIT_FAILURE; + } } void truncate_main(void) { - int cr = !(toys.optflags&1); + int cr = !(toys.optflags&1); - // Create files with mask rwrwrw. - // Nonexistent files are only an error if we're supposed to create them. - loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr, - do_truncate); + // Create files with mask rwrwrw. + // Nonexistent files are only an error if we're supposed to create them. + loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr, + do_truncate); } diff --git a/toys/other/unshare.c b/toys/other/unshare.c index bdee66bc..9a938186 100644 --- a/toys/other/unshare.c +++ b/toys/other/unshare.c @@ -1,26 +1,24 @@ -/* vi: set sw=4 ts=4: - * - * unshare.c - run command in new context +/* unshare.c - run command in new context * * Copyright 2011 Rob Landley <rob@landley.net> USE_UNSHARE(NEWTOY(unshare, "<1^nium", TOYFLAG_USR|TOYFLAG_BIN)) config UNSHARE - bool "unshare" - default y - depends on TOYBOX_CONTAINER - help - usage: unshare [-muin] COMMAND... - - Create new namespace(s) for this process and its children, so some - attribute is not shared with the parent process. This is part of - Linux Containers. Each process can have its own: - - -m Mount/unmount tree - -u Host and domain names - -i SysV IPC (message queues, semaphores, shared memory) - -n Network address, sockets, routing, iptables + bool "unshare" + default y + depends on TOYBOX_CONTAINER + help + usage: unshare [-muin] COMMAND... + + Create new namespace(s) for this process and its children, so some + attribute is not shared with the parent process. This is part of + Linux Containers. Each process can have its own: + + -m Mount/unmount tree + -u Host and domain names + -i SysV IPC (message queues, semaphores, shared memory) + -n Network address, sockets, routing, iptables */ #include "toys.h" @@ -29,15 +27,13 @@ extern int unshare (int __flags); void unshare_main(void) { - unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET,0}; - unsigned f=0; - int i; + unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET, 0}; + unsigned f=0; + int i; - for (i=0; flags[i]; i++) - if (toys.optflags & (1<<i)) - f |= flags[i]; + for (i=0; flags[i]; i++) if (toys.optflags & (1<<i)) f |= flags[i]; - if(unshare(f)) perror_exit("failed"); + if(unshare(f)) perror_exit("failed"); - xexec(toys.optargs); + xexec(toys.optargs); } diff --git a/toys/other/uptime.c b/toys/other/uptime.c index dfd62b6c..f4ce5e46 100644 --- a/toys/other/uptime.c +++ b/toys/other/uptime.c @@ -1,50 +1,45 @@ -/* vi: set sw=4 ts=4: - * - * uptime.c - Tell how long the system has been running. +/* uptime.c - Tell how long the system has been running. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_UPTIME(NEWTOY(uptime, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config UPTIME - bool "uptime" - default y - help - usage: uptime + bool "uptime" + default y + help + usage: uptime - Tell how long the system has been running and the system load - averages for the past 1, 5 and 15 minutes. + Tell how long the system has been running and the system load + averages for the past 1, 5 and 15 minutes. */ #include "toys.h" void uptime_main(void) { - struct sysinfo info; - time_t tmptime; - struct tm * now; - unsigned int days, hours, minutes; - - // Obtain the data we need. - sysinfo(&info); - time(&tmptime); - now = localtime(&tmptime); - - // Time - xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec); - // Uptime - info.uptime /= 60; - minutes = info.uptime%60; - info.uptime /= 60; - hours = info.uptime%24; - days = info.uptime/24; - if (days) xprintf("%d day%s, ", days, (days!=1)?"s":""); - if (hours) - xprintf("%2d:%02d, ", hours, minutes); - else - printf("%d min, ", minutes); - - printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0, - info.loads[1]/65536.0, info.loads[2]/65536.0); - + struct sysinfo info; + time_t tmptime; + struct tm * now; + unsigned int days, hours, minutes; + + // Obtain the data we need. + sysinfo(&info); + time(&tmptime); + now = localtime(&tmptime); + + // Time + xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec); + // Uptime + info.uptime /= 60; + minutes = info.uptime%60; + info.uptime /= 60; + hours = info.uptime%24; + days = info.uptime/24; + if (days) xprintf("%d day%s, ", days, (days!=1)?"s":""); + if (hours) xprintf("%2d:%02d, ", hours, minutes); + else printf("%d min, ", minutes); + + printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0, + info.loads[1]/65536.0, info.loads[2]/65536.0); } diff --git a/toys/other/usleep.c b/toys/other/usleep.c index ff7fe88b..6040cc06 100644 --- a/toys/other/usleep.c +++ b/toys/other/usleep.c @@ -1,30 +1,26 @@ -/* vi: set sw=4 ts=4: - * - * usleep.c - Wait for a number of microseconds. +/* usleep.c - Wait for a number of microseconds. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN)) config USLEEP - bool "usleep" - default y - help - usage: usleep MICROSECONDS - - Pause for MICROSECONDS microseconds. + bool "usleep" + default y + help + usage: usleep MICROSECONDS + Pause for MICROSECONDS microseconds. */ #include "toys.h" void usleep_main(void) { - struct timespec tv; - long delay = atol(*toys.optargs); - - tv.tv_sec = delay/1000000; - tv.tv_nsec = (delay%1000000) * 1000; - toys.exitval = !!nanosleep(&tv, NULL); + struct timespec tv; + long delay = atol(*toys.optargs); + tv.tv_sec = delay/1000000; + tv.tv_nsec = (delay%1000000) * 1000; + toys.exitval = !!nanosleep(&tv, NULL); } diff --git a/toys/other/vconfig.c b/toys/other/vconfig.c index 92d9d7f0..18225fc4 100644 --- a/toys/other/vconfig.c +++ b/toys/other/vconfig.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * vconfig.c - Creates virtual ethernet devices. +/* vconfig.c - Creates virtual ethernet devices. * * Copyright 2012 Sandeep Sharma <sandeep.jack2756@gmail.com>, Kyungwan Han <asura321@gmail.com> * @@ -9,20 +7,19 @@ USE_VCONFIG(NEWTOY(vconfig, "<2>4", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) config VCONFIG - bool "vconfig" - default y - help - usage: vconfig COMMAND [OPTIONS] + bool "vconfig" + default y + help + usage: vconfig COMMAND [OPTIONS] - add [interface-name] [vlan_id] - rem [vlan-name] - set_flag [interface-name] [flag-num] [0 | 1] - set_egress_map [vlan-name] [skb_priority] [vlan_qos] - set_ingress_map [vlan-name] [skb_priority] [vlan_qos] - set_name_type [name-type] - - Create and remove virtual ethernet devices + add [interface-name] [vlan_id] + rem [vlan-name] + set_flag [interface-name] [flag-num] [0 | 1] + set_egress_map [vlan-name] [skb_priority] [vlan_qos] + set_ingress_map [vlan-name] [skb_priority] [vlan_qos] + set_name_type [name-type] + Create and remove virtual ethernet devices */ #include "toys.h" @@ -34,16 +31,15 @@ config VCONFIG */ static int strtol_range(char *str, int min, int max) { - char *endptr = NULL; - errno = 0; - long ret_value = strtol(str, &endptr, 10); - if(errno) perror_exit("Invalid num %s", str); - else { - if(endptr && (*endptr != '\0' || endptr == str)) - perror_exit("Not a valid num %s", str); - } - if(ret_value >= min && ret_value <= max) return ret_value; - else perror_exit("Number %s is not in valid [%d-%d] Range\n", str, min, max); + char *endptr = NULL; + errno = 0; + long ret_value = strtol(str, &endptr, 10); + + if(errno) perror_exit("Invalid num %s", str); + else if(endptr && (*endptr != '\0' || endptr == str)) + perror_exit("Not a valid num %s", str); + if(ret_value >= min && ret_value <= max) return ret_value; + else perror_exit("Number %s is not in valid [%d-%d] Range\n", str, min, max); } /* * vconfig main function. @@ -51,83 +47,84 @@ static int strtol_range(char *str, int min, int max) void vconfig_main(void) { #define MAX_VLAN_ID 4094 - struct vlan_ioctl_args request; - char *interface_name = NULL; - unsigned int name_type = VLAN_NAME_TYPE_PLUS_VID; - char *cmd; - int fd = 0; - int vlan_id = 0; - - if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror_exit("Can't open socket"); //Use socket instead of open - memset(&request, 0, sizeof(struct vlan_ioctl_args)); // Null set all the VLAN info's. - cmd = toys.optargs[0]; // Fetch cmd and proceed. - if(strcmp(cmd, "set_name_type") == 0) { - if(strcmp(toys.optargs[1], "VLAN_PLUS_VID") == 0) { - name_type = VLAN_NAME_TYPE_PLUS_VID; - } - else if(strcmp(toys.optargs[1], "VLAN_PLUS_VID_NO_PAD") == 0) { - name_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; - } - else if(strcmp(toys.optargs[1], "DEV_PLUS_VID") == 0) { - name_type = VLAN_NAME_TYPE_RAW_PLUS_VID; - } - else if(strcmp(toys.optargs[1], "DEV_PLUS_VID_NO_PAD") == 0) { - name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; - } - else perror_exit("ERROR: Invalid name type"); - - request.u.name_type = name_type; - request.cmd = SET_VLAN_NAME_TYPE_CMD; - if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { - xprintf("Successful set_name_type for VLAN subsystem\n"); - exit(EXIT_SUCCESS); - } - else perror_exit("Failed to set set_name_type:"); - } - else { - interface_name = toys.optargs[1]; // Store interface name. - if(strlen(interface_name) > 15) perror_exit("ERROR:if_name length can not be greater than 15"); - strcpy(request.device1, interface_name); //we had exited if interface_name length greater than 15, so here it never overflows. - } + struct vlan_ioctl_args request; + char *interface_name = NULL; + unsigned int name_type = VLAN_NAME_TYPE_PLUS_VID; + char *cmd; + int fd = 0; + int vlan_id = 0; - if(strcmp(cmd, "add") == 0) { - request.cmd = ADD_VLAN_CMD; - if(toys.optargs[2]) vlan_id = strtol_range(toys.optargs[2], 0, MAX_VLAN_ID); - else vlan_id = 0; - request.u.VID = vlan_id; - } - else if(strcmp(cmd, "rem") == 0) { - request.cmd = DEL_VLAN_CMD; - } - else if(strcmp(cmd, "set_flag") == 0) { - request.cmd = SET_VLAN_FLAG_CMD; - if(toys.optargs[2]) request.u.flag = strtol_range(toys.optargs[2], 0, 1); - else request.u.flag = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); - else request.vlan_qos = 0; + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror_exit("Can't open socket"); //Use socket instead of open + memset(&request, 0, sizeof(struct vlan_ioctl_args)); // Null set all the VLAN info's. + cmd = toys.optargs[0]; // Fetch cmd and proceed. + if(strcmp(cmd, "set_name_type") == 0) { + if(strcmp(toys.optargs[1], "VLAN_PLUS_VID") == 0) { + name_type = VLAN_NAME_TYPE_PLUS_VID; } - else if(strcmp(cmd, "set_egress_map") == 0) { - request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; - if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); - else request.u.skb_priority = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); - else request.vlan_qos = 0; + else if(strcmp(toys.optargs[1], "VLAN_PLUS_VID_NO_PAD") == 0) { + name_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; } - else if(strcmp(cmd, "set_ingress_map") == 0) { - request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; - if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); - else request.u.skb_priority = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); //To set flag we must have to set vlan_qos - else request.vlan_qos = 0; + else if(strcmp(toys.optargs[1], "DEV_PLUS_VID") == 0) { + name_type = VLAN_NAME_TYPE_RAW_PLUS_VID; } - else { - xclose(fd); - perror_exit("Unknown command %s", cmd); + else if(strcmp(toys.optargs[1], "DEV_PLUS_VID_NO_PAD") == 0) { + name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; } + else perror_exit("ERROR: Invalid name type"); + + request.u.name_type = name_type; + request.cmd = SET_VLAN_NAME_TYPE_CMD; if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { - if(strcmp(cmd, "add") == 0 && vlan_id == 1) - xprintf("WARNING: VLAN 1 does not work with many switches,consider another number if you have problems.\n"); - xprintf("Successful %s on device %s\n", cmd, interface_name); + xprintf("Successful set_name_type for VLAN subsystem\n"); + exit(EXIT_SUCCESS); } - else perror_exit("Failed to %s, on vlan subsystem %s.", cmd, interface_name); -} + else perror_exit("Failed to set set_name_type:"); + } + else { + interface_name = toys.optargs[1]; // Store interface name. + if(strlen(interface_name) > 15) perror_exit("ERROR:if_name length can not be greater than 15"); + strcpy(request.device1, interface_name); //we had exited if interface_name length greater than 15, so here it never overflows. + } + + if(strcmp(cmd, "add") == 0) { + request.cmd = ADD_VLAN_CMD; + if(toys.optargs[2]) vlan_id = strtol_range(toys.optargs[2], 0, MAX_VLAN_ID); + else vlan_id = 0; + request.u.VID = vlan_id; + } + else if(strcmp(cmd, "rem") == 0) { + request.cmd = DEL_VLAN_CMD; + } + else if(strcmp(cmd, "set_flag") == 0) { + request.cmd = SET_VLAN_FLAG_CMD; + if(toys.optargs[2]) request.u.flag = strtol_range(toys.optargs[2], 0, 1); + else request.u.flag = 0; + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else if(strcmp(cmd, "set_egress_map") == 0) { + request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; + if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); + else request.u.skb_priority = 0; + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else if(strcmp(cmd, "set_ingress_map") == 0) { + request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; + if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); + else request.u.skb_priority = 0; + //To set flag we must have to set vlan_qos + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else { + xclose(fd); + perror_exit("Unknown command %s", cmd); + } + if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { + if(strcmp(cmd, "add") == 0 && vlan_id == 1) + xprintf("WARNING: VLAN 1 does not work with many switches,consider another number if you have problems.\n"); + xprintf("Successful %s on device %s\n", cmd, interface_name); + } + else perror_exit("Failed to %s, on vlan subsystem %s.", cmd, interface_name); +} diff --git a/toys/other/vmstat.c b/toys/other/vmstat.c index 1c348f2a..16d45f2a 100644 --- a/toys/other/vmstat.c +++ b/toys/other/vmstat.c @@ -1,189 +1,184 @@ -/* vi: set sw=4 ts=4: - * - * vmstat.c - Report virtual memory statistics. +/* vmstat.c - Report virtual memory statistics. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN)) config VMSTAT - bool "vmstat" - default y - help - usage: vmstat [-n] [delay [count]] - -n Display the header only once - delay The delay between updates in seconds, when not specified - the average since boot is displayed. - count Number of updates to display, the default is inifinite. + bool "vmstat" + default y + help + usage: vmstat [-n] [delay [count]] + -n Display the header only once + delay The delay between updates in seconds, when not specified + the average since boot is displayed. + count Number of updates to display, the default is inifinite. */ #include "toys.h" -void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked, - uint64_t * sys_irq, uint64_t * sys_ctxt, - uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait) +void read_proc_stat(unsigned int *proc_running, unsigned int *proc_blocked, + uint64_t *sys_irq, uint64_t *sys_ctxt, uint64_t *cpu_user, uint64_t *cpu_sys, + uint64_t *cpu_idle, uint64_t *cpu_wait) { - char * off; - uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; - int fd = xopen("/proc/stat", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/stat is too large"); - - off = strstr(toybuf, "cpu "); - // Ignoring steal and guest fields for now. - if (off) sscanf(off, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \ - " %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle, - cpu_wait, &c_irq, &c_sirq); - *cpu_user = c_user + c_nice; - *cpu_sys = c_sys + c_irq + c_sirq; - off = strstr(toybuf, "intr"); - if (off) sscanf(off, "intr %"PRIu64, sys_irq); - - off = strstr(toybuf, "ctxt"); - if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt); - - off = strstr(toybuf, "procs_running"); - if (off) sscanf(off, "procs_running %u", proc_running); - (*proc_running)--; // look, i'm invisible. - - off = strstr(toybuf, "procs_blocked"); - if (off) sscanf(off, "procs_blocked %u", proc_blocked); - - close(fd); + char * off; + uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; + int fd = xopen("/proc/stat", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/stat is too large"); + + off = strstr(toybuf, "cpu "); + // Ignoring steal and guest fields for now. + if (off) sscanf(off, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \ + " %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle, + cpu_wait, &c_irq, &c_sirq); + *cpu_user = c_user + c_nice; + *cpu_sys = c_sys + c_irq + c_sirq; + off = strstr(toybuf, "intr"); + if (off) sscanf(off, "intr %"PRIu64, sys_irq); + + off = strstr(toybuf, "ctxt"); + if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt); + + off = strstr(toybuf, "procs_running"); + if (off) sscanf(off, "procs_running %u", proc_running); + (*proc_running)--; // look, i'm invisible. + + off = strstr(toybuf, "procs_blocked"); + if (off) sscanf(off, "procs_blocked %u", proc_blocked); + + close(fd); } -void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free, - unsigned long * mem_buff, unsigned long * mem_cache) +void read_proc_meminfo(unsigned long *mem_swapped, unsigned long *mem_free, + unsigned long *mem_buff, unsigned long *mem_cache) { - char * off; - unsigned long swap_total, swap_free; - int fd = xopen("/proc/meminfo", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/meminfo is too large"); + char * off; + unsigned long swap_total, swap_free; + int fd = xopen("/proc/meminfo", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/meminfo is too large"); - off = strstr(toybuf, "MemFree"); - if (off) sscanf(off, "MemFree: %lu kB", mem_free); + off = strstr(toybuf, "MemFree"); + if (off) sscanf(off, "MemFree: %lu kB", mem_free); - off = strstr(toybuf, "Buffers"); - if (off) sscanf(off, "Buffers: %lu kB", mem_buff); + off = strstr(toybuf, "Buffers"); + if (off) sscanf(off, "Buffers: %lu kB", mem_buff); - off = strstr(toybuf, "Cached"); - if (off) sscanf(off, "Cached: %lu kB", mem_cache); + off = strstr(toybuf, "Cached"); + if (off) sscanf(off, "Cached: %lu kB", mem_cache); - off = strstr(toybuf, "SwapFree"); - if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); + off = strstr(toybuf, "SwapFree"); + if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); - off = strstr(toybuf, "SwapTotal"); - if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); - *mem_swapped = swap_total - swap_free; + off = strstr(toybuf, "SwapTotal"); + if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); + *mem_swapped = swap_total - swap_free; - close(fd); + close(fd); } -void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out, - unsigned long * swap_bytes_in, unsigned long * swap_bytes_out) +void read_proc_vmstat(unsigned long *io_pages_in, unsigned long *io_pages_out, + unsigned long *swap_bytes_in, unsigned long *swap_bytes_out) { - char * off; - unsigned long s_pages_in, s_pages_out; - unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; - int fd = xopen("/proc/vmstat", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/vmstat is too large"); - - off = strstr(toybuf, "pgpgin"); - if (off) sscanf(off, "pgpgin %lu", io_pages_in); - - off = strstr(toybuf, "pgpgout"); - if (off) sscanf(off, "pgpgout %lu", io_pages_out); - - off = strstr(toybuf, "pswpin"); - if (off) sscanf(off, "pswpin %lu", &s_pages_in); - *swap_bytes_in = s_pages_in * pagesize_kb; - - off = strstr(toybuf, "pswpout"); - if (off) sscanf(off, "pswpout %lu", &s_pages_out); - *swap_bytes_out = s_pages_out * pagesize_kb; - - close(fd); + char *off; + unsigned long s_pages_in, s_pages_out; + unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; + int fd = xopen("/proc/vmstat", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/vmstat is too large"); + + off = strstr(toybuf, "pgpgin"); + if (off) sscanf(off, "pgpgin %lu", io_pages_in); + + off = strstr(toybuf, "pgpgout"); + if (off) sscanf(off, "pgpgout %lu", io_pages_out); + + off = strstr(toybuf, "pswpin"); + if (off) sscanf(off, "pswpin %lu", &s_pages_in); + *swap_bytes_in = s_pages_in * pagesize_kb; + + off = strstr(toybuf, "pswpout"); + if (off) sscanf(off, "pswpout %lu", &s_pages_out); + *swap_bytes_out = s_pages_out * pagesize_kb; + + close(fd); } void vmstat_main(void) { - const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; - unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; - unsigned int running = 0, blocked = 0; - unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; - unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; - uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; - int first_run = 1; - int no_header = toys.optflags; - unsigned num_rows = 22; - - if (toys.optc >= 1) - loop_delay = atoi(toys.optargs[0]); - if (toys.optc >= 2) - loop_max_num = atoi(toys.optargs[1]); - - if (loop_max_num < 0 || loop_delay < 0) - error_exit("Invalid arguments"); - - while(1) { - uint64_t total_jif; - int idx = loop_num%2; - - if(first_run || (!(loop_num % num_rows) && !no_header)) { - unsigned rows = 0, cols = 0; - terminal_size(&cols, &rows); - num_rows = (rows > 3)? rows - 3 : 22; - printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); - printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n"); - } - - read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], - &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); - read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); - read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); - - if (first_run) { - struct sysinfo inf; - sysinfo(&inf); - first_run = 0; - total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; - printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, - (unsigned) (swap_bytes_in[idx]/inf.uptime), - (unsigned) (swap_bytes_out[idx]/inf.uptime), - (unsigned) (io_pages_in[idx]/inf.uptime), - (unsigned) (io_pages_out[idx]/inf.uptime), - (unsigned) (sys_irq[idx]/inf.uptime), - (unsigned) (sys_ctxt[idx]/inf.uptime), - (unsigned) (100*cpu_user[idx]/total_jif), - (unsigned) (100*cpu_sys[idx]/total_jif), - (unsigned) (100*cpu_idle[idx]/total_jif), - (unsigned) (100*cpu_wait[idx]/total_jif)); - }else{ - total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; - printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, - (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), - (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), - (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), - (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), - (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), - (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), - (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), - (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif), - (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), - (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); - } - - loop_num++; - if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) - break; - sleep(loop_delay); - } + const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; + unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; + unsigned int running = 0, blocked = 0; + unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; + unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; + uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; + int first_run = 1; + int no_header = toys.optflags; + unsigned num_rows = 22; + + if (toys.optc >= 1) loop_delay = atoi(toys.optargs[0]); + if (toys.optc >= 2) loop_max_num = atoi(toys.optargs[1]); + + if (loop_max_num < 0 || loop_delay < 0) error_exit("Invalid arguments"); + + while(1) { + uint64_t total_jif; + int idx = loop_num%2; + + if(first_run || (!(loop_num % num_rows) && !no_header)) { + unsigned rows = 0, cols = 0; + terminal_size(&cols, &rows); + num_rows = (rows > 3)? rows - 3 : 22; + printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); + printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n"); + } + + read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], + &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); + read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); + read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); + + if (first_run) { + struct sysinfo inf; + sysinfo(&inf); + first_run = 0; + total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; + printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, + (unsigned) (swap_bytes_in[idx]/inf.uptime), + (unsigned) (swap_bytes_out[idx]/inf.uptime), + (unsigned) (io_pages_in[idx]/inf.uptime), + (unsigned) (io_pages_out[idx]/inf.uptime), + (unsigned) (sys_irq[idx]/inf.uptime), + (unsigned) (sys_ctxt[idx]/inf.uptime), + (unsigned) (100*cpu_user[idx]/total_jif), + (unsigned) (100*cpu_sys[idx]/total_jif), + (unsigned) (100*cpu_idle[idx]/total_jif), + (unsigned) (100*cpu_wait[idx]/total_jif)); + }else{ + total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; + printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, + (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), + (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), + (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), + (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), + (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), + (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), + (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), + (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif), + (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), + (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); + } + + loop_num++; + if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) + break; + sleep(loop_delay); + } } diff --git a/toys/other/w.c b/toys/other/w.c index 097a4386..c271e8bd 100644 --- a/toys/other/w.c +++ b/toys/other/w.c @@ -1,34 +1,33 @@ -/* vi: set sw=4 ts=4: - * - * w.c - shows logged in users +/* w.c - shows logged in users * * Copyright 2012 Gaurang Shastri <gmshastri@gmail.com> USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config W - bool "w" - default y - help - usage: w + bool "w" + default y + help + usage: w - Show who is logged on and since how long they logged in. + Show who is logged on and since how long they logged in. */ #include "toys.h" void w_main(void) { - struct utmpx *x; + struct utmpx *x; - xprintf("USER TTY LOGIN@ FROM"); - setutxent(); - while ((x=getutxent()) != NULL) - if (x->ut_type==7) { - time_t tt = x->ut_tv.tv_sec; + xprintf("USER TTY LOGIN@ FROM"); + setutxent(); + while ((x=getutxent()) != NULL) { + if (x->ut_type==7) { + time_t tt = x->ut_tv.tv_sec; - xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line, - ctime(&tt), x->ut_host); - } - xputc('\n'); + xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line, + ctime(&tt), x->ut_host); + } + } + xputc('\n'); } diff --git a/toys/other/which.c b/toys/other/which.c index 44b1f568..fc65fe8a 100644 --- a/toys/other/which.c +++ b/toys/other/which.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * which.c - Find executable files in $PATH. +/* which.c - Find executable files in $PATH. * * Copyright 2006 Rob landley <rob@landley.net> USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN)) config WHICH - bool "which" - default y - help - usage: which [-a] filename ... + bool "which" + default y + help + usage: which [-a] filename ... - Search $PATH for executable files matching filename(s). + Search $PATH for executable files matching filename(s). - -a Show all matches + -a Show all matches */ #include "toys.h" @@ -24,46 +22,47 @@ config WHICH static int which_in_path(char *filename) { - struct string_list *list; + struct string_list *list; - // If they gave us a path, don't worry about $PATH or -a + // If they gave us a path, don't worry about $PATH or -a - if (strchr(filename, '/')) { - // Confirm it has the executable bit set, and it's not a directory. - if (!access(filename, X_OK)) { - struct stat st; + if (strchr(filename, '/')) { + // Confirm it has the executable bit set, and it's not a directory. + if (!access(filename, X_OK)) { + struct stat st; - if (!stat(filename, &st) && S_ISREG(st.st_mode)) { - puts(filename); - return 0; - } - return 1; - } - } + if (!stat(filename, &st) && S_ISREG(st.st_mode)) { + puts(filename); + return 0; + } + return 1; + } + } - // Search $PATH for matches. - list = find_in_path(getenv("PATH"), filename); - if (!list) return 1; + // Search $PATH for matches. + list = find_in_path(getenv("PATH"), filename); + if (!list) return 1; - // Print out matches - while (list) { - if (!access(list->str, X_OK)) { - puts(list->str); - // If we should stop at one match, do so - if (!toys.optflags) { - llist_traverse(list, free); - break; - } - } - free(llist_pop(&list)); - } + // Print out matches + while (list) { + if (!access(list->str, X_OK)) { + puts(list->str); + // If we should stop at one match, do so + if (!toys.optflags) { + llist_traverse(list, free); + break; + } + } + free(llist_pop(&list)); + } - return 0; + return 0; } void which_main(void) { - int i; - for (i=0; toys.optargs[i]; i++) - toys.exitval |= which_in_path(toys.optargs[i]); + int i; + + for (i=0; toys.optargs[i]; i++) + toys.exitval |= which_in_path(toys.optargs[i]); } diff --git a/toys/other/whoami.c b/toys/other/whoami.c index e6131498..a7ed047a 100644 --- a/toys/other/whoami.c +++ b/toys/other/whoami.c @@ -1,31 +1,29 @@ -/* vi: set sw=4 ts=4: - * - * whoami.c - Print effective user name +/* whoami.c - Print effective user name * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> USE_WHOAMI(NEWTOY(whoami, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config WHOAMI - bool "whoami" - default y - help - usage: whoami + bool "whoami" + default y + help + usage: whoami - Print effective user name. + Print effective user name. */ #include "toys.h" void whoami_main(void) { - struct passwd *pw = getpwuid(geteuid()); + struct passwd *pw = getpwuid(geteuid()); - if (!pw) { - perror("getpwuid"); - toys.exitval = 1; - return; - } + if (!pw) { + perror("getpwuid"); + toys.exitval = 1; + return; + } - xputs(pw->pw_name); + xputs(pw->pw_name); } diff --git a/toys/other/yes.c b/toys/other/yes.c index 90bf522d..773a5a88 100644 --- a/toys/other/yes.c +++ b/toys/other/yes.c @@ -1,31 +1,29 @@ -/* vi: set sw=4 ts=4: - * - * yes.c - Repeatedly output a string. +/* yes.c - Repeatedly output a string. * * Copyright 2007 Rob Landley <rob@landley.net> USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config YES - bool "yes" - default y - help - usage: yes [args...] + bool "yes" + default y + help + usage: yes [args...] - Repeatedly output line until killed. If no args, output 'y'. + Repeatedly output line until killed. If no args, output 'y'. */ #include "toys.h" void yes_main(void) { - for (;;) { - int i; - for (i=0; toys.optargs[i]; i++) { - if (i) xputc(' '); - xprintf("%s", toys.optargs[i]); - } - if (!i) xputc('y'); - xputc('\n'); - } + for (;;) { + int i; + for (i=0; toys.optargs[i]; i++) { + if (i) xputc(' '); + xprintf("%s", toys.optargs[i]); + } + if (!i) xputc('y'); + xputc('\n'); + } } diff --git a/toys/posix/basename.c b/toys/posix/basename.c index 9f228b41..75f3baa4 100644 --- a/toys/posix/basename.c +++ b/toys/posix/basename.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * basename.c - Return non-directory portion of a pathname +/* basename.c - Return non-directory portion of a pathname * * Copyright 2012 Tryn Mirell <tryn@mirell.org> * @@ -10,36 +8,36 @@ USE_BASENAME(NEWTOY(basename, "<1>2", TOYFLAG_USR|TOYFLAG_BIN)) config BASENAME - bool "basename" - default y - help - usage: basename string [suffix] + bool "basename" + default y + help + usage: basename string [suffix] - Return non-directory portion of a pathname removing suffix + Return non-directory portion of a pathname removing suffix */ #include "toys.h" void basename_main(void) { - char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base; - - while ((base = strrchr(arg, '/'))) { - if (base == arg) break; - if (!base[1]) *base = 0; - else { - base++; - break; - } + char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base; + + while ((base = strrchr(arg, '/'))) { + if (base == arg) break; + if (!base[1]) *base = 0; + else { + base++; + break; } + } - if (!base) base = arg; - - // chop off the suffix if provided - if (suffix) { - arg = base + strlen(base) - strlen(suffix); - if (arg > base && !strcmp(arg, suffix)) *arg = 0; - } - - puts(base); + if (!base) base = arg; + + // chop off the suffix if provided + if (suffix) { + arg = base + strlen(base) - strlen(suffix); + if (arg > base && !strcmp(arg, suffix)) *arg = 0; + } + + puts(base); } diff --git a/toys/posix/cal.c b/toys/posix/cal.c index 1c018e2f..e4301a64 100644 --- a/toys/posix/cal.c +++ b/toys/posix/cal.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cal.c - show calendar. +/* cal.c - show calendar. * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,14 +7,14 @@ USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN)) config CAL - bool "cal" - default y - help - usage: cal [[month] year] - Print a calendar. - - With one argument, prints all months of the specified year. - With two arguments, prints calendar for month and year. + bool "cal" + default y + help + usage: cal [[month] year] + Print a calendar. + + With one argument, prints all months of the specified year. + With two arguments, prints calendar for month and year. */ #include "toys.h" @@ -26,51 +24,51 @@ config CAL static char *calstrings(char *buf, struct tm *tm) { - char temp[21]; - int wday, mday, start, len, line; - - // header - len = strftime(temp, 21, "%B %Y", tm); - len += (20-len)/2; - buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, ""); - buf++; - buf += sprintf(buf, "Su Mo Tu We Th Fr Sa "); - buf++; - - // What day of the week does this month start on? - if (tm->tm_mday>1) - start = (36+tm->tm_wday-tm->tm_mday)%7; - else start = tm->tm_wday; - - // What day does this month end on? Alas, libc doesn't tell us... - len = 31; - if (tm->tm_mon == 1) { - int year = tm->tm_year; - len = 28; - if (!(year & 3) && !((year&100) && !(year&400))) len++; - } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; - - for (mday=line=0;line<6;line++) { - for (wday=0; wday<7; wday++) { - char *pat = " "; - if (!mday ? wday==start : mday<len) { - pat = "%2d "; - mday++; - } - buf += sprintf(buf, pat, mday); - } - buf++; - } - - return buf; + char temp[21]; + int wday, mday, start, len, line; + + // header + len = strftime(temp, 21, "%B %Y", tm); + len += (20-len)/2; + buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, ""); + buf++; + buf += sprintf(buf, "Su Mo Tu We Th Fr Sa "); + buf++; + + // What day of the week does this month start on? + if (tm->tm_mday>1) + start = (36+tm->tm_wday-tm->tm_mday)%7; + else start = tm->tm_wday; + + // What day does this month end on? Alas, libc doesn't tell us... + len = 31; + if (tm->tm_mon == 1) { + int year = tm->tm_year; + len = 28; + if (!(year & 3) && !((year&100) && !(year&400))) len++; + } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; + + for (mday=line=0;line<6;line++) { + for (wday=0; wday<7; wday++) { + char *pat = " "; + if (!mday ? wday==start : mday<len) { + pat = "%2d "; + mday++; + } + buf += sprintf(buf, pat, mday); + } + buf++; + } + + return buf; } void xcheckrange(long val, long low, long high) { - char *err = "%ld %s than %ld"; + char *err = "%ld %s than %ld"; - if (val < low) error_exit(err, val, "less", low); - if (val > high) error_exit(err, val, "greater", high); + if (val < low) error_exit(err, val, "less", low); + if (val > high) error_exit(err, val, "greater", high); } // Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line @@ -78,57 +76,57 @@ void xcheckrange(long val, long low, long high) void cal_main(void) { - struct tm *tm; - char *buf = toybuf; - - if (toys.optc) { - // Conveniently starts zeroed - tm = (struct tm *)toybuf; - buf += sizeof(struct tm); - - // Last argument is year, one before that (if any) is month. - xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); - tm->tm_year -= 1900; - tm->tm_mday = 1; - tm->tm_hour = 12; // noon to avoid timezone weirdness - if (toys.optc) { - xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); - tm->tm_mon--; - - // Print 12 months of the year - - } else { - char *bufs[12]; - int i, j, k; - - for (i=0; i<12; i++) { - tm->tm_mon=i; - mktime(tm); - buf = calstrings(bufs[i]=buf, tm); - } - - // 4 rows, 6 lines each, 3 columns - for (i=0; i<4; i++) { - for (j=0; j<8; j++) { - for(k=0; k<3; k++) { - char **b = bufs+(k+i*3); - *b += printf("%s ", *b); - } - puts(""); - } - } - return; - } - - // What day of the week does that start on? - mktime(tm); - - } else { - time_t now; - time(&now); - tm = localtime(&now); - } - - calstrings(buf, tm); - while (*buf) buf += printf("%s\n", buf); + struct tm *tm; + char *buf = toybuf; + + if (toys.optc) { + // Conveniently starts zeroed + tm = (struct tm *)toybuf; + buf += sizeof(struct tm); + + // Last argument is year, one before that (if any) is month. + xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); + tm->tm_year -= 1900; + tm->tm_mday = 1; + tm->tm_hour = 12; // noon to avoid timezone weirdness + if (toys.optc) { + xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); + tm->tm_mon--; + + // Print 12 months of the year + + } else { + char *bufs[12]; + int i, j, k; + + for (i=0; i<12; i++) { + tm->tm_mon=i; + mktime(tm); + buf = calstrings(bufs[i]=buf, tm); + } + + // 4 rows, 6 lines each, 3 columns + for (i=0; i<4; i++) { + for (j=0; j<8; j++) { + for(k=0; k<3; k++) { + char **b = bufs+(k+i*3); + *b += printf("%s ", *b); + } + puts(""); + } + } + return; + } + + // What day of the week does that start on? + mktime(tm); + + } else { + time_t now; + time(&now); + tm = localtime(&now); + } + + calstrings(buf, tm); + while (*buf) buf += printf("%s\n", buf); } diff --git a/toys/posix/cat.c b/toys/posix/cat.c index 160bd6ff..431c7751 100644 --- a/toys/posix/cat.c +++ b/toys/posix/cat.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cat.c - copy inputs to stdout. +/* cat.c - copy inputs to stdout. * * Copyright 2006 Rob Landley <rob@landley.net> * @@ -9,34 +7,34 @@ USE_CAT(NEWTOY(cat, "u", TOYFLAG_BIN)) config CAT - bool "cat" - default y - help - usage: cat [-u] [file...] - Copy (concatenate) files to stdout. If no files listed, copy from stdin. - Filename "-" is a synonym for stdin. + bool "cat" + default y + help + usage: cat [-u] [file...] + Copy (concatenate) files to stdout. If no files listed, copy from stdin. + Filename "-" is a synonym for stdin. - -u Copy one byte at a time (slow). + -u Copy one byte at a time (slow). */ #include "toys.h" static void do_cat(int fd, char *name) { - int len, size=toys.optflags ? 1 : sizeof(toybuf); + int len, size=toys.optflags ? 1 : sizeof(toybuf); - for (;;) { - len = read(fd, toybuf, size); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - xwrite(1, toybuf, len); - } + for (;;) { + len = read(fd, toybuf, size); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + xwrite(1, toybuf, len); + } } void cat_main(void) { - loopfiles(toys.optargs, do_cat); + loopfiles(toys.optargs, do_cat); } diff --git a/toys/posix/chgrp.c b/toys/posix/chgrp.c index 48ce6751..ed2ff9b2 100644 --- a/toys/posix/chgrp.c +++ b/toys/posix/chgrp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * chown.c - Change ownership +/* chgrp.c - Change user and group ownership * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> * @@ -13,103 +11,103 @@ USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv", TOYFLAG_BIN)) USE_CHGRP(OLDTOY(chown, chgrp, "<2hPLHRfv", TOYFLAG_BIN)) config CHGRP - bool "chgrp/chown" - default y - help - usage: chown [-RHLP] [-fvh] [owner][:group] file... - usage: chgrp [-RHLP] [-fvh] group file... - - Change ownership of one or more files. - - -f suppress most error messages. - -h change symlinks instead of what they point to - -R recurse into subdirectories (implies -h). - -H with -R change target of symlink, follow command line symlinks - -L with -R change target of symlink, follow all symlinks - -P with -R change symlink, do not follow symlinks (default) - -v verbose output. + bool "chgrp/chown" + default y + help + usage: chown [-RHLP] [-fvh] [owner][:group] file... + usage: chgrp [-RHLP] [-fvh] group file... + + Change ownership of one or more files. + + -f suppress most error messages. + -h change symlinks instead of what they point to + -R recurse into subdirectories (implies -h). + -H with -R change target of symlink, follow command line symlinks + -L with -R change target of symlink, follow all symlinks + -P with -R change symlink, do not follow symlinks (default) + -v verbose output. */ #define FOR_chgrp #include "toys.h" GLOBALS( - uid_t owner; - gid_t group; - char *owner_name, *group_name; - int symfollow; + uid_t owner; + gid_t group; + char *owner_name, *group_name; + int symfollow; ) static int do_chgrp(struct dirtree *node) { - int fd, ret, flags = toys.optflags; - - // Depth first search - if (!dirtree_notdotdot(node)) return 0; - if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode)) - return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0); - - fd = dirtree_parentfd(node); - ret = fchownat(fd, node->name, TT.owner, TT.group, - (flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R)) - ? 0 : AT_SYMLINK_NOFOLLOW); - - if (ret || (flags & FLAG_v)) { - char *path = dirtree_path(node, 0); - if (flags & FLAG_v) - xprintf("%s %s%s%s %s\n", toys.which->name, - TT.owner_name ? TT.owner_name : "", - toys.which->name[2]=='o' && TT.group_name ? ":" : "", - TT.group_name ? TT.group_name : "", path); - if (ret == -1 && !(toys.optflags & FLAG_f)) - perror_msg("changing owner:group of '%s' to '%s:%s'", path, - TT.owner_name, TT.group_name); - free(path); - } - toys.exitval |= ret; - - return 0; + int fd, ret, flags = toys.optflags; + + // Depth first search + if (!dirtree_notdotdot(node)) return 0; + if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode)) + return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0); + + fd = dirtree_parentfd(node); + ret = fchownat(fd, node->name, TT.owner, TT.group, + (flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R)) + ? 0 : AT_SYMLINK_NOFOLLOW); + + if (ret || (flags & FLAG_v)) { + char *path = dirtree_path(node, 0); + if (flags & FLAG_v) + xprintf("%s %s%s%s %s\n", toys.which->name, + TT.owner_name ? TT.owner_name : "", + toys.which->name[2]=='o' && TT.group_name ? ":" : "", + TT.group_name ? TT.group_name : "", path); + if (ret == -1 && !(toys.optflags & FLAG_f)) + perror_msg("changing owner:group of '%s' to '%s:%s'", path, + TT.owner_name, TT.group_name); + free(path); + } + toys.exitval |= ret; + + return 0; } void chgrp_main(void) { - int ischown = toys.which->name[2] == 'o'; - char **s, *own; - - // Distinguish chown from chgrp - if (ischown) { - char *grp; - struct passwd *p; - - own = xstrdup(*toys.optargs); - if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) { - *(grp++) = 0; - TT.group_name = grp; - } - if (*own) { - TT.owner_name = own; - p = getpwnam(own); - // TODO: trailing garbage? - if (!p && isdigit(*own)) p=getpwuid(atoi(own)); - if (!p) error_exit("no user '%s'", own); - TT.owner = p->pw_uid; - } - } else TT.group_name = *toys.optargs; - - if (TT.group_name) { - struct group *g; - g = getgrnam(TT.group_name); - if (!g) g=getgrgid(atoi(TT.group_name)); - if (!g) error_exit("no group '%s'", TT.group_name); - TT.group = g->gr_gid; - } - - for (s=toys.optargs+1; *s; s++) { - struct dirtree *new = dirtree_add_node(AT_FDCWD, *s, - toys.optflags&(FLAG_H|FLAG_L)); - if (new) handle_callback(new, do_chgrp); - else toys.exitval = 1; - } - - if (CFG_TOYBOX_FREE) free(own); + int ischown = toys.which->name[2] == 'o'; + char **s, *own; + + // Distinguish chown from chgrp + if (ischown) { + char *grp; + struct passwd *p; + + own = xstrdup(*toys.optargs); + if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) { + *(grp++) = 0; + TT.group_name = grp; + } + if (*own) { + TT.owner_name = own; + p = getpwnam(own); + // TODO: trailing garbage? + if (!p && isdigit(*own)) p=getpwuid(atoi(own)); + if (!p) error_exit("no user '%s'", own); + TT.owner = p->pw_uid; + } + } else TT.group_name = *toys.optargs; + + if (TT.group_name) { + struct group *g; + g = getgrnam(TT.group_name); + if (!g) g=getgrgid(atoi(TT.group_name)); + if (!g) error_exit("no group '%s'", TT.group_name); + TT.group = g->gr_gid; + } + + for (s=toys.optargs+1; *s; s++) { + struct dirtree *new = dirtree_add_node(AT_FDCWD, *s, + toys.optflags&(FLAG_H|FLAG_L)); + if (new) handle_callback(new, do_chgrp); + else toys.exitval = 1; + } + + if (CFG_TOYBOX_FREE) free(own); } diff --git a/toys/posix/chmod.c b/toys/posix/chmod.c index dcef9751..89b6e083 100644 --- a/toys/posix/chmod.c +++ b/toys/posix/chmod.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * chmod.c - Change file mode bits +/* chmod.c - Change file mode bits * * Copyright 2012 Rob Landley <rob@landley.net> * @@ -9,59 +7,59 @@ USE_CHMOD(NEWTOY(chmod, "<2?vR", TOYFLAG_BIN)) config CHMOD - bool "chmod" - default y - help - usage: chmod [-R] MODE FILE... + bool "chmod" + default y + help + usage: chmod [-R] MODE FILE... - Change mode of listed file[s] (recursively with -R). + Change mode of listed file[s] (recursively with -R). - MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] + MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] - Stanzas are applied in order: For each category (u = user, - g = group, o = other, a = all three, if none specified default is a), - set (+), clear (-), or copy (=), r = read, w = write, x = execute. - s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s). - suid/sgid: execute as the user/group who owns the file. - sticky: can't delete files you don't own out of this directory - X = x for directories or if any category already has x set. + Stanzas are applied in order: For each category (u = user, + g = group, o = other, a = all three, if none specified default is a), + set (+), clear (-), or copy (=), r = read, w = write, x = execute. + s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s). + suid/sgid: execute as the user/group who owns the file. + sticky: can't delete files you don't own out of this directory + X = x for directories or if any category already has x set. - Or MODE can be an octal value up to 7777 ug uuugggooo top + - bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom + Or MODE can be an octal value up to 7777 ug uuugggooo top + + bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom - Examples: - chmod u+w file - allow owner of "file" to write to it. - chmod 744 file - user can read/write/execute, everyone else read only + Examples: + chmod u+w file - allow owner of "file" to write to it. + chmod 744 file - user can read/write/execute, everyone else read only */ #define FOR_chmod #include "toys.h" GLOBALS( - char *mode; + char *mode; ) int do_chmod(struct dirtree *try) { - mode_t mode; + mode_t mode; - if (!dirtree_notdotdot(try)) return 0; + if (!dirtree_notdotdot(try)) return 0; - mode = string_to_mode(TT.mode, try->st.st_mode); - if (toys.optflags & FLAG_v) { - char *s = dirtree_path(try, 0); - printf("chmod '%s' to %04o\n", s, mode); - free(s); - } - wfchmodat(dirtree_parentfd(try), try->name, mode); + mode = string_to_mode(TT.mode, try->st.st_mode); + if (toys.optflags & FLAG_v) { + char *s = dirtree_path(try, 0); + printf("chmod '%s' to %04o\n", s, mode); + free(s); + } + wfchmodat(dirtree_parentfd(try), try->name, mode); - return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0; + return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0; } void chmod_main(void) { - TT.mode = *toys.optargs; - char **file; + TT.mode = *toys.optargs; + char **file; - for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); + for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); } diff --git a/toys/posix/cksum.c b/toys/posix/cksum.c index 3e27b4cb..1192077c 100644 --- a/toys/posix/cksum.c +++ b/toys/posix/cksum.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cksum.c - produce crc32 checksum value for each input +/* cksum.c - produce crc32 checksum value for each input * * Copyright 2008 Rob Landley <rob@landley.net> * @@ -9,78 +7,77 @@ USE_CKSUM(NEWTOY(cksum, "IPLN", TOYFLAG_BIN)) config CKSUM - bool "cksum" - default y - help - usage: cksum [-IPLN] [file...] - - For each file, output crc32 checksum value, length and name of file. - If no files listed, copy from stdin. Filename "-" is a synonym for stdin. - - -L Little endian (defaults to big endian) - -P Pre-inversion - -I Skip post-inversion - -N Do not include length in CRC calculation + bool "cksum" + default y + help + usage: cksum [-IPLN] [file...] + + For each file, output crc32 checksum value, length and name of file. + If no files listed, copy from stdin. Filename "-" is a synonym for stdin. + + -L Little endian (defaults to big endian) + -P Pre-inversion + -I Skip post-inversion + -N Do not include length in CRC calculation */ #define FOR_cksum #include "toys.h" GLOBALS( - unsigned crc_table[256]; + unsigned crc_table[256]; ) static unsigned cksum_be(unsigned crc, unsigned char c) { - return (crc<<8)^TT.crc_table[(crc>>24)^c]; + return (crc<<8)^TT.crc_table[(crc>>24)^c]; } static unsigned cksum_le(unsigned crc, unsigned char c) { - return TT.crc_table[(crc^c)&0xff] ^ (crc>>8); + return TT.crc_table[(crc^c)&0xff] ^ (crc>>8); } static void do_cksum(int fd, char *name) { - unsigned crc = (toys.optflags&4) ? 0xffffffff : 0; - uint64_t llen = 0, llen2; - unsigned (*cksum)(unsigned crc, unsigned char c); - - - cksum = (toys.optflags&2) ? cksum_le : cksum_be; - // CRC the data - - for (;;) { - int len, i; - - len = read(fd, toybuf, sizeof(toybuf)); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - - llen += len; - for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]); - } - - // CRC the length - - llen2 = llen; - if (!(toys.optflags&1)) { - while (llen) { - crc = cksum(crc, llen); - llen >>= 8; - } - } - - printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2); - if (strcmp("-", name)) printf(" %s", name); - xputc('\n'); + unsigned crc = (toys.optflags&4) ? 0xffffffff : 0; + uint64_t llen = 0, llen2; + unsigned (*cksum)(unsigned crc, unsigned char c); + + cksum = (toys.optflags&2) ? cksum_le : cksum_be; + // CRC the data + + for (;;) { + int len, i; + + len = read(fd, toybuf, sizeof(toybuf)); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + + llen += len; + for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]); + } + + // CRC the length + + llen2 = llen; + if (!(toys.optflags&1)) { + while (llen) { + crc = cksum(crc, llen); + llen >>= 8; + } + } + + printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2); + if (strcmp("-", name)) printf(" %s", name); + xputc('\n'); } void cksum_main(void) { - crc_init(TT.crc_table, toys.optflags&2); - loopfiles(toys.optargs, do_cksum); + crc_init(TT.crc_table, toys.optflags&2); + loopfiles(toys.optargs, do_cksum); } diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index 4bbd3f30..13990d45 100644 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cmp.c - Compare two files. +/* cmp.c - Compare two files. * * Copyright 2012 Timothy Elliott <tle@holymonkey.com> * @@ -9,80 +7,78 @@ USE_CMP(NEWTOY(cmp, "<2>2ls", TOYFLAG_USR|TOYFLAG_BIN)) config CMP - bool "cmp" - default y - help - usage: cmp [-l] [-s] FILE1 FILE2 + bool "cmp" + default y + help + usage: cmp [-l] [-s] FILE1 FILE2 - Compare the contents of two files. + Compare the contents of two files. - -l show all differing bytes - -s silent + -l show all differing bytes + -s silent */ #define FOR_cmp #include "toys.h" GLOBALS( - int fd; - char *name; + int fd; + char *name; ) -// This handles opening the file and +// This handles opening the file and void do_cmp(int fd, char *name) { - int i, len1, len2, min_len, size = sizeof(toybuf)/2; - long byte_no = 1, line_no = 1; - char *buf2 = toybuf+size; + int i, len1, len2, min_len, size = sizeof(toybuf)/2; + long byte_no = 1, line_no = 1; + char *buf2 = toybuf+size; - // First time through, cache the data and return. - if (!TT.fd) { - TT.name = name; - // On return the old filehandle is closed, and this assures that even - // if we were called with stdin closed, the new filehandle != 0. - TT.fd = dup(fd); - return; - } + // First time through, cache the data and return. + if (!TT.fd) { + TT.name = name; + // On return the old filehandle is closed, and this assures that even + // if we were called with stdin closed, the new filehandle != 0. + TT.fd = dup(fd); + return; + } - for (;;) { - len1 = readall(TT.fd, toybuf, size); - len2 = readall(fd, buf2, size); + for (;;) { + len1 = readall(TT.fd, toybuf, size); + len2 = readall(fd, buf2, size); - min_len = len1 < len2 ? len1 : len2; - for (i=0; i<min_len; i++) { - if (toybuf[i] != buf2[i]) { - toys.exitval = 1; - if (toys.optflags & FLAG_l) - printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]); - else { - if (!(toys.optflags & FLAG_s)) { - printf("%s %s differ: char %ld, line %ld\n", - TT.name, name, byte_no, line_no); - toys.exitval++; - } - goto out; - } - } - byte_no++; - if (toybuf[i] == '\n') line_no++; - } - if (len1 != len2) { - if (!(toys.optflags & FLAG_s)) { - fprintf(stderr, "cmp: EOF on %s\n", - len1 < len2 ? TT.name : name); - } - toys.exitval = 1; - break; - } - if (len1 < 1) break; - } + min_len = len1 < len2 ? len1 : len2; + for (i=0; i<min_len; i++) { + if (toybuf[i] != buf2[i]) { + toys.exitval = 1; + if (toys.optflags & FLAG_l) + printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]); + else { + if (!(toys.optflags & FLAG_s)) { + printf("%s %s differ: char %ld, line %ld\n", + TT.name, name, byte_no, line_no); + toys.exitval++; + } + goto out; + } + } + byte_no++; + if (toybuf[i] == '\n') line_no++; + } + if (len1 != len2) { + if (!(toys.optflags & FLAG_s)) + fprintf(stderr, "cmp: EOF on %s\n", len1 < len2 ? TT.name : name); + toys.exitval = 1; + break; + } + if (len1 < 1) break; + } out: - if (CFG_TOYBOX_FREE) close(TT.fd); + if (CFG_TOYBOX_FREE) close(TT.fd); } void cmp_main(void) { - loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp); + loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp); } diff --git a/toys/posix/comm.c b/toys/posix/comm.c index 477d5160..bbdcccef 100644 --- a/toys/posix/comm.c +++ b/toys/posix/comm.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * comm.c - select or reject lines common to two files +/* comm.c - select or reject lines common to two files * * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net> * @@ -10,18 +8,18 @@ USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN)) config COMM - bool "comm" - default y - help - usage: comm [-123] FILE1 FILE2 + bool "comm" + default y + help + usage: comm [-123] FILE1 FILE2 - Reads FILE1 and FILE2, which should be ordered, and produces three text - columns as output: lines only in FILE1; lines only in FILE2; and lines - in both files. Filename "-" is a synonym for stdin. + Reads FILE1 and FILE2, which should be ordered, and produces three text + columns as output: lines only in FILE1; lines only in FILE2; and lines + in both files. Filename "-" is a synonym for stdin. - -1 suppress the output column of lines unique to FILE1 - -2 suppress the output column of lines unique to FILE2 - -3 suppress the output column of lines duplicated in FILE1 and FILE2 + -1 suppress the output column of lines unique to FILE1 + -2 suppress the output column of lines unique to FILE2 + -3 suppress the output column of lines duplicated in FILE1 and FILE2 */ #define FOR_comm @@ -29,54 +27,55 @@ config COMM static void writeline(const char *line, int col) { - if (col == 0 && toys.optflags & FLAG_1) return; - else if (col == 1) { - if (toys.optflags & FLAG_2) return; - if (!(toys.optflags & FLAG_1)) putchar('\t'); - } else if (col == 2) { - if (toys.optflags & FLAG_3) return; - if (!(toys.optflags & FLAG_1)) putchar('\t'); - if (!(toys.optflags & FLAG_2)) putchar('\t'); - } - puts(line); + if (col == 0 && toys.optflags & FLAG_1) return; + else if (col == 1) { + if (toys.optflags & FLAG_2) return; + if (!(toys.optflags & FLAG_1)) putchar('\t'); + } else if (col == 2) { + if (toys.optflags & FLAG_3) return; + if (!(toys.optflags & FLAG_1)) putchar('\t'); + if (!(toys.optflags & FLAG_2)) putchar('\t'); + } + puts(line); } void comm_main(void) { - int file[2]; - char *line[2]; - int i; + int file[2]; + char *line[2]; + int i; - if (toys.optflags == 7) return; + if (toys.optflags == 7) return; - for (i = 0; i < 2; i++) { - file[i] = strcmp("-", toys.optargs[i]) ? xopen(toys.optargs[i], O_RDONLY) : 0; - line[i] = get_line(file[i]); - } + for (i = 0; i < 2; i++) { + file[i] = strcmp("-", toys.optargs[i]) + ? xopen(toys.optargs[i], O_RDONLY) : 0; + line[i] = get_line(file[i]); + } - while (line[0] && line[1]) { - int order = strcmp(line[0], line[1]); + while (line[0] && line[1]) { + int order = strcmp(line[0], line[1]); - if (order == 0) { - writeline(line[0], 2); - for (i = 0; i < 2; i++) { - free(line[i]); - line[i] = get_line(file[i]); - } - } else { - i = order < 0 ? 0 : 1; - writeline(line[i], i); - free(line[i]); - line[i] = get_line(file[i]); - } - } + if (order == 0) { + writeline(line[0], 2); + for (i = 0; i < 2; i++) { + free(line[i]); + line[i] = get_line(file[i]); + } + } else { + i = order < 0 ? 0 : 1; + writeline(line[i], i); + free(line[i]); + line[i] = get_line(file[i]); + } + } - /* print rest of the longer file */ - for (i = line[0] ? 0 : 1; line[i];) { - writeline(line[i], i); - free(line[i]); - line[i] = get_line(file[i]); - } + /* print rest of the longer file */ + for (i = line[0] ? 0 : 1; line[i];) { + writeline(line[i], i); + free(line[i]); + line[i] = get_line(file[i]); + } - if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]); + if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]); } diff --git a/toys/posix/cp.c b/toys/posix/cp.c index b7834e86..e25dad46 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -1,8 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cp.c - Copy files. - * - * Copyright 2008 Rob Landley <rob@landley.net> +/* Copyright 2008 Rob Landley <rob@landley.net> * * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html * @@ -11,35 +7,35 @@ USE_CP(NEWTOY(cp, "<2"USE_CP_MORE("rdavsl")"RHLPfip", TOYFLAG_BIN)) config CP - bool "cp (broken by dirtree changes)" - default n - help - usage: cp [-fipRHLP] SOURCE... DEST - - Copy files from SOURCE to DEST. If more than one SOURCE, DEST must - be a directory. - - -f force copy by deleting destination file - -i interactive, prompt before overwriting existing DEST - -p preserve timestamps, ownership, and permissions - -R recurse into subdirectories (DEST must be a directory) - -H Follow symlinks listed on command line - -L Follow all symlinks - -P Do not follow symlinks [default] + bool "cp (broken by dirtree changes)" + default n + help + usage: cp [-fipRHLP] SOURCE... DEST + + Copy files from SOURCE to DEST. If more than one SOURCE, DEST must + be a directory. + + -f force copy by deleting destination file + -i interactive, prompt before overwriting existing DEST + -p preserve timestamps, ownership, and permissions + -R recurse into subdirectories (DEST must be a directory) + -H Follow symlinks listed on command line + -L Follow all symlinks + -P Do not follow symlinks [default] config CP_MORE - bool "cp -rdavsl options" - default y - depends on CP - help - usage: cp [-rdavsl] - - -r synonym for -R - -d don't dereference symlinks - -a same as -dpr - -l hard link instead of copy - -s symlink instead of copy - -v verbose + bool "cp -rdavsl options" + default y + depends on CP + help + usage: cp [-rdavsl] + + -r synonym for -R + -d don't dereference symlinks + -a same as -dpr + -l hard link instead of copy + -s symlink instead of copy + -v verbose */ #define FOR_cp @@ -48,180 +44,176 @@ config CP_MORE // TODO: PLHlsd GLOBALS( - char *destname; - int destisdir; - int keep_symlinks; + char *destname; + int destisdir; + int keep_symlinks; ) // Copy an individual file or directory to target. void cp_file(char *src, char *dst, struct stat *srcst) { - int fdout = -1; - - // -i flag is specified and dst file exists. - if ((toys.optflags&FLAG_i) && !access(dst, R_OK) - && !yesno("cp: overwrite", 1)) - return; - - if (toys.optflags & FLAG_v) - printf("'%s' -> '%s'\n", src, dst); - - // Copy directory or file to destination. - - if (S_ISDIR(srcst->st_mode)) { - struct stat st2; - - // Always make directory writeable to us, so we can create files in it. - // - // Yes, there's a race window between mkdir() and open() so it's - // possible that -p can be made to chown a directory other than the one - // we created. The closest we can do to closing this is make sure - // that what we open _is_ a directory rather than something else. - - if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST) - || 0>(fdout=open(dst, 0)) || fstat(fdout, &st2) - || !S_ISDIR(st2.st_mode)) - { - perror_exit("mkdir '%s'", dst); - } - } else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) { - char *link = xreadlink(src); - - // Note: -p currently has no effect on symlinks. How do you get a - // filehandle to them? O_NOFOLLOW causes the open to fail. - if (!link || symlink(link, dst)) perror_msg("link '%s'", dst); - free(link); - return; - } else if (toys.optflags & FLAG_l) { - if (link(src, dst)) perror_msg("link '%s'"); - return; - } else { - int fdin, i; - - fdin = xopen(src, O_RDONLY); - for (i=2 ; i; i--) { - fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode); - if (fdout>=0 || !(toys.optflags & FLAG_f)) break; - unlink(dst); - } - if (fdout<0) perror_exit("%s", dst); - xsendfile(fdin, fdout); - close(fdin); - } - - // Inability to set these isn't fatal, some require root access. - // Can't do fchmod() etc here because -p works on mkdir, too. - - if (toys.optflags & (FLAG_p|FLAG_a)) { - int mask = umask(0); - struct utimbuf ut; - - (void) fchown(fdout,srcst->st_uid, srcst->st_gid); - ut.actime = srcst->st_atime; - ut.modtime = srcst->st_mtime; - utime(dst, &ut); - umask(mask); - } - xclose(fdout); + int fdout = -1; + + // -i flag is specified and dst file exists. + if ((toys.optflags&FLAG_i) && !access(dst, R_OK) + && !yesno("cp: overwrite", 1)) + return; + + if (toys.optflags & FLAG_v) printf("'%s' -> '%s'\n", src, dst); + + // Copy directory or file to destination. + + if (S_ISDIR(srcst->st_mode)) { + struct stat st2; + + // Always make directory writeable to us, so we can create files in it. + // + // Yes, there's a race window between mkdir() and open() so it's + // possible that -p can be made to chown a directory other than the one + // we created. The closest we can do to closing this is make sure + // that what we open _is_ a directory rather than something else. + + if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST) + || 0>(fdout=open(dst, 0)) || fstat(fdout, &st2) || !S_ISDIR(st2.st_mode)) + { + perror_exit("mkdir '%s'", dst); + } + } else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) { + char *link = xreadlink(src); + + // Note: -p currently has no effect on symlinks. How do you get a + // filehandle to them? O_NOFOLLOW causes the open to fail. + if (!link || symlink(link, dst)) perror_msg("link '%s'", dst); + free(link); + return; + } else if (toys.optflags & FLAG_l) { + if (link(src, dst)) perror_msg("link '%s'"); + return; + } else { + int fdin, i; + + fdin = xopen(src, O_RDONLY); + for (i=2 ; i; i--) { + fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode); + if (fdout>=0 || !(toys.optflags & FLAG_f)) break; + unlink(dst); + } + if (fdout<0) perror_exit("%s", dst); + xsendfile(fdin, fdout); + close(fdin); + } + + // Inability to set these isn't fatal, some require root access. + // Can't do fchmod() etc here because -p works on mkdir, too. + + if (toys.optflags & (FLAG_p|FLAG_a)) { + int mask = umask(0); + struct utimbuf ut; + + (void) fchown(fdout,srcst->st_uid, srcst->st_gid); + ut.actime = srcst->st_atime; + ut.modtime = srcst->st_mtime; + utime(dst, &ut); + umask(mask); + } + xclose(fdout); } // Callback from dirtree_read() for each file/directory under a source dir. int cp_node(struct dirtree *node) { - char *path = dirtree_path(node, 0); // TODO: use openat() instead - char *s = path+strlen(path); - struct dirtree *n; - - // Find appropriate chunk of path for destination. - - n = node; - if (!TT.destisdir) n = n->parent; - for (;;n = n->parent) { - while (s!=path) { - if (*(--s)=='/') break; - } - if (!n) break; - } - if (s != path) s++; - - s = xmsprintf("%s/%s", TT.destname, s); - cp_file(path, s, &(node->st)); - free(s); - free(path); // redo this whole darn function. - - return 0; + char *path = dirtree_path(node, 0); // TODO: use openat() instead + char *s = path+strlen(path); + struct dirtree *n; + + // Find appropriate chunk of path for destination. + + n = node; + if (!TT.destisdir) n = n->parent; + for (;;n = n->parent) { + while (s!=path) if (*(--s)=='/') break; + if (!n) break; + } + if (s != path) s++; + + s = xmsprintf("%s/%s", TT.destname, s); + cp_file(path, s, &(node->st)); + free(s); + free(path); // redo this whole darn function. + + return 0; } void cp_main(void) { - char *dpath = NULL; - struct stat st, std; - int i; + char *dpath = NULL; + struct stat st, std; + int i; - // Identify destination + // Identify destination - if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++; - else if (toys.optc>1) error_exit("'%s' not directory", TT.destname); + if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++; + else if (toys.optc>1) error_exit("'%s' not directory", TT.destname); // TODO: This is too early: we haven't created it yet if we need to - if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a)) - dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL); + if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a)) + dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL); - // Loop through sources + // Loop through sources - for (i=0; i<toys.optc; i++) { - char *dst, *src = toys.optargs[i]; + for (i=0; i<toys.optc; i++) { + char *dst, *src = toys.optargs[i]; - // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). + // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). - if (!strncmp(src, TT.destname)) continue; + if (!strncmp(src, TT.destname)) continue; - // Skip nonexistent sources. + // Skip nonexistent sources. - TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); - if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st) - || (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino)) - { + TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); + if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st) + || (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino)) + { objection: - perror_msg("bad '%s'", src); - toys.exitval = 1; - continue; - } - - // Copy directory or file. - - if (TT.destisdir) { - char *s; - - // Catch "cp -R .. ." and friends that would go on forever - if (dpath && (s = realpath(src, NULL)) { - int i = strlen(s); - i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/')); - free(s); - - if (i) goto objection; - } - - // Create destination filename within directory - dst = strrchr(src, '/'); - if (dst) dst++; - else dst=src; - dst = xmsprintf("%s/%s", TT.destname, dst); - } else dst = TT.destname; - - if (S_ISDIR(st.st_mode)) { - if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { - cp_file(src, dst, &st); - - TT.keep_symlinks++; - dirtree_read(src, cp_node); - } else error_msg("Skipped dir '%s'", src); - } else cp_file(src, dst, &st); - if (TT.destisdir) free(dst); - } - - if (CFG_TOYBOX_FREE) free(dpath); - return; + perror_msg("bad '%s'", src); + toys.exitval = 1; + continue; + } + + // Copy directory or file. + + if (TT.destisdir) { + char *s; + + // Catch "cp -R .. ." and friends that would go on forever + if (dpath && (s = realpath(src, NULL)) { + int i = strlen(s); + i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/')); + free(s); + + if (i) goto objection; + } + + // Create destination filename within directory + dst = strrchr(src, '/'); + if (dst) dst++; + else dst=src; + dst = xmsprintf("%s/%s", TT.destname, dst); + } else dst = TT.destname; + + if (S_ISDIR(st.st_mode)) { + if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { + cp_file(src, dst, &st); + + TT.keep_symlinks++; + dirtree_read(src, cp_node); + } else error_msg("Skipped dir '%s'", src); + } else cp_file(src, dst, &st); + if (TT.destisdir) free(dst); + } + + if (CFG_TOYBOX_FREE) free(dpath); + return; } diff --git a/toys/posix/date.c b/toys/posix/date.c index 9beaaa1a..68751043 100644 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * date.c - set/get the date +/* date.c - set/get the date * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * @@ -9,83 +7,83 @@ USE_DATE(NEWTOY(date, "r:u", TOYFLAG_BIN)) config DATE - bool "date" - default y - help - usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy] + bool "date" + default y + help + usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy] - Set/get the current date/time + Set/get the current date/time */ #define FOR_date #include "toys.h" GLOBALS( - char *file; + char *file; ) void date_main(void) { - const char *format_string = "%a %b %e %H:%M:%S %Z %Y"; - time_t now = time(NULL); - struct tm tm; - - if (TT.file) { - struct stat st; - - xstat(TT.file, &st); - now = st.st_mtim.tv_sec; - } - ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); - - // Display the date? - if (!toys.optargs[0] || toys.optargs[0][0] == '+') { - if (toys.optargs[0]) format_string = toys.optargs[0]+1; - if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) - perror_msg("bad format `%s'", format_string); - - puts(toybuf); - - // Set the date - } else { - struct timeval tv; - char *s = *toys.optargs; - int len = strlen(s); - - if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s); - - // Date format: mmddhhmm[[cc]yy] - memset(&tm, 0, sizeof(tm)); - len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min); - tm.tm_mon--; - - // If year specified, overwrite one we fetched earlier - if (len > 8) { - sscanf(s, "%u", &tm.tm_year); - if (len == 12) tm.tm_year -= 1900; - /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */ - else if (tm.tm_year < 69) tm.tm_year += 100; - } - - if (toys.optflags & FLAG_u) { - // Get the UTC version of a struct tm - char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0; - setenv("TZ", "UTC", 1); - tzset(); - tv.tv_sec = mktime(&tm); - if (CFG_TOYBOX_FREE) { - if (tz) setenv("TZ", tz, 1); - else unsetenv("TZ"); - tzset(); - } - } else tv.tv_sec = mktime(&tm); - - if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]); - tv.tv_usec = 0; - if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) - perror_msg("bad format `%s'", format_string); - puts(toybuf); - if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); + const char *format_string = "%a %b %e %H:%M:%S %Z %Y"; + time_t now = time(NULL); + struct tm tm; + + if (TT.file) { + struct stat st; + + xstat(TT.file, &st); + now = st.st_mtim.tv_sec; + } + ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); + + // Display the date? + if (!toys.optargs[0] || toys.optargs[0][0] == '+') { + if (toys.optargs[0]) format_string = toys.optargs[0]+1; + if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) + perror_msg("bad format `%s'", format_string); + + puts(toybuf); + + // Set the date + } else { + struct timeval tv; + char *s = *toys.optargs; + int len = strlen(s); + + if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s); + + // Date format: mmddhhmm[[cc]yy] + memset(&tm, 0, sizeof(tm)); + len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min); + tm.tm_mon--; + + // If year specified, overwrite one we fetched earlier + if (len > 8) { + sscanf(s, "%u", &tm.tm_year); + if (len == 12) tm.tm_year -= 1900; + /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */ + else if (tm.tm_year < 69) tm.tm_year += 100; } + + if (toys.optflags & FLAG_u) { + // Get the UTC version of a struct tm + char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0; + setenv("TZ", "UTC", 1); + tzset(); + tv.tv_sec = mktime(&tm); + if (CFG_TOYBOX_FREE) { + if (tz) setenv("TZ", tz, 1); + else unsetenv("TZ"); + tzset(); + } + } else tv.tv_sec = mktime(&tm); + + if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]); + tv.tv_usec = 0; + if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) + perror_msg("bad format `%s'", format_string); + puts(toybuf); + if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); + } } diff --git a/toys/posix/df.c b/toys/posix/df.c index 66e86b3b..5641ff34 100644 --- a/toys/posix/df.c +++ b/toys/posix/df.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * df.c - report free disk space. +/* df.c - report free disk space. * * Copyright 2006 Rob Landley <rob@landley.net> * @@ -9,156 +7,155 @@ USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN)) config DF - bool "df (disk free)" - default y - help - usage: df [-t type] [FILESYSTEM ...] + bool "df (disk free)" + default y + help + usage: df [-t type] [FILESYSTEM ...] - The "disk free" command, df shows total/used/available disk space for - each filesystem listed on the command line, or all currently mounted - filesystems. + The "disk free" command, df shows total/used/available disk space for + each filesystem listed on the command line, or all currently mounted + filesystems. - -t type - Display only filesystems of this type. + -t type Display only filesystems of this type. config DF_PEDANTIC - bool "options -P and -k" - default y - depends on DF - help - usage: df [-Pk] + bool "options -P and -k" + default y + depends on DF + help + usage: df [-Pk] - -P The SUSv3 "Pedantic" option + -P The SUSv3 "Pedantic" option - Provides a slightly less useful output format dictated by - the Single Unix Specification version 3, and sets the - units to 512 bytes instead of the default 1024 bytes. + Provides a slightly less useful output format dictated by + the Single Unix Specification version 3, and sets the + units to 512 bytes instead of the default 1024 bytes. - -k Sets units back to 1024 bytes (the default without -P) + -k Sets units back to 1024 bytes (the default without -P) */ #define FOR_df #include "toys.h" GLOBALS( - struct arg_list *fstype; + struct arg_list *fstype; - long units; + long units; ) static void show_mt(struct mtab_list *mt) { - int len; - long long size, used, avail, percent, block; - char *device; - - // Return if it wasn't found (should never happen, but with /etc/mtab...) - if (!mt) return; - - // If we have -t, skip other filesystem types - if (TT.fstype) { - struct arg_list *al; - - for (al = TT.fstype; al; al = al->next) { - if (!strcmp(mt->type, al->arg)) break; - } - if (!al) return; - } - - // If we don't have -a, skip synthetic filesystems - if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return; - - // Figure out how much total/used/free space this filesystem has, - // forcing 64-bit math because filesystems are big now. - block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1; - size = (block * mt->statvfs.f_blocks) / TT.units; - used = (block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) / TT.units; - avail = (block * (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree)) - / TT.units; - if (!(used+avail)) percent = 0; - else { - percent = (used*100)/(used+avail); - if (used*100 != percent*(used+avail)) percent++; - } - - device = *mt->device == '/' ? realpath(mt->device, NULL) : NULL; - if (!device) device = mt->device; - - // Figure out appropriate spacing - len = 25 - strlen(device); - if (len < 1) len = 1; - if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { - xprintf("%s %lld %lld %lld %lld%% %s\n", device, size, used, avail, - percent, mt->dir); - } else { - xprintf("%s% *lld % 10lld % 9lld % 3lld%% %s\n", device, len, - size, used, avail, percent, mt->dir); - } - - if (device != mt->device) free(device); + int len; + long long size, used, avail, percent, block; + char *device; + + // Return if it wasn't found (should never happen, but with /etc/mtab...) + if (!mt) return; + + // If we have -t, skip other filesystem types + if (TT.fstype) { + struct arg_list *al; + + for (al = TT.fstype; al; al = al->next) + if (!strcmp(mt->type, al->arg)) break; + + if (!al) return; + } + + // If we don't have -a, skip synthetic filesystems + if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return; + + // Figure out how much total/used/free space this filesystem has, + // forcing 64-bit math because filesystems are big now. + block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1; + size = (block * mt->statvfs.f_blocks) / TT.units; + used = (block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) / TT.units; + avail = (block * (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree)) + / TT.units; + if (!(used+avail)) percent = 0; + else { + percent = (used*100)/(used+avail); + if (used*100 != percent*(used+avail)) percent++; + } + + device = *mt->device == '/' ? realpath(mt->device, NULL) : NULL; + if (!device) device = mt->device; + + // Figure out appropriate spacing + len = 25 - strlen(device); + if (len < 1) len = 1; + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { + xprintf("%s %lld %lld %lld %lld%% %s\n", device, size, used, avail, + percent, mt->dir); + } else { + xprintf("%s% *lld % 10lld % 9lld % 3lld%% %s\n", device, len, + size, used, avail, percent, mt->dir); + } + + if (device != mt->device) free(device); } void df_main(void) { - struct mtab_list *mt, *mt2, *mtlist; - - // Handle -P and -k - TT.units = 1024; - if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { - // Units are 512 bytes if you select "pedantic" without "kilobytes". - if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512; - printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", - TT.units); - } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); - - mtlist = getmountlist(1); - - // If we have a list of filesystems on the command line, loop through them. - if (*toys.optargs) { - char **next; - - for(next = toys.optargs; *next; next++) { - struct stat st; - - // Stat it (complain if we can't). - if(stat(*next, &st)) { - perror_msg("`%s'", *next); - toys.exitval = 1; - continue; - } - - // Find and display this filesystem. Use _last_ hit in case of - // -- bind mounts. - mt2 = NULL; - for (mt = mtlist; mt; mt = mt->next) { - if (st.st_dev == mt->stat.st_dev) { - mt2 = mt; - break; - } - } - show_mt(mt2); - } - } else { - // Get and loop through mount list. - - for (mt = mtlist; mt; mt = mt->next) { - struct mtab_list *mt2, *mt3; - - if (!mt->stat.st_dev) continue; - - // Filter out overmounts. - mt3 = mt; - for (mt2 = mt->next; mt2; mt2 = mt2->next) { - if (mt->stat.st_dev == mt2->stat.st_dev) { - // For --bind mounts, take last match - if (!strcmp(mt->device, mt2->device)) mt3 = mt2; - // Filter out overmounts - mt2->stat.st_dev = 0; - } - } - show_mt(mt3); - } - } - - if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free); + struct mtab_list *mt, *mt2, *mtlist; + + // Handle -P and -k + TT.units = 1024; + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { + // Units are 512 bytes if you select "pedantic" without "kilobytes". + if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512; + printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", + TT.units); + } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); + + mtlist = getmountlist(1); + + // If we have a list of filesystems on the command line, loop through them. + if (*toys.optargs) { + char **next; + + for(next = toys.optargs; *next; next++) { + struct stat st; + + // Stat it (complain if we can't). + if(stat(*next, &st)) { + perror_msg("`%s'", *next); + toys.exitval = 1; + continue; + } + + // Find and display this filesystem. Use _last_ hit in case of + // -- bind mounts. + mt2 = NULL; + for (mt = mtlist; mt; mt = mt->next) { + if (st.st_dev == mt->stat.st_dev) { + mt2 = mt; + break; + } + } + show_mt(mt2); + } + } else { + // Get and loop through mount list. + + for (mt = mtlist; mt; mt = mt->next) { + struct mtab_list *mt2, *mt3; + + if (!mt->stat.st_dev) continue; + + // Filter out overmounts. + mt3 = mt; + for (mt2 = mt->next; mt2; mt2 = mt2->next) { + if (mt->stat.st_dev == mt2->stat.st_dev) { + // For --bind mounts, take last match + if (!strcmp(mt->device, mt2->device)) mt3 = mt2; + // Filter out overmounts + mt2->stat.st_dev = 0; + } + } + show_mt(mt3); + } + } + + if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free); } diff --git a/toys/posix/dirname.c b/toys/posix/dirname.c index 5dc60181..06470ad8 100644 --- a/toys/posix/dirname.c +++ b/toys/posix/dirname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dirname.c - show directory portion of path +/* dirname.c - show directory portion of path * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,17 +7,17 @@ USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config DIRNAME - bool "dirname" - default y - help - usage: dirname PATH + bool "dirname" + default y + help + usage: dirname PATH - Show directory portion of path. + Show directory portion of path. */ #include "toys.h" void dirname_main(void) { - puts(dirname(*toys.optargs)); + puts(dirname(*toys.optargs)); } diff --git a/toys/posix/du.c b/toys/posix/du.c index 8013810c..68cf286d 100644 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * du.c - disk usage program. +/* du.c - disk usage program. * * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com> * @@ -9,45 +7,45 @@ USE_DU(NEWTOY(du, "d#<0hmlcaHkLsx", TOYFLAG_USR|TOYFLAG_BIN)) config DU - bool "du" - default y - help - usage: du [-d N] [-askxHLlmc] [file...] - - Estimate file space usage (default in unit of 512 blocks). - -a Show all file sizes - -H Follow symlinks on cmdline - -L Follow all symlinks - -k Show size in units of 1024. - -s Show only the total Size for each file specified - -x Estimate size only on the same device - -c Print total size of all arguments - -d N Limit output to directories (and files with -a) of depth < N - -l Count sizes many times if hard linked - -h Sizes in human readable format (e.g., 1K 243M 2G ) - -m Sizes in megabytes + bool "du" + default y + help + usage: du [-d N] [-askxHLlmc] [file...] + + Estimate file space usage (default in unit of 512 blocks). + -a Show all file sizes + -H Follow symlinks on cmdline + -L Follow all symlinks + -k Show size in units of 1024. + -s Show only the total Size for each file specified + -x Estimate size only on the same device + -c Print total size of all arguments + -d N Limit output to directories (and files with -a) of depth < N + -l Count sizes many times if hard linked + -h Sizes in human readable format (e.g., 1K 243M 2G ) + -m Sizes in megabytes */ #define FOR_du #include "toys.h" GLOBALS( - long maxdepth; - long depth; - long *dirsum; - long total; - dev_t st_dev; - struct arg_list *inodes; + long maxdepth; + long depth; + long *dirsum; + long total; + dev_t st_dev; + struct arg_list *inodes; ) typedef struct node_size { - struct dirtree *node; - long size; + struct dirtree *node; + long size; }node_size; typedef struct inode_ent { - ino_t ino; - dev_t dev; + ino_t ino; + dev_t dev; }inode_ent_t; /* @@ -56,18 +54,18 @@ typedef struct inode_ent { char *make_pathproper(char *str) { - char *path = str; - switch(strlen(str)) { - case 1: - if(str[0] == '.') path = xstrdup("./"); - break; - case 2: - if(str[0] == '.' && str[1] == '.') path = xstrdup("../"); - break; - default: - break; - } - return path; + char *path = str; + switch(strlen(str)) { + case 1: + if(str[0] == '.') path = xstrdup("./"); + break; + case 2: + if(str[0] == '.' && str[1] == '.') path = xstrdup("../"); + break; + default: + break; + } + return path; } /* @@ -75,38 +73,38 @@ char *make_pathproper(char *str) */ void print(long size, char* name) { - unsigned long long tempsize = (unsigned long long)size * 512; - unsigned long unit = 512; - char *sizestr = NULL; - if(TT.depth > TT.maxdepth) return; - if(toys.optflags & FLAG_h) unit = 0; - if(toys.optflags & FLAG_k) unit = 1024; - if(toys.optflags & FLAG_m) unit = 1024*1024; - sizestr = make_human_readable(tempsize, unit); //make human readable string, depending upon unit size. - xprintf("%s\t%s\n",sizestr, name); - free(sizestr); + unsigned long long tempsize = (unsigned long long)size * 512; + unsigned long unit = 512; + char *sizestr = NULL; + if(TT.depth > TT.maxdepth) return; + if(toys.optflags & FLAG_h) unit = 0; + if(toys.optflags & FLAG_k) unit = 1024; + if(toys.optflags & FLAG_m) unit = 1024*1024; + sizestr = make_human_readable(tempsize, unit); //make human readable string, depending upon unit size. + xprintf("%s\t%s\n",sizestr, name); + free(sizestr); } /* - * free the inodes which are stored for hard link reference + * free the inodes which are stored for hard link reference */ void free_inodes(void *data) { - void *arg = ((struct arg_list*)data)->arg; - if(arg) free(arg); - free(data); + void *arg = ((struct arg_list*)data)->arg; + if(arg) free(arg); + free(data); } /* * allocate and add a node to the list */ static void llist_add_inode(struct arg_list **old, void *data) -{ - struct arg_list *new = xmalloc(sizeof(struct arg_list)); +{ + struct arg_list *new = xmalloc(sizeof(struct arg_list)); - new->arg = (char*)data; - new->next = *old; - *old = new; + new->arg = (char*)data; + new->next = *old; + *old = new; } /* @@ -114,14 +112,14 @@ static void llist_add_inode(struct arg_list **old, void *data) */ int is_inode_present(struct stat *st) { - struct arg_list *temparg = NULL; - inode_ent_t *ent = NULL; - if(!TT.inodes) return 0; - for(temparg = TT.inodes; temparg; temparg = (struct arg_list *)temparg->next) { - ent = (inode_ent_t*)temparg->arg; - if(ent && ent->ino == st->st_ino && ent->dev == st->st_dev) return 1; - } - return 0; + struct arg_list *temparg = NULL; + inode_ent_t *ent = NULL; + if(!TT.inodes) return 0; + for(temparg = TT.inodes; temparg; temparg = (struct arg_list *)temparg->next) { + ent = (inode_ent_t*)temparg->arg; + if(ent && ent->ino == st->st_ino && ent->dev == st->st_dev) return 1; + } + return 0; } /* @@ -129,66 +127,66 @@ int is_inode_present(struct stat *st) */ int do_du(struct dirtree *node) { - inode_ent_t *ino_details = NULL; - node_size *nd = NULL; - if(!dirtree_notdotdot(node)) return 0; - if((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) //if file not on same device, don't count size - return DIRTREE_RECURSE; - - if(!(toys.optflags & FLAG_l) && node->st.st_nlink > 1 && !node->extra) { //keeping reference for hard links - if(is_inode_present(&node->st)) return DIRTREE_RECURSE; - ino_details = xzalloc(sizeof(inode_ent_t)); - ino_details->ino = node->st.st_ino; - ino_details->dev = node->st.st_dev; - llist_add_inode(&TT.inodes, (void*)ino_details); - } + inode_ent_t *ino_details = NULL; + node_size *nd = NULL; + if(!dirtree_notdotdot(node)) return 0; + if((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) //if file not on same device, don't count size + return DIRTREE_RECURSE; - if(S_ISDIR(node->st.st_mode)) { - if(!(node->extra && (long)((node_size*)(node->extra))->node == (long)node)) { - nd = xzalloc(sizeof(node_size)); - nd->node = node; - nd->size = 0; - TT.dirsum = (long*)&(nd->size); - node->extra = (long)nd; - *TT.dirsum = 0; - TT.depth++; - return (DIRTREE_RECURSE|DIRTREE_COMEAGAIN | ((toys.optflags & FLAG_L) ? DIRTREE_SYMFOLLOW : 0)); //DIRTREE_COMEAGAIN to comeback and print the entry. - } - else if(node->extra) { //extra is set for a returning DIR entry. - long offset = 0; - nd = (node_size*)node->extra; - offset = nd->size; - nd->size += node->st.st_blocks; - TT.depth--; - if(!(toys.optflags & FLAG_s)) - print(*TT.dirsum, dirtree_path(node, NULL)); - if((node->parent) && (node->parent->extra)) { - /* when returning from internal directory, get the saved size of the parent and continue from there */ - nd = (node_size*)node->parent->extra; - TT.dirsum = (long*)&(nd->size); - *TT.dirsum += offset; - *TT.dirsum += node->st.st_blocks; - return DIRTREE_RECURSE; - } - else if(!node->parent) { - /*if node has no parent, it means it is the top in the tree, stop recursing here */ - TT.total += *TT.dirsum; - if((toys.optflags & FLAG_s)) - print(*TT.dirsum, dirtree_path(node, NULL)); - return 0; - } - } + if(!(toys.optflags & FLAG_l) && node->st.st_nlink > 1 && !node->extra) { //keeping reference for hard links + if(is_inode_present(&node->st)) return DIRTREE_RECURSE; + ino_details = xzalloc(sizeof(inode_ent_t)); + ino_details->ino = node->st.st_ino; + ino_details->dev = node->st.st_dev; + llist_add_inode(&TT.inodes, (void*)ino_details); + } + + if(S_ISDIR(node->st.st_mode)) { + if(!(node->extra && (long)((node_size*)(node->extra))->node == (long)node)) { + nd = xzalloc(sizeof(node_size)); + nd->node = node; + nd->size = 0; + TT.dirsum = (long*)&(nd->size); + node->extra = (long)nd; + *TT.dirsum = 0; + TT.depth++; + return (DIRTREE_RECURSE|DIRTREE_COMEAGAIN | ((toys.optflags & FLAG_L) ? DIRTREE_SYMFOLLOW : 0)); //DIRTREE_COMEAGAIN to comeback and print the entry. } - else if(!(node->parent)) { - /* this is the file specified on cmdline */ - TT.total += node->st.st_blocks; - print(node->st.st_blocks, dirtree_path(node, NULL)); + else if(node->extra) { //extra is set for a returning DIR entry. + long offset = 0; + nd = (node_size*)node->extra; + offset = nd->size; + nd->size += node->st.st_blocks; + TT.depth--; + if(!(toys.optflags & FLAG_s)) + print(*TT.dirsum, dirtree_path(node, NULL)); + if((node->parent) && (node->parent->extra)) { + /* when returning from internal directory, get the saved size of the parent and continue from there */ + nd = (node_size*)node->parent->extra; + TT.dirsum = (long*)&(nd->size); + *TT.dirsum += offset; + *TT.dirsum += node->st.st_blocks; + return DIRTREE_RECURSE; + } + else if(!node->parent) { + /*if node has no parent, it means it is the top in the tree, stop recursing here */ + TT.total += *TT.dirsum; + if((toys.optflags & FLAG_s)) + print(*TT.dirsum, dirtree_path(node, NULL)); return 0; + } } - if(TT.dirsum) *TT.dirsum += node->st.st_blocks; - if(toys.optflags & FLAG_a && !(toys.optflags & FLAG_s)) - print(node->st.st_blocks, dirtree_path(node, NULL)); - return DIRTREE_RECURSE; + } + else if(!(node->parent)) { + /* this is the file specified on cmdline */ + TT.total += node->st.st_blocks; + print(node->st.st_blocks, dirtree_path(node, NULL)); + return 0; + } + if(TT.dirsum) *TT.dirsum += node->st.st_blocks; + if(toys.optflags & FLAG_a && !(toys.optflags & FLAG_s)) + print(node->st.st_blocks, dirtree_path(node, NULL)); + return DIRTREE_RECURSE; } /* @@ -196,22 +194,22 @@ int do_du(struct dirtree *node) */ void du_main(void) { - int symfollow = toys.optflags & (FLAG_H | FLAG_L); - TT.total = 0; - TT.inodes = NULL; - - if(!(toys.optflags & FLAG_d)) TT.maxdepth = INT_MAX; - if(toys.optc == 0) toys.optargs[0] = "./"; - while(*toys.optargs) { - TT.depth = 0; - char *path = make_pathproper(*toys.optargs); - struct dirtree *root = dirtree_add_node(AT_FDCWD, path, symfollow); //create a node - if(root) { - TT.st_dev = root->st.st_dev; - handle_callback(root, do_du); //this will recurse thru the DIR children. - } - toys.optargs++; + int symfollow = toys.optflags & (FLAG_H | FLAG_L); + TT.total = 0; + TT.inodes = NULL; + + if(!(toys.optflags & FLAG_d)) TT.maxdepth = INT_MAX; + if(toys.optc == 0) toys.optargs[0] = "./"; + while(*toys.optargs) { + TT.depth = 0; + char *path = make_pathproper(*toys.optargs); + struct dirtree *root = dirtree_add_node(AT_FDCWD, path, symfollow); //create a node + if(root) { + TT.st_dev = root->st.st_dev; + handle_callback(root, do_du); //this will recurse thru the DIR children. } - if(TT.inodes) llist_traverse(TT.inodes, free_inodes); //free the stored nodes - if(toys.optflags & FLAG_c) print(TT.total, "total"); + toys.optargs++; + } + if(TT.inodes) llist_traverse(TT.inodes, free_inodes); //free the stored nodes + if(toys.optflags & FLAG_c) print(TT.total, "total"); } diff --git a/toys/posix/echo.c b/toys/posix/echo.c index 1bf4d399..28284bfb 100644 --- a/toys/posix/echo.c +++ b/toys/posix/echo.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * echo.c - echo supporting -n and -e. +/* echo.c - echo supporting -n and -e. * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -9,27 +7,27 @@ USE_ECHO(NEWTOY(echo, "^?en", TOYFLAG_BIN)) config ECHO - bool "echo" - default y - help - usage: echo [-ne] [args...] + bool "echo" + default y + help + usage: echo [-ne] [args...] - Write each argument to stdout, with one space between each, followed - by a newline. + Write each argument to stdout, with one space between each, followed + by a newline. - -n No trailing newline. - -e Process the following escape sequences: - \\ backslash - \0NNN octal values (1 to 3 digits) - \a alert (beep/flash) - \b backspace - \c stop output here (avoids trailing newline) - \f form feed - \n newline - \r carriage return - \t horizontal tab - \v vertical tab - \xHH hexadecimal values (1 to 2 digits) + -n No trailing newline. + -e Process the following escape sequences: + \\ backslash + \0NNN octal values (1 to 3 digits) + \a alert (beep/flash) + \b backspace + \c stop output here (avoids trailing newline) + \f form feed + \n newline + \r carriage return + \t horizontal tab + \v vertical tab + \xHH hexadecimal values (1 to 2 digits) */ #define FOR_echo @@ -37,58 +35,56 @@ config ECHO void echo_main(void) { - int i = 0, out; - char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c; + int i = 0, out; + char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c; - for (;;) { - arg = toys.optargs[i]; - if (!arg) break; - if (i++) xputc(' '); + for (;;) { + arg = toys.optargs[i]; + if (!arg) break; + if (i++) xputc(' '); - // Should we output arg verbatim? + // Should we output arg verbatim? - if (!(toys.optflags&FLAG_e)) { - xprintf("%s", arg); - continue; - } + if (!(toys.optflags & FLAG_e)) { + xprintf("%s", arg); + continue; + } - // Handle -e + // Handle -e - for (c=arg;;) { - if (!(out = *(c++))) break; + for (c=arg;;) { + if (!(out = *(c++))) break; - // handle \escapes - if (out == '\\' && *c) { - int n = 0, slash = *(c++); - char *found = strchr(from, slash); - if (found) out = to[found-from]; - else if (slash == 'c') goto done; - else if (slash == '0') { - out = 0; - while (*c>='0' && *c<='7' && n++<3) - out = (out*8)+*(c++)-'0'; - } else if (slash == 'x') { - out = 0; - while (n++<2) { - if (*c>='0' && *c<='9') - out = (out*16)+*(c++)-'0'; - else { - int temp = tolower(*c); - if (temp>='a' && temp<='f') { - out = (out*16)+temp-'a'+10; - c++; - } else break; - } - } - // Slash in front of unknown character, print literal. - } else c--; - } - xputc(out); - } - } + // handle \escapes + if (out == '\\' && *c) { + int n = 0, slash = *(c++); + char *found = strchr(from, slash); + if (found) out = to[found-from]; + else if (slash == 'c') goto done; + else if (slash == '0') { + out = 0; + while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0'; + } else if (slash == 'x') { + out = 0; + while (n++<2) { + if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0'; + else { + int temp = tolower(*c); + if (temp>='a' && temp<='f') { + out = (out*16)+temp-'a'+10; + c++; + } else break; + } + } + // Slash in front of unknown character, print literal. + } else c--; + } + xputc(out); + } + } - // Output "\n" if no -n - if (!(toys.optflags&FLAG_n)) xputc('\n'); + // Output "\n" if no -n + if (!(toys.optflags&FLAG_n)) xputc('\n'); done: - xflush(); + xflush(); } diff --git a/toys/posix/env.c b/toys/posix/env.c index 32272799..8f7ccf1f 100644 --- a/toys/posix/env.c +++ b/toys/posix/env.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * env.c - Set the environment for command invocation. +/* env.c - Set the environment for command invocation. * * Copyright 2012 Tryn Mirell <tryn@mirell.org> * @@ -9,14 +7,14 @@ USE_ENV(NEWTOY(env, "^i", TOYFLAG_USR|TOYFLAG_BIN)) config ENV - bool "env" - default y - help - usage: env [-i] [NAME=VALUE...] [command [option...]] + bool "env" + default y + help + usage: env [-i] [NAME=VALUE...] [command [option...]] - Set the environment for command invocation. + Set the environment for command invocation. - -i Clear existing environment. + -i Clear existing environment. */ #include "toys.h" @@ -25,29 +23,29 @@ extern char **environ; void env_main(void) { - char **ev; - char **command = NULL; - char *del = "="; - - if (toys.optflags) clearenv(); - - for (ev = toys.optargs; *ev != NULL; ev++) { - char *env, *val = NULL; - - env = strtok(*ev, del); - - if (env) val = strtok(NULL, del); - - if (val) setenv(env, val, 1); - else { - command = ev; - break; - } + char **ev; + char **command = NULL; + char *del = "="; + + if (toys.optflags) clearenv(); + + for (ev = toys.optargs; *ev != NULL; ev++) { + char *env, *val = NULL; + + env = strtok(*ev, del); + + if (env) val = strtok(NULL, del); + + if (val) setenv(env, val, 1); + else { + command = ev; + break; } - - if (!command) { - char **ep; - for (ep = environ; *ep; ep++) xputs(*ep); - return; - } else xexec(command); + } + + if (!command) { + char **ep; + for (ep = environ; *ep; ep++) xputs(*ep); + return; + } else xexec(command); } diff --git a/toys/posix/false.c b/toys/posix/false.c index 7208ea7a..73458bea 100644 --- a/toys/posix/false.c +++ b/toys/posix/false.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * false.c - Return nonzero. +/* false.c - Return nonzero. * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -9,15 +7,15 @@ USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN)) config FALSE - bool "false" - default y - help - Return nonzero. + bool "false" + default y + help + Return nonzero. */ #include "toys.h" void false_main(void) { - toys.exitval = 1; + toys.exitval = 1; } diff --git a/toys/posix/head.c b/toys/posix/head.c index 77978f74..ba7b7385 100644 --- a/toys/posix/head.c +++ b/toys/posix/head.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * head.c - copy first lines from input to stdout. +/* head.c - copy first lines from input to stdout. * * Copyright 2006 Timothy Elliott <tle@holymonkey.com> * @@ -9,52 +7,51 @@ USE_HEAD(NEWTOY(head, "n#<0=10", TOYFLAG_BIN)) config HEAD - bool "head" - default y - help - usage: head [-n number] [file...] + bool "head" + default y + help + usage: head [-n number] [file...] - Copy first lines from files to stdout. If no files listed, copy from - stdin. Filename "-" is a synonym for stdin. + Copy first lines from files to stdout. If no files listed, copy from + stdin. Filename "-" is a synonym for stdin. - -n Number of lines to copy. + -n Number of lines to copy. */ #define FOR_head #include "toys.h" GLOBALS( - long lines; - int file_no; + long lines; + int file_no; ) static void do_head(int fd, char *name) { - int i, len, lines=TT.lines, size=sizeof(toybuf); - - if (toys.optc > 1) { - // Print an extra newline for all but the first file - if (TT.file_no++) xprintf("\n"); - xprintf("==> %s <==\n", name); - xflush(); - } - - while (lines) { - len = read(fd, toybuf, size); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - - for(i=0; i<len;) - if (toybuf[i++] == '\n' && !--lines) break; - - xwrite(1, toybuf, i); - } + int i, len, lines=TT.lines, size=sizeof(toybuf); + + if (toys.optc > 1) { + // Print an extra newline for all but the first file + if (TT.file_no++) xprintf("\n"); + xprintf("==> %s <==\n", name); + xflush(); + } + + while (lines) { + len = read(fd, toybuf, size); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + + for(i=0; i<len;) if (toybuf[i++] == '\n' && !--lines) break; + + xwrite(1, toybuf, i); + } } void head_main(void) { - loopfiles(toys.optargs, do_head); + loopfiles(toys.optargs, do_head); } diff --git a/toys/posix/id.c b/toys/posix/id.c index 523d4f3a..0cdd2b0c 100644 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * id.c - print real and effective user and group IDs +/* id.c - print real and effective user and group IDs * * Copyright 2012 Sony Network Entertainment, Inc. * @@ -11,18 +9,18 @@ USE_ID(NEWTOY(id, "nGgru", TOYFLAG_BIN)) config ID - bool "id" - default y - help - usage: id [-nGgru] - - Print user and group ID. - - -n print names instead of numeric IDs (to be used with -Ggu) - -G Show only the group IDs - -g Show only the effective group ID - -r Show real ID instead of effective ID - -u Show only the effective user ID + bool "id" + default y + help + usage: id [-nGgru] + + Print user and group ID. + + -n print names instead of numeric IDs (to be used with -Ggu) + -G Show only the group IDs + -g Show only the effective group ID + -r Show real ID instead of effective ID + -u Show only the effective user ID */ #define FOR_id @@ -30,85 +28,83 @@ config ID static void s_or_u(char *s, unsigned u, int done) { - if (toys.optflags & FLAG_n) printf("%s", s); - else printf("%u", u); - if (done) { - xputc('\n'); - exit(0); - } + if (toys.optflags & FLAG_n) printf("%s", s); + else printf("%u", u); + if (done) { + xputc('\n'); + exit(0); + } } static void showid(char *header, unsigned u, char *s) { - printf("%s%u(%s)", header, u, s); + printf("%s%u(%s)", header, u, s); } struct passwd *xgetpwuid(uid_t uid) { - struct passwd *pwd = getpwuid(uid); - if (!pwd) error_exit(NULL); - return pwd; + struct passwd *pwd = getpwuid(uid); + if (!pwd) error_exit(NULL); + return pwd; } struct group *xgetgrgid(gid_t gid) { - struct group *group = getgrgid(gid); - if (!group) error_exit(NULL); - return group; + struct group *group = getgrgid(gid); + if (!group) error_exit(NULL); + return group; } void id_main(void) { - int flags = toys.optflags, i, ngroups; - struct passwd *pw; - struct group *grp; - uid_t uid = getuid(), euid = geteuid(); - gid_t gid = getgid(), egid = getegid(), *groups; - - /* check if a username is given */ - if (*toys.optargs) { - if (!(pw = getpwnam(*toys.optargs))) - error_exit("no such user '%s'", *toys.optargs); - uid = euid = pw->pw_uid; - gid = egid = pw->pw_gid; - } - - i = toys.optflags & FLAG_r; - pw = xgetpwuid(i ? uid : euid); - if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); - - grp = xgetgrgid(i ? gid : egid); - if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); - - if (!(flags & FLAG_G)) { - showid("uid=", pw->pw_uid, pw->pw_name); - showid(" gid=", grp->gr_gid, grp->gr_name); - - if (!i) { - if (uid != euid) { - pw = xgetpwuid(euid); - showid(" euid=", pw->pw_uid, pw->pw_name); - } - if (gid != egid) { - grp = xgetgrgid(egid); - showid(" egid=", grp->gr_gid, grp->gr_name); - } - } - - showid(" groups=", grp->gr_gid, grp->gr_name); - } - - - groups = (gid_t *)toybuf; - if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups))) - perror_exit(0); - - for (i = 0; i < ngroups; i++) { - xputc(' '); - if (!(grp = getgrgid(groups[i]))) perror_msg(0); - else if (flags & FLAG_G) - s_or_u(grp->gr_name, grp->gr_gid, 0); - else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); - } - xputc('\n'); + int flags = toys.optflags, i, ngroups; + struct passwd *pw; + struct group *grp; + uid_t uid = getuid(), euid = geteuid(); + gid_t gid = getgid(), egid = getegid(), *groups; + + // check if a username is given + if (*toys.optargs) { + if (!(pw = getpwnam(*toys.optargs))) + error_exit("no such user '%s'", *toys.optargs); + uid = euid = pw->pw_uid; + gid = egid = pw->pw_gid; + } + + i = toys.optflags & FLAG_r; + pw = xgetpwuid(i ? uid : euid); + if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); + + grp = xgetgrgid(i ? gid : egid); + if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); + + if (!(flags & FLAG_G)) { + showid("uid=", pw->pw_uid, pw->pw_name); + showid(" gid=", grp->gr_gid, grp->gr_name); + + if (!i) { + if (uid != euid) { + pw = xgetpwuid(euid); + showid(" euid=", pw->pw_uid, pw->pw_name); + } + if (gid != egid) { + grp = xgetgrgid(egid); + showid(" egid=", grp->gr_gid, grp->gr_name); + } + } + + showid(" groups=", grp->gr_gid, grp->gr_name); + } + + groups = (gid_t *)toybuf; + if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups))) + perror_exit(0); + + for (i = 0; i < ngroups; i++) { + xputc(' '); + if (!(grp = getgrgid(groups[i]))) perror_msg(0); + else if (flags & FLAG_G) s_or_u(grp->gr_name, grp->gr_gid, 0); + else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); + } + xputc('\n'); } diff --git a/toys/posix/kill.c b/toys/posix/kill.c index 7810b899..2d1606b4 100644 --- a/toys/posix/kill.c +++ b/toys/posix/kill.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * kill.c - a program to send signals to processes +/* kill.c - a program to send signals to processes * * Copyright 2012 Daniel Walter <d.walter@0x90.at> * @@ -9,65 +7,64 @@ USE_KILL(NEWTOY(kill, "?s: l", TOYFLAG_BIN)) config KILL - bool "kill" - default y - help - usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid... - - Send a signal to a process + bool "kill" + default y + help + usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid... + Send a signal to a process */ #define FOR_kill #include "toys.h" GLOBALS( - char *signame; + char *signame; ) void kill_main(void) { - int signum; - char *tmp, **args = toys.optargs; - pid_t pid; + int signum; + char *tmp, **args = toys.optargs; + pid_t pid; - // list signal(s) - if (toys.optflags & FLAG_l) { - if (*args) { - int signum = sig_to_num(*args); - char *s = NULL; + // list signal(s) + if (toys.optflags & FLAG_l) { + if (*args) { + int signum = sig_to_num(*args); + char *s = NULL; - if (signum>=0) s = num_to_sig(signum&127); - puts(s ? s : "UNKNOWN"); - } else sig_to_num(NULL); - return; - } + if (signum>=0) s = num_to_sig(signum&127); + puts(s ? s : "UNKNOWN"); + } else sig_to_num(NULL); + return; + } - // signal must come before pids, so "kill -9 -1" isn't confusing. + // signal must come before pids, so "kill -9 -1" isn't confusing. - if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1; - if (TT.signame) { - char *arg; - int i = strtol(TT.signame, &arg, 10); - if (!*arg) arg = num_to_sig(i); - else arg = TT.signame; + if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1; + if (TT.signame) { + char *arg; + int i = strtol(TT.signame, &arg, 10); + if (!*arg) arg = num_to_sig(i); + else arg = TT.signame; - if (!arg || -1 == (signum = sig_to_num(arg))) - error_exit("Unknown signal '%s'", arg); - } else signum = SIGTERM; + if (!arg || -1 == (signum = sig_to_num(arg))) + error_exit("Unknown signal '%s'", arg); + } else signum = SIGTERM; - if (!*args) { - toys.exithelp++; - error_exit("missing argument"); - } + if (!*args) { + toys.exithelp++; + error_exit("missing argument"); + } - while (*args) { - char *arg = *(args++); + while (*args) { + char *arg = *(args++); - pid = strtol(arg, &tmp, 10); - if (*tmp || kill(pid, signum) < 0) { - error_msg("unknown pid '%s'", arg); - toys.exitval = EXIT_FAILURE; - } - } + pid = strtol(arg, &tmp, 10); + if (*tmp || kill(pid, signum) < 0) { + error_msg("unknown pid '%s'", arg); + toys.exitval = EXIT_FAILURE; + } + } } diff --git a/toys/posix/link.c b/toys/posix/link.c index 69a9a60f..38d2cf05 100644 --- a/toys/posix/link.c +++ b/toys/posix/link.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * link.c - hardlink a file +/* link.c - hardlink a file * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,19 +7,19 @@ USE_LINK(NEWTOY(link, "<2>2", TOYFLAG_USR|TOYFLAG_BIN)) config LINK - bool "link" - default y - help - usage: link FILE NEWLINK + bool "link" + default y + help + usage: link FILE NEWLINK - Create hardlink to a file. + Create hardlink to a file. */ #include "toys.h" void link_main(void) { - if (link(toys.optargs[0], toys.optargs[1])) - perror_exit("couldn't link '%s' to '%s'", toys.optargs[1], - toys.optargs[0]); + if (link(toys.optargs[0], toys.optargs[1])) + perror_exit("couldn't link '%s' to '%s'", toys.optargs[1], + toys.optargs[0]); } diff --git a/toys/posix/ln.c b/toys/posix/ln.c index a83df7f6..bde77269 100644 --- a/toys/posix/ln.c +++ b/toys/posix/ln.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * ln.c - Create filesystem links +/* ln.c - Create filesystem links * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * @@ -9,17 +7,17 @@ USE_LN(NEWTOY(ln, "<1nfs", TOYFLAG_BIN)) config LN - bool "ln" - default y - help - usage: ln [-sf] [FROM...] TO + bool "ln" + default y + help + usage: ln [-sf] [FROM...] TO - Create a link between FROM and TO. - With only one argument, create link in current directory. + Create a link between FROM and TO. + With only one argument, create link in current directory. - -s Create a symbolic link - -f Force the creation of the link, even if TO already exists - -n Symlink at destination treated as file + -s Create a symbolic link + -f Force the creation of the link, even if TO already exists + -n Symlink at destination treated as file */ #define FOR_ln @@ -27,41 +25,41 @@ config LN void ln_main(void) { - char *dest = toys.optargs[--toys.optc], *new; - struct stat buf; - int i; + char *dest = toys.optargs[--toys.optc], *new; + struct stat buf; + int i; - // With one argument, create link in current directory. - if (!toys.optc) { - toys.optc++; - dest="."; - } + // With one argument, create link in current directory. + if (!toys.optc) { + toys.optc++; + dest="."; + } - // Is destination a directory? - if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf) - || !S_ISDIR(buf.st_mode)) - { - if (toys.optc>1) error_exit("'%s' not a directory"); - buf.st_mode = 0; - } + // Is destination a directory? + if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf) + || !S_ISDIR(buf.st_mode)) + { + if (toys.optc>1) error_exit("'%s' not a directory"); + buf.st_mode = 0; + } - for (i=0; i<toys.optc; i++) { - int rc; - char *try = toys.optargs[i]; + for (i=0; i<toys.optc; i++) { + int rc; + char *try = toys.optargs[i]; - if (S_ISDIR(buf.st_mode)) { - new = strrchr(try, '/'); - if (!new) new = try; - new = xmsprintf("%s/%s", dest, new); - } else new = dest; - /* Silently unlink the existing target. If it doesn't exist, - * then we just move on */ - if (toys.optflags & FLAG_f) unlink(new); + if (S_ISDIR(buf.st_mode)) { + new = strrchr(try, '/'); + if (!new) new = try; + new = xmsprintf("%s/%s", dest, new); + } else new = dest; + /* Silently unlink the existing target. If it doesn't exist, + * then we just move on */ + if (toys.optflags & FLAG_f) unlink(new); - rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new); - if (rc) - perror_exit("cannot create %s link from '%s' to '%s'", - (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new); - if (new != dest) free(new); - } + rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new); + if (rc) + perror_exit("cannot create %s link from '%s' to '%s'", + (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new); + if (new != dest) free(new); + } } diff --git a/toys/posix/logname.c b/toys/posix/logname.c index 6ebdb329..b638ea2f 100644 --- a/toys/posix/logname.c +++ b/toys/posix/logname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * logname.c - Print user's login name. +/* logname.c - Print user's login name. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -9,19 +7,19 @@ USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_BIN)) config LOGNAME - bool "logname" - default y - help - usage: logname + bool "logname" + default y + help + usage: logname - Prints the calling user's name or an error when this cannot be - determined. + Prints the calling user's name or an error when this cannot be + determined. */ #include "toys.h" void logname_main(void) { - if (getlogin_r(toybuf, sizeof(toybuf))) error_exit("no login name"); - xputs(toybuf); + if (getlogin_r(toybuf, sizeof(toybuf))) error_exit("no login name"); + xputs(toybuf); } diff --git a/toys/posix/ls.c b/toys/posix/ls.c index 6492fb9e..201c7e24 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * ls.c - list files +/* ls.c - list files * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * Copyright 2012 Rob Landley <rob@landley.net> @@ -11,43 +9,43 @@ USE_LS(NEWTOY(ls, "goACFHLRSacdfiklmnpqrstux1", TOYFLAG_BIN)) config LS - bool "ls" - default y - help - usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] - list files - - what to show: - -a all files including .hidden - -c use ctime for timestamps - -d directory, not contents - -i inode number - -k block sizes in kilobytes - -p put a '/' after directory names - -q unprintable chars as '?' - -s size (in blocks) - -u use access time for timestamps - -A list all files except . and .. - -H follow command line symlinks - -L follow symlinks - -R recursively list files in subdirectories - -F append file type indicator (/=dir, *=exe, @=symlink, |=FIFO) - - output formats: - -1 list one file per line - -C columns (sorted vertically) - -g like -l but no owner - -l long (show full details for each file) - -m comma separated - -n like -l but numeric uid/gid - -o like -l but no group - -x columns (sorted horizontally) - - sorting (default is alphabetical): - -f unsorted - -r reverse - -t timestamp - -S size + bool "ls" + default y + help + usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] + list files + + what to show: + -a all files including .hidden + -c use ctime for timestamps + -d directory, not contents + -i inode number + -k block sizes in kilobytes + -p put a '/' after directory names + -q unprintable chars as '?' + -s size (in blocks) + -u use access time for timestamps + -A list all files except . and .. + -H follow command line symlinks + -L follow symlinks + -R recursively list files in subdirectories + -F append file type indicator (/=dir, *=exe, @=symlink, |=FIFO) + + output formats: + -1 list one file per line + -C columns (sorted vertically) + -g like -l but no owner + -l long (show full details for each file) + -m comma separated + -n like -l but numeric uid/gid + -o like -l but no group + -x columns (sorted horizontally) + + sorting (default is alphabetical): + -f unsorted + -r reverse + -t timestamp + -S size */ #define FOR_ls @@ -58,156 +56,156 @@ config LS // ls -lR starts .: then ./subdir: GLOBALS( - struct dirtree *files; + struct dirtree *files; - unsigned screen_width; - int nl_title; + unsigned screen_width; + int nl_title; - // group and user can make overlapping use of the utoa() buf, so move it - char uid_buf[12]; + // group and user can make overlapping use of the utoa() buf, so move it + char uid_buf[12]; ) void dlist_to_dirtree(struct dirtree *parent) { - // Turn double_list into dirtree - struct dirtree *dt = parent->child; - if (dt) { - dt->parent->next = NULL; - while (dt) { - dt->parent = parent; - dt = dt->next; - } + // Turn double_list into dirtree + struct dirtree *dt = parent->child; + if (dt) { + dt->parent->next = NULL; + while (dt) { + dt->parent = parent; + dt = dt->next; } + } } static char endtype(struct stat *st) { - mode_t mode = st->st_mode; - if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/'; - if (toys.optflags & FLAG_F) { - if (S_ISLNK(mode)) return '@'; - if (S_ISREG(mode) && (mode&0111)) return '*'; - if (S_ISFIFO(mode)) return '|'; - if (S_ISSOCK(mode)) return '='; - } - return 0; + mode_t mode = st->st_mode; + if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/'; + if (toys.optflags & FLAG_F) { + if (S_ISLNK(mode)) return '@'; + if (S_ISREG(mode) && (mode&0111)) return '*'; + if (S_ISFIFO(mode)) return '|'; + if (S_ISSOCK(mode)) return '='; + } + return 0; } static char *getusername(uid_t uid) { - struct passwd *pw = getpwuid(uid); - utoa_to_buf(uid, TT.uid_buf, 12); - return pw ? pw->pw_name : TT.uid_buf; + struct passwd *pw = getpwuid(uid); + utoa_to_buf(uid, TT.uid_buf, 12); + return pw ? pw->pw_name : TT.uid_buf; } static char *getgroupname(gid_t gid) { - struct group *gr = getgrgid(gid); - return gr ? gr->gr_name : utoa(gid); + struct group *gr = getgrgid(gid); + return gr ? gr->gr_name : utoa(gid); } // Figure out size of printable entry fields for display indent/wrap static void entrylen(struct dirtree *dt, unsigned *len) { - struct stat *st = &(dt->st); - unsigned flags = toys.optflags; - - *len = strlen(dt->name); - if (endtype(st)) ++*len; - if (flags & FLAG_m) ++*len; - - if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino)); - if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { - unsigned fn = flags & FLAG_n; - len[2] = numlen(st->st_nlink); - len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid)); - len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid)); - len[5] = numlen(st->st_size); - } - if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks)); + struct stat *st = &(dt->st); + unsigned flags = toys.optflags; + + *len = strlen(dt->name); + if (endtype(st)) ++*len; + if (flags & FLAG_m) ++*len; + + if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino)); + if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { + unsigned fn = flags & FLAG_n; + len[2] = numlen(st->st_nlink); + len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid)); + len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid)); + len[5] = numlen(st->st_size); + } + if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks)); } static int compare(void *a, void *b) { - struct dirtree *dta = *(struct dirtree **)a; - struct dirtree *dtb = *(struct dirtree **)b; - int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1; - - if (toys.optflags & FLAG_S) { - if (dta->st.st_size > dtb->st.st_size) ret = -1; - else if (dta->st.st_size < dtb->st.st_size) ret = 1; - } - if (toys.optflags & FLAG_t) { - if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1; - else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1; - } - if (!ret) ret = strcmp(dta->name, dtb->name); - return ret * reverse; + struct dirtree *dta = *(struct dirtree **)a; + struct dirtree *dtb = *(struct dirtree **)b; + int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1; + + if (toys.optflags & FLAG_S) { + if (dta->st.st_size > dtb->st.st_size) ret = -1; + else if (dta->st.st_size < dtb->st.st_size) ret = 1; + } + if (toys.optflags & FLAG_t) { + if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1; + else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1; + } + if (!ret) ret = strcmp(dta->name, dtb->name); + return ret * reverse; } // callback from dirtree_recurse() determining how to handle this entry. static int filter(struct dirtree *new) { - int flags = toys.optflags; + int flags = toys.optflags; - // Special case to handle enormous dirs without running out of memory. - if (flags == (FLAG_1|FLAG_f)) { - xprintf("%s\n", new->name); - return 0; - } + // Special case to handle enormous dirs without running out of memory. + if (flags == (FLAG_1|FLAG_f)) { + xprintf("%s\n", new->name); + return 0; + } - if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; - if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; - if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; + if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; + if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; + if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; - if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE; - if (!(flags & FLAG_A) && new->name[0]=='.') return 0; + if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE; + if (!(flags & FLAG_A) && new->name[0]=='.') return 0; - return dirtree_notdotdot(new) & DIRTREE_SAVE; + return dirtree_notdotdot(new) & DIRTREE_SAVE; } // For column view, calculate horizontal position (for padding) and return // index of next entry to display. static unsigned long next_column(unsigned long ul, unsigned long dtlen, - unsigned columns, unsigned *xpos) + unsigned columns, unsigned *xpos) { - unsigned long transition; - unsigned height, widecols; + unsigned long transition; + unsigned height, widecols; - // Horizontal sort is easy - if (!(toys.optflags & FLAG_C)) { - *xpos = ul % columns; - return ul; - } + // Horizontal sort is easy + if (!(toys.optflags & FLAG_C)) { + *xpos = ul % columns; + return ul; + } - // vertical sort + // vertical sort - // For -x, calculate height of display, rounded up - height = (dtlen+columns-1)/columns; + // For -x, calculate height of display, rounded up + height = (dtlen+columns-1)/columns; - // Sanity check: does wrapping render this column count impossible - // due to the right edge wrapping eating a whole row? - if (height*columns - dtlen >= height) { - *xpos = columns; - return 0; - } + // Sanity check: does wrapping render this column count impossible + // due to the right edge wrapping eating a whole row? + if (height*columns - dtlen >= height) { + *xpos = columns; + return 0; + } - // Uneven rounding goes along right edge - widecols = dtlen % height; - if (!widecols) widecols = height; - transition = widecols * columns; - if (ul < transition) { - *xpos = ul % columns; - return (*xpos*height) + (ul/columns); - } + // Uneven rounding goes along right edge + widecols = dtlen % height; + if (!widecols) widecols = height; + transition = widecols * columns; + if (ul < transition) { + *xpos = ul % columns; + return (*xpos*height) + (ul/columns); + } - ul -= transition; - *xpos = ul % (columns-1); + ul -= transition; + *xpos = ul % (columns-1); - return (*xpos*height) + widecols + (ul/(columns-1)); + return (*xpos*height) + widecols + (ul/(columns-1)); } // Display a list of dirtree entries, according to current format @@ -215,250 +213,247 @@ static unsigned long next_column(unsigned long ul, unsigned long dtlen, static void listfiles(int dirfd, struct dirtree *indir) { - struct dirtree *dt, **sort = 0; - unsigned long dtlen = 0, ul = 0; - unsigned width, flags = toys.optflags, totals[7], len[7], - *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4; - - memset(totals, 0, sizeof(totals)); - - // Silently descend into single directory listed by itself on command line. - // In this case only show dirname/total header when given -R. - if (!indir->parent) { - if (!(dt = indir->child)) return; - if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { - dt->extra = 1; - listfiles(open(dt->name, 0), dt); - return; - } - } else { - // Read directory contents. We dup() the fd because this will close it. - indir->data = dup(dirfd); - dirtree_recurse(indir, filter, (flags&FLAG_L)); + struct dirtree *dt, **sort = 0; + unsigned long dtlen = 0, ul = 0; + unsigned width, flags = toys.optflags, totals[7], len[7], + *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4; + + memset(totals, 0, sizeof(totals)); + + // Silently descend into single directory listed by itself on command line. + // In this case only show dirname/total header when given -R. + if (!indir->parent) { + if (!(dt = indir->child)) return; + if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { + dt->extra = 1; + listfiles(open(dt->name, 0), dt); + return; } - - // Copy linked list to array and sort it. Directories go in array because - // we visit them in sorted order. - - for (;;) { - for (dt = indir->child; dt; dt = dt->next) { - if (sort) sort[dtlen] = dt; - dtlen++; + } else { + // Read directory contents. We dup() the fd because this will close it. + indir->data = dup(dirfd); + dirtree_recurse(indir, filter, (flags&FLAG_L)); + } + + // Copy linked list to array and sort it. Directories go in array because + // we visit them in sorted order. + + for (;;) { + for (dt = indir->child; dt; dt = dt->next) { + if (sort) sort[dtlen] = dt; + dtlen++; + } + if (sort) break; + sort = xmalloc(dtlen * sizeof(void *)); + dtlen = 0; + continue; + } + + // Label directory if not top of tree, or if -R + if (indir->parent && (!indir->extra || (flags & FLAG_R))) + { + char *path = dirtree_path(indir, 0); + + if (TT.nl_title++) xputc('\n'); + xprintf("%s:\n", path); + free(path); + } + + if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); + + // Find largest entry in each field for display alignment + if (flags & (FLAG_C|FLAG_x)) { + + // columns can't be more than toybuf can hold, or more than files, + // or > 1/2 screen width (one char filename, one space). + if (columns > TT.screen_width/2) columns = TT.screen_width/2; + if (columns > dtlen) columns = dtlen; + + // Try to fit as many columns as we can, dropping down by one each time + for (;columns > 1; columns--) { + unsigned c, totlen = columns; + + memset(colsizes, 0, columns*sizeof(unsigned)); + for (ul=0; ul<dtlen; ul++) { + entrylen(sort[next_column(ul, dtlen, columns, &c)], len); + if (c == columns) break; + // Does this put us over budget? + if (*len > colsizes[c]) { + totlen += *len-colsizes[c]; + colsizes[c] = *len; + if (totlen > TT.screen_width) break; } - if (sort) break; - sort = xmalloc(dtlen * sizeof(void *)); - dtlen = 0; - continue; + } + // If it fit, stop here + if (ul == dtlen) break; } + } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) { + unsigned long blocks = 0; - // Label directory if not top of tree, or if -R - if (indir->parent && (!indir->extra || (flags & FLAG_R))) + for (ul = 0; ul<dtlen; ul++) { - char *path = dirtree_path(indir, 0); - - if (TT.nl_title++) xputc('\n'); - xprintf("%s:\n", path); - free(path); + entrylen(sort[ul], len); + for (width=0; width<6; width++) + if (len[width] > totals[width]) totals[width] = len[width]; + blocks += sort[ul]->st.st_blocks; } - if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); + if (indir->parent) xprintf("total %lu\n", blocks); + } - // Find largest entry in each field for display alignment - if (flags & (FLAG_C|FLAG_x)) { + // Loop through again to produce output. + memset(toybuf, ' ', 256); + width = 0; + for (ul = 0; ul<dtlen; ul++) { + unsigned curcol; + unsigned long next = next_column(ul, dtlen, columns, &curcol); + struct stat *st = &(sort[next]->st); + mode_t mode = st->st_mode; + char et = endtype(st); + + // Skip directories at the top of the tree when -d isn't set + if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; + TT.nl_title=1; + + // Handle padding and wrapping for display purposes + entrylen(sort[next], len); + if (ul) { + if (flags & FLAG_m) xputc(','); + if (flags & (FLAG_C|FLAG_x)) { + if (!curcol) xputc('\n'); + } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) { + xputc('\n'); + width = 0; + } else { + xputc(' '); + width++; + } + } + width += *len; - // columns can't be more than toybuf can hold, or more than files, - // or > 1/2 screen width (one char filename, one space). - if (columns > TT.screen_width/2) columns = TT.screen_width/2; - if (columns > dtlen) columns = dtlen; - - // Try to fit as many columns as we can, dropping down by one each time - for (;columns > 1; columns--) { - unsigned c, totlen = columns; - - memset(colsizes, 0, columns*sizeof(unsigned)); - for (ul=0; ul<dtlen; ul++) { - entrylen(sort[next_column(ul, dtlen, columns, &c)], len); - if (c == columns) break; - // Does this put us over budget? - if (*len > colsizes[c]) { - totlen += *len-colsizes[c]; - colsizes[c] = *len; - if (totlen > TT.screen_width) break; - } - } - // If it fit, stop here - if (ul == dtlen) break; - } - } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) { - unsigned long blocks = 0; - - for (ul = 0; ul<dtlen; ul++) - { - entrylen(sort[ul], len); - for (width=0; width<6; width++) - if (len[width] > totals[width]) totals[width] = len[width]; - blocks += sort[ul]->st.st_blocks; - } + if (flags & FLAG_i) xprintf("% *lu ", len[1], (unsigned long)st->st_ino); + if (flags & FLAG_s) xprintf("% *lu ", len[6], (unsigned long)st->st_blocks); - if (indir->parent) xprintf("total %lu\n", blocks); + if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { + struct tm *tm; + char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad; + int i, bit; + + perm[10]=0; + for (i=0; i<9; i++) { + bit = mode & (1<<i); + c = i%3; + if (!c && (mode & (1<<((d=i/3)+9)))) { + c = "tss"[d]; + if (!bit) c &= ~0x20; + } else c = bit ? "xwr"[c] : '-'; + perm[9-i] = c; + } + + if (S_ISDIR(mode)) c = 'd'; + else if (S_ISBLK(mode)) c = 'b'; + else if (S_ISCHR(mode)) c = 'c'; + else if (S_ISLNK(mode)) c = 'l'; + else if (S_ISFIFO(mode)) c = 'p'; + else if (S_ISSOCK(mode)) c = 's'; + else c = '-'; + *perm = c; + + tm = localtime(&(st->st_mtime)); + strftime(thyme, sizeof(thyme), "%F %H:%M", tm); + + if (flags&FLAG_o) grp = grpad = toybuf+256; + else { + grp = (flags&FLAG_n) ? utoa(st->st_gid) : getgroupname(st->st_gid); + grpad = toybuf+256-(totals[4]-len[4]); + } + + if (flags&FLAG_g) usr = upad = toybuf+256; + else { + upad = toybuf+255-(totals[3]-len[3]); + if (flags&FLAG_n) { + usr = TT.uid_buf; + utoa_to_buf(st->st_uid, TT.uid_buf, 12); + } else usr = getusername(st->st_uid); + } + + // Coerce the st types into something we know we can print. + xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, + (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, + (int64_t)st->st_size, thyme); } - // Loop through again to produce output. - memset(toybuf, ' ', 256); - width = 0; - for (ul = 0; ul<dtlen; ul++) { - unsigned curcol; - unsigned long next = next_column(ul, dtlen, columns, &curcol); - struct stat *st = &(sort[next]->st); - mode_t mode = st->st_mode; - char et = endtype(st); - - // Skip directories at the top of the tree when -d isn't set - if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; - TT.nl_title=1; - - // Handle padding and wrapping for display purposes - entrylen(sort[next], len); - if (ul) { - if (flags & FLAG_m) xputc(','); - if (flags & (FLAG_C|FLAG_x)) { - if (!curcol) xputc('\n'); - } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) { - xputc('\n'); - width = 0; - } else { - xputc(' '); - width++; - } - } - width += *len; - - if (flags & FLAG_i) - xprintf("% *lu ", len[1], (unsigned long)st->st_ino); - if (flags & FLAG_s) - xprintf("% *lu ", len[6], (unsigned long)st->st_blocks); - - if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { - struct tm *tm; - char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad; - int i, bit; - - perm[10]=0; - for (i=0; i<9; i++) { - bit = mode & (1<<i); - c = i%3; - if (!c && (mode & (1<<((d=i/3)+9)))) { - c = "tss"[d]; - if (!bit) c &= ~0x20; - } else c = bit ? "xwr"[c] : '-'; - perm[9-i] = c; - } - - if (S_ISDIR(mode)) c = 'd'; - else if (S_ISBLK(mode)) c = 'b'; - else if (S_ISCHR(mode)) c = 'c'; - else if (S_ISLNK(mode)) c = 'l'; - else if (S_ISFIFO(mode)) c = 'p'; - else if (S_ISSOCK(mode)) c = 's'; - else c = '-'; - *perm = c; - - tm = localtime(&(st->st_mtime)); - strftime(thyme, sizeof(thyme), "%F %H:%M", tm); - - if (flags&FLAG_o) grp = grpad = toybuf+256; - else { - grp = (flags&FLAG_n) ? utoa(st->st_gid) - : getgroupname(st->st_gid); - grpad = toybuf+256-(totals[4]-len[4]); - } - - if (flags&FLAG_g) usr = upad = toybuf+256; - else { - upad = toybuf+255-(totals[3]-len[3]); - if (flags&FLAG_n) { - usr = TT.uid_buf; - utoa_to_buf(st->st_uid, TT.uid_buf, 12); - } else usr = getusername(st->st_uid); - } - - // Coerce the st types into something we know we can print. - xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, - (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, - (int64_t)st->st_size, thyme); - } + if (flags & FLAG_q) { + char *p; + for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); + } else xprintf("%s", sort[next]->name); + if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) + xprintf(" -> %s", sort[next]->symlink); - if (flags & FLAG_q) { - char *p; - for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); - } else xprintf("%s", sort[next]->name); - if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) - xprintf(" -> %s", sort[next]->symlink); + if (et) xputc(et); - if (et) xputc(et); - - // Pad columns - if (flags & (FLAG_C|FLAG_x)) { - curcol = colsizes[curcol] - *len; - if (curcol >= 0) xprintf("%s", toybuf+255-curcol); - } + // Pad columns + if (flags & (FLAG_C|FLAG_x)) { + curcol = colsizes[curcol] - *len; + if (curcol >= 0) xprintf("%s", toybuf+255-curcol); } + } - if (width) xputc('\n'); + if (width) xputc('\n'); - // Free directory entries, recursing first if necessary. + // Free directory entries, recursing first if necessary. - for (ul = 0; ul<dtlen; free(sort[ul++])) { - if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) - || !dirtree_notdotdot(sort[ul])) continue; + for (ul = 0; ul<dtlen; free(sort[ul++])) { + if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) + || !dirtree_notdotdot(sort[ul])) continue; - // Recurse into dirs if at top of the tree or given -R - if (!indir->parent || (flags & FLAG_R)) - listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); - } - free(sort); - if (dirfd != AT_FDCWD) close(indir->data); + // Recurse into dirs if at top of the tree or given -R + if (!indir->parent || (flags & FLAG_R)) + listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); + } + free(sort); + if (dirfd != AT_FDCWD) close(indir->data); } void ls_main(void) { - char **s, *noargs[] = {".", 0}; - struct dirtree *dt; - - // Do we have an implied -1 - if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) - toys.optflags |= FLAG_1; - else { - TT.screen_width = 80; - terminal_size(&TT.screen_width, NULL); + char **s, *noargs[] = {".", 0}; + struct dirtree *dt; + + // Do we have an implied -1 + if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) + toys.optflags |= FLAG_1; + else { + TT.screen_width = 80; + terminal_size(&TT.screen_width, NULL); + } + // The optflags parsing infrastructure should really do this for us, + // but currently it has "switch off when this is set", so "-dR" and "-Rd" + // behave differently + if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; + + // Iterate through command line arguments, collecting directories and files. + // Non-absolute paths are relative to current directory. + TT.files = dirtree_add_node(0, 0, 0); + for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { + dt = dirtree_add_node(AT_FDCWD, *s, + (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l); + + if (!dt) { + toys.exitval = 1; + continue; } - // The optflags parsing infrastructure should really do this for us, - // but currently it has "switch off when this is set", so "-dR" and "-Rd" - // behave differently - if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; - - // Iterate through command line arguments, collecting directories and files. - // Non-absolute paths are relative to current directory. - TT.files = dirtree_add_node(0, 0, 0); - for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { - dt = dirtree_add_node(AT_FDCWD, *s, - (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l); - - if (!dt) { - toys.exitval = 1; - continue; - } - // Typecast means double_list->prev temporarirly goes in dirtree->parent - dlist_add_nomalloc((struct double_list **)&TT.files->child, - (struct double_list *)dt); - } + // Typecast means double_list->prev temporarirly goes in dirtree->parent + dlist_add_nomalloc((struct double_list **)&TT.files->child, + (struct double_list *)dt); + } - // Turn double_list into dirtree - dlist_to_dirtree(TT.files); + // Turn double_list into dirtree + dlist_to_dirtree(TT.files); - // Display the files we collected - listfiles(AT_FDCWD, TT.files); + // Display the files we collected + listfiles(AT_FDCWD, TT.files); - if (CFG_TOYBOX_FREE) free(TT.files); + if (CFG_TOYBOX_FREE) free(TT.files); } diff --git a/toys/posix/mkdir.c b/toys/posix/mkdir.c index e4e591d7..33fb8326 100644 --- a/toys/posix/mkdir.c +++ b/toys/posix/mkdir.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mkdir.c - Make directories +/* mkdir.c - Make directories * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> * @@ -11,65 +9,65 @@ USE_MKDIR(NEWTOY(mkdir, "<1p", TOYFLAG_BIN)) config MKDIR - bool "mkdir" - default y - help - usage: mkdir [-p] [dirname...] - Create one or more directories. + bool "mkdir" + default y + help + usage: mkdir [-p] [dirname...] + Create one or more directories. - -p make parent directories as needed. + -p make parent directories as needed. */ #define FOR_mkdir #include "toys.h" GLOBALS( - long mode; + long mode; ) static int do_mkdir(char *dir) { - struct stat buf; - char *s; + struct stat buf; + char *s; - // mkdir -p one/two/three is not an error if the path already exists, - // but is if "three" is a file. The others we dereference and catch - // not-a-directory along the way, but the last one we must explicitly - // test for. Might as well do it up front. + // mkdir -p one/two/three is not an error if the path already exists, + // but is if "three" is a file. The others we dereference and catch + // not-a-directory along the way, but the last one we must explicitly + // test for. Might as well do it up front. - if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) { - errno = EEXIST; - return 1; - } + if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) { + errno = EEXIST; + return 1; + } - for (s=dir; ; s++) { - char save=0; + for (s=dir; ; s++) { + char save=0; - // Skip leading / of absolute paths. - if (s!=dir && *s == '/' && toys.optflags) { - save = *s; - *s = 0; - } else if (*s) continue; + // Skip leading / of absolute paths. + if (s!=dir && *s == '/' && toys.optflags) { + save = *s; + *s = 0; + } else if (*s) continue; - if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST)) - return 1; + if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST)) + return 1; - if (!(*s = save)) break; - } + if (!(*s = save)) break; + } - return 0; + return 0; } void mkdir_main(void) { - char **s; + char **s; - TT.mode = 0777; + TT.mode = 0777; - for (s=toys.optargs; *s; s++) { - if (do_mkdir(*s)) { - perror_msg("cannot create directory '%s'", *s); - toys.exitval = 1; - } - } + for (s=toys.optargs; *s; s++) { + if (do_mkdir(*s)) { + perror_msg("cannot create directory '%s'", *s); + toys.exitval = 1; + } + } } diff --git a/toys/posix/mkfifo.c b/toys/posix/mkfifo.c index 44775788..44fbc994 100644 --- a/toys/posix/mkfifo.c +++ b/toys/posix/mkfifo.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mkfifo.c - Create FIFOs (named pipes) +/* mkfifo.c - Create FIFOs (named pipes) * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> * @@ -11,35 +9,35 @@ USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN)) config MKFIFO - bool "mkfifo" - default y - help - usage: mkfifo [fifo_name...] + bool "mkfifo" + default y + help + usage: mkfifo [fifo_name...] - Create FIFOs (named pipes). + Create FIFOs (named pipes). */ #define FOR_mkfifo #include "toys.h" GLOBALS( - char *m_string; - mode_t mode; + char *m_string; + mode_t mode; ) void mkfifo_main(void) { - char **s; - - TT.mode = 0666; - if (toys.optflags & FLAG_m) { - TT.mode = string_to_mode(TT.m_string, 0); - } - - for (s = toys.optargs; *s; s++) { - if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) { - perror_msg("cannot create fifo '%s'", *s); - toys.exitval = 1; - } - } + char **s; + + TT.mode = 0666; + if (toys.optflags & FLAG_m) { + TT.mode = string_to_mode(TT.m_string, 0); + } + + for (s = toys.optargs; *s; s++) { + if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) { + perror_msg("cannot create fifo '%s'", *s); + toys.exitval = 1; + } + } } diff --git a/toys/posix/nice.c b/toys/posix/nice.c index d45429f8..4b587ee6 100644 --- a/toys/posix/nice.c +++ b/toys/posix/nice.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * nice.c - Run a program at a different niceness level. +/* nice.c - Run a program at a different niceness level. * * Copyright 2010 Rob Landley <rob@landley.net> * @@ -9,32 +7,32 @@ USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_USR|TOYFLAG_BIN)) config NICE - bool "nice" - default y - help - usage: nice [-n PRIORITY] command [args...] + bool "nice" + default y + help + usage: nice [-n PRIORITY] command [args...] - Run a command line at an increased or decreased scheduling priority. + Run a command line at an increased or decreased scheduling priority. - Higher numbers make a program yield more CPU time, from -20 (highest - priority) to 19 (lowest). By default processes inherit their parent's - niceness (usually 0). By default this command adds 10 to the parent's - priority. Only root can set a negative niceness level. + Higher numbers make a program yield more CPU time, from -20 (highest + priority) to 19 (lowest). By default processes inherit their parent's + niceness (usually 0). By default this command adds 10 to the parent's + priority. Only root can set a negative niceness level. */ #define FOR_nice #include "toys.h" GLOBALS( - long priority; + long priority; ) void nice_main(void) { - if (!toys.optflags) TT.priority = 10; + if (!toys.optflags) TT.priority = 10; - errno = 0; - if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority"); + errno = 0; + if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority"); - xexec(toys.optargs); + xexec(toys.optargs); } diff --git a/toys/posix/nohup.c b/toys/posix/nohup.c index e11fb094..b936a093 100644 --- a/toys/posix/nohup.c +++ b/toys/posix/nohup.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * nohup.c - run commandline with SIGHUP blocked. +/* nohup.c - run commandline with SIGHUP blocked. * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,34 +7,34 @@ USE_NOHUP(NEWTOY(nohup, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config NOHUP - bool "nohup" - default y - help - usage: nohup COMMAND [ARGS...] + bool "nohup" + default y + help + usage: nohup COMMAND [ARGS...] - Run a command that survives the end of its terminal. - If stdin is a tty, redirect from /dev/null - If stdout is a tty, redirect to file "nohup.out" + Run a command that survives the end of its terminal. + If stdin is a tty, redirect from /dev/null + If stdout is a tty, redirect to file "nohup.out" */ #include "toys.h" void nohup_main(void) { - signal(SIGHUP, SIG_IGN); - if (isatty(1)) { - close(1); - if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, - S_IRUSR|S_IWUSR )) - { - char *temp = getenv("HOME"); - temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out"); - xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR); - } - } - if (isatty(0)) { - close(0); - open("/dev/null", O_RDONLY); - } - xexec(toys.optargs); + signal(SIGHUP, SIG_IGN); + if (isatty(1)) { + close(1); + if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, + S_IRUSR|S_IWUSR )) + { + char *temp = getenv("HOME"); + temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out"); + xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR); + } + } + if (isatty(0)) { + close(0); + open("/dev/null", O_RDONLY); + } + xexec(toys.optargs); } diff --git a/toys/posix/od.c b/toys/posix/od.c index ef420b87..948a99e1 100644 --- a/toys/posix/od.c +++ b/toys/posix/od.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * od.c - Provide octal/hex dumps of data +/* od.c - Provide octal/hex dumps of data * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * Copyright 2012 Rob Landley <rob@landley.net> @@ -10,253 +8,253 @@ USE_OD(NEWTOY(od, "j#vN#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN)) config OD - bool "od" - default y - help - usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg] + bool "od" + default y + help + usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg] - -A Address base (decimal, octal, hexdecimal, none) - -t output type(s) a (ascii) c (char) d (decimal) foux + -A Address base (decimal, octal, hexdecimal, none) + -t output type(s) a (ascii) c (char) d (decimal) foux */ #define FOR_od #include "toys.h" GLOBALS( - struct arg_list *output_base; - char *address_base; - long max_count; - long jump_bytes; - - unsigned types, leftover, star, address_idx; - char *buf; - uint64_t bufs[4]; // force 64-bit alignment - off_t pos; + struct arg_list *output_base; + char *address_base; + long max_count; + long jump_bytes; + + unsigned types, leftover, star, address_idx; + char *buf; + uint64_t bufs[4]; // force 64-bit alignment + off_t pos; ) static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si" - "dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp"; + "dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp"; struct odtype { - int type; - int size; + int type; + int size; }; static void od_outline(void) { - unsigned flags = toys.optflags; - char *abases[] = {"", "%07d", "%07o", "%06x"}; - struct odtype *types = (struct odtype *)toybuf, *t; - int i, len; - - if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover); - - // Handle duplciate lines as * - if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover - && !memcmp(TT.bufs, TT.bufs + 2, 16)) - { - if (!TT.star) { - xputs("*"); - TT.star++; - } - - // Print line position - } else { - TT.star = 0; - - xprintf(abases[TT.address_idx], TT.pos); - if (!TT.leftover) { - if (TT.address_idx) xputc('\n'); - return; - } - } - - TT.pos += len = TT.leftover; - TT.leftover = 0; - if (TT.star) return; - - // For each output type, print one line - - for (i=0; i<TT.types; i++) { - int j = 0, pad = i ? 8 : 0; - char buf[128]; - - t = types+i; - while (j<len) { - unsigned k; - int throw = 0; - - // Handle ascii - if (t->type < 2) { - char c = TT.buf[j++]; - pad += 4; - - if (!t->type) { - c &= 127; - if (c<=32) sprintf(buf, "%.3s", ascii+(3*c)); - else if (c==127) strcpy(buf, "del"); - else sprintf(buf, "%c", c); - } else { - char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c); - if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]); - else if (c < 32 || c >= 127) sprintf(buf, "%03o", c); - else { - // TODO: this should be UTF8 aware. - sprintf(buf, "%c", c); - } - } - } else if (CFG_TOYBOX_FLOAT && t->type == 6) { - long double ld; - union {float f; double d; long double ld;} fdl; - - memcpy(&fdl, TT.buf+j, t->size); - j += t->size; - if (sizeof(float) == t->size) { - ld = fdl.f; - pad += (throw = 8)+7; - } else if (sizeof(double) == t->size) { - ld = fdl.d; - pad += (throw = 17)+8; - } else if (sizeof(long double) == t->size) { - ld = fdl.ld; - pad += (throw = 21)+9; - } else error_exit("bad -tf '%d'", t->size); - - sprintf(buf, "%.*Le", throw, ld); - // Integer types - } else { - unsigned long long ll = 0, or; - char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"}, - *class = c[t->type-2]; - - // Work out width of field - if (t->size == 8) { - or = -1LL; - if (t->type == 2) or >>= 1; - } else or = (1LL<<(8*t->size))-1; - throw = sprintf(buf, class, 0, or); - - // Accumulate integer based on size argument - for (k=0; k < t->size; k++) { - or = TT.buf[j++]; - ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k)); - } - - // Handle negative values - if (t->type == 2) { - or = sizeof(or) - t->size; - throw++; - if (or && (ll & (1l<<((8*t->size)-1)))) - ll |= ((or<<(8*or))-1) << (8*t->size); - } - - sprintf(buf, class, throw, ll); - pad += throw+1; - } - xprintf("%*s", pad, buf); - pad = 0; - } - xputc('\n'); - } - - // buffer toggle for "same as last time" check. - TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs); + unsigned flags = toys.optflags; + char *abases[] = {"", "%07d", "%07o", "%06x"}; + struct odtype *types = (struct odtype *)toybuf, *t; + int i, len; + + if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover); + + // Handle duplciate lines as * + if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover + && !memcmp(TT.bufs, TT.bufs + 2, 16)) + { + if (!TT.star) { + xputs("*"); + TT.star++; + } + + // Print line position + } else { + TT.star = 0; + + xprintf(abases[TT.address_idx], TT.pos); + if (!TT.leftover) { + if (TT.address_idx) xputc('\n'); + return; + } + } + + TT.pos += len = TT.leftover; + TT.leftover = 0; + if (TT.star) return; + + // For each output type, print one line + + for (i=0; i<TT.types; i++) { + int j = 0, pad = i ? 8 : 0; + char buf[128]; + + t = types+i; + while (j<len) { + unsigned k; + int throw = 0; + + // Handle ascii + if (t->type < 2) { + char c = TT.buf[j++]; + pad += 4; + + if (!t->type) { + c &= 127; + if (c<=32) sprintf(buf, "%.3s", ascii+(3*c)); + else if (c==127) strcpy(buf, "del"); + else sprintf(buf, "%c", c); + } else { + char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c); + if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]); + else if (c < 32 || c >= 127) sprintf(buf, "%03o", c); + else { + // TODO: this should be UTF8 aware. + sprintf(buf, "%c", c); + } + } + } else if (CFG_TOYBOX_FLOAT && t->type == 6) { + long double ld; + union {float f; double d; long double ld;} fdl; + + memcpy(&fdl, TT.buf+j, t->size); + j += t->size; + if (sizeof(float) == t->size) { + ld = fdl.f; + pad += (throw = 8)+7; + } else if (sizeof(double) == t->size) { + ld = fdl.d; + pad += (throw = 17)+8; + } else if (sizeof(long double) == t->size) { + ld = fdl.ld; + pad += (throw = 21)+9; + } else error_exit("bad -tf '%d'", t->size); + + sprintf(buf, "%.*Le", throw, ld); + // Integer types + } else { + unsigned long long ll = 0, or; + char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"}, + *class = c[t->type-2]; + + // Work out width of field + if (t->size == 8) { + or = -1LL; + if (t->type == 2) or >>= 1; + } else or = (1LL<<(8*t->size))-1; + throw = sprintf(buf, class, 0, or); + + // Accumulate integer based on size argument + for (k=0; k < t->size; k++) { + or = TT.buf[j++]; + ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k)); + } + + // Handle negative values + if (t->type == 2) { + or = sizeof(or) - t->size; + throw++; + if (or && (ll & (1l<<((8*t->size)-1)))) + ll |= ((or<<(8*or))-1) << (8*t->size); + } + + sprintf(buf, class, throw, ll); + pad += throw+1; + } + xprintf("%*s", pad, buf); + pad = 0; + } + xputc('\n'); + } + + // buffer toggle for "same as last time" check. + TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs); } static void do_od(int fd, char *name) { - // Skip input, possibly more than one entire file. - if (TT.jump_bytes < TT.pos) { - off_t off = lskip(fd, TT.jump_bytes); - if (off > 0) TT.pos += off; - if (TT.jump_bytes < TT.pos) return; - } - - for(;;) { - char *buf = TT.buf + TT.leftover; - int len = 16 - TT.leftover; - - if (toys.optflags & FLAG_N) { - if (!TT.max_count) break; - if (TT.max_count < len) len = TT.max_count; - } - - len = readall(fd, buf, len); - if (len < 0) { - perror_msg("%s", name); - break; - } - if (TT.max_count) TT.max_count -= len; - TT.leftover += len; - if (TT.leftover < 16) break; - - od_outline(); - } + // Skip input, possibly more than one entire file. + if (TT.jump_bytes < TT.pos) { + off_t off = lskip(fd, TT.jump_bytes); + if (off > 0) TT.pos += off; + if (TT.jump_bytes < TT.pos) return; + } + + for(;;) { + char *buf = TT.buf + TT.leftover; + int len = 16 - TT.leftover; + + if (toys.optflags & FLAG_N) { + if (!TT.max_count) break; + if (TT.max_count < len) len = TT.max_count; + } + + len = readall(fd, buf, len); + if (len < 0) { + perror_msg("%s", name); + break; + } + if (TT.max_count) TT.max_count -= len; + TT.leftover += len; + if (TT.leftover < 16) break; + + od_outline(); + } } static void append_base(char *base) { - char *s = base; - struct odtype *types = (struct odtype *)toybuf; - int type; - - for (;;) { - int size = 1; - - if (!*s) return; - if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break; - if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break; - - if (isdigit(*s)) { - size = strtol(s, &s, 10); - if (type < 2 && size != 1) break; - if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double)); - else if (size < 0 || size > 8) break; - } else if (CFG_TOYBOX_FLOAT && type == 6) { - int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)}; - if (-1 == (size = stridx("FDL", *s))) size = sizeof(double); - else { - s++; - size = sizes[size]; - } - } else if (type > 1) { - if (-1 == (size = stridx("CSIL", *s))) size = 4; - else { - s++; - size = 1 << size; - } - } - - types[TT.types].type = type; - types[TT.types].size = size; - TT.types++; - } - - error_exit("bad -t %s", base); + char *s = base; + struct odtype *types = (struct odtype *)toybuf; + int type; + + for (;;) { + int size = 1; + + if (!*s) return; + if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break; + if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break; + + if (isdigit(*s)) { + size = strtol(s, &s, 10); + if (type < 2 && size != 1) break; + if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double)); + else if (size < 0 || size > 8) break; + } else if (CFG_TOYBOX_FLOAT && type == 6) { + int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)}; + if (-1 == (size = stridx("FDL", *s))) size = sizeof(double); + else { + s++; + size = sizes[size]; + } + } else if (type > 1) { + if (-1 == (size = stridx("CSIL", *s))) size = 4; + else { + s++; + size = 1 << size; + } + } + + types[TT.types].type = type; + types[TT.types].size = size; + TT.types++; + } + + error_exit("bad -t %s", base); } void od_main(void) { - struct arg_list *arg; + struct arg_list *arg; - TT.buf = (char *)TT.bufs; + TT.buf = (char *)TT.bufs; - if (!TT.address_base) TT.address_idx = 2; - else if (0>(TT.address_idx = stridx("ndox", *TT.address_base))) - error_exit("bad -A '%c'", *TT.address_base); + if (!TT.address_base) TT.address_idx = 2; + else if (0>(TT.address_idx = stridx("ndox", *TT.address_base))) + error_exit("bad -A '%c'", *TT.address_base); - // Collect -t entries + // Collect -t entries - for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg); - if (toys.optflags & FLAG_b) append_base("o1"); - if (toys.optflags & FLAG_d) append_base("u2"); - if (toys.optflags & FLAG_o) append_base("o2"); - if (toys.optflags & FLAG_s) append_base("d2"); - if (toys.optflags & FLAG_x) append_base("x2"); - if (!TT.output_base) append_base("o2"); + for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg); + if (toys.optflags & FLAG_b) append_base("o1"); + if (toys.optflags & FLAG_d) append_base("u2"); + if (toys.optflags & FLAG_o) append_base("o2"); + if (toys.optflags & FLAG_s) append_base("d2"); + if (toys.optflags & FLAG_x) append_base("x2"); + if (!TT.output_base) append_base("o2"); - loopfiles(toys.optargs, do_od); + loopfiles(toys.optargs, do_od); - if (TT.leftover) od_outline(); - od_outline(); + if (TT.leftover) od_outline(); + od_outline(); } diff --git a/toys/posix/patch.c b/toys/posix/patch.c index 40d7cbcf..12e4b8c3 100644 --- a/toys/posix/patch.c +++ b/toys/posix/patch.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * patch.c - Apply a "universal" diff. +/* patch.c - Apply a "universal" diff. * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -24,39 +22,39 @@ USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"ulp#i:R", TOYFLAG_USR|TOYFLAG_BIN)) config PATCH - bool "patch" - default y - help - usage: patch [-i file] [-p depth] [-Ru] + bool "patch" + default y + help + usage: patch [-i file] [-p depth] [-Ru] - Apply a unified diff to one or more files. + Apply a unified diff to one or more files. - -i Input file (defaults=stdin) - -l Loose match (ignore whitespace) - -p Number of '/' to strip from start of file paths (default=all) - -R Reverse patch. - -u Ignored (only handles "unified" diffs) + -i Input file (defaults=stdin) + -l Loose match (ignore whitespace) + -p Number of '/' to strip from start of file paths (default=all) + -R Reverse patch. + -u Ignored (only handles "unified" diffs) - This version of patch only handles unified diffs, and only modifies - a file when all all hunks to that file apply. Patch prints failed - hunks to stderr, and exits with nonzero status if any hunks fail. + This version of patch only handles unified diffs, and only modifies + a file when all all hunks to that file apply. Patch prints failed + hunks to stderr, and exits with nonzero status if any hunks fail. - A file compared against /dev/null (or with a date <= the epoch) is - created/deleted as appropriate. + A file compared against /dev/null (or with a date <= the epoch) is + created/deleted as appropriate. */ #define FOR_patch #include "toys.h" GLOBALS( - char *infile; - long prefix; - - struct double_list *current_hunk; - long oldline, oldlen, newline, newlen; - long linenum; - int context, state, filein, fileout, filepatch, hunknum; - char *tempname; + char *infile; + long prefix; + + struct double_list *current_hunk; + long oldline, oldlen, newline, newlen; + long linenum; + int context, state, filein, fileout, filepatch, hunknum; + char *tempname; ) // Dispose of a line of input, either by writing it out or discarding it. @@ -70,59 +68,59 @@ GLOBALS( static void do_line(void *data) { - struct double_list *dlist = (struct double_list *)data; + struct double_list *dlist = (struct double_list *)data; - if (TT.state>1 && *dlist->data != TT.state) { - char *s = dlist->data+(TT.state>3 ? 1 : 0); - int i = TT.state == 2 ? 2 : TT.fileout; + if (TT.state>1 && *dlist->data != TT.state) { + char *s = dlist->data+(TT.state>3 ? 1 : 0); + int i = TT.state == 2 ? 2 : TT.fileout; - xwrite(i, s, strlen(s)); - xwrite(i, "\n", 1); - } + xwrite(i, s, strlen(s)); + xwrite(i, "\n", 1); + } - if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data); + if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data); - free(dlist->data); - free(data); + free(dlist->data); + free(data); } static void finish_oldfile(void) { - if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); - TT.fileout = TT.filein = -1; + if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); + TT.fileout = TT.filein = -1; } static void fail_hunk(void) { - if (!TT.current_hunk) return; - TT.current_hunk->prev->next = 0; + if (!TT.current_hunk) return; + TT.current_hunk->prev->next = 0; - fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n", - TT.hunknum, TT.oldline, TT.newline); - toys.exitval = 1; + fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n", + TT.hunknum, TT.oldline, TT.newline); + toys.exitval = 1; - // If we got to this point, we've seeked to the end. Discard changes to - // this file and advance to next file. + // If we got to this point, we've seeked to the end. Discard changes to + // this file and advance to next file. - TT.state = 2; - llist_traverse(TT.current_hunk, do_line); - TT.current_hunk = NULL; - delete_tempfile(TT.filein, TT.fileout, &TT.tempname); - TT.state = 0; + TT.state = 2; + llist_traverse(TT.current_hunk, do_line); + TT.current_hunk = NULL; + delete_tempfile(TT.filein, TT.fileout, &TT.tempname); + TT.state = 0; } -// Compare ignoring whitespace. Just returns +// Compare ignoring whitespace. Just returns static int loosecmp(char *aa, char *bb) { - int a = 0, b = 0; - - for (;;) { - while (isspace(aa[a])) a++; - while (isspace(bb[b])) b++; - if (aa[a] != bb[b]) return 1; - if (!aa[a]) return 0; - a++, b++; - } + int a = 0, b = 0; + + for (;;) { + while (isspace(aa[a])) a++; + while (isspace(bb[b])) b++; + if (aa[a] != bb[b]) return 1; + if (!aa[a]) return 0; + a++, b++; + } } // Given a hunk of a unified diff, make the appropriate change to the file. @@ -134,116 +132,114 @@ static int loosecmp(char *aa, char *bb) static int apply_one_hunk(void) { - struct double_list *plist, *buf = NULL, *check; - int matcheof = 0, reverse = toys.optflags & FLAG_R, backwarn = 0; - int (*lcmp)(char *aa, char *bb); - - lcmp = (toys.optflags & FLAG_l) ? (void *)loosecmp : (void *)strcmp; - - // Break doubly linked list so we can use singly linked traversal function. - TT.current_hunk->prev->next = NULL; - - // Match EOF if there aren't as many ending context lines as beginning - for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; - else matcheof = 0; - if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data); - } - matcheof = matcheof < TT.context; - - if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); - - // Loop through input data searching for this hunk. Match all context - // lines and all lines to be removed until we've found the end of a - // complete hunk. - plist = TT.current_hunk; - buf = NULL; - if (TT.context) for (;;) { - char *data = get_line(TT.filein); - - TT.linenum++; - - // Figure out which line of hunk to compare with next. (Skip lines - // of the hunk we'd be adding.) - while (plist && *plist->data == "+-"[reverse]) { - if (data && !lcmp(data, plist->data+1)) { - if (!backwarn) backwarn = TT.linenum; - } - plist = plist->next; - } - - // Is this EOF? - if (!data) { - if (PATCH_DEBUG) fprintf(stderr, "INEOF\n"); - - // Does this hunk need to match EOF? - if (!plist && matcheof) break; - - if (backwarn) - fprintf(stderr, "Possibly reversed hunk %d at %ld\n", - TT.hunknum, TT.linenum); - - // File ended before we found a place for this hunk. - fail_hunk(); - goto done; - } else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data); - check = dlist_add(&buf, data); - - // Compare this line with next expected line of hunk. - - // A match can fail because the next line doesn't match, or because - // we hit the end of a hunk that needed EOF, and this isn't EOF. - - // If match failed, flush first line of buffered data and - // recheck buffered data for a new match until we find one or run - // out of buffer. - - for (;;) { - if (!plist || lcmp(check->data, plist->data+1)) { - // Match failed. Write out first line of buffered data and - // recheck remaining buffered data for a new match. - - if (PATCH_DEBUG) - fprintf(stderr, "NOT: %s\n", plist->data); - - TT.state = 3; - check = llist_pop(&buf); - check->prev->next = buf; - buf->prev = check->prev; - do_line(check); - plist = TT.current_hunk; - - // If we've reached the end of the buffer without confirming a - // match, read more lines. - if (check==buf) { - buf = 0; - break; - } - check = buf; - } else { - if (PATCH_DEBUG) - fprintf(stderr, "MAYBE: %s\n", plist->data); - // This line matches. Advance plist, detect successful match. - plist = plist->next; - if (!plist && !matcheof) goto out; - check = check->next; - if (check == buf) break; - } - } - } + struct double_list *plist, *buf = NULL, *check; + int matcheof = 0, reverse = toys.optflags & FLAG_R, backwarn = 0; + int (*lcmp)(char *aa, char *bb); + + lcmp = (toys.optflags & FLAG_l) ? (void *)loosecmp : (void *)strcmp; + + // Break doubly linked list so we can use singly linked traversal function. + TT.current_hunk->prev->next = NULL; + + // Match EOF if there aren't as many ending context lines as beginning + for (plist = TT.current_hunk; plist; plist = plist->next) { + if (plist->data[0]==' ') matcheof++; + else matcheof = 0; + if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data); + } + matcheof = matcheof < TT.context; + + if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); + + // Loop through input data searching for this hunk. Match all context + // lines and all lines to be removed until we've found the end of a + // complete hunk. + plist = TT.current_hunk; + buf = NULL; + if (TT.context) for (;;) { + char *data = get_line(TT.filein); + + TT.linenum++; + + // Figure out which line of hunk to compare with next. (Skip lines + // of the hunk we'd be adding.) + while (plist && *plist->data == "+-"[reverse]) { + if (data && !lcmp(data, plist->data+1)) { + if (!backwarn) backwarn = TT.linenum; + } + plist = plist->next; + } + + // Is this EOF? + if (!data) { + if (PATCH_DEBUG) fprintf(stderr, "INEOF\n"); + + // Does this hunk need to match EOF? + if (!plist && matcheof) break; + + if (backwarn) + fprintf(stderr, "Possibly reversed hunk %d at %ld\n", + TT.hunknum, TT.linenum); + + // File ended before we found a place for this hunk. + fail_hunk(); + goto done; + } else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data); + check = dlist_add(&buf, data); + + // Compare this line with next expected line of hunk. + + // A match can fail because the next line doesn't match, or because + // we hit the end of a hunk that needed EOF, and this isn't EOF. + + // If match failed, flush first line of buffered data and + // recheck buffered data for a new match until we find one or run + // out of buffer. + + for (;;) { + if (!plist || lcmp(check->data, plist->data+1)) { + // Match failed. Write out first line of buffered data and + // recheck remaining buffered data for a new match. + + if (PATCH_DEBUG) fprintf(stderr, "NOT: %s\n", plist->data); + + TT.state = 3; + check = llist_pop(&buf); + check->prev->next = buf; + buf->prev = check->prev; + do_line(check); + plist = TT.current_hunk; + + // If we've reached the end of the buffer without confirming a + // match, read more lines. + if (check==buf) { + buf = 0; + break; + } + check = buf; + } else { + if (PATCH_DEBUG) fprintf(stderr, "MAYBE: %s\n", plist->data); + // This line matches. Advance plist, detect successful match. + plist = plist->next; + if (!plist && !matcheof) goto out; + check = check->next; + if (check == buf) break; + } + } + } out: - // We have a match. Emit changed data. - TT.state = "-+"[reverse]; - llist_traverse(TT.current_hunk, do_line); - TT.current_hunk = NULL; - TT.state = 1; + // We have a match. Emit changed data. + TT.state = "-+"[reverse]; + llist_traverse(TT.current_hunk, do_line); + TT.current_hunk = NULL; + TT.state = 1; done: - if (buf) { - buf->prev->next = NULL; - llist_traverse(buf, do_line); - } + if (buf) { + buf->prev->next = NULL; + llist_traverse(buf, do_line); + } - return TT.state; + return TT.state; } // Read a patch file and find hunks, opening/creating/deleting files. @@ -256,172 +252,170 @@ done: void patch_main(void) { - int reverse = toys.optflags&FLAG_R, state = 0, patchlinenum = 0, - strip = 0; - char *oldname = NULL, *newname = NULL; - - if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); - TT.filein = TT.fileout = -1; - - // Loop through the lines in the patch - for (;;) { - char *patchline; - - patchline = get_line(TT.filepatch); - if (!patchline) break; - - // Other versions of patch accept damaged patches, - // so we need to also. - if (strip || !patchlinenum++) { - int len = strlen(patchline); - if (patchline[len-1] == '\r') { - if (!strip) fprintf(stderr, "Removing DOS newlines\n"); - strip = 1; - patchline[len-1]=0; - } - } - if (!*patchline) { - free(patchline); - patchline = xstrdup(" "); - } - - // Are we assembling a hunk? - if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { - dlist_add(&TT.current_hunk, patchline); - - if (*patchline != '+') TT.oldlen--; - if (*patchline != '-') TT.newlen--; - - // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; - - // If we've consumed all expected hunk lines, apply the hunk. - - if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); - continue; - } - fail_hunk(); - state = 0; - continue; - } - - // Open a new file? - if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { - char *s, **name = &oldname; - int i; - - if (*patchline == '+') { - name = &newname; - state = 1; - } - - free(*name); - finish_oldfile(); - - // Trim date from end of filename (if any). We don't care. - for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; - i = atoi(s); - if (i>1900 && i<=1970) - *name = xstrdup("/dev/null"); - else { - *s = 0; - *name = xstrdup(patchline+4); - } - - // We defer actually opening the file because svn produces broken - // patches that don't signal they want to create a new file the - // way the patch man page says, so you have to read the first hunk - // and _guess_. - - // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ - // but a missing ,value means the value is 1. - } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { - int i; - char *s = patchline+4; - - // Read oldline[,oldlen] +newline[,newlen] - - TT.oldlen = TT.newlen = 1; - TT.oldline = strtol(s, &s, 10); - if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); - TT.newline = strtol(s+2, &s, 10); - if (*s == ',') TT.newlen = strtol(s+1, &s, 10); - - TT.context = 0; - state = 2; - - // If this is the first hunk, open the file. - if (TT.filein == -1) { - int oldsum, newsum, del = 0; - char *name; - - oldsum = TT.oldline + TT.oldlen; - newsum = TT.newline + TT.newlen; - - name = reverse ? oldname : newname; - - // We're deleting oldname if new file is /dev/null (before -p) - // or if new hunk is empty (zero context) after patching - if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) - { - name = reverse ? newname : oldname; - del++; - } - - // handle -p path truncation. - for (i = 0, s = name; *s;) { - if ((toys.optflags & FLAG_p) && TT.prefix == i) break; - if (*s++ != '/') continue; - while (*s == '/') s++; - name = s; - i++; - } - - if (del) { - printf("removing %s\n", name); - xunlink(name); - state = 0; - // If we've got a file to open, do so. - } else if (!(toys.optflags & FLAG_p) || i <= TT.prefix) { - // If the old file was null, we're creating a new one. - if ((!strcmp(oldname, "/dev/null") || !oldsum) - && access(name, F_OK)) - { - printf("creating %s\n", name); - s = strrchr(name, '/'); - if (s) { - *s = 0; - xmkpath(name, -1); - *s = '/'; - } - TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666); - } else { - printf("patching %s\n", name); - TT.filein = xopen(name, O_RDWR); - } - TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); - TT.linenum = 0; - TT.hunknum = 0; - } - } - - TT.hunknum++; - - continue; - } - - // If we didn't continue above, discard this line. - free(patchline); - } - - finish_oldfile(); - - if (CFG_TOYBOX_FREE) { - close(TT.filepatch); - free(oldname); - free(newname); - } + int reverse = toys.optflags&FLAG_R, state = 0, patchlinenum = 0, + strip = 0; + char *oldname = NULL, *newname = NULL; + + if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); + TT.filein = TT.fileout = -1; + + // Loop through the lines in the patch + for (;;) { + char *patchline; + + patchline = get_line(TT.filepatch); + if (!patchline) break; + + // Other versions of patch accept damaged patches, + // so we need to also. + if (strip || !patchlinenum++) { + int len = strlen(patchline); + if (patchline[len-1] == '\r') { + if (!strip) fprintf(stderr, "Removing DOS newlines\n"); + strip = 1; + patchline[len-1]=0; + } + } + if (!*patchline) { + free(patchline); + patchline = xstrdup(" "); + } + + // Are we assembling a hunk? + if (state >= 2) { + if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + dlist_add(&TT.current_hunk, patchline); + + if (*patchline != '+') TT.oldlen--; + if (*patchline != '-') TT.newlen--; + + // Context line? + if (*patchline==' ' && state==2) TT.context++; + else state=3; + + // If we've consumed all expected hunk lines, apply the hunk. + + if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); + continue; + } + fail_hunk(); + state = 0; + continue; + } + + // Open a new file? + if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { + char *s, **name = &oldname; + int i; + + if (*patchline == '+') { + name = &newname; + state = 1; + } + + free(*name); + finish_oldfile(); + + // Trim date from end of filename (if any). We don't care. + for (s = patchline+4; *s && *s!='\t'; s++) + if (*s=='\\' && s[1]) s++; + i = atoi(s); + if (i>1900 && i<=1970) *name = xstrdup("/dev/null"); + else { + *s = 0; + *name = xstrdup(patchline+4); + } + + // We defer actually opening the file because svn produces broken + // patches that don't signal they want to create a new file the + // way the patch man page says, so you have to read the first hunk + // and _guess_. + + // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ + // but a missing ,value means the value is 1. + } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { + int i; + char *s = patchline+4; + + // Read oldline[,oldlen] +newline[,newlen] + + TT.oldlen = TT.newlen = 1; + TT.oldline = strtol(s, &s, 10); + if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); + TT.newline = strtol(s+2, &s, 10); + if (*s == ',') TT.newlen = strtol(s+1, &s, 10); + + TT.context = 0; + state = 2; + + // If this is the first hunk, open the file. + if (TT.filein == -1) { + int oldsum, newsum, del = 0; + char *name; + + oldsum = TT.oldline + TT.oldlen; + newsum = TT.newline + TT.newlen; + + name = reverse ? oldname : newname; + + // We're deleting oldname if new file is /dev/null (before -p) + // or if new hunk is empty (zero context) after patching + if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) + { + name = reverse ? newname : oldname; + del++; + } + + // handle -p path truncation. + for (i = 0, s = name; *s;) { + if ((toys.optflags & FLAG_p) && TT.prefix == i) break; + if (*s++ != '/') continue; + while (*s == '/') s++; + name = s; + i++; + } + + if (del) { + printf("removing %s\n", name); + xunlink(name); + state = 0; + // If we've got a file to open, do so. + } else if (!(toys.optflags & FLAG_p) || i <= TT.prefix) { + // If the old file was null, we're creating a new one. + if ((!strcmp(oldname, "/dev/null") || !oldsum) && access(name, F_OK)) + { + printf("creating %s\n", name); + s = strrchr(name, '/'); + if (s) { + *s = 0; + xmkpath(name, -1); + *s = '/'; + } + TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666); + } else { + printf("patching %s\n", name); + TT.filein = xopen(name, O_RDWR); + } + TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); + TT.linenum = 0; + TT.hunknum = 0; + } + } + + TT.hunknum++; + + continue; + } + + // If we didn't continue above, discard this line. + free(patchline); + } + + finish_oldfile(); + + if (CFG_TOYBOX_FREE) { + close(TT.filepatch); + free(oldname); + free(newname); + } } diff --git a/toys/posix/pwd.c b/toys/posix/pwd.c index d5a3bb69..f70f9098 100644 --- a/toys/posix/pwd.c +++ b/toys/posix/pwd.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * pwd.c - Print working directory. +/* pwd.c - Print working directory. * * Copyright 2006 Rob Landley <rob@landley.net> * @@ -11,20 +9,20 @@ USE_PWD(NEWTOY(pwd, NULL, TOYFLAG_BIN)) config PWD - bool "pwd" - default y - help - usage: pwd + bool "pwd" + default y + help + usage: pwd - The print working directory command prints the current directory. + The print working directory command prints the current directory. */ #include "toys.h" void pwd_main(void) { - char *pwd = xgetcwd(); + char *pwd = xgetcwd(); - xprintf("%s\n", pwd); - if (CFG_TOYBOX_FREE) free(pwd); + xprintf("%s\n", pwd); + if (CFG_TOYBOX_FREE) free(pwd); } diff --git a/toys/posix/rmdir.c b/toys/posix/rmdir.c index be93cb69..289b0156 100644 --- a/toys/posix/rmdir.c +++ b/toys/posix/rmdir.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * rmdir.c - remove directory/path +/* rmdir.c - remove directory/path * * Copyright 2008 Rob Landley <rob@landley.net> * @@ -9,35 +7,35 @@ USE_RMDIR(NEWTOY(rmdir, "<1p", TOYFLAG_BIN)) config RMDIR - bool "rmdir" - default y - help - usage: rmdir [-p] [dirname...] - Remove one or more directories. + bool "rmdir" + default y + help + usage: rmdir [-p] [dirname...] + Remove one or more directories. - -p Remove path. + -p Remove path. */ #include "toys.h" static void do_rmdir(char *name) { - for (;;) { - char *temp; - - if (rmdir(name)) { - perror_msg("%s",name); - return; - } - if (!toys.optflags) return; - if (!(temp=strrchr(name,'/'))) return; - *temp=0; - } + for (;;) { + char *temp; + + if (rmdir(name)) { + perror_msg("%s",name); + return; + } + if (!toys.optflags) return; + if (!(temp=strrchr(name,'/'))) return; + *temp=0; + } } void rmdir_main(void) { - char **s; + char **s; - for (s=toys.optargs; *s; s++) do_rmdir(*s); + for (s=toys.optargs; *s; s++) do_rmdir(*s); } diff --git a/toys/posix/sed.c b/toys/posix/sed.c index a3ba9e38..15099cc6 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -1,21 +1,24 @@ -/* vi: set sw=4 ts=4: +/* sed.c - Stream editor. * - * sed.c - Stream editor. - * - * Copyright 2008 Rob Landley <rob@landley.net> + * Copyright 2012 Rob Landley <rob@landley.net> * * See http://opengroup.org/onlinepubs/9699919799/utilities/sed.c USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN)) config SED - bool "sed" - default n - help - usage: sed [-irn] {command | [-e command]...} [FILE...] + bool "sed" + default n + help + usage: sed [-irn] {command | [-e command]...} [FILE...] + + Stream EDitor, transforms text by appling script of command to each line + of input. - Stream EDitor, transforms text by appling commands to each line - of input. + -e Add expression to the command script (if no -e, use first argument) + -i Modify file in place + -n No default output (p commands only) + -r Use extended regular expression syntex */ #define FOR_sed @@ -23,40 +26,106 @@ config SED #include "lib/xregcomp.h" GLOBALS( - struct arg_list *commands; + struct arg_list *scripts; + struct double_list *commands; + + void *parsed; ) +// Digested version of what sed commands can actually tell use to do. + + struct sed_command { - // Doubly linked list of commands. - struct sed_command *next, *prev; + // double_list compatibility (easier to create in-order) + struct sed_command *next, *prev; - // Regexes for s/match/data/ and /match_begin/,/match_end/command - regex_t *match, *match_begin, *match_end; + // data string for (saicytb) + char c, *data; + // Regexes for s/match/data/ and /begin/,/end/command + regex_t *match, *begin, *end; + // For numeric ranges ala 10,20command + long lstart, lstop; + // Which match to replace, 0 for all. s and w commands can write to a file + int which, outfd; +}; - // For numeric ranges ala 10,20command - int first_line, last_line; +// Space. Space. Gotta get past space. Spaaaaaaaace! (But not newline.) +void spaceorb(char **s) +{ + while (**s == ' ' || **s == '\t') *s++; +} - // Which match to replace, 0 for all. - int which; +void parse_scripts(void) +{ + struct sed_command *commands = 0; + struct arg_list *script; + int which = 0; + long l; - // s and w commands can write to a file. Slight optimization: we use 0 - // instead of -1 to mean no file here, because even when there's no stdin - // our input file would take fd 0. - int outfd; + for (script = TT.scripts; *script; script = script->next) { + char *str = script->arg, *s; + struct sed_command *cmd; - // Data string for (saicytb) - char *data; + which++; + for (i=1;;) { + if (!*str) break; - // Which command letter is this? - char command; -}; + cmd = xzalloc(sizeof(struct sed_command)); + + // Identify prefix + for (;;) { + long l; + + spaceorb(&str); + if (*str == '$') { + l = -1; + str++; + } else if (isdigit(*str)) l = strtol(str, &str, 10); + else if (!cmd->lstart) break; + else goto parse_fail; + + spaceorb(&str); + if (!cmd->lstart) { + if (!l) goto parse_fail; + cmd->lstart = l; + if (*str != ',') break; + str++; + continue; + } + cmd->lstop = l; + break; + } else if (*str == '/') { + printf("regex\n"); + } + l = stridx("{bcdDgGhHlnNpPstwxyrqia= \t#:}", *str); + if (l == -1) goto parse_fail; + + + } + } + + return; + +parse_fail: + error_exit("bad expression %d@%d: %s", which, i, script->arg+i); +} void sed_main(void) { - struct arg_list *test; + char **files=toys.optargs; + + // If no -e, use first argument + if (!TT.scripts) { + if (!*files) error_exit("Need script"); + (TT.scripts=xzalloc(sizeof(struct arg_list)))->arg=*(files++); + } + - for (test = TT.commands; test; test = test->next) - dprintf(2,"command=%s\n",test->arg); + { + struct arg_list *test; - printf("Hello world\n"); + for (test = TT.commands; test; test = test->next) + dprintf(2,"command=%s\n",test->arg); + while (*files) dprintf(2,"file=%s\n", *(files++)); + } } diff --git a/toys/posix/sh.c b/toys/posix/sh.c index 44c39119..30900b30 100644 --- a/toys/posix/sh.c +++ b/toys/posix/sh.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sh.c - toybox shell +/* sh.c - toybox shell * * Copyright 2006 Rob Landley <rob@landley.net> * @@ -30,157 +28,157 @@ USE_SH(NEWTOY(sh, "c:i", TOYFLAG_BIN)) USE_SH(OLDTOY(toysh, sh, "c:i", TOYFLAG_BIN)) config SH - bool "sh (toysh)" - default n - help - usage: sh [-c command] [script] + bool "sh (toysh)" + default n + help + usage: sh [-c command] [script] - Command shell. Runs a shell script, or reads input interactively - and responds to it. + Command shell. Runs a shell script, or reads input interactively + and responds to it. - -c command line to execute + -c command line to execute config SH_TTY - bool "Interactive shell (terminal control)" - default n - depends on SH - help - Add terminal control to toysh. This is necessary for interactive use, - so the shell isn't killed by CTRL-C. + bool "Interactive shell (terminal control)" + default n + depends on SH + help + Add terminal control to toysh. This is necessary for interactive use, + so the shell isn't killed by CTRL-C. config SH_PROFILE - bool "Profile support" - default n - depends on SH_TTY - help - Read /etc/profile and ~/.profile when running interactively. + bool "Profile support" + default n + depends on SH_TTY + help + Read /etc/profile and ~/.profile when running interactively. - Also enables the built-in command "source". + Also enables the built-in command "source". config SH_JOBCTL - bool "Job Control (fg, bg, jobs)" - default n - depends on SH_TTY - help - Add job control to toysh. This lets toysh handle CTRL-Z, and enables - the built-in commands "fg", "bg", and "jobs". + bool "Job Control (fg, bg, jobs)" + default n + depends on SH_TTY + help + Add job control to toysh. This lets toysh handle CTRL-Z, and enables + the built-in commands "fg", "bg", and "jobs". - With pipe support, enable use of "&" to run background processes. + With pipe support, enable use of "&" to run background processes. config SH_FLOWCTL - bool "Flow control (if, while, for, functions)" - default n - depends on SH - help - Add flow control to toysh. This enables the if/then/else/fi, - while/do/done, and for/do/done constructs. + bool "Flow control (if, while, for, functions)" + default n + depends on SH + help + Add flow control to toysh. This enables the if/then/else/fi, + while/do/done, and for/do/done constructs. - With pipe support, this enables the ability to define functions - using the "function name" or "name()" syntax, plus curly brackets - "{ }" to group commands. + With pipe support, this enables the ability to define functions + using the "function name" or "name()" syntax, plus curly brackets + "{ }" to group commands. config SH_QUOTES - bool "Smarter argument parsing (quotes)" - default n - depends on SH - help - Add support for parsing "" and '' style quotes to the toysh command - parser, with lets arguments have spaces in them. + bool "Smarter argument parsing (quotes)" + default n + depends on SH + help + Add support for parsing "" and '' style quotes to the toysh command + parser, with lets arguments have spaces in them. config SH_WILDCARDS - bool "Wildcards ( ?*{,} )" - default n - depends on SH_QUOTES - help - Expand wildcards in argument names, ala "ls -l *.t?z" and - "rm subdir/{one,two,three}.txt". + bool "Wildcards ( ?*{,} )" + default n + depends on SH_QUOTES + help + Expand wildcards in argument names, ala "ls -l *.t?z" and + "rm subdir/{one,two,three}.txt". config SH_PROCARGS - bool "Executable arguments ( `` and $() )" - default n - depends on SH_QUOTES - help - Add support for executing arguments contianing $() and ``, using - the output of the command as the new argument value(s). + bool "Executable arguments ( `` and $() )" + default n + depends on SH_QUOTES + help + Add support for executing arguments contianing $() and ``, using + the output of the command as the new argument value(s). - (Bash calls this "command substitution".) + (Bash calls this "command substitution".) config SH_ENVVARS - bool "Environment variable support" - default n - depends on SH_QUOTES - help - Substitute environment variable values for $VARNAME or ${VARNAME}, - and enable the built-in command "export". + bool "Environment variable support" + default n + depends on SH_QUOTES + help + Substitute environment variable values for $VARNAME or ${VARNAME}, + and enable the built-in command "export". config SH_LOCALS - bool "Local variables" - default n - depends on SH_ENVVARS - help - Support for local variables, fancy prompts ($PS1), the "set" command, - and $?. + bool "Local variables" + default n + depends on SH_ENVVARS + help + Support for local variables, fancy prompts ($PS1), the "set" command, + and $?. config SH_ARRAYS - bool "Array variables" - default n - depends on SH_LOCALS - help - Support for ${blah[blah]} style array variables. + bool "Array variables" + default n + depends on SH_LOCALS + help + Support for ${blah[blah]} style array variables. config SH_PIPES - bool "Pipes and redirects ( | > >> < << & && | || () ; )" - default n - depends on SH - help - Support multiple commands on the same command line. This includes - | pipes, > >> < redirects, << here documents, || && conditional - execution, () subshells, ; sequential execution, and (with job - control) & background processes. + bool "Pipes and redirects ( | > >> < << & && | || () ; )" + default n + depends on SH + help + Support multiple commands on the same command line. This includes + | pipes, > >> < redirects, << here documents, || && conditional + execution, () subshells, ; sequential execution, and (with job + control) & background processes. config SH_BUILTINS - bool "Builtin commands" - default n - depends on SH - help - Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set, - unset, read, alias. + bool "Builtin commands" + default n + depends on SH + help + Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set, + unset, read, alias. config EXIT - bool - default n - depends on SH - help - usage: exit [status] + bool + default n + depends on SH + help + usage: exit [status] - Exit shell. If no return value supplied on command line, use value - of most recent command, or 0 if none. + Exit shell. If no return value supplied on command line, use value + of most recent command, or 0 if none. config CD - bool - default n - depends on SH - help - usage: cd [path] + bool + default n + depends on SH + help + usage: cd [path] - Change current directory. With no arguments, go to $HOME. + Change current directory. With no arguments, go to $HOME. config CD_P - bool # "-P support for cd" - default n - depends on SH - help - usage: cd [-PL] - - -P Physical path: resolve symlinks in path. - -L Cancel previous -P and restore default behavior. + bool # "-P support for cd" + default n + depends on SH + help + usage: cd [-PL] + + -P Physical path: resolve symlinks in path. + -L Cancel previous -P and restore default behavior. */ #define FOR_sh #include "toys.h" GLOBALS( - char *command; + char *command; ) // A single executable, its arguments, and other information we know about it. @@ -195,20 +193,20 @@ GLOBALS( // What we know about a single process. struct command { - struct command *next; - int flags; // exit, suspend, && || - int pid; // pid (or exit code) - int argc; - char *argv[0]; + struct command *next; + int flags; // exit, suspend, && || + int pid; // pid (or exit code) + int argc; + char *argv[0]; }; // A collection of processes piped into/waiting on each other. struct pipeline { - struct pipeline *next; - int job_id; - struct command *cmd; - char *cmdline; // Unparsed line for display purposes - int cmdlinelen; // How long is cmdline? + struct pipeline *next; + int job_id; + struct command *cmd; + char *cmdline; // Unparsed line for display purposes + int cmdlinelen; // How long is cmdline? }; // Parse one word from the command line, appending one or more argv[] entries @@ -217,23 +215,23 @@ struct pipeline { // hit an ending token. static char *parse_word(char *start, struct command **cmd) { - char *end; + char *end; - // Detect end of line (and truncate line at comment) - if (CFG_SH_PIPES && strchr("><&|(;", *start)) return 0; + // Detect end of line (and truncate line at comment) + if (CFG_SH_PIPES && strchr("><&|(;", *start)) return 0; - // Grab next word. (Add dequote and envvar logic here) - end = start; - while (*end && !isspace(*end)) end++; - (*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start); + // Grab next word. (Add dequote and envvar logic here) + end = start; + while (*end && !isspace(*end)) end++; + (*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start); - // Allocate more space if there's no room for NULL terminator. + // Allocate more space if there's no room for NULL terminator. - if (!((*cmd)->argc & 7)) - *cmd=xrealloc(*cmd, - sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *)); - (*cmd)->argv[(*cmd)->argc] = 0; - return end; + if (!((*cmd)->argc & 7)) + *cmd=xrealloc(*cmd, + sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *)); + (*cmd)->argv[(*cmd)->argc] = 0; + return end; } // Parse a line of text into a pipeline. @@ -241,149 +239,149 @@ static char *parse_word(char *start, struct command **cmd) static char *parse_pipeline(char *cmdline, struct pipeline *line) { - struct command **cmd = &(line->cmd); - char *start = line->cmdline = cmdline; - - if (!cmdline) return 0; - - if (CFG_SH_JOBCTL) line->cmdline = cmdline; - - // Parse command into argv[] - for (;;) { - char *end; - - // Skip leading whitespace and detect end of line. - while (isspace(*start)) start++; - if (!*start || *start=='#') { - if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; - return 0; - } - - // Allocate next command structure if necessary - if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *)); - - // Parse next argument and add the results to argv[] - end = parse_word(start, cmd); - - // If we hit the end of this command, how did it end? - if (!end) { - if (CFG_SH_PIPES && *start) { - if (*start==';') { - start++; - break; - } - // handle | & < > >> << || && - } - break; - } - start = end; - } - - if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; - - return start; + struct command **cmd = &(line->cmd); + char *start = line->cmdline = cmdline; + + if (!cmdline) return 0; + + if (CFG_SH_JOBCTL) line->cmdline = cmdline; + + // Parse command into argv[] + for (;;) { + char *end; + + // Skip leading whitespace and detect end of line. + while (isspace(*start)) start++; + if (!*start || *start=='#') { + if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; + return 0; + } + + // Allocate next command structure if necessary + if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *)); + + // Parse next argument and add the results to argv[] + end = parse_word(start, cmd); + + // If we hit the end of this command, how did it end? + if (!end) { + if (CFG_SH_PIPES && *start) { + if (*start==';') { + start++; + break; + } + // handle | & < > >> << || && + } + break; + } + start = end; + } + + if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; + + return start; } // Execute the commands in a pipeline static void run_pipeline(struct pipeline *line) { - struct toy_list *tl; - struct command *cmd = line->cmd; - if (!cmd || !cmd->argc) return; - - tl = toy_find(cmd->argv[0]); - // Is this command a builtin that should run in this process? - if (tl && (tl->flags & TOYFLAG_NOFORK)) { - struct toy_context temp; - - // This fakes lots of what toybox_main() does. - memcpy(&temp, &toys, sizeof(struct toy_context)); - memset(&toys, 0, sizeof(struct toy_context)); - toy_init(tl, cmd->argv); - tl->toy_main(); - cmd->pid = toys.exitval; - free(toys.optargs); - if (toys.old_umask) umask(toys.old_umask); - memcpy(&toys, &temp, sizeof(struct toy_context)); - } else { - int status; - - cmd->pid = vfork(); - if (!cmd->pid) xexec(cmd->argv); - else waitpid(cmd->pid, &status, 0); - - if (CFG_SH_FLOWCTL || CFG_SH_PIPES) { - if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status); - if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status); - } - } - - return; + struct toy_list *tl; + struct command *cmd = line->cmd; + if (!cmd || !cmd->argc) return; + + tl = toy_find(cmd->argv[0]); + // Is this command a builtin that should run in this process? + if (tl && (tl->flags & TOYFLAG_NOFORK)) { + struct toy_context temp; + + // This fakes lots of what toybox_main() does. + memcpy(&temp, &toys, sizeof(struct toy_context)); + memset(&toys, 0, sizeof(struct toy_context)); + toy_init(tl, cmd->argv); + tl->toy_main(); + cmd->pid = toys.exitval; + free(toys.optargs); + if (toys.old_umask) umask(toys.old_umask); + memcpy(&toys, &temp, sizeof(struct toy_context)); + } else { + int status; + + cmd->pid = vfork(); + if (!cmd->pid) xexec(cmd->argv); + else waitpid(cmd->pid, &status, 0); + + if (CFG_SH_FLOWCTL || CFG_SH_PIPES) { + if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status); + if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status); + } + } + + return; } // Free the contents of a command structure static void free_cmd(void *data) { - struct command *cmd=(struct command *)data; + struct command *cmd=(struct command *)data; - while(cmd->argc) free(cmd->argv[--cmd->argc]); + while(cmd->argc) free(cmd->argv[--cmd->argc]); } // Parse a command line and do what it says to do. static void handle(char *command) { - struct pipeline line; - char *start = command; + struct pipeline line; + char *start = command; - // Loop through commands in this line + // Loop through commands in this line - for (;;) { + for (;;) { - // Parse a group of connected commands + // Parse a group of connected commands - memset(&line,0,sizeof(struct pipeline)); - start = parse_pipeline(start, &line); - if (!line.cmd) break; + memset(&line,0,sizeof(struct pipeline)); + start = parse_pipeline(start, &line); + if (!line.cmd) break; - // Run those commands + // Run those commands - run_pipeline(&line); - llist_traverse(line.cmd, free_cmd); - } + run_pipeline(&line); + llist_traverse(line.cmd, free_cmd); + } } void cd_main(void) { - char *dest = *toys.optargs ? *toys.optargs : getenv("HOME"); - xchdir(dest); + char *dest = *toys.optargs ? *toys.optargs : getenv("HOME"); + xchdir(dest); } void exit_main(void) { - exit(*toys.optargs ? atoi(*toys.optargs) : 0); + exit(*toys.optargs ? atoi(*toys.optargs) : 0); } void sh_main(void) { - FILE *f; - - // Set up signal handlers and grab control of this tty. - if (CFG_SH_TTY) { - if (isatty(0)) toys.optflags |= 1; - } - f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL; - if (TT.command) handle(TT.command); - else { - size_t cmdlen = 0; - for (;;) { - char *command = 0; - if (!f) xputc('$'); - if (1 > getline(&command, &cmdlen, f ? f : stdin)) break; - handle(command); - free(command); - } - } - - toys.exitval = 1; + FILE *f; + + // Set up signal handlers and grab control of this tty. + if (CFG_SH_TTY) { + if (isatty(0)) toys.optflags |= 1; + } + f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL; + if (TT.command) handle(TT.command); + else { + size_t cmdlen = 0; + for (;;) { + char *command = 0; + if (!f) xputc('$'); + if (1 > getline(&command, &cmdlen, f ? f : stdin)) break; + handle(command); + free(command); + } + } + + toys.exitval = 1; } diff --git a/toys/posix/sleep.c b/toys/posix/sleep.c index c544e0ac..a83f1e56 100644 --- a/toys/posix/sleep.c +++ b/toys/posix/sleep.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sleep.c - Wait for a number of seconds. +/* sleep.c - Wait for a number of seconds. * * Copyright 2007 Rob Landley <rob@landley.net> * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> @@ -10,20 +8,20 @@ USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN)) config SLEEP - bool "sleep" - default y - help - usage: sleep SECONDS + bool "sleep" + default y + help + usage: sleep SECONDS - Wait before exiting. + Wait before exiting. config SLEEP_FLOAT - bool - default y - depends on SLEEP && TOYBOX_FLOAT - help - The delay can be a decimal fraction. An optional suffix can be "m" - (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). + bool + default y + depends on SLEEP && TOYBOX_FLOAT + help + The delay can be a decimal fraction. An optional suffix can be "m" + (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). */ #include "toys.h" @@ -31,21 +29,21 @@ config SLEEP_FLOAT void sleep_main(void) { - if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs)); - else { - char *arg; - double d = strtod(*toys.optargs, &arg); - struct timespec tv; - - // Parse suffix - if (*arg) { - int ismhd[]={1,60,3600,86400}; - char *smhd = "smhd", *c = strchr(smhd, *arg); - if (!c) error_exit("Unknown suffix '%c'", *arg); - d *= ismhd[c-smhd]; - } - - tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d)); - toys.exitval = !!nanosleep(&tv, NULL); - } + if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs)); + else { + char *arg; + double d = strtod(*toys.optargs, &arg); + struct timespec tv; + + // Parse suffix + if (*arg) { + int ismhd[]={1,60,3600,86400}; + char *smhd = "smhd", *c = strchr(smhd, *arg); + if (!c) error_exit("Unknown suffix '%c'", *arg); + d *= ismhd[c-smhd]; + } + + tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d)); + toys.exitval = !!nanosleep(&tv, NULL); + } } diff --git a/toys/posix/sort.c b/toys/posix/sort.c index 8f26f5d3..41b020b9 100644 --- a/toys/posix/sort.c +++ b/toys/posix/sort.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sort.c - put input lines into order +/* sort.c - put input lines into order * * Copyright 2004, 2008 Rob Landley <rob@landley.net> * @@ -9,54 +7,54 @@ USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")USE_SORT_BIG("S:T:m" "o:k*t:xbMcszdfi") "run", TOYFLAG_USR|TOYFLAG_BIN)) config SORT - bool "sort" - default y - help - usage: sort [-run] [FILE...] + bool "sort" + default y + help + usage: sort [-run] [FILE...] - Sort all lines of text from input files (or stdin) to stdout. + Sort all lines of text from input files (or stdin) to stdout. - -r reverse - -u unique lines only - -n numeric order (instead of alphabetical) + -r reverse + -u unique lines only + -n numeric order (instead of alphabetical) config SORT_BIG - bool "SuSv3 options (Support -ktcsbdfiozM)" - default y - depends on SORT - help - usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE] - - -b ignore leading blanks (or trailing blanks in second part of key) - -c check whether input is sorted - -d dictionary order (use alphanumeric and whitespace chars only) - -f force uppercase (case insensitive sort) - -i ignore nonprinting characters - -M month sort (jan, feb, etc). - -x Hexadecimal numerical sort - -s skip fallback sort (only sort with keys) - -z zero (null) terminated input - -k sort by "key" (see below) - -t use a key separator other than whitespace - -o output to FILE instead of stdout - - Sorting by key looks at a subset of the words on each line. -k2 - uses the second word to the end of the line, -k2,2 looks at only - the second word, -k2,4 looks from the start of the second to the end - of the fourth word. Specifying multiple keys uses the later keys as - tie breakers, in order. A type specifier appended to a sort key - (such as -2,2n) applies only to sorting that key. + bool "SuSv3 options (Support -ktcsbdfiozM)" + default y + depends on SORT + help + usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE] + + -b ignore leading blanks (or trailing blanks in second part of key) + -c check whether input is sorted + -d dictionary order (use alphanumeric and whitespace chars only) + -f force uppercase (case insensitive sort) + -i ignore nonprinting characters + -M month sort (jan, feb, etc). + -x Hexadecimal numerical sort + -s skip fallback sort (only sort with keys) + -z zero (null) terminated input + -k sort by "key" (see below) + -t use a key separator other than whitespace + -o output to FILE instead of stdout + + Sorting by key looks at a subset of the words on each line. -k2 + uses the second word to the end of the line, -k2,2 looks at only + the second word, -k2,4 looks from the start of the second to the end + of the fourth word. Specifying multiple keys uses the later keys as + tie breakers, in order. A type specifier appended to a sort key + (such as -2,2n) applies only to sorting that key. config SORT_FLOAT - bool "Floating point (-g)" - default y - depends on SORT_BIG - help - usage: sort [-g] + bool "Floating point (-g)" + default y + depends on SORT_BIG + help + usage: sort [-g] - This version of sort requires floating point. + This version of sort requires floating point. - -g general numeric sort (double precision with nan and inf) + -g general numeric sort (double precision with nan and inf) */ @@ -64,14 +62,14 @@ config SORT_FLOAT #include "toys.h" GLOBALS( - char *key_separator; - struct arg_list *raw_keys; - char *outfile; - char *ignore1, ignore2; // GNU compatability NOPs for -S and -T. - - void *key_list; - int linecount; - char **lines; + char *key_separator; + struct arg_list *raw_keys; + char *outfile; + char *ignore1, ignore2; // GNU compatability NOPs for -S and -T. + + void *key_list; + int linecount; + char **lines; ) // The sort types are n, g, and M. @@ -83,321 +81,320 @@ GLOBALS( struct sort_key { - struct sort_key *next_key; // linked list - unsigned range[4]; // start word, start char, end word, end char - int flags; + struct sort_key *next_key; // linked list + unsigned range[4]; // start word, start char, end word, end char + int flags; }; // Copy of the part of this string corresponding to a key/flags. static char *get_key_data(char *str, struct sort_key *key, int flags) { - int start=0, end, len, i, j; + int start=0, end, len, i, j; - // Special case whole string, so we don't have to make a copy + // Special case whole string, so we don't have to make a copy - if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] - && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; + if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] + && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; - // Find start of key on first pass, end on second pass + // Find start of key on first pass, end on second pass - len = strlen(str); - for (j=0; j<2; j++) { - if (!key->range[2*j]) end=len; + len = strlen(str); + for (j=0; j<2; j++) { + if (!key->range[2*j]) end=len; - // Loop through fields - else { - end=0; - for (i=1; i < key->range[2*j]+j; i++) { + // Loop through fields + else { + end=0; + for (i=1; i < key->range[2*j]+j; i++) { - // Skip leading blanks - if (str[end] && !TT.key_separator) - while (isspace(str[end])) end++; + // Skip leading blanks + if (str[end] && !TT.key_separator) + while (isspace(str[end])) end++; - // Skip body of key - for (; str[end]; end++) { - if (TT.key_separator) { - if (str[end]==*TT.key_separator) break; - } else if (isspace(str[end])) break; - } - } + // Skip body of key + for (; str[end]; end++) { + if (TT.key_separator) { + if (str[end]==*TT.key_separator) break; + } else if (isspace(str[end])) break; } - if (!j) start=end; - } - - // Key with explicit separator starts after the separator - if (TT.key_separator && str[start]==*TT.key_separator) start++; - - // Strip leading and trailing whitespace if necessary - if (flags&FLAG_b) while (isspace(str[start])) start++; - if (flags&FLAG_bb) while (end>start && isspace(str[end-1])) end--; - - // Handle offsets on start and end - if (key->range[3]) { - end += key->range[3]-1; - if (end>len) end=len; - } - if (key->range[1]) { - start += key->range[1]-1; - if (start>len) start=len; - } - - // Make the copy - if (end<start) end=start; - str = xstrndup(str+start, end-start); - - // Handle -d - if (flags&FLAG_d) { - for (start = end = 0; str[end]; end++) - if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end]; - str[start] = 0; - } - - // Handle -i - if (flags&FLAG_i) { - for (start = end = 0; str[end]; end++) - if (isprint(str[end])) str[start++] = str[end]; - str[start] = 0; + } } - - // Handle -f - if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]); - - return str; + if (!j) start=end; + } + + // Key with explicit separator starts after the separator + if (TT.key_separator && str[start]==*TT.key_separator) start++; + + // Strip leading and trailing whitespace if necessary + if (flags&FLAG_b) while (isspace(str[start])) start++; + if (flags&FLAG_bb) while (end>start && isspace(str[end-1])) end--; + + // Handle offsets on start and end + if (key->range[3]) { + end += key->range[3]-1; + if (end>len) end=len; + } + if (key->range[1]) { + start += key->range[1]-1; + if (start>len) start=len; + } + + // Make the copy + if (end<start) end=start; + str = xstrndup(str+start, end-start); + + // Handle -d + if (flags&FLAG_d) { + for (start = end = 0; str[end]; end++) + if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end]; + str[start] = 0; + } + + // Handle -i + if (flags&FLAG_i) { + for (start = end = 0; str[end]; end++) + if (isprint(str[end])) str[start++] = str[end]; + str[start] = 0; + } + + // Handle -f + if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]); + + return str; } // append a sort_key to key_list. static struct sort_key *add_key(void) { - void **stupid_compiler = &TT.key_list; - struct sort_key **pkey = (struct sort_key **)stupid_compiler; + void **stupid_compiler = &TT.key_list; + struct sort_key **pkey = (struct sort_key **)stupid_compiler; - while (*pkey) pkey = &((*pkey)->next_key); - return *pkey = xzalloc(sizeof(struct sort_key)); + while (*pkey) pkey = &((*pkey)->next_key); + return *pkey = xzalloc(sizeof(struct sort_key)); } // Perform actual comparison static int compare_values(int flags, char *x, char *y) { - int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x); - - // Ascii sort - if (!ff) return strcmp(x, y); + int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x); - if (CFG_SORT_FLOAT && ff == FLAG_g) { - char *xx,*yy; - double dx = strtod(x,&xx), dy = strtod(y,&yy); - int xinf, yinf; + // Ascii sort + if (!ff) return strcmp(x, y); - // not numbers < NaN < -infinity < numbers < +infinity + if (CFG_SORT_FLOAT && ff == FLAG_g) { + char *xx,*yy; + double dx = strtod(x,&xx), dy = strtod(y,&yy); + int xinf, yinf; - if (x==xx) return y==yy ? 0 : -1; - if (y==yy) return 1; + // not numbers < NaN < -infinity < numbers < +infinity - // Check for isnan - if (dx!=dx) return (dy!=dy) ? 0 : -1; - if (dy!=dy) return 1; + if (x==xx) return y==yy ? 0 : -1; + if (y==yy) return 1; - // Check for infinity. (Could underflow, but avoids needing libm.) - xinf = (1.0/dx == 0.0); - yinf = (1.0/dy == 0.0); - if (xinf) { - if(dx<0) return (yinf && dy<0) ? 0 : -1; - return (yinf && dy>0) ? 0 : 1; - } - if (yinf) return dy<0 ? 1 : -1; - - return dx>dy ? 1 : (dx<dy ? -1 : 0); - } else if (CFG_SORT_BIG && ff == FLAG_M) { - struct tm thyme; - int dx; - char *xx,*yy; - - xx = strptime(x,"%b",&thyme); - dx = thyme.tm_mon; - yy = strptime(y,"%b",&thyme); - if (!xx) return !yy ? 0 : -1; - else if (!yy) return 1; - else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon; - - } else if (CFG_SORT_BIG && ff == FLAG_x) { - return strtol(x, NULL, 16)-strtol(y, NULL, 16); - // This has to be ff == FLAG_n - } else { - // Full floating point version of -n - if (CFG_SORT_FLOAT) { - double dx = atof(x), dy = atof(y); + // Check for isnan + if (dx!=dx) return (dy!=dy) ? 0 : -1; + if (dy!=dy) return 1; - return dx>dy ? 1 : (dx<dy ? -1 : 0); - // Integer version of -n for tiny systems - } else return atoi(x)-atoi(y); + // Check for infinity. (Could underflow, but avoids needing libm.) + xinf = (1.0/dx == 0.0); + yinf = (1.0/dy == 0.0); + if (xinf) { + if(dx<0) return (yinf && dy<0) ? 0 : -1; + return (yinf && dy>0) ? 0 : 1; } + if (yinf) return dy<0 ? 1 : -1; + + return dx>dy ? 1 : (dx<dy ? -1 : 0); + } else if (CFG_SORT_BIG && ff == FLAG_M) { + struct tm thyme; + int dx; + char *xx,*yy; + + xx = strptime(x,"%b",&thyme); + dx = thyme.tm_mon; + yy = strptime(y,"%b",&thyme); + if (!xx) return !yy ? 0 : -1; + else if (!yy) return 1; + else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon; + + } else if (CFG_SORT_BIG && ff == FLAG_x) { + return strtol(x, NULL, 16)-strtol(y, NULL, 16); + // This has to be ff == FLAG_n + } else { + // Full floating point version of -n + if (CFG_SORT_FLOAT) { + double dx = atof(x), dy = atof(y); + + return dx>dy ? 1 : (dx<dy ? -1 : 0); + // Integer version of -n for tiny systems + } else return atoi(x)-atoi(y); + } } - // Callback from qsort(): Iterate through key_list and perform comparisons. static int compare_keys(const void *xarg, const void *yarg) { - int flags = toys.optflags, retval = 0; - char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg; - struct sort_key *key; - - if (CFG_SORT_BIG) { - for (key=(struct sort_key *)TT.key_list; !retval && key; - key = key->next_key) - { - flags = key->flags ? key->flags : toys.optflags; + int flags = toys.optflags, retval = 0; + char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg; + struct sort_key *key; - // Chop out and modify key chunks, handling -dfib + if (CFG_SORT_BIG) { + for (key=(struct sort_key *)TT.key_list; !retval && key; + key = key->next_key) + { + flags = key->flags ? key->flags : toys.optflags; - x = get_key_data(xx, key, flags); - y = get_key_data(yy, key, flags); + // Chop out and modify key chunks, handling -dfib - retval = compare_values(flags, x, y); + x = get_key_data(xx, key, flags); + y = get_key_data(yy, key, flags); - // Free the copies get_key_data() made. + retval = compare_values(flags, x, y); - if (x != xx) free(x); - if (y != yy) free(y); + // Free the copies get_key_data() made. - if (retval) break; - } - } else retval = compare_values(flags, xx, yy); + if (x != xx) free(x); + if (y != yy) free(y); - // Perform fallback sort if necessary - if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) { - retval = strcmp(xx, yy); - flags = toys.optflags; + if (retval) break; } + } else retval = compare_values(flags, xx, yy); + + // Perform fallback sort if necessary + if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) { + retval = strcmp(xx, yy); + flags = toys.optflags; + } - return retval * ((flags&FLAG_r) ? -1 : 1); + return retval * ((flags&FLAG_r) ? -1 : 1); } // Callback from loopfiles to handle input files. static void sort_read(int fd, char *name) { - // Read each line from file, appending to a big array. - - for (;;) { - char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z)) - ? get_rawline(fd, NULL, 0) : get_line(fd); - - if (!line) break; - - // handle -c here so we don't allocate more memory than necessary. - if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) { - int j = (toys.optflags&FLAG_u) ? -1 : 0; - - if (TT.lines && compare_keys((void *)&TT.lines, &line)>j) - error_exit("%s: Check line %d\n", name, TT.linecount); - free(TT.lines); - TT.lines = (char **)line; - } else { - if (!(TT.linecount&63)) - TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64)); - TT.lines[TT.linecount] = line; - } - TT.linecount++; + // Read each line from file, appending to a big array. + + for (;;) { + char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z)) + ? get_rawline(fd, NULL, 0) : get_line(fd); + + if (!line) break; + + // handle -c here so we don't allocate more memory than necessary. + if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) { + int j = (toys.optflags&FLAG_u) ? -1 : 0; + + if (TT.lines && compare_keys((void *)&TT.lines, &line)>j) + error_exit("%s: Check line %d\n", name, TT.linecount); + free(TT.lines); + TT.lines = (char **)line; + } else { + if (!(TT.linecount&63)) + TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64)); + TT.lines[TT.linecount] = line; } + TT.linecount++; + } } void sort_main(void) { - int idx, fd = 1; - - // Open output file if necessary. - if (CFG_SORT_BIG && TT.outfile) - fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); - - // Parse -k sort keys. - if (CFG_SORT_BIG && TT.raw_keys) { - struct arg_list *arg; - - for (arg = TT.raw_keys; arg; arg = arg->next) { - struct sort_key *key = add_key(); - char *temp; - int flag; - - idx = 0; - temp = arg->arg; - while (*temp) { - // Start of range - key->range[2*idx] = (unsigned)strtol(temp, &temp, 10); - if (*temp=='.') - key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10); - - // Handle flags appended to a key type. - for (;*temp;temp++) { - char *temp2, *optlist; - - // Note that a second comma becomes an "Unknown key" error. - - if (*temp==',' && !idx++) { - temp++; - break; - } - - // Which flag is this? - - optlist = toys.which->options; - temp2 = strchr(optlist, *temp); - flag = (1<<(optlist-temp2+strlen(optlist)-1)); - - // Was it a flag that can apply to a key? - - if (!temp2 || flag>FLAG_b - || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) - { - error_exit("Unknown key option."); - } - // b after , means strip _trailing_ space, not leading. - if (idx && flag==FLAG_b) flag = FLAG_bb; - key->flags |= flag; - } - } + int idx, fd = 1; + + // Open output file if necessary. + if (CFG_SORT_BIG && TT.outfile) + fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); + + // Parse -k sort keys. + if (CFG_SORT_BIG && TT.raw_keys) { + struct arg_list *arg; + + for (arg = TT.raw_keys; arg; arg = arg->next) { + struct sort_key *key = add_key(); + char *temp; + int flag; + + idx = 0; + temp = arg->arg; + while (*temp) { + // Start of range + key->range[2*idx] = (unsigned)strtol(temp, &temp, 10); + if (*temp=='.') + key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10); + + // Handle flags appended to a key type. + for (;*temp;temp++) { + char *temp2, *optlist; + + // Note that a second comma becomes an "Unknown key" error. + + if (*temp==',' && !idx++) { + temp++; + break; + } + + // Which flag is this? + + optlist = toys.which->options; + temp2 = strchr(optlist, *temp); + flag = (1<<(optlist-temp2+strlen(optlist)-1)); + + // Was it a flag that can apply to a key? + + if (!temp2 || flag>FLAG_b + || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) + { + error_exit("Unknown key option."); + } + // b after , means strip _trailing_ space, not leading. + if (idx && flag==FLAG_b) flag = FLAG_bb; + key->flags |= flag; } + } } + } - // global b flag strips both leading and trailing spaces - if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb; + // global b flag strips both leading and trailing spaces + if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb; - // If no keys, perform alphabetic sort over the whole line. - if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1; + // If no keys, perform alphabetic sort over the whole line. + if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1; - // Open input files and read data, populating TT.lines[TT.linecount] - loopfiles(toys.optargs, sort_read); + // Open input files and read data, populating TT.lines[TT.linecount] + loopfiles(toys.optargs, sort_read); - // The compare (-c) logic was handled in sort_read(), - // so if we got here, we're done. - if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now; + // The compare (-c) logic was handled in sort_read(), + // so if we got here, we're done. + if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now; - // Perform the actual sort - qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys); + // Perform the actual sort + qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys); - // handle unique (-u) - if (toys.optflags&FLAG_u) { - int jdx; + // handle unique (-u) + if (toys.optflags&FLAG_u) { + int jdx; - for (jdx=0, idx=1; idx<TT.linecount; idx++) { - if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) - free(TT.lines[idx]); - else TT.lines[++jdx] = TT.lines[idx]; - } - if (TT.linecount) TT.linecount = jdx+1; + for (jdx=0, idx=1; idx<TT.linecount; idx++) { + if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) + free(TT.lines[idx]); + else TT.lines[++jdx] = TT.lines[idx]; } + if (TT.linecount) TT.linecount = jdx+1; + } - // Output result - for (idx = 0; idx<TT.linecount; idx++) { - char *s = TT.lines[idx]; - xwrite(fd, s, strlen(s)); - if (CFG_TOYBOX_FREE) free(s); - xwrite(fd, "\n", 1); - } + // Output result + for (idx = 0; idx<TT.linecount; idx++) { + char *s = TT.lines[idx]; + xwrite(fd, s, strlen(s)); + if (CFG_TOYBOX_FREE) free(s); + xwrite(fd, "\n", 1); + } exit_now: - if (CFG_TOYBOX_FREE) { - if (fd != 1) close(fd); - free(TT.lines); - } + if (CFG_TOYBOX_FREE) { + if (fd != 1) close(fd); + free(TT.lines); + } } diff --git a/toys/posix/tail.c b/toys/posix/tail.c index d0711c0c..bdbbfb30 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tail.c - copy last lines from input to stdout. +/* tail.c - copy last lines from input to stdout. * * Copyright 2012 Timothy Elliott <tle@holymonkey.com> * @@ -9,62 +7,62 @@ USE_TAIL(NEWTOY(tail, "fc-n-", TOYFLAG_BIN)) config TAIL - bool "tail" - default y - help - usage: tail [-n|c number] [-f] [file...] + bool "tail" + default y + help + usage: tail [-n|c number] [-f] [file...] - Copy last lines from files to stdout. If no files listed, copy from - stdin. Filename "-" is a synonym for stdin. + Copy last lines from files to stdout. If no files listed, copy from + stdin. Filename "-" is a synonym for stdin. - -n output the last X lines (default 10), +X counts from start. - -c output the last X bytes, +X counts from start - -f follow file, waiting for more data to be appended + -n output the last X lines (default 10), +X counts from start. + -c output the last X bytes, +X counts from start + -f follow file, waiting for more data to be appended config TAIL_SEEK - bool "tail seek support" - default y - depends on TAIL - help - This version uses lseek, which is faster on large files. + bool "tail seek support" + default y + depends on TAIL + help + This version uses lseek, which is faster on large files. */ #define FOR_tail #include "toys.h" GLOBALS( - long lines; - long bytes; + long lines; + long bytes; - int file_no; + int file_no; ) struct line_list { - struct line_list *next, *prev; - char *data; - int len; + struct line_list *next, *prev; + char *data; + int len; }; static struct line_list *get_chunk(int fd, int len) { - struct line_list *line = xmalloc(sizeof(struct line_list)+len); + struct line_list *line = xmalloc(sizeof(struct line_list)+len); - line->data = ((char *)line) + sizeof(struct line_list); - line->len = readall(fd, line->data, len); + line->data = ((char *)line) + sizeof(struct line_list); + line->len = readall(fd, line->data, len); - if (line->len < 1) { - free(line); - return 0; - } + if (line->len < 1) { + free(line); + return 0; + } - return line; + return line; } static void dump_chunk(void *ptr) { - struct line_list *list = ptr; - xwrite(1, list->data, list->len); - free(list); + struct line_list *list = ptr; + xwrite(1, list->data, list->len); + free(list); } // Reading through very large files is slow. Using lseek can speed things @@ -72,156 +70,156 @@ static void dump_chunk(void *ptr) // Note: bytes and lines are negative here. static int try_lseek(int fd, long bytes, long lines) { - struct line_list *list = 0, *temp; - int flag = 0, chunk = sizeof(toybuf); - ssize_t pos = lseek(fd, 0, SEEK_END); - - // If lseek() doesn't work on this stream, return now. - if (pos<0) return 0; - - // Seek to the right spot, output data from there. - if (bytes) { - if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET); - xsendfile(fd, 1); - return 1; - } - - // Read from end to find enough lines, then output them. - - bytes = pos; - while (lines && pos) { - int offset; - - // Read in next chunk from end of file - if (chunk>pos) chunk = pos; - pos -= chunk; - if (pos != lseek(fd, pos, SEEK_SET)) { - perror_msg("seek failed"); - break; - } - if (!(temp = get_chunk(fd, chunk))) break; - if (list) list->next = temp; - list = temp; - - // Count newlines in this chunk. - offset = list->len; - while (offset--) { - // If the last line ends with a newline, that one doesn't count. - if (!flag) { - flag++; - - continue; - } - - // Start outputting data right after newline - if (list->data[offset] == '\n' && !++lines) { - offset++; - list->data += offset; - list->len -= offset; - - break; - } - } - } - - // Output stored data - llist_traverse(list, dump_chunk); - - // In case of -f - lseek(fd, bytes, SEEK_SET); - return 1; + struct line_list *list = 0, *temp; + int flag = 0, chunk = sizeof(toybuf); + ssize_t pos = lseek(fd, 0, SEEK_END); + + // If lseek() doesn't work on this stream, return now. + if (pos<0) return 0; + + // Seek to the right spot, output data from there. + if (bytes) { + if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET); + xsendfile(fd, 1); + return 1; + } + + // Read from end to find enough lines, then output them. + + bytes = pos; + while (lines && pos) { + int offset; + + // Read in next chunk from end of file + if (chunk>pos) chunk = pos; + pos -= chunk; + if (pos != lseek(fd, pos, SEEK_SET)) { + perror_msg("seek failed"); + break; + } + if (!(temp = get_chunk(fd, chunk))) break; + if (list) list->next = temp; + list = temp; + + // Count newlines in this chunk. + offset = list->len; + while (offset--) { + // If the last line ends with a newline, that one doesn't count. + if (!flag) { + flag++; + + continue; + } + + // Start outputting data right after newline + if (list->data[offset] == '\n' && !++lines) { + offset++; + list->data += offset; + list->len -= offset; + + break; + } + } + } + + // Output stored data + llist_traverse(list, dump_chunk); + + // In case of -f + lseek(fd, bytes, SEEK_SET); + return 1; } // Called for each file listed on command line, and/or stdin static void do_tail(int fd, char *name) { - long bytes = TT.bytes, lines = TT.lines; - - if (toys.optc > 1) { - if (TT.file_no++) xputc('\n'); - xprintf("==> %s <==\n", name); - } - - // Are we measuring from the end of the file? - - if (bytes<0 || lines<0) { - struct line_list *list = 0, *new; - - // The slow codepath is always needed, and can handle all input, - // so make lseek support optional. - if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines)); - - // Read data until we run out, keep a trailing buffer - else for (;;) { - int len, count; - char *try; - - if (!(new = get_chunk(fd, sizeof(toybuf)))) break; - // append in order - dlist_add_nomalloc((struct double_list **)&list, - (struct double_list *)new); - - // Measure new chunk, discarding extra data from buffer - len = new->len; - try = new->data; - for (count=0; count<len; count++) { - if ((toys.optflags & FLAG_c) && bytes) { - bytes++; - continue; - } - - if (lines) { - if(try[count] != '\n' && count != len-1) continue; - if (lines<0) { - if (!++lines) ++lines; - continue; - } - } - - // Time to discard data; given that bytes and lines were - // nonzero coming in, we can't discard too much if we're - // measuring right. - do { - char c = *(list->data++); - if (!(--list->len)) { - struct line_list *next = list->next; - list->prev->next = next; - list->next->prev = list->prev; - free(list); - list = next; - } - if (c == '\n') break; - } while (lines); - } - } - - // Output/free the buffer. - llist_traverse(list, dump_chunk); - - // Measuring from the beginning of the file. - } else for (;;) { - int len, offset = 0; - - // Error while reading does not exit. Error writing does. - len = read(fd, toybuf, sizeof(toybuf)); - if (len<1) break; - while (bytes > 1 || lines > 1) { - bytes--; - if (toybuf[offset++] == '\n') lines--; - if (offset >= len) break; - } - if (offset<len) xwrite(1, toybuf+offset, len-offset); - } - - // -f support: cache name/descriptor + long bytes = TT.bytes, lines = TT.lines; + + if (toys.optc > 1) { + if (TT.file_no++) xputc('\n'); + xprintf("==> %s <==\n", name); + } + + // Are we measuring from the end of the file? + + if (bytes<0 || lines<0) { + struct line_list *list = 0, *new; + + // The slow codepath is always needed, and can handle all input, + // so make lseek support optional. + if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines)); + + // Read data until we run out, keep a trailing buffer + else for (;;) { + int len, count; + char *try; + + if (!(new = get_chunk(fd, sizeof(toybuf)))) break; + // append in order + dlist_add_nomalloc((struct double_list **)&list, + (struct double_list *)new); + + // Measure new chunk, discarding extra data from buffer + len = new->len; + try = new->data; + for (count=0; count<len; count++) { + if ((toys.optflags & FLAG_c) && bytes) { + bytes++; + continue; + } + + if (lines) { + if(try[count] != '\n' && count != len-1) continue; + if (lines<0) { + if (!++lines) ++lines; + continue; + } + } + + // Time to discard data; given that bytes and lines were + // nonzero coming in, we can't discard too much if we're + // measuring right. + do { + char c = *(list->data++); + if (!(--list->len)) { + struct line_list *next = list->next; + list->prev->next = next; + list->next->prev = list->prev; + free(list); + list = next; + } + if (c == '\n') break; + } while (lines); + } + } + + // Output/free the buffer. + llist_traverse(list, dump_chunk); + + // Measuring from the beginning of the file. + } else for (;;) { + int len, offset = 0; + + // Error while reading does not exit. Error writing does. + len = read(fd, toybuf, sizeof(toybuf)); + if (len<1) break; + while (bytes > 1 || lines > 1) { + bytes--; + if (toybuf[offset++] == '\n') lines--; + if (offset >= len) break; + } + if (offset<len) xwrite(1, toybuf+offset, len-offset); + } + + // -f support: cache name/descriptor } void tail_main(void) { - // if nothing specified, default -n to -10 - if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10; + // if nothing specified, default -n to -10 + if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10; - loopfiles(toys.optargs, do_tail); + loopfiles(toys.optargs, do_tail); - // do -f stuff + // do -f stuff } diff --git a/toys/posix/tee.c b/toys/posix/tee.c index e6342f4c..03885109 100644 --- a/toys/posix/tee.c +++ b/toys/posix/tee.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tee.c - cat to multiple outputs. +/* tee.c - cat to multiple outputs. * * Copyright 2008 Rob Landley <rob@landley.net> * @@ -9,66 +7,65 @@ USE_TEE(NEWTOY(tee, "ia", TOYFLAG_BIN)) config TEE - bool "tee" - default y - help - usage: tee [-ai] [file...] + bool "tee" + default y + help + usage: tee [-ai] [file...] - Copy stdin to each listed file, and also to stdout. - Filename "-" is a synonym for stdout. + Copy stdin to each listed file, and also to stdout. + Filename "-" is a synonym for stdout. - -a append to files. - -i ignore SIGINT. + -a append to files. + -i ignore SIGINT. */ #define FOR_tee #include "toys.h" GLOBALS( - void *outputs; + void *outputs; ) struct fd_list { - struct fd_list *next; - int fd; + struct fd_list *next; + int fd; }; // Open each output file, saving filehandles to a linked list. static void do_tee_open(int fd, char *name) { - struct fd_list *temp; + struct fd_list *temp; - temp = xmalloc(sizeof(struct fd_list)); - temp->next = TT.outputs; - temp->fd = fd; - TT.outputs = temp; + temp = xmalloc(sizeof(struct fd_list)); + temp->next = TT.outputs; + temp->fd = fd; + TT.outputs = temp; } void tee_main(void) { - if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN); + if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN); - // Open output files - loopfiles_rw(toys.optargs, - O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), - 0666, 0, do_tee_open); + // Open output files + loopfiles_rw(toys.optargs, + O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), + 0666, 0, do_tee_open); - for (;;) { - struct fd_list *fdl; - int len; + for (;;) { + struct fd_list *fdl; + int len; - // Read data from stdin - len = xread(0, toybuf, sizeof(toybuf)); - if (len<1) break; + // Read data from stdin + len = xread(0, toybuf, sizeof(toybuf)); + if (len<1) break; - // Write data to each output file, plus stdout. - fdl = TT.outputs; - for (;;) { - if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1; - if (!fdl) break; - fdl = fdl->next; - } + // Write data to each output file, plus stdout. + fdl = TT.outputs; + for (;;) { + if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1; + if (!fdl) break; + fdl = fdl->next; } - + } } diff --git a/toys/posix/true.c b/toys/posix/true.c index e2e7ea62..09e551c3 100644 --- a/toys/posix/true.c +++ b/toys/posix/true.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * true.c - Return zero. +/* true.c - Return zero. * * Copyright 2007 Rob Landley <rob@landley.net> * @@ -9,15 +7,15 @@ USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN)) config TRUE - bool "true" - default y - help - Return zero. + bool "true" + default y + help + Return zero. */ #include "toys.h" void true_main(void) { - return; + return; } diff --git a/toys/posix/tty.c b/toys/posix/tty.c index 661e919a..578c9aff 100644 --- a/toys/posix/tty.c +++ b/toys/posix/tty.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tty.c - Show stdin's terminal name +/* tty.c - Show stdin's terminal name * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,24 +7,24 @@ USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN)) config TTY - bool "tty" - default y - help - Show filename of terminal connected to stdin. + bool "tty" + default y + help + Show filename of terminal connected to stdin. - Prints "not a tty" and exits with nonzero status if no terminal - is connected to stdin. + Prints "not a tty" and exits with nonzero status if no terminal + is connected to stdin. - -s silent mode + -s silent mode */ #include "toys.h" void tty_main(void) { - char *tty = ttyname(0); + char *tty = ttyname(0); - if (!toys.optflags) puts(tty ? tty : "not a tty"); + if (!toys.optflags) puts(tty ? tty : "not a tty"); - toys.exitval = !tty; + toys.exitval = !tty; } diff --git a/toys/posix/uname.c b/toys/posix/uname.c index fcc92a08..2c1a0504 100644 --- a/toys/posix/uname.c +++ b/toys/posix/uname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * uname.c - return system name +/* uname.c - return system name * * Copyright 2008 Rob Landley <rob@landley.net> * @@ -9,19 +7,19 @@ USE_UNAME(NEWTOY(uname, "amvrns", TOYFLAG_BIN)) config UNAME - bool "uname" - default y - help - usage: uname [-asnrvmpio] + bool "uname" + default y + help + usage: uname [-asnrvmpio] - Print system information. + Print system information. - -s System name - -n Network (domain) name - -r Release number - -v Version (build date) - -m Machine (hardware) name - -a All of the above + -s System name + -n Network (domain) name + -r Release number + -v Version (build date) + -m Machine (hardware) name + -a All of the above */ #define FOR_uname @@ -42,34 +40,34 @@ config UNAME void uname_main(void) { - int i, flags = toys.optflags, needspace=0; + int i, flags = toys.optflags, needspace=0; - uname((void *)toybuf); + uname((void *)toybuf); - if (!flags) flags = FLAG_s; - for (i=0; i<5; i++) { - char *c = toybuf+(65*i); + if (!flags) flags = FLAG_s; + for (i=0; i<5; i++) { + char *c = toybuf+(65*i); - if (flags & ((1<<i)|FLAG_a)) { - int len = strlen(c); + if (flags & ((1<<i)|FLAG_a)) { + int len = strlen(c); - // This problem originates in autoconf, so of course the solution - // is horribly ugly. + // This problem originates in autoconf, so of course the solution + // is horribly ugly. #ifdef GROSS - if (i==4 && !strcmp(c,"x86_64")) { - printf(GROSS); - continue; - } + if (i==4 && !strcmp(c,"x86_64")) { + printf(GROSS); + continue; + } #endif - if (needspace++) { - // We can't decrement on the first entry, because - // needspace would be 0 - *(--c)=' '; - len++; - } - xwrite(1, c, len); - } - } - putchar('\n'); + if (needspace++) { + // We can't decrement on the first entry, because + // needspace would be 0 + *(--c)=' '; + len++; + } + xwrite(1, c, len); + } + } + putchar('\n'); } diff --git a/toys/posix/uniq.c b/toys/posix/uniq.c index f42b7293..bd41d4af 100644 --- a/toys/posix/uniq.c +++ b/toys/posix/uniq.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * uniq.c - report or filter out repeated lines in a file +/* uniq.c - report or filter out repeated lines in a file * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> * @@ -9,116 +7,113 @@ USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_BIN)) config UNIQ - bool "uniq" - default y - help - usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]] - - Report or filter out repeated lines in a file - - -c show counts before each line - -d show only lines that are repeated - -u show only lines that are unique - -i ignore case when comparing lines - -z lines end with \0 not \n - -w compare maximum X chars per line - -f ignore first X fields - -s ignore first X chars + bool "uniq" + default y + help + usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]] + + Report or filter out repeated lines in a file + + -c show counts before each line + -d show only lines that are repeated + -u show only lines that are unique + -i ignore case when comparing lines + -z lines end with \0 not \n + -w compare maximum X chars per line + -f ignore first X fields + -s ignore first X chars */ #define FOR_uniq #include "toys.h" GLOBALS( - long maxchars; - long nchars; - long nfields; - long repeats; + long maxchars; + long nchars; + long nfields; + long repeats; ) static char *skip(char *str) { - long nchars = TT.nchars, nfields; - - // Skip fields first - for (nfields = TT.nfields; nfields; str++) { - while (*str && isspace(*str)) str++; - while (*str && !isspace(*str)) str++; - nfields--; - } - // Skip chars - while (*str && nchars--) str++; - - return str; + long nchars = TT.nchars, nfields; + + // Skip fields first + for (nfields = TT.nfields; nfields; str++) { + while (*str && isspace(*str)) str++; + while (*str && !isspace(*str)) str++; + nfields--; + } + // Skip chars + while (*str && nchars--) str++; + + return str; } static void print_line(FILE *f, char *line) { - if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return; - if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1); - fputs(line, f); - if (toys.optflags & FLAG_z) fputc(0, f); + if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return; + if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1); + fputs(line, f); + if (toys.optflags & FLAG_z) fputc(0, f); } void uniq_main(void) { - FILE *infile = stdin, *outfile = stdout; - char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n'; - size_t thissize, prevsize = 0, tmpsize; - - if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r"); - if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w"); - - if (toys.optflags & FLAG_z) eol = 0; - - // If first line can't be read - if (getdelim(&prevline, &prevsize, eol, infile) < 0) - return; - - while (getdelim(&thisline, &thissize, eol, infile) > 0) { - int diff; - char *t1, *t2; - - // If requested get the chosen fields + character offsets. - if (TT.nfields || TT.nchars) { - t1 = skip(thisline); - t2 = skip(prevline); - } else { - t1 = thisline; - t2 = prevline; - } - - if (TT.maxchars == 0) { - diff = !(toys.optflags & FLAG_i) - ? strcmp(t1, t2) - : strcasecmp(t1, t2); - } else { - diff = !(toys.optflags & FLAG_i) - ? strncmp(t1, t2, TT.maxchars) - : strncasecmp(t1, t2, TT.maxchars); - } - - if (diff == 0) { // same - TT.repeats++; - } else { - print_line(outfile, prevline); - - TT.repeats = 0; - - tmpline = prevline; - prevline = thisline; - thisline = tmpline; - - tmpsize = prevsize; - prevsize = thissize; - thissize = tmpsize; - } - } - - print_line(outfile, prevline); - - if (CFG_TOYBOX_FREE) { - free(prevline); - free(thisline); - } + FILE *infile = stdin, *outfile = stdout; + char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n'; + size_t thissize, prevsize = 0, tmpsize; + + if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r"); + if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w"); + + if (toys.optflags & FLAG_z) eol = 0; + + // If first line can't be read + if (getdelim(&prevline, &prevsize, eol, infile) < 0) + return; + + while (getdelim(&thisline, &thissize, eol, infile) > 0) { + int diff; + char *t1, *t2; + + // If requested get the chosen fields + character offsets. + if (TT.nfields || TT.nchars) { + t1 = skip(thisline); + t2 = skip(prevline); + } else { + t1 = thisline; + t2 = prevline; + } + + if (TT.maxchars == 0) { + diff = !(toys.optflags & FLAG_i) ? strcmp(t1, t2) : strcasecmp(t1, t2); + } else { + diff = !(toys.optflags & FLAG_i) ? strncmp(t1, t2, TT.maxchars) + : strncasecmp(t1, t2, TT.maxchars); + } + + if (diff == 0) { // same + TT.repeats++; + } else { + print_line(outfile, prevline); + + TT.repeats = 0; + + tmpline = prevline; + prevline = thisline; + thisline = tmpline; + + tmpsize = prevsize; + prevsize = thissize; + thissize = tmpsize; + } + } + + print_line(outfile, prevline); + + if (CFG_TOYBOX_FREE) { + free(prevline); + free(thisline); + } } diff --git a/toys/posix/unlink.c b/toys/posix/unlink.c index 19660c5d..4faef9dc 100644 --- a/toys/posix/unlink.c +++ b/toys/posix/unlink.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * unlink.c - delete one file +/* unlink.c - delete one file * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,18 +7,18 @@ USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) config UNLINK - bool "unlink" - default y - help - usage: unlink FILE + bool "unlink" + default y + help + usage: unlink FILE - Deletes one file. + Deletes one file. */ #include "toys.h" void unlink_main(void) { - if (unlink(*toys.optargs)) - perror_exit("Couldn't unlink `%s'", *toys.optargs); + if (unlink(*toys.optargs)) + perror_exit("Couldn't unlink `%s'", *toys.optargs); } diff --git a/toys/posix/wc.c b/toys/posix/wc.c index 3896b73a..19ba4b8b 100644 --- a/toys/posix/wc.c +++ b/toys/posix/wc.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * wc.c - Word count +/* wc.c - Word count * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,90 +7,88 @@ USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN)) config WC - bool "wc" - default y - help - usage: wc -lwcm [FILE...] + bool "wc" + default y + help + usage: wc -lwcm [FILE...] - Count lines, words, and characters in input. + Count lines, words, and characters in input. - -l show lines - -w show words - -c show bytes - -m show characters + -l show lines + -w show words + -c show bytes + -m show characters - By default outputs lines, words, bytes, and filename for each - argument (or from stdin if none). Displays only either bytes - or characters. + By default outputs lines, words, bytes, and filename for each + argument (or from stdin if none). Displays only either bytes + or characters. */ #define FOR_wc #include "toys.h" GLOBALS( - unsigned long totals[3]; + unsigned long totals[3]; ) static void show_lengths(unsigned long *lengths, char *name) { - int i, nospace = 1; - for (i=0; i<3; i++) { - if (!toys.optflags || (toys.optflags&(1<<i))) { - xprintf(" %ld"+nospace, lengths[i]); - nospace = 0; - } - TT.totals[i] += lengths[i]; - } - if (*toys.optargs) xprintf(" %s", name); - xputc('\n'); + int i, nospace = 1; + for (i=0; i<3; i++) { + if (!toys.optflags || (toys.optflags&(1<<i))) { + xprintf(" %ld"+nospace, lengths[i]); + nospace = 0; + } + TT.totals[i] += lengths[i]; + } + if (*toys.optargs) xprintf(" %s", name); + xputc('\n'); } static void do_wc(int fd, char *name) { - int i, len, clen=1, space; - wchar_t wchar; - unsigned long word=0, lengths[]={0,0,0}; + int i, len, clen=1, space; + wchar_t wchar; + unsigned long word=0, lengths[]={0,0,0}; - for (;;) { - len = read(fd, toybuf, sizeof(toybuf)); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - for (i=0; i<len; i+=clen) { - if(toys.optflags&8) { - clen = mbrtowc(&wchar, toybuf+i, len-i, 0); - if(clen==(size_t)(-1)) { - if(i!=len-1) { - clen = 1; - continue; - } - else break; - } - if(clen==(size_t)(-2)) break; - if(clen==0) clen=1; - space = iswspace(wchar); - } - else space = isspace(toybuf[i]); + for (;;) { + len = read(fd, toybuf, sizeof(toybuf)); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + for (i=0; i<len; i+=clen) { + if(toys.optflags&8) { + clen = mbrtowc(&wchar, toybuf+i, len-i, 0); + if(clen==(size_t)(-1)) { + if(i!=len-1) { + clen = 1; + continue; + } else break; + } + if(clen==(size_t)(-2)) break; + if(clen==0) clen=1; + space = iswspace(wchar); + } else space = isspace(toybuf[i]); - if (toybuf[i]==10) lengths[0]++; - if (space) word=0; - else { - if (!word) lengths[1]++; - word=1; - } - lengths[2]++; - } - } + if (toybuf[i]==10) lengths[0]++; + if (space) word=0; + else { + if (!word) lengths[1]++; + word=1; + } + lengths[2]++; + } + } - show_lengths(lengths, name); + show_lengths(lengths, name); } void wc_main(void) { - setlocale(LC_ALL, ""); - toys.optflags |= (toys.optflags&8)>>1; - loopfiles(toys.optargs, do_wc); - if (toys.optc>1) show_lengths(TT.totals, "total"); + setlocale(LC_ALL, ""); + toys.optflags |= (toys.optflags&8)>>1; + loopfiles(toys.optargs, do_wc); + if (toys.optc>1) show_lengths(TT.totals, "total"); } diff --git a/toys/posix/who.c b/toys/posix/who.c index 5f888d71..d09a9325 100644 --- a/toys/posix/who.c +++ b/toys/posix/who.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * who.c - display who is on the system +/* who.c - display who is on the system * * Copyright 2012 ProFUSION Embedded Systems * @@ -11,36 +9,35 @@ USE_WHO(NEWTOY(who, NULL, TOYFLAG_BIN)) config WHO - bool "who" - default n - help - usage: who - - Print logged user information on system + bool "who" + default n + help + usage: who + Print logged user information on system */ #include "toys.h" void who_main(void) { - struct utmpx *entry; - - setutxent(); + struct utmpx *entry; - while ((entry = getutxent())) { - if (entry->ut_type == USER_PROCESS) { - time_t time; - int time_size; - char * times; + setutxent(); - time = entry->ut_tv.tv_sec; - times = ctime(&time); - time_size = strlen(times) - 2; - printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, time_size, time_size, ctime(&time), entry->ut_host); + while ((entry = getutxent())) { + if (entry->ut_type == USER_PROCESS) { + time_t time; + int time_size; + char * times; - } + time = entry->ut_tv.tv_sec; + times = ctime(&time); + time_size = strlen(times) - 2; + printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, + time_size, time_size, ctime(&time), entry->ut_host); } + } - endutxent(); + endutxent(); } diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c index 8f19d07f..18b70f2e 100644 --- a/toys/posix/xargs.c +++ b/toys/posix/xargs.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * xargs.c - Run command with arguments taken from stdin. +/* xargs.c - Run command with arguments taken from stdin. * * Copyright 2011 Rob Landley <rob@landley.net> * @@ -9,42 +7,42 @@ USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0", TOYFLAG_USR|TOYFLAG_BIN)) config XARGS - bool "xargs" - default y - help - usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND... - - Run command line one or more times, appending arguments from stdin. - - If command exits with 255, don't launch another even if arguments remain. - - -s Size in bytes per command line - -n Max number of arguments per command - -0 Each argument is NULL terminated, no whitespace or quote processing - #-p Prompt for y/n from tty before running each command - #-t Trace, print command line to stderr - #-x Exit if can't fit everything in one command - #-r Don't run command with empty input - #-L Max number of lines of input per command - -E stop at line matching string + bool "xargs" + default y + help + usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND... + + Run command line one or more times, appending arguments from stdin. + + If command exits with 255, don't launch another even if arguments remain. + + -s Size in bytes per command line + -n Max number of arguments per command + -0 Each argument is NULL terminated, no whitespace or quote processing + #-p Prompt for y/n from tty before running each command + #-t Trace, print command line to stderr + #-x Exit if can't fit everything in one command + #-r Don't run command with empty input + #-L Max number of lines of input per command + -E stop at line matching string */ #define FOR_xargs #include "toys.h" GLOBALS( - long max_bytes; - long max_entries; - long L; - char *eofstr; - char *I; - - long entries, bytes; - char delim; + long max_bytes; + long max_entries; + long L; + char *eofstr; + char *I; + + long entries, bytes; + char delim; ) // If out==NULL count TT.bytes and TT.entries, stopping at max. -// Otherwise, fill out out[] +// Otherwise, fill out out[] // Returning NULL means need more data. // Returning char * means hit data limits, start of data left over @@ -53,135 +51,135 @@ GLOBALS( static char *handle_entries(char *data, char **entry) { - if (TT.delim) { - char *s = data; - - // Chop up whitespace delimited string into args - while (*s) { - char *save; - - while (isspace(*s)) { - if (entry) *s = 0; - s++; - } - - if (TT.max_entries && TT.entries >= TT.max_entries) - return *s ? s : (char *)1; - - if (!*s) break; - save = s; - - for (;;) { - if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save; - if (!*s || isspace(*s)) break; - s++; - } - if (TT.eofstr) { - int len = s-save; - if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len)) - return (char *)2; - } - if (entry) entry[TT.entries] = save; - ++TT.entries; - } - - // -0 support - } else { - TT.bytes += strlen(data)+1; - if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data; - if (TT.max_entries && TT.entries >= TT.max_entries) - return (char *)1; - if (entry) entry[TT.entries] = data; - TT.entries++; - } - - return NULL; + if (TT.delim) { + char *s = data; + + // Chop up whitespace delimited string into args + while (*s) { + char *save; + + while (isspace(*s)) { + if (entry) *s = 0; + s++; + } + + if (TT.max_entries && TT.entries >= TT.max_entries) + return *s ? s : (char *)1; + + if (!*s) break; + save = s; + + for (;;) { + if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save; + if (!*s || isspace(*s)) break; + s++; + } + if (TT.eofstr) { + int len = s-save; + if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len)) + return (char *)2; + } + if (entry) entry[TT.entries] = save; + ++TT.entries; + } + + // -0 support + } else { + TT.bytes += strlen(data)+1; + if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data; + if (TT.max_entries && TT.entries >= TT.max_entries) + return (char *)1; + if (entry) entry[TT.entries] = data; + TT.entries++; + } + + return NULL; } void xargs_main(void) { - struct double_list *dlist = NULL; - int entries, bytes, done = 0, status; - char *data = NULL; - - if (!(toys.optflags & FLAG_0)) TT.delim = '\n'; - - // If no optargs, call echo. - if (!toys.optc) { - free(toys.optargs); - *(toys.optargs = xzalloc(2*sizeof(char *)))="echo"; - toys.optc = 1; - } - - for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++) - bytes += strlen(toys.optargs[entries]); - - // Loop through exec chunks. - while (data || !done) { - char **out; - - TT.entries = 0; - TT.bytes = bytes; - - // Loop reading input - for (;;) { - - // Read line - if (!data) { - ssize_t l = 0; - l = getdelim(&data, (size_t *)&l, TT.delim, stdin); - - if (l<0) { - data = 0; - done++; - break; - } - } - dlist_add(&dlist, data); - - // Count data used - data = handle_entries(data, NULL); - if (!data) continue; - if (data == (char *)2) done++; - if ((long)data <= 2) data = 0; - else data = xstrdup(data); - - break; - } - - // Accumulate cally thing - - if (data && !TT.entries) error_exit("argument too long"); - out = xzalloc((entries+TT.entries+1)*sizeof(char *)); - - if (dlist) { - struct double_list *dtemp; - - // Fill out command line to exec - memcpy(out, toys.optargs, entries*sizeof(char *)); - TT.entries = 0; - TT.bytes = bytes; - dlist->prev->next = 0; - for (dtemp = dlist; dtemp; dtemp = dtemp->next) - handle_entries(dtemp->data, out+entries); - } - pid_t pid=fork(); - if (!pid) { - xclose(0); - open("/dev/null", O_RDONLY); - xexec(out); - } - waitpid(pid, &status, 0); - status = WEXITSTATUS(status); - - // Abritrary number of execs, can't just leak memory each time... - while (dlist) { - struct double_list *dtemp = dlist->next; - - free(dlist->data); - free(dlist); - dlist = dtemp; - } - free(out); - } + struct double_list *dlist = NULL; + int entries, bytes, done = 0, status; + char *data = NULL; + + if (!(toys.optflags & FLAG_0)) TT.delim = '\n'; + + // If no optargs, call echo. + if (!toys.optc) { + free(toys.optargs); + *(toys.optargs = xzalloc(2*sizeof(char *)))="echo"; + toys.optc = 1; + } + + for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++) + bytes += strlen(toys.optargs[entries]); + + // Loop through exec chunks. + while (data || !done) { + char **out; + + TT.entries = 0; + TT.bytes = bytes; + + // Loop reading input + for (;;) { + + // Read line + if (!data) { + ssize_t l = 0; + l = getdelim(&data, (size_t *)&l, TT.delim, stdin); + + if (l<0) { + data = 0; + done++; + break; + } + } + dlist_add(&dlist, data); + + // Count data used + data = handle_entries(data, NULL); + if (!data) continue; + if (data == (char *)2) done++; + if ((long)data <= 2) data = 0; + else data = xstrdup(data); + + break; + } + + // Accumulate cally thing + + if (data && !TT.entries) error_exit("argument too long"); + out = xzalloc((entries+TT.entries+1)*sizeof(char *)); + + if (dlist) { + struct double_list *dtemp; + + // Fill out command line to exec + memcpy(out, toys.optargs, entries*sizeof(char *)); + TT.entries = 0; + TT.bytes = bytes; + dlist->prev->next = 0; + for (dtemp = dlist; dtemp; dtemp = dtemp->next) + handle_entries(dtemp->data, out+entries); + } + pid_t pid=fork(); + if (!pid) { + xclose(0); + open("/dev/null", O_RDONLY); + xexec(out); + } + waitpid(pid, &status, 0); + status = WEXITSTATUS(status); + + // Abritrary number of execs, can't just leak memory each time... + while (dlist) { + struct double_list *dtemp = dlist->next; + + free(dlist->data); + free(dlist); + dlist = dtemp; + } + free(out); + } } |