diff options
author | Chris Johns <chrisj@rtems.org> | 2008-07-29 02:21:15 +0000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2008-07-29 02:21:15 +0000 |
commit | 3899a5379f4bfa067e73b4612a547a308a6634ec (patch) | |
tree | f837533ace01e934da6089cdca360822d85cc662 /cpukit/libmisc/shell | |
parent | 2008-07-27 Ralf Corsépius <ralf.corsepius@rtems.org> (diff) | |
download | rtems-3899a5379f4bfa067e73b4612a547a308a6634ec.tar.bz2 |
2008-07-29 Chris Johns <chrisj@rtems.org>
* libblock/Makefile.am: Removed src/show_bdbuf.c.
* libblock/src/show_bdbuf.c: Removed.
* libblock/include/rtems/bdbuf.h, cpukit/libblock/src/bdbuf.c:
Rewritten the bdbuf code. Remove pre-emption disable, score
access, fixed many bugs and increased performance.
* libblock/include/rtems/blkdev.h: Added
RTEMS_BLKDEV_CAPABILITIES block device request. Cleaned up
comments. Added block and user fields to the sg buffer
request. Move to rtems_* namespace.
* libblock/include/rtems/diskdevs.h,
cpukit/libblock/src/diskdevs.c: Move to rtems_* namespace. Add a
capabilities field for drivers. Change rtems_disk_lookup to
rtems_disk_obtain to match the release call. You do not lookup and
release a disk, you obtain and release a disk.
* libblock/include/rtems/ide_part_table.h,
libblock/include/rtems/ramdisk.h, libblock/src/ide_part_table.c:
Move to rtems_* namespace.
* libblock/include/rtems/nvdisk.h: Formatting change.
* libblock/src/blkdev.c: Move to rtems_* namespace. Change
rtems_disk_lookup to rtems_disk_obtain
* libblock/src/flashdisk.c: Move to rtems_* namespace. Use the new
support for the block number in the scatter/grather request
struct. This allows non-continuous buffer requests for those
drivers that can support increasing performance.
* libblock/src/nvdisk.c: Move to rtems_* namespace. Removed
warnings. Added better error checking. Fixed some comments.
* libblock/src/ramdisk.c: Move to rtems_* namespace. Added some
trace functions to help debugging upper layers. Use the new
support for the block number in the scatter/grather request
struct. This allows non-continuous buffer requests for those
drivers that can support increasing performance.
* libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Use new chains
API. Removed temporary hack and changed
set_errno_and_return_minus_one to
rtems_set_errno_and_return_minus_one. Move fat_buf_access from
header and stopped it being inlined. Updated to libblock changes.
* libfs/src/dosfs/fat_fat_operations.c,
libfs/src/dosfs/fat_file.c, libfs/src/dosfs/msdos_create.c,
libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_eval.c,
libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_format.c,
libfs/src/dosfs/msdos_free.c, libfs/src/dosfs/msdos_initsupp.c,
libfs/src/dosfs/msdos_misc.c, libfs/src/dosfs/msdos_mknod.c: Use
new chains API. Removed temporary hack and changed
set_errno_and_return_minus_one to
rtems_set_errno_and_return_minus_one. Updated to libblock changes.
* libmisc/Makefile.am: Add new ls and rm command files.
* libmisc/shell/cmp-ls.c, libmisc/shell/extern-ls.h,
libmisc/shell/filemode.c, libmisc/shell/print-ls.c,
libmisc/shell/pwcache.c, libmisc/shell/utils-ls.c,
libmisc/shell/vis.c, shell/vis.h: New.
* libmisc/shell/extern-cp.h, libmisc/shell/main_cp.c,
libmisc/shell/utils-cp.c: Fixed the usage call bug.
* libmisc/shell/main_blksync.c: Updated to the new block IO ioctl
command.
* libmisc/shell/main_ls.c, libmisc/shell/main_rm.c: Updated to BSD
commands with more features.
* score/src/coremutex.c: Fix the strick order mutex code.
* libmisc/shell/shell.c: Change shell tasks mode to be timeslice
and no ASR.
* sapi/include/confdefs.h: Change ata_driver_task_priority to
rtems_ata_driver_task_priority. Add the new BD buf cache
parameters with defaults.
* score/src/interr.c: Do not return if the CPU halt call returns.
Diffstat (limited to 'cpukit/libmisc/shell')
-rw-r--r-- | cpukit/libmisc/shell/cmp-ls.c | 200 | ||||
-rw-r--r-- | cpukit/libmisc/shell/extern-cp.h | 2 | ||||
-rw-r--r-- | cpukit/libmisc/shell/extern-ls.h | 195 | ||||
-rw-r--r-- | cpukit/libmisc/shell/filemode.c | 150 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_blksync.c | 2 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_cp.c | 4 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_ls.c | 822 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_rm.c | 711 | ||||
-rw-r--r-- | cpukit/libmisc/shell/print-ls.c | 480 | ||||
-rw-r--r-- | cpukit/libmisc/shell/pwcache.c | 116 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shell.c | 2 | ||||
-rw-r--r-- | cpukit/libmisc/shell/utils-cp.c | 4 | ||||
-rw-r--r-- | cpukit/libmisc/shell/utils-ls.c | 113 | ||||
-rw-r--r-- | cpukit/libmisc/shell/vis.c | 384 | ||||
-rw-r--r-- | cpukit/libmisc/shell/vis.h | 91 |
15 files changed, 3154 insertions, 122 deletions
diff --git a/cpukit/libmisc/shell/cmp-ls.c b/cpukit/libmisc/shell/cmp-ls.c new file mode 100644 index 0000000000..e146762f08 --- /dev/null +++ b/cpukit/libmisc/shell/cmp-ls.c @@ -0,0 +1,200 @@ +/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93"; +#else +__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $"); +#endif +#endif /* not lint */ +#endif + +#include <sys/types.h> +#include <sys/stat.h> + +#include <fts.h> +#include <string.h> + +#include "extern-ls.h" + +#if defined(__rtems__) || defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \ + defined(_XOPEN_SOURCE) || defined(__NetBSD__) +#define ATIMENSEC_CMP(x, op, y) ((x)->st_atime op (y)->st_atime) +#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctime op (y)->st_ctime) +#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtime op (y)->st_mtime) +#else +#define ATIMENSEC_CMP(x, op, y) \ + ((x)->st_atime.tv_nsec op (y)->st_atime.tv_nsec) +#define CTIMENSEC_CMP(x, op, y) \ + ((x)->st_ctime.tv_nsec op (y)->st_ctime.tv_nsec) +#define MTIMENSEC_CMP(x, op, y) \ + ((x)->st_mtime.tv_nsec op (y)->st_mtime.tv_nsec) +#endif + +int +namecmp(const FTSENT *a, const FTSENT *b) +{ + + return (strcmp(a->fts_name, b->fts_name)); +} + +int +revnamecmp(const FTSENT *a, const FTSENT *b) +{ + + return (strcmp(b->fts_name, a->fts_name)); +} + +int +modcmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_mtime > a->fts_statp->st_mtime) + return (1); + else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime) + return (-1); + else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (1); + else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (-1); + else + return (namecmp(a, b)); +} + +int +revmodcmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_mtime > a->fts_statp->st_mtime) + return (-1); + else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime) + return (1); + else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (-1); + else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (1); + else + return (revnamecmp(a, b)); +} + +int +acccmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_atime > a->fts_statp->st_atime) + return (1); + else if (b->fts_statp->st_atime < a->fts_statp->st_atime) + return (-1); + else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (1); + else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (-1); + else + return (namecmp(a, b)); +} + +int +revacccmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_atime > a->fts_statp->st_atime) + return (-1); + else if (b->fts_statp->st_atime < a->fts_statp->st_atime) + return (1); + else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (-1); + else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (1); + else + return (revnamecmp(a, b)); +} + +int +statcmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_ctime > a->fts_statp->st_ctime) + return (1); + else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime) + return (-1); + else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (1); + else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (-1); + else + return (namecmp(a, b)); +} + +int +revstatcmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_ctime > a->fts_statp->st_ctime) + return (-1); + else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime) + return (1); + else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) + return (-1); + else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) + return (1); + else + return (revnamecmp(a, b)); +} + +int +sizecmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_size > a->fts_statp->st_size) + return (1); + if (b->fts_statp->st_size < a->fts_statp->st_size) + return (-1); + else + return (namecmp(a, b)); +} + +int +revsizecmp(const FTSENT *a, const FTSENT *b) +{ + + if (b->fts_statp->st_size > a->fts_statp->st_size) + return (-1); + if (b->fts_statp->st_size < a->fts_statp->st_size) + return (1); + else + return (revnamecmp(a, b)); +} diff --git a/cpukit/libmisc/shell/extern-cp.h b/cpukit/libmisc/shell/extern-cp.h index ba6ff9c4de..093b30ff10 100644 --- a/cpukit/libmisc/shell/extern-cp.h +++ b/cpukit/libmisc/shell/extern-cp.h @@ -84,7 +84,7 @@ int set_utimes(const char *, struct stat *); int setfile(rtems_shell_cp_globals* cp_globals, struct stat *, int); int preserve_dir_acls(struct stat *, char *, char *); int preserve_fd_acls(int, int); -void usage(); +void usage(rtems_shell_cp_globals* cp_globals); __END_DECLS diff --git a/cpukit/libmisc/shell/extern-ls.h b/cpukit/libmisc/shell/extern-ls.h new file mode 100644 index 0000000000..01575ba7df --- /dev/null +++ b/cpukit/libmisc/shell/extern-ls.h @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ls.h 8.1 (Berkeley) 5/31/93 + * $FreeBSD: src/bin/ls/ls.h,v 1.23 2008/04/04 03:57:46 grog Exp $ + */ + +#ifndef _EXTERN_LS_H_ +#define _EXTERN_LS_H_ + +#define NO_PRINT 1 +//#define COLORLS 1 + +#include <sys/cdefs.h> +#include <setjmp.h> + +#define major(d) rtems_filesystem_dev_major_t(d) +#define minor(d) rtems_filesystem_dev_minor_t(d) + +const char *user_from_uid(uid_t uid, int nouser); + +typedef struct { + int blocksize; + int termwidth; + int sortkey; + int rval; + int output; + time_t now; + + int f_accesstime; + int f_column; + int f_columnacross; + int f_flags; + int f_grouponly; + int f_humanize; + int f_inode; + int f_listdir; + int f_listdot; + int f_longform; + int f_nonprint; + int f_nosort; + int f_numericonly; + int f_octal; + int f_octal_escape; + int f_recursive; + int f_reversesort; + int f_sectime; + int f_singlecol; + int f_size; + int f_statustime; + int f_stream; + int f_type; + int f_typedir; + int f_whiteout; + + int exit_code; + jmp_buf exit_jmp; +} rtems_shell_ls_globals; + +#define blocksize globals->blocksize +#define termwidth globals->termwidth +#define sortkey globals->sortkey +#define rval globals->rval +#define output globals->output +#define now globals->now + +#define f_accesstime globals->f_accesstime +#define f_column globals->f_column +#define f_columnacross globals->f_columnacross +#define f_flags globals->f_flags +#define f_grouponly globals->f_grouponly +#define f_humanize globals->f_humanize +#define f_inode globals->f_inode +#define f_listdir globals->f_listdir +#define f_listdot globals->f_listdot +#define f_longform globals->f_longform +#define f_nonprint globals->f_nonprint +#define f_nosort globals->f_nosort +#define f_numericonly globals->f_numericonly +#define f_octal globals->f_octal +#define f_octal_escape globals->f_octal_escape +#define f_recursive globals->f_recursive +#define f_reversesort globals->f_reversesort +#define f_sectime globals->f_sectime +#define f_singlecol globals->f_singlecol +#define f_size globals->f_size +#define f_statustime globals->f_statustime +#define f_stream globals->f_stream +#define f_type globals->f_type +#define f_typedir globals->f_typedir +#define f_whiteout globals->f_whiteout + +#define exit_jump &(globals->exit_jmp) + +void rtems_shell_ls_exit(rtems_shell_ls_globals* globals, int code); + +#define exit(ec) rtems_shell_ls_exit(globals, ec) + + +typedef struct { + FTSENT *list; + u_int64_t btotal; + u_int64_t stotal; + int entries; + int maxlen; + int s_block; + int s_flags; + int s_group; + int s_inode; + int s_nlink; + int s_size; + int s_user; + int s_major; + int s_minor; +} DISPLAY; + +typedef struct { + char *user; + char *group; + char *flags; + char data[1]; +} NAMES; + +#define acccmp rtems_shell_ls_acccmp +#define revacccmp rtems_shell_ls_revacccmp +#define modcmp rtems_shell_ls_modcmp +#define revmodcmp rtems_shell_ls_revmodcmp +#define namecmp rtems_shell_ls_namecmp +#define revnamecmp rtems_shell_ls_revnamecmp +#define statcmp rtems_shell_ls_statcmp +#define revstatcmp rtems_shell_ls_revstatcmp +#define sizecmp rtems_shell_ls_sizecmp +#define revsizecmp rtems_shell_ls_revsizecmp +#define printescaped rtems_shell_ls_printescaped +#define printacol rtems_shell_ls_printacol +#define printcol rtems_shell_ls_printcol +#define printlong rtems_shell_ls_printlong +#define printscol rtems_shell_ls_printscol +#define printstream rtems_shell_ls_printstream +#define usage rtems_shell_ls_usage + +int acccmp(const FTSENT *, const FTSENT *); +int revacccmp(const FTSENT *, const FTSENT *); +int modcmp(const FTSENT *, const FTSENT *); +int revmodcmp(const FTSENT *, const FTSENT *); +int namecmp(const FTSENT *, const FTSENT *); +int revnamecmp(const FTSENT *, const FTSENT *); +int statcmp(const FTSENT *, const FTSENT *); +int revstatcmp(const FTSENT *, const FTSENT *); +int sizecmp(const FTSENT *, const FTSENT *); +int revsizecmp(const FTSENT *, const FTSENT *); + +int printescaped(rtems_shell_ls_globals* globals, const char *); +void printacol(rtems_shell_ls_globals* globals, DISPLAY *); +void printcol(rtems_shell_ls_globals* globals, DISPLAY *); +void printlong(rtems_shell_ls_globals* globals, DISPLAY *); +void printscol(rtems_shell_ls_globals* globals, DISPLAY *); +void printstream(rtems_shell_ls_globals* globals, DISPLAY *); +int safe_print(rtems_shell_ls_globals* globals, const char *); +void usage(rtems_shell_ls_globals* globals); + +void strmode(mode_t mode, char *p); + +#define DAYSPERNYEAR 365 +#define SECSPERDAY (60 * 60 * 24) + +#endif /* !_EXTERN_H_ */ diff --git a/cpukit/libmisc/shell/filemode.c b/cpukit/libmisc/shell/filemode.c new file mode 100644 index 0000000000..6d77a1be95 --- /dev/null +++ b/cpukit/libmisc/shell/filemode.c @@ -0,0 +1,150 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.5 2007/01/09 00:28:12 imp Exp $"); + +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> + +void +strmode(mode, p) + mode_t mode; + char *p; +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + case S_IFBLK: /* block special */ + *p++ = 'b'; + break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#ifdef S_IFIFO + case S_IFIFO: /* fifo */ + *p++ = 'p'; + break; +#endif +#ifdef S_IFWHT + case S_IFWHT: /* whiteout */ + *p++ = 'w'; + break; +#endif + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR | S_ISUID)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP | S_ISGID)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + case S_ISGID: + *p++ = 'S'; + break; + case S_IXGRP | S_ISGID: + *p++ = 's'; + break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH | S_ISVTX)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + case S_ISVTX: + *p++ = 'T'; + break; + case S_IXOTH | S_ISVTX: + *p++ = 't'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} diff --git a/cpukit/libmisc/shell/main_blksync.c b/cpukit/libmisc/shell/main_blksync.c index 0089a75adf..8226aefc9a 100644 --- a/cpukit/libmisc/shell/main_blksync.c +++ b/cpukit/libmisc/shell/main_blksync.c @@ -58,7 +58,7 @@ int rtems_shell_main_blksync( return 1; } - if (ioctl (fd, BLKIO_SYNCDEV) < 0) { + if (ioctl (fd, RTEMS_BLKIO_SYNCDEV) < 0) { fprintf( stderr, "%s: driver sync failed: %s\n", argv[0], strerror (errno)); return 1; } diff --git a/cpukit/libmisc/shell/main_cp.c b/cpukit/libmisc/shell/main_cp.c index 3111a4db74..773ec5ad69 100644 --- a/cpukit/libmisc/shell/main_cp.c +++ b/cpukit/libmisc/shell/main_cp.c @@ -175,14 +175,14 @@ main_cp(rtems_shell_cp_globals* cp_globals, int argc, char *argv[]) vflag = 1; break; default: - usage(); + usage(cp_globals); break; } argc -= getopt_reent.optind; argv += getopt_reent.optind; if (argc < 2) - usage(); + usage(cp_globals); fts_options = FTS_NOCHDIR | FTS_PHYSICAL; if (Rflag && rflag) diff --git a/cpukit/libmisc/shell/main_ls.c b/cpukit/libmisc/shell/main_ls.c index c81e35efda..d52229b521 100644 --- a/cpukit/libmisc/shell/main_ls.c +++ b/cpukit/libmisc/shell/main_ls.c @@ -1,104 +1,758 @@ +/* $NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $ */ + /* - * LS Shell Command Implmentation + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. * - * Author: Fernando RUIZ CASAS - * Work: fernando.ruiz@ctv.es - * Home: correo@fernando-ruiz.com + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * $Id$ + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ls.c 8.7 (Berkeley) 8/5/94"; +#else +__RCSID("$NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $"); +#endif +#endif /* not lint */ #endif +#include <rtems.h> +#include <rtems/shell.h> +#include <rtems/shellconfig.h> +#include <getopt.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fts.h> +#include <locale.h> #include <stdio.h> -#include <string.h> #include <stdlib.h> -#include <ctype.h> -#include <dirent.h> -#include <time.h> -#include <fcntl.h> +#include <string.h> #include <unistd.h> +#include <termios.h> #include <pwd.h> #include <grp.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <stddef.h> -#include <rtems.h> -#include <rtems/shell.h> -#include "internal.h" +#include "extern-ls.h" + +static void display(rtems_shell_ls_globals* globals, FTSENT *, FTSENT *); +static int mastercmp_listdir(const FTSENT **, const FTSENT **); +static int mastercmp_no_listdir(const FTSENT **, const FTSENT **); +static void traverse(rtems_shell_ls_globals* globals, int, char **, int); + +static void (*printfcn)(rtems_shell_ls_globals* globals, DISPLAY *); +static int (*sortfcn)(const FTSENT *, const FTSENT *); + +#define BY_NAME 0 +#define BY_SIZE 1 +#define BY_TIME 2 + +#if RTEMS_REMOVED +long blocksize; /* block size units */ +int termwidth = 80; /* default terminal width */ +int sortkey = BY_NAME; +int rval = EXIT_SUCCESS; /* exit value - set if error encountered */ + +/* flags */ +int f_accesstime; /* use time of last access */ +int f_column; /* columnated format */ +int f_columnacross; /* columnated format, sorted across */ +int f_flags; /* show flags associated with a file */ +int f_grouponly; /* long listing without owner */ +int f_humanize; /* humanize the size field */ +int f_inode; /* print inode */ +int f_listdir; /* list actual directory, not contents */ +int f_listdot; /* list files beginning with . */ +int f_longform; /* long listing format */ +int f_nonprint; /* show unprintables as ? */ +int f_nosort; /* don't sort output */ +int f_numericonly; /* don't convert uid/gid to name */ +int f_octal; /* print octal escapes for nongraphic characters */ +int f_octal_escape; /* like f_octal but use C escapes if possible */ +int f_recursive; /* ls subdirectories also */ +int f_reversesort; /* reverse whatever sort is used */ +int f_sectime; /* print the real time for all files */ +int f_singlecol; /* use single column output */ +int f_size; /* list size in short listing */ +int f_statustime; /* use time of last mode change */ +int f_stream; /* stream format */ +int f_type; /* add type character for non-regular files */ +int f_typedir; /* add type character for directories */ +int f_whiteout; /* show whiteout entries */ +#endif + +void +rtems_shell_ls_exit (rtems_shell_ls_globals* globals, int code) +{ + globals->exit_code = code; + longjmp (globals->exit_jmp, 1); +} + +static int main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[]); + +int +rtems_shell_main_ls(int argc, char *argv[]) +{ + rtems_shell_ls_globals ls_globals; + rtems_shell_ls_globals* globals = &ls_globals; + memset (globals, 0, sizeof (ls_globals)); + termwidth = 80; + sortkey = BY_NAME; + rval = EXIT_SUCCESS; + ls_globals.exit_code = 1; + if (setjmp (ls_globals.exit_jmp) == 0) + return main_ls (globals, argc, argv); + return ls_globals.exit_code; +} + +int +main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[]) +{ + static char dot[] = ".", *dotav[] = { dot, NULL }; + //struct winsize win; + int ch, fts_options; + int kflag = 0; + const char *p; + + struct getopt_data getopt_reent; + memset(&getopt_reent, 0, sizeof(getopt_data)); + +#if RTEMS_REMOVED + setprogname(argv[0]); +#endif + setlocale(LC_ALL, ""); + + /* Terminal defaults to -Cq, non-terminal defaults to -1. */ + if (isatty(STDOUT_FILENO)) { +#if RTEMS_REMOVED + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && + win.ws_col > 0) + termwidth = win.ws_col; + f_column = f_nonprint = 1; +#endif + } else + f_singlecol = 1; + + /* Root is -A automatically. */ + if (!getuid()) + f_listdot = 1; + + fts_options = FTS_PHYSICAL; + while ((ch = getopt_r(argc, argv, + "1ABCFLRSTWabcdfghiklmnopqrstuwx", &getopt_reent)) != -1) { + switch (ch) { + /* + * The -1, -C, -l, -m and -x options all override each other so + * shell aliasing works correctly. + */ + case '1': + f_singlecol = 1; + f_column = f_columnacross = f_longform = f_stream = 0; + break; + case 'C': + f_column = 1; + f_columnacross = f_longform = f_singlecol = f_stream = + 0; + break; + case 'g': + if (f_grouponly != -1) + f_grouponly = 1; + f_longform = 1; + f_column = f_columnacross = f_singlecol = f_stream = 0; + break; + case 'l': + f_longform = 1; + f_column = f_columnacross = f_singlecol = f_stream = 0; + /* Never let -g take precedence over -l. */ + f_grouponly = -1; + break; + case 'm': + f_stream = 1; + f_column = f_columnacross = f_longform = f_singlecol = + 0; + break; + case 'x': + f_columnacross = 1; + f_column = f_longform = f_singlecol = f_stream = 0; + break; + /* The -c and -u options override each other. */ + case 'c': + f_statustime = 1; + f_accesstime = 0; + break; + case 'u': + f_accesstime = 1; + f_statustime = 0; + break; + case 'F': + f_type = 1; + break; + case 'L': + fts_options &= ~FTS_PHYSICAL; + fts_options |= FTS_LOGICAL; + break; + case 'R': + f_recursive = 1; + break; + case 'a': + fts_options |= FTS_SEEDOT; + /* FALLTHROUGH */ + case 'A': + f_listdot = 1; + break; + /* The -B option turns off the -b, -q and -w options. */ + case 'B': + f_nonprint = 0; + f_octal = 1; + f_octal_escape = 0; + break; + /* The -b option turns off the -B, -q and -w options. */ + case 'b': + f_nonprint = 0; + f_octal = 0; + f_octal_escape = 1; + break; + /* The -d option turns off the -R option. */ + case 'd': + f_listdir = 1; + f_recursive = 0; + break; + case 'f': + f_nosort = 1; + break; + case 'i': + f_inode = 1; + break; + case 'k': + blocksize = 1024; + kflag = 1; + break; + /* The -h option forces all sizes to be measured in bytes. */ + case 'h': + f_humanize = 1; + break; + case 'n': + f_numericonly = 1; + break; + case 'o': + f_flags = 1; + break; + case 'p': + f_typedir = 1; + break; + /* The -q option turns off the -B, -b and -w options. */ + case 'q': + f_nonprint = 1; + f_octal = 0; + f_octal_escape = 0; + break; + case 'r': + f_reversesort = 1; + break; + case 'S': + sortkey = BY_SIZE; + break; + case 's': + f_size = 1; + break; + case 'T': + f_sectime = 1; + break; + case 't': + sortkey = BY_TIME; + break; + case 'W': + f_whiteout = 1; + break; + /* The -w option turns off the -B, -b and -q options. */ + case 'w': + f_nonprint = 0; + f_octal = 0; + f_octal_escape = 0; + break; + default: + case '?': + usage(globals); + } + } + argc -= getopt_reent.optind; + argv += getopt_reent.optind; + + if (f_column || f_columnacross || f_stream) { + if ((p = getenv("COLUMNS")) != NULL) + termwidth = atoi(p); + } + + /* + * If both -g and -l options, let -l take precedence. + */ + if (f_grouponly == -1) + f_grouponly = 0; + + /* + * If not -F, -i, -l, -p, -S, -s or -t options, don't require stat + * information. + */ + if (!f_inode && !f_longform && !f_size && !f_type && !f_typedir && + sortkey == BY_NAME) + fts_options |= FTS_NOSTAT; + + /* + * If not -F, -d or -l options, follow any symbolic links listed on + * the command line. + */ + if (!f_longform && !f_listdir && !f_type) + fts_options |= FTS_COMFOLLOW; + + /* + * If -W, show whiteout entries + */ +#ifdef FTS_WHITEOUT + if (f_whiteout) + fts_options |= FTS_WHITEOUT; +#endif + + /* If -l or -s, figure out block size. */ + if (f_inode || f_longform || f_size) { +#if RTEMS_REMOVED + if (!kflag) + (void)getbsize(NULL, &blocksize); +#else + blocksize = 1024; +#endif + blocksize /= 512; + } + + /* Select a sort function. */ + if (f_reversesort) { + switch (sortkey) { + case BY_NAME: + sortfcn = revnamecmp; + break; + case BY_SIZE: + sortfcn = revsizecmp; + break; + case BY_TIME: + if (f_accesstime) + sortfcn = revacccmp; + else if (f_statustime) + sortfcn = revstatcmp; + else /* Use modification time. */ + sortfcn = revmodcmp; + break; + } + } else { + switch (sortkey) { + case BY_NAME: + sortfcn = namecmp; + break; + case BY_SIZE: + sortfcn = sizecmp; + break; + case BY_TIME: + if (f_accesstime) + sortfcn = acccmp; + else if (f_statustime) + sortfcn = statcmp; + else /* Use modification time. */ + sortfcn = modcmp; + break; + } + } + + /* Select a print function. */ + if (f_singlecol) + printfcn = printscol; + else if (f_columnacross) + printfcn = printacol; + else if (f_longform) + printfcn = printlong; + else if (f_stream) + printfcn = printstream; + else + printfcn = printcol; + + if (argc) + traverse(globals, argc, argv, fts_options); + else + traverse(globals, 1, dotav, fts_options); + exit(rval); + /* NOTREACHED */ + return 0; +} + +#if RTEMS_REMOVED +static int output; /* If anything output. */ +#endif -int rtems_shell_main_ls( - int argc, - char *argv[] -) +/* + * Traverse() walks the logical directory structure specified by the argv list + * in the order specified by the mastercmp() comparison function. During the + * traversal it passes linked lists of structures to display() which represent + * a superset (may be exact set) of the files to be displayed. + */ +static void +traverse(rtems_shell_ls_globals* globals, int argc, char *argv[], int options) { - char *fname; - DIR *dirp; - struct dirent *dp; - struct stat stat_buf; - struct passwd *pwd; - struct group *grp; - char *user; - char *group; - char sbuf[256]; - char nbuf[1024]; - int n; - int size; - - fname = "."; - if (argc>1) - fname = argv[1]; - - if ((dirp = opendir(fname)) == NULL) { - fprintf(stderr,"%s: %s: No such file or directory.\n", argv[0], fname); - return errno; - } - n = 0; - size = 0; - while ((dp = readdir(dirp)) != NULL) { - strcpy(nbuf,fname); - if (nbuf[strlen(nbuf)-1]!='/') - strcat(nbuf,"/"); - strcat(nbuf,dp->d_name); /* always the fullpathname. Avoid ftpd problem.*/ - if (stat(nbuf, &stat_buf) == 0) { /* AWFUL but works...*/ - strftime(sbuf,sizeof(sbuf)-1,"%b %d %H:%M", gmtime(&stat_buf.st_mtime)); - pwd = getpwuid(stat_buf.st_uid); - user = pwd?pwd->pw_name:"nouser"; - grp = getgrgid(stat_buf.st_gid); - group = grp?grp->gr_name:"nogrp"; - printf("%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %11d %s %s%c\n", - (S_ISLNK(stat_buf.st_mode)?('l'): - (S_ISDIR(stat_buf.st_mode)?('d'):('-'))), - (stat_buf.st_mode & S_IRUSR)?('r'):('-'), - (stat_buf.st_mode & S_IWUSR)?('w'):('-'), - (stat_buf.st_mode & S_IXUSR)?('x'):('-'), - (stat_buf.st_mode & S_IRGRP)?('r'):('-'), - (stat_buf.st_mode & S_IWGRP)?('w'):('-'), - (stat_buf.st_mode & S_IXGRP)?('x'):('-'), - (stat_buf.st_mode & S_IROTH)?('r'):('-'), - (stat_buf.st_mode & S_IWOTH)?('w'):('-'), - (stat_buf.st_mode & S_IXOTH)?('x'):('-'), - (int)stat_buf.st_nlink, - user,group, - (int)stat_buf.st_size, - sbuf, - dp->d_name, - S_ISDIR(stat_buf.st_mode)?'/':' '); - n++; - size += stat_buf.st_size; + FTS *ftsp; + FTSENT *p, *chp; + int ch_options; + + if ((ftsp = + fts_open(argv, options, + f_nosort ? NULL : f_listdir ? + mastercmp_listdir : mastercmp_no_listdir)) == NULL) + err(exit_jump, EXIT_FAILURE, NULL); + + display(globals, NULL, fts_children(ftsp, 0)); + if (f_listdir) + { + fts_close(ftsp); + return; } - } - printf("%d files %d bytes occupied\n",n,size); - closedir(dirp); - return 0; + + /* + * If not recursing down this tree and don't need stat info, just get + * the names. + */ + ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; + + while ((p = fts_read(ftsp)) != NULL) + switch (p->fts_info) { + case FTS_DC: + warnx("%s: directory causes a cycle", p->fts_name); + break; + case FTS_DNR: + case FTS_ERR: + warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); + rval = EXIT_FAILURE; + break; + case FTS_D: + if (p->fts_level != FTS_ROOTLEVEL && + p->fts_name[0] == '.' && !f_listdot) + break; + + /* + * If already output something, put out a newline as + * a separator. If multiple arguments, precede each + * directory with its name. + */ + if (output) + (void)printf("\n%s:\n", p->fts_path); + else if (argc > 1) { + (void)printf("%s:\n", p->fts_path); + output = 1; + } + + chp = fts_children(ftsp, ch_options); + display(globals, p, chp); + + if (!f_recursive && chp != NULL) + (void)fts_set(ftsp, p, FTS_SKIP); + break; + } + fts_close(ftsp); + if (errno) + err(exit_jump, EXIT_FAILURE, "fts_read"); +} + +/* + * Display() takes a linked list of FTSENT structures and passes the list + * along with any other necessary information to the print function. P + * points to the parent directory of the display list. + */ +static void +display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list) +{ + struct stat *sp; + DISPLAY d; + FTSENT *cur; + NAMES *np; + u_int64_t btotal, stotal, maxblock, maxsize; + int maxinode, maxnlink, maxmajor, maxminor; + int bcfile, entries, flen, glen, ulen, maxflags, maxgroup, maxlen; + int maxuser, needstats; + const char *user, *group; + char buf[21]; /* 64 bits == 20 digits, +1 for NUL */ + char nuser[12], ngroup[12]; + char *flags = NULL; + +#ifdef __GNUC__ + /* This outrageous construct just to shut up a GCC warning. */ + (void) &maxsize; +#endif + + /* + * If list is NULL there are two possibilities: that the parent + * directory p has no children, or that fts_children() returned an + * error. We ignore the error case since it will be replicated + * on the next call to fts_read() on the post-order visit to the + * directory p, and will be signalled in traverse(). + */ + if (list == NULL) + return; + + needstats = f_inode || f_longform || f_size; + flen = 0; + maxinode = maxnlink = 0; + bcfile = 0; + maxuser = maxgroup = maxflags = maxlen = 0; + btotal = stotal = maxblock = maxsize = 0; + maxmajor = maxminor = 0; + for (cur = list, entries = 0; cur; cur = cur->fts_link) { + if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { + warnx("%s: %s", + cur->fts_name, strerror(cur->fts_errno)); + cur->fts_number = NO_PRINT; + rval = EXIT_FAILURE; + continue; + } + + /* + * P is NULL if list is the argv list, to which different rules + * apply. + */ + if (p == NULL) { + /* Directories will be displayed later. */ + if (cur->fts_info == FTS_D && !f_listdir) { + cur->fts_number = NO_PRINT; + continue; + } + } else { + /* Only display dot file if -a/-A set. */ + if (cur->fts_name[0] == '.' && !f_listdot) { + cur->fts_number = NO_PRINT; + continue; + } + } + if (cur->fts_namelen > maxlen) + maxlen = cur->fts_namelen; + if (needstats) { + sp = cur->fts_statp; + if (sp->st_blocks > maxblock) + maxblock = sp->st_blocks; + if (sp->st_ino > maxinode) + maxinode = sp->st_ino; + if (sp->st_nlink > maxnlink) + maxnlink = sp->st_nlink; + if (sp->st_size > maxsize) + maxsize = sp->st_size; + if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) { + bcfile = 1; + if (major(sp->st_rdev) > maxmajor) + maxmajor = major(sp->st_rdev); + if (minor(sp->st_rdev) > maxminor) + maxminor = minor(sp->st_rdev); + } + + btotal += sp->st_blocks; + stotal += sp->st_size; + if (f_longform) { + if (f_numericonly || + (user = user_from_uid(sp->st_uid, 0)) == + NULL) { + (void)snprintf(nuser, sizeof(nuser), + "%u", sp->st_uid); + user = nuser; + } + if (f_numericonly || + (group = group_from_gid(sp->st_gid, 0)) == + NULL) { + (void)snprintf(ngroup, sizeof(ngroup), + "%u", sp->st_gid); + group = ngroup; + } + if ((ulen = strlen(user)) > maxuser) + maxuser = ulen; + if ((glen = strlen(group)) > maxgroup) + maxgroup = glen; +#if RTEMS_REMOVED + if (f_flags) { + flags = + flags_to_string(sp->st_flags, "-"); + if ((flen = strlen(flags)) > maxflags) + maxflags = flen; + } else +#endif + flen = 0; + + if ((np = malloc(sizeof(NAMES) + + ulen + glen + flen + 3)) == NULL) + err(exit_jump, EXIT_FAILURE, NULL); + + np->user = &np->data[0]; + (void)strcpy(np->user, user); + np->group = &np->data[ulen + 1]; + (void)strcpy(np->group, group); + + if (f_flags) { + np->flags = &np->data[ulen + glen + 2]; + (void)strcpy(np->flags, flags); + } + cur->fts_pointer = np; + } + } + ++entries; + } + + if (!entries) + return; + + d.list = list; + d.entries = entries; + d.maxlen = maxlen; + if (needstats) { + d.btotal = btotal; + d.stotal = stotal; + if (f_humanize) { + d.s_block = 4; /* min buf length for humanize_number */ + } else { + (void)snprintf(buf, sizeof(buf), "%llu", + (long long)howmany(maxblock, blocksize)); + d.s_block = strlen(buf); + } + d.s_flags = maxflags; + d.s_group = maxgroup; + (void)snprintf(buf, sizeof(buf), "%u", maxinode); + d.s_inode = strlen(buf); + (void)snprintf(buf, sizeof(buf), "%u", maxnlink); + d.s_nlink = strlen(buf); + if (f_humanize) { + d.s_size = 4; /* min buf length for humanize_number */ + } else { + (void)snprintf(buf, sizeof(buf), "%llu", + (long long)maxsize); + d.s_size = strlen(buf); + } + d.s_user = maxuser; + if (bcfile) { + (void)snprintf(buf, sizeof(buf), "%u", maxmajor); + d.s_major = strlen(buf); + (void)snprintf(buf, sizeof(buf), "%u", maxminor); + d.s_minor = strlen(buf); + if (d.s_major + d.s_minor + 2 > d.s_size) + d.s_size = d.s_major + d.s_minor + 2; + else if (d.s_size - d.s_minor - 2 > d.s_major) + d.s_major = d.s_size - d.s_minor - 2; + } else { + d.s_major = 0; + d.s_minor = 0; + } + } + + printfcn(globals, &d); + output = 1; + + if (f_longform) + for (cur = list; cur; cur = cur->fts_link) + free(cur->fts_pointer); +} + +/* + * Ordering for mastercmp: + * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories + * as larger than directories. Within either group, use the sort function. + * All other levels use the sort function. Error entries remain unsorted. + */ +static int +mastercmp_no_listdir(const FTSENT **a, const FTSENT **b) +{ + int a_info, b_info; + int l_f_listdir = 0; + + a_info = (*a)->fts_info; + if (a_info == FTS_ERR) + return (0); + b_info = (*b)->fts_info; + if (b_info == FTS_ERR) + return (0); + + if (a_info == FTS_NS || b_info == FTS_NS) { + if (b_info != FTS_NS) + return (1); + else if (a_info != FTS_NS) + return (-1); + else + return (namecmp(*a, *b)); + } + + if (a_info != b_info && !l_f_listdir && + (*a)->fts_level == FTS_ROOTLEVEL) { + if (a_info == FTS_D) + return (1); + else if (b_info == FTS_D) + return (-1); + } + return (sortfcn(*a, *b)); +} + +static int +mastercmp_listdir(const FTSENT **a, const FTSENT **b) +{ + int a_info, b_info; + int l_f_listdir = 1; + + a_info = (*a)->fts_info; + if (a_info == FTS_ERR) + return (0); + b_info = (*b)->fts_info; + if (b_info == FTS_ERR) + return (0); + + if (a_info == FTS_NS || b_info == FTS_NS) { + if (b_info != FTS_NS) + return (1); + else if (a_info != FTS_NS) + return (-1); + else + return (namecmp(*a, *b)); + } + + if (a_info != b_info && !l_f_listdir && + (*a)->fts_level == FTS_ROOTLEVEL) { + if (a_info == FTS_D) + return (1); + else if (b_info == FTS_D) + return (-1); + } + return (sortfcn(*a, *b)); } rtems_shell_cmd_t rtems_shell_LS_Command = { diff --git a/cpukit/libmisc/shell/main_rm.c b/cpukit/libmisc/shell/main_rm.c index 9bf60b61cf..f833fc6b39 100644 --- a/cpukit/libmisc/shell/main_rm.c +++ b/cpukit/libmisc/shell/main_rm.c @@ -1,50 +1,699 @@ -/* - * RM Shell Command Implmentation - * - * Author: Fernando RUIZ CASAS - * Work: fernando.ruiz@ctv.es - * Home: correo@fernando-ruiz.com +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * $Id$ + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1990, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94"; +#endif /* not lint */ #endif +#if 0 +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.58 2006/10/31 02:22:36 delphij Exp $"); +#endif + +#include <rtems.h> +#include <rtems/shell.h> +#include <rtems/shellconfig.h> +#include <getopt.h> + +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/mount.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <fts.h> +#include <grp.h> +#include <pwd.h> #include <stdio.h> -#include <unistd.h> +#include <stdlib.h> #include <string.h> -#include <errno.h> +#include <unistd.h> -#include <rtems.h> -#include <rtems/shell.h> -#include "internal.h" +/* RTEMS specific changes */ +typedef struct { + int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; + int rflag, Iflag; + uid_t uid; + int exit_code; + jmp_buf exit_jmp; +} rtems_shell_rm_globals; + +#define dflag globals->dflag +#define eval globals->eval +#define fflag globals->fflag +#define iflag globals->iflag +#define Pflag globals->Pflag +#define vflag globals->vflag +#define Wflag globals->Wflag +#define stdin_ok globals->stdin_ok +#define rflag globals->rflag +#define Iflag globals->Iflag +#define xuid globals->uid +#define exit_jump &(globals->exit_jmp) + +#include <setjmp.h> + +#define exit(ec) rtems_shell_rm_exit(globals, ec) +void +rtems_shell_rm_exit (rtems_shell_rm_globals* globals, int code) +{ + globals->exit_code = code; + longjmp (globals->exit_jmp, 1); +} + +static int main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[]); + +int +rtems_shell_main_rm(int argc, char *argv[]) +{ + rtems_shell_rm_globals rm_globals; + memset (&rm_globals, 0, sizeof (rm_globals)); + rm_globals.exit_code = 1; + if (setjmp (rm_globals.exit_jmp) == 0) + return main_rm (&rm_globals, argc, argv); + return rm_globals.exit_code; +} + +#define check(a1, a2, a3) check_rm(globals, a1, a2, a3) +#define check2(a1) check2_rm(globals, a1) +#define checkdot(a1) checkdot_rm(globals, a1) +#define checkslash(a1) checkslash_rm(globals, a1) +#define rm_file(a1) rm_file_rm(globals, a1) +#define rm_overwrite(a1, a2) rm_overwrite_rm(globals, a1, a2) +#define rm_tree(a1) rm_tree_rm(globals, a1) +#define usage() usage_rm(globals) + + +/* RTEMS changes */ + +static int check_rm(rtems_shell_rm_globals* globals, char *, char *, struct stat *); +static int check2_rm(rtems_shell_rm_globals* globals, char **); +static void checkdot_rm(rtems_shell_rm_globals* globals, char **); +static void checkslash_rm(rtems_shell_rm_globals* globals, char **); +static void rm_file_rm(rtems_shell_rm_globals* globals, char **); +static int rm_overwrite_rm(rtems_shell_rm_globals* globals, char *, struct stat *); +static void rm_tree_rm(rtems_shell_rm_globals* globals, char **); +static void usage_rm(rtems_shell_rm_globals* globals); + +/* + * rm -- + * This rm is different from historic rm's, but is expected to match + * POSIX 1003.2 behavior. The most visible difference is that -f + * has two specific effects now, ignore non-existent files and force + * file removal. + */ +int +main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[]) +{ + int ch; + char *p; + + struct getopt_data getopt_reent; + memset(&getopt_reent, 0, sizeof(getopt_data)); + + /* + * Test for the special case where the utility is called as + * "unlink", for which the functionality provided is greatly + * simplified. + */ + if ((p = rindex(argv[0], '/')) == NULL) + p = argv[0]; + else + ++p; + if (strcmp(p, "unlink") == 0) { + while (getopt_r(argc, argv, "", &getopt_reent) != -1) + usage(); + argc -= getopt_reent.optind; + argv += getopt_reent.optind; + if (argc != 1) + usage(); + rm_file(&argv[0]); + exit(eval); + } + + Pflag = rflag = 0; + while ((ch = getopt_r(argc, argv, "dfiIPRrvW", &getopt_reent)) != -1) + switch(ch) { + case 'd': + dflag = 1; + break; + case 'f': + fflag = 1; + iflag = 0; + break; + case 'i': + fflag = 0; + iflag = 1; + break; + case 'I': + Iflag = 1; + break; + case 'P': + Pflag = 1; + break; + case 'R': + case 'r': /* Compatibility. */ + rflag = 1; + break; + case 'v': + vflag = 1; + break; + case 'W': + Wflag = 1; + break; + default: + usage(); + } + argc -= getopt_reent.optind; + argv += getopt_reent.optind; + + if (argc < 1) { + if (fflag) + return (0); + usage(); + } + + checkdot(argv); + if (getenv("POSIXLY_CORRECT") == NULL) + checkslash(argv); + xuid = geteuid(); + + if (*argv) { + stdin_ok = isatty(STDIN_FILENO); + + if (Iflag) { + if (check2(argv) == 0) + exit (1); + } + if (rflag) + rm_tree(argv); + else + rm_file(argv); + } + + exit (eval); + return 0; +} + +void +rm_tree_rm(rtems_shell_rm_globals* globals, char **argv) +{ + FTS *fts; + FTSENT *p; + int needstat; + int flags; + int rval; + + /* + * Remove a file hierarchy. If forcing removal (-f), or interactive + * (-i) or can't ask anyway (stdin_ok), don't stat the file. + */ + needstat = !xuid || (!fflag && !iflag && stdin_ok); + + /* + * If the -i option is specified, the user can skip on the pre-order + * visit. The fts_number field flags skipped directories. + */ +#define SKIPPED 1 + + flags = FTS_PHYSICAL; + if (!needstat) + flags |= FTS_NOSTAT; + if (Wflag) + flags |= FTS_WHITEOUT; + if (!(fts = fts_open(argv, flags, NULL))) { + if (fflag && errno == ENOENT) + return; + err(exit_jump, 1, "fts_open"); + } + while ((p = fts_read(fts)) != NULL) { + switch (p->fts_info) { + case FTS_DNR: + if (!fflag || p->fts_errno != ENOENT) { + warnx("%s: %s", + p->fts_path, strerror(p->fts_errno)); + eval = 1; + } + continue; + case FTS_ERR: + errx(exit_jump, 1, "%s: %s", p->fts_path, strerror(p->fts_errno)); + case FTS_NS: + /* + * Assume that since fts_read() couldn't stat the + * file, it can't be unlinked. + */ + if (!needstat) + break; + if (!fflag || p->fts_errno != ENOENT) { + warnx("%s: %s", + p->fts_path, strerror(p->fts_errno)); + eval = 1; + } + continue; + case FTS_D: + /* Pre-order: give user chance to skip. */ + if (!fflag && !check(p->fts_path, p->fts_accpath, + p->fts_statp)) { + (void)fts_set(fts, p, FTS_SKIP); + p->fts_number = SKIPPED; + } +#if RTEMS_REMOVED + else if (!xuid && + (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && + !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && + chflags(p->fts_accpath, + p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0) + goto err; +#endif + continue; + case FTS_DP: + /* Post-order: see if user skipped. */ + if (p->fts_number == SKIPPED) + continue; + break; + default: + if (!fflag && + !check(p->fts_path, p->fts_accpath, p->fts_statp)) + continue; + } + + rval = 0; +#if RTEMS_REMOVED + if (!xuid && + (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && + !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE))) + rval = chflags(p->fts_accpath, + p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)); +#endif + if (rval == 0) { + /* + * If we can't read or search the directory, may still be + * able to remove it. Don't print out the un{read,search}able + * message unless the remove fails. + */ + switch (p->fts_info) { + case FTS_DP: + case FTS_DNR: + rval = rmdir(p->fts_accpath); + if (rval == 0 || (fflag && errno == ENOENT)) { + if (rval == 0 && vflag) + (void)printf("%s\n", + p->fts_path); + continue; + } + break; + +#if RTEMS_REMOVED + case FTS_W: + rval = undelete(p->fts_accpath); + if (rval == 0 && (fflag && errno == ENOENT)) { + if (vflag) + (void)printf("%s\n", + p->fts_path); + continue; + } + break; +#endif + + case FTS_NS: + /* + * Assume that since fts_read() couldn't stat + * the file, it can't be unlinked. + */ + if (fflag) + continue; + /* FALLTHROUGH */ + default: + if (Pflag) + if (!rm_overwrite(p->fts_accpath, NULL)) + continue; + rval = unlink(p->fts_accpath); + if (rval == 0 || (fflag && errno == ENOENT)) { + if (rval == 0 && vflag) + (void)printf("%s\n", + p->fts_path); + continue; + } + } + } +#if RTEMS_REMOVED +err: +#endif + warn("%s", p->fts_path); + eval = 1; + } + if (errno) + err(exit_jump, 1, "fts_read"); + fts_close(fts); +} + +#define S_ISWHT(m) (0) + +void +rm_file_rm(rtems_shell_rm_globals* globals, char **argv) +{ + struct stat sb; + int rval; + char *f; + + /* + * Remove a file. POSIX 1003.2 states that, by default, attempting + * to remove a directory is an error, so must always stat the file. + */ + while ((f = *argv++) != NULL) { + /* Assume if can't stat the file, can't unlink it. */ + if (lstat(f, &sb)) { +#if RTEMS_REMOVED + if (Wflag) { + sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; + } else { +#endif + if (!fflag || errno != ENOENT) { + warn("%s", f); + eval = 1; + } + continue; +#if RTEMS_REMOVED + } +#endif + } else if (Wflag) { + warnx("%s: %s", f, strerror(EEXIST)); + eval = 1; + continue; + } + + if (S_ISDIR(sb.st_mode) && !dflag) { + warnx("%s: is a directory", f); + eval = 1; + continue; + } + if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb)) + continue; + rval = 0; +#if RTEMS_REMOVED + if (!xuid && !S_ISWHT(sb.st_mode) && + (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) && + !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE))) + rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE)); +#endif + if (rval == 0) { + if (S_ISWHT(sb.st_mode)) +#if RTEMS_REMOVED + rval = undelete(f); +#endif + ; + else if (S_ISDIR(sb.st_mode)) + rval = rmdir(f); + else { + if (Pflag) + if (!rm_overwrite(f, &sb)) + continue; + rval = unlink(f); + } + } + if (rval && (!fflag || errno != ENOENT)) { + warn("%s", f); + eval = 1; + } + if (vflag && rval == 0) + (void)printf("%s\n", f); + } +} + +/* + * rm_overwrite -- + * Overwrite the file 3 times with varying bit patterns. + * + * XXX + * This is a cheap way to *really* delete files. Note that only regular + * files are deleted, directories (and therefore names) will remain. + * Also, this assumes a fixed-block file system (like FFS, or a V7 or a + * System V file system). In a logging file system, you'll have to have + * kernel support. + */ +int +rm_overwrite_rm(rtems_shell_rm_globals* globals, char *file, struct stat *sbp) +{ + struct stat sb; +#if RTEMS_REMOVED + struct statfs fsb; +#endif + off_t len; + int bsize, fd, wlen; + char *buf = NULL; + + fd = -1; + if (sbp == NULL) { + if (lstat(file, &sb)) + goto err; + sbp = &sb; + } + if (!S_ISREG(sbp->st_mode)) + return (1); + if (sbp->st_nlink > 1 && !fflag) { + warnx("%s (inode %lu): not overwritten due to multiple links", + file, sbp->st_ino); + return (0); + } + if ((fd = open(file, O_WRONLY, 0)) == -1) + goto err; +#if RTEMS_REMOVED + if (fstatfs(fd, &fsb) == -1) + goto err; + bsize = MAX(fsb.f_iosize, 1024); +#endif + bsize = 1024; + if ((buf = malloc(bsize)) == NULL) + err(exit_jump, 1, "%s: malloc", file); + +#define PASS(byte) { \ + memset(buf, byte, bsize); \ + for (len = sbp->st_size; len > 0; len -= wlen) { \ + wlen = len < bsize ? len : bsize; \ + if (write(fd, buf, wlen) != wlen) \ + goto err; \ + } \ +} + PASS(0xff); + if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) + goto err; + PASS(0x00); + if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) + goto err; + PASS(0xff); + if (!fsync(fd) && !close(fd)) { + free(buf); + return (1); + } + +err: eval = 1; + if (buf) + free(buf); + if (fd != -1) + close(fd); + warn("%s", file); + return (0); +} + +void strmode(mode_t mode, char *p); +char *fflagstostr(u_long flags); +const char *user_from_uid(uid_t uid, int nouser); + +int +check_rm(rtems_shell_rm_globals* globals, char *path, char *name, struct stat *sp) +{ + int ch, first; + char modep[15], *flagsp; + + /* Check -i first. */ + if (iflag) + (void)fprintf(stderr, "remove %s? ", path); + else { + /* + * If it's not a symbolic link and it's unwritable and we're + * talking to a terminal, ask. Symbolic links are excluded + * because their permissions are meaningless. Check stdin_ok + * first because we may not have stat'ed the file. + */ +#if RTEMS_REMOVED + if (!stdin_ok || S_ISLNK(sp->st_mode) || + (!access(name, W_OK) && + !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && + (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !xuid))) +#endif + if (!stdin_ok || S_ISLNK(sp->st_mode) || + (!access(name, W_OK))) + return (1); + strmode(sp->st_mode, modep); +#if RTEMS_REMOVED + if ((flagsp = fflagstostr(sp->st_flags)) == NULL) + err(exit_jump, 1, "fflagstostr"); +#else + flagsp = "no supported"; +#endif + if (Pflag) + errx(exit_jump, 1, + "%s: -P was specified, but file is not writable", + path); + (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ", + modep + 1, modep[9] == ' ' ? "" : " ", + user_from_uid(sp->st_uid, 0), + group_from_gid(sp->st_gid, 0), + *flagsp ? flagsp : "", *flagsp ? " " : "", + path); + free(flagsp); + } + (void)fflush(stderr); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + return (first == 'y' || first == 'Y'); +} + +#define ISSLASH(a) ((a)[0] == '/' && (a)[1] == '\0') +void +checkslash_rm(rtems_shell_rm_globals* globals, char **argv) +{ + char **t, **u; + int complained; + + complained = 0; + for (t = argv; *t;) { + if (ISSLASH(*t)) { + if (!complained++) + warnx("\"/\" may not be removed"); + eval = 1; + for (u = t; u[0] != NULL; ++u) + u[0] = u[1]; + } else { + ++t; + } + } +} + +int +check2_rm(rtems_shell_rm_globals* globals, char **argv) +{ + struct stat st; + int first; + int ch; + int fcount = 0; + int dcount = 0; + int i; + const char *dname = NULL; + + for (i = 0; argv[i]; ++i) { + if (lstat(argv[i], &st) == 0) { + if (S_ISDIR(st.st_mode)) { + ++dcount; + dname = argv[i]; /* only used if 1 dir */ + } else { + ++fcount; + } + } + } + first = 0; + while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') { + if (dcount && rflag) { + fprintf(stderr, "recursively remove"); + if (dcount == 1) + fprintf(stderr, " %s", dname); + else + fprintf(stderr, " %d dirs", dcount); + if (fcount == 1) + fprintf(stderr, " and 1 file"); + else if (fcount > 1) + fprintf(stderr, " and %d files", fcount); + } else if (dcount + fcount > 3) { + fprintf(stderr, "remove %d files", dcount + fcount); + } else { + return(1); + } + fprintf(stderr, "? "); + fflush(stderr); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + if (ch == EOF) + break; + } + return (first == 'y' || first == 'Y'); +} + +#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) +void +checkdot_rm(rtems_shell_rm_globals* globals, char **argv) +{ + char *p, **save, **t; + int complained; + + complained = 0; + for (t = argv; *t;) { + if ((p = strrchr(*t, '/')) != NULL) + ++p; + else + p = *t; + if (ISDOT(p)) { + if (!complained++) + warnx("\".\" and \"..\" may not be removed"); + eval = 1; + for (save = t; (t[0] = t[1]) != NULL; ++t) + continue; + t = save; + } else + ++t; + } +} -int rtems_shell_main_rm( - int argc, - char *argv[] -) +void +usage_rm(rtems_shell_rm_globals* globals) { - int n = 1; - while ( n<argc ) { - if (unlink(argv[n])) { - fprintf(stderr,"%s: %s: %s\n", argv[0], argv[n], strerror(errno)); - return -1; - } - n++; - } - return 0; + (void)fprintf(stderr, "%s\n%s\n", + "usage: rm [-f | -i] [-dIPRrvW] file ...", + " unlink file"); + exit(1); } rtems_shell_cmd_t rtems_shell_RM_Command = { "rm", /* name */ - "rm n1 [n2 [n3...]] # remove files", /* usage */ + "[-f | -i] [-dIPRrvW] file ...", /* usage */ "files", /* topic */ rtems_shell_main_rm, /* command */ NULL, /* alias */ diff --git a/cpukit/libmisc/shell/print-ls.c b/cpukit/libmisc/shell/print-ls.c new file mode 100644 index 0000000000..de7e757cf8 --- /dev/null +++ b/cpukit/libmisc/shell/print-ls.c @@ -0,0 +1,480 @@ +/* $NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94"; +#else +__RCSID("$NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $"); +#endif +#endif /* not lint */ +#endif + +#include <rtems.h> +#include <rtems/libio.h> + +#include <sys/param.h> +#include <sys/stat.h> + +#include <err.h> +#include <errno.h> +#include <fts.h> +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +//#include <tzfile.h> +#include <unistd.h> +//#include <util.h> + +#include "extern-ls.h" + +#if RTEMS_REMOVED +extern int termwidth; +#endif + +static int printaname(rtems_shell_ls_globals* globals, FTSENT *, int, int); +static void printlink(rtems_shell_ls_globals* globals, FTSENT *); +static void printtime(rtems_shell_ls_globals* globals, time_t); +static int printtype(u_int); + +#if RTEMS_REMOVED +static time_t now; +#endif + +#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) + +void +printscol(rtems_shell_ls_globals* globals, DISPLAY *dp) +{ + FTSENT *p; + + for (p = dp->list; p; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + (void)printaname(globals, p, dp->s_inode, dp->s_block); + (void)putchar('\n'); + } +} + +void +printlong(rtems_shell_ls_globals* globals, DISPLAY *dp) +{ + struct stat *sp; + FTSENT *p; + NAMES *np; + char buf[20]; //, szbuf[5]; + + now = time(NULL); + + if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) { +#if RTEMS_REMOVED + if (f_humanize) { + if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal, + "", HN_AUTOSCALE, + (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) + err(exit_jump, 1, "humanize_number"); + (void)printf("total %s\n", szbuf); + } else { +#endif + (void)printf("total %llu\n", + (long long)(howmany(dp->btotal, blocksize))); +#if RTEMS_REMOVED + } +#endif + } + + for (p = dp->list; p; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + sp = p->fts_statp; + if (f_inode) + (void)printf("%*lu ", dp->s_inode, + (unsigned long)sp->st_ino); + if (f_size && !f_humanize) { + (void)printf("%*llu ", dp->s_block, + (long long)howmany(sp->st_blocks, blocksize)); + } + (void)strmode(sp->st_mode, buf); + np = p->fts_pointer; + (void)printf("%s %*lu ", buf, dp->s_nlink, + (unsigned long)sp->st_nlink); + if (!f_grouponly) + (void)printf("%-*s ", dp->s_user, np->user); + (void)printf("%-*s ", dp->s_group, np->group); + if (f_flags) + (void)printf("%-*s ", dp->s_flags, np->flags); + if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) + (void)printf("%*lu, %*lu ", + dp->s_major, major(sp->st_rdev), dp->s_minor, + minor(sp->st_rdev)); + else +#if RTEMS_REMOVED + if (f_humanize) { + if ((humanize_number(szbuf, sizeof(szbuf), + sp->st_size, "", HN_AUTOSCALE, + (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) + err(1, "humanize_number"); + (void)printf("%*s ", dp->s_size, szbuf); + } else { +#endif + (void)printf("%*llu ", dp->s_size, + (long long)sp->st_size); +#if RTEMS_REMOVED + } +#endif + if (f_accesstime) + printtime(globals, sp->st_atime); + else if (f_statustime) + printtime(globals, sp->st_ctime); + else + printtime(globals, sp->st_mtime); + if (f_octal || f_octal_escape) + (void)safe_print(globals, p->fts_name); + else if (f_nonprint) + (void)printescaped(globals, p->fts_name); + else + (void)printf("%s", p->fts_name); + + if (f_type || (f_typedir && S_ISDIR(sp->st_mode))) + (void)printtype(sp->st_mode); + if (S_ISLNK(sp->st_mode)) + printlink(globals, p); + (void)putchar('\n'); + } +} + +void +printcol(rtems_shell_ls_globals* globals, DISPLAY *dp) +{ + static FTSENT **array; + static int lastentries = -1; + FTSENT *p; + int base, chcnt, col, colwidth, num; + int numcols, numrows, row; + //char szbuf[5]; + + colwidth = dp->maxlen; + if (f_inode) + colwidth += dp->s_inode + 1; + if (f_size) { + if (f_humanize) + colwidth += dp->s_size + 1; + else + colwidth += dp->s_block + 1; + } + if (f_type || f_typedir) + colwidth += 1; + + colwidth += 1; + + if (termwidth < 2 * colwidth) { + printscol(globals, dp); + return; + } + + /* + * Have to do random access in the linked list -- build a table + * of pointers. + */ + if (dp->entries > lastentries) { + lastentries = dp->entries; + if ((array = + realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { + warn(NULL); + printscol(globals, dp); + } + } + for (p = dp->list, num = 0; p; p = p->fts_link) + if (p->fts_number != NO_PRINT) + array[num++] = p; + + numcols = termwidth / colwidth; + colwidth = termwidth / numcols; /* spread out if possible */ + numrows = num / numcols; + if (num % numcols) + ++numrows; + + if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) { +#if RTEMS_REMOVED + if (f_humanize) { + if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal, + "", HN_AUTOSCALE, + (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) + err(1, "humanize_number"); + (void)printf("total %s\n", szbuf); + } else { +#endif + (void)printf("total %llu\n", + (long long)(howmany(dp->btotal, blocksize))); +#if RTEMS_REMOVED + } +#endif + } + for (row = 0; row < numrows; ++row) { + for (base = row, chcnt = col = 0; col < numcols; ++col) { + chcnt = printaname(globals, array[base], dp->s_inode, + f_humanize && 0 ? dp->s_size : dp->s_block); + if ((base += numrows) >= num) + break; + while (chcnt++ < colwidth) + (void)putchar(' '); + } + (void)putchar('\n'); + } +} + +void +printacol(rtems_shell_ls_globals* globals, DISPLAY *dp) +{ + FTSENT *p; + int chcnt, col, colwidth; + int numcols; + //char szbuf[5]; + + colwidth = dp->maxlen; + if (f_inode) + colwidth += dp->s_inode + 1; + if (f_size) { + if (f_humanize) + colwidth += dp->s_size + 1; + else + colwidth += dp->s_block + 1; + } + if (f_type || f_typedir) + colwidth += 1; + + colwidth += 1; + + if (termwidth < 2 * colwidth) { + printscol(globals, dp); + return; + } + + numcols = termwidth / colwidth; + colwidth = termwidth / numcols; /* spread out if possible */ + + if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) { +#if RTEMS_REMOVED + if (f_humanize) { + if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal, + "", HN_AUTOSCALE, + (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) + err(1, "humanize_number"); + (void)printf("total %s\n", szbuf); + } else { +#endif + (void)printf("total %llu\n", + (long long)(howmany(dp->btotal, blocksize))); +#if RTEMS_REMOVED + } +#endif + } + chcnt = col = 0; + for (p = dp->list; p; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + if (col >= numcols) { + chcnt = col = 0; + (void)putchar('\n'); + } + chcnt = printaname(globals, p, dp->s_inode, + f_humanize && 0 ? dp->s_size : dp->s_block); + while (chcnt++ < colwidth) + (void)putchar(' '); + col++; + } + (void)putchar('\n'); +} + +void +printstream(rtems_shell_ls_globals* globals, DISPLAY *dp) +{ + FTSENT *p; + int col; + int extwidth; + + extwidth = 0; + if (f_inode) + extwidth += dp->s_inode + 1; + if (f_size) { + if (f_humanize) + extwidth += dp->s_size + 1; + else + extwidth += dp->s_block + 1; + } + if (f_type) + extwidth += 1; + + for (col = 0, p = dp->list; p != NULL; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + if (col > 0) { + (void)putchar(','), col++; + if (col + 1 + extwidth + p->fts_namelen >= termwidth) + (void)putchar('\n'), col = 0; + else + (void)putchar(' '), col++; + } + col += printaname(globals, p, dp->s_inode, + f_humanize && 0 ? dp->s_size : dp->s_block); + } + (void)putchar('\n'); +} + +/* + * print [inode] [size] name + * return # of characters printed, no trailing characters. + */ +static int +printaname(rtems_shell_ls_globals* globals, + FTSENT *p, int inodefield, int sizefield) +{ + struct stat *sp; + int chcnt; + //char szbuf[5]; + + sp = p->fts_statp; + chcnt = 0; + if (f_inode) + chcnt += printf("%*lu ", inodefield, (unsigned long)sp->st_ino); + if (f_size) { +#if RTEMS_REMOVED + if (f_humanize) { + if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size, + "", HN_AUTOSCALE, + (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) + err(1, "humanize_number"); + chcnt += printf("%*s ", sizefield, szbuf); + } else { +#endif + chcnt += printf("%*llu ", sizefield, + (long long)howmany(sp->st_blocks, blocksize)); +#if RTEMS_REMOVED + } +#endif + } + if (f_octal || f_octal_escape) + chcnt += safe_print(globals, p->fts_name); + else if (f_nonprint) + chcnt += printescaped(globals, p->fts_name); + else + chcnt += printf("%s", p->fts_name); + if (f_type || (f_typedir && S_ISDIR(sp->st_mode))) + chcnt += printtype(sp->st_mode); + return (chcnt); +} + +static void +printtime(rtems_shell_ls_globals* globals, time_t ftime) +{ + int i; + char *longstring; + + longstring = ctime(&ftime); + for (i = 4; i < 11; ++i) + (void)putchar(longstring[i]); + +#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) + if (f_sectime) + for (i = 11; i < 24; i++) + (void)putchar(longstring[i]); + else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now) + for (i = 11; i < 16; ++i) + (void)putchar(longstring[i]); + else { + (void)putchar(' '); + for (i = 20; i < 24; ++i) + (void)putchar(longstring[i]); + } + (void)putchar(' '); +} + +static int +printtype(u_int mode) +{ + switch (mode & S_IFMT) { + case S_IFDIR: + (void)putchar('/'); + return (1); + case S_IFIFO: + (void)putchar('|'); + return (1); + case S_IFLNK: + (void)putchar('@'); + return (1); + case S_IFSOCK: + (void)putchar('='); + return (1); +#if RTEMS_REMOVED + case S_IFWHT: + (void)putchar('%'); + return (1); +#endif + } + if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { + (void)putchar('*'); + return (1); + } + return (0); +} + +static void +printlink(rtems_shell_ls_globals* globals, FTSENT *p) +{ + int lnklen; + char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; + + if (p->fts_level == FTS_ROOTLEVEL) + (void)snprintf(name, sizeof(name), "%s", p->fts_name); + else + (void)snprintf(name, sizeof(name), + "%s/%s", p->fts_parent->fts_accpath, p->fts_name); + if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { + (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); + return; + } + path[lnklen] = '\0'; + (void)printf(" -> "); + if (f_octal || f_octal_escape) + (void)safe_print(globals, path); + else if (f_nonprint) + (void)printescaped(globals, path); + else + (void)printf("%s", path); +} diff --git a/cpukit/libmisc/shell/pwcache.c b/cpukit/libmisc/shell/pwcache.c new file mode 100644 index 0000000000..6b50bd6eb1 --- /dev/null +++ b/cpukit/libmisc/shell/pwcache.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/lib/libc/gen/pwcache.c,v 1.11 2007/01/09 00:27:55 imp Exp $"); + +#include <sys/types.h> + +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include <string.h> +//#include <utmp.h> + +#define UT_NAMESIZE 64 + +#define NCACHE 64 /* power of 2 */ +#define MASK (NCACHE - 1) /* bits to store with */ + +const char * +user_from_uid(uid_t uid, int nouser) +{ + static struct ncache { + uid_t uid; + int found; + char name[UT_NAMESIZE + 1]; + } c_uid[NCACHE]; + static int pwopen; + struct passwd *pw; + struct ncache *cp; + + cp = c_uid + (uid & MASK); + if (cp->uid != uid || !*cp->name) { + if (pwopen == 0) { + //setpassent(1); + pwopen = 1; + } + pw = getpwuid(uid); + cp->uid = uid; + if (pw != NULL) { + cp->found = 1; + (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE); + cp->name[UT_NAMESIZE] = '\0'; + } else { + cp->found = 0; + (void)snprintf(cp->name, UT_NAMESIZE, "%u", uid); + if (nouser) + return (NULL); + } + } + return ((nouser && !cp->found) ? NULL : cp->name); +} + +char * +group_from_gid(gid_t gid, int nogroup) +{ + static struct ncache { + gid_t gid; + int found; + char name[UT_NAMESIZE + 1]; + } c_gid[NCACHE]; + static int gropen; + struct group *gr; + struct ncache *cp; + + cp = c_gid + (gid & MASK); + if (cp->gid != gid || !*cp->name) { + if (gropen == 0) { + //setgroupent(1); + gropen = 1; + } + gr = getgrgid(gid); + cp->gid = gid; + if (gr != NULL) { + cp->found = 1; + (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE); + cp->name[UT_NAMESIZE] = '\0'; + } else { + cp->found = 0; + (void)snprintf(cp->name, UT_NAMESIZE, "%u", gid); + if (nogroup) + return (NULL); + } + } + return ((nogroup && !cp->found) ? NULL : cp->name); +} + diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c index 3b002b5548..02f6bfbd4d 100644 --- a/cpukit/libmisc/shell/shell.c +++ b/cpukit/libmisc/shell/shell.c @@ -980,7 +980,7 @@ static rtems_status_code rtems_shell_run ( name, task_priority, task_stacksize, - RTEMS_DEFAULT_MODES, + RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR, RTEMS_LOCAL | RTEMS_FLOATING_POINT, &task_id ); diff --git a/cpukit/libmisc/shell/utils-cp.c b/cpukit/libmisc/shell/utils-cp.c index defd5dd021..6c525c982f 100644 --- a/cpukit/libmisc/shell/utils-cp.c +++ b/cpukit/libmisc/shell/utils-cp.c @@ -465,11 +465,11 @@ preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir) } void -usage(void) +usage(rtems_shell_cp_globals* cp_globals) { - (void)fprintf(stderr, "%s\n%s\n", "usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file", " cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... " "target_directory"); + longjmp (cp_globals->exit_jmp, 1); } diff --git a/cpukit/libmisc/shell/utils-ls.c b/cpukit/libmisc/shell/utils-ls.c new file mode 100644 index 0000000000..c7629e786a --- /dev/null +++ b/cpukit/libmisc/shell/utils-ls.c @@ -0,0 +1,113 @@ +/* $NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95"; +#else +__RCSID("$NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $"); +#endif +#endif /* not lint */ +#endif + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <fts.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vis.h> + +#include "extern-ls.h" + +#define SIZE_T_MAX 255 + +int +safe_print(rtems_shell_ls_globals* globals, const char *src) +{ + size_t len; + char *name; + int flags; + + flags = VIS_NL | VIS_OCTAL; + if (f_octal_escape) + flags |= VIS_CSTYLE; + + len = strlen(src); + if (len != 0 && SIZE_T_MAX/len <= 4) { + errx(exit_jump, EXIT_FAILURE, "%s: name too long", src); + /* NOTREACHED */ + } + + name = (char *)malloc(4*len+1); + if (name != NULL) { + len = strvis(name, src, flags); + printf("%s", name); + free(name); + return len; + } else + errx(exit_jump, EXIT_FAILURE, "out of memory!"); + /* NOTREACHED */ +} + +int +printescaped(rtems_shell_ls_globals* globals, const char *src) +{ + unsigned char c; + int n; + + for (n = 0; (c = *src) != '\0'; ++src, ++n) + if (isprint(c)) + (void)putchar(c); + else + (void)putchar('?'); + return n; +} + +void +usage(rtems_shell_ls_globals* globals) +{ + + (void)fprintf(stderr, + "usage: %s [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n", + "ls"); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} diff --git a/cpukit/libmisc/shell/vis.c b/cpukit/libmisc/shell/vis.c new file mode 100644 index 0000000000..3ae560d53b --- /dev/null +++ b/cpukit/libmisc/shell/vis.c @@ -0,0 +1,384 @@ +/* $NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define _DIAGASSERT(a) + +#if 0 +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $"); +#endif /* LIBC_SCCS and not lint */ +#endif + +#include <sys/types.h> + +#include <assert.h> +#include <vis.h> +#include <stdlib.h> + +#if !HAVE_VIS || !HAVE_SVIS +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#undef BELL +#define BELL '\a' + +#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') +#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') +#define issafe(c) (c == '\b' || c == BELL || c == '\r') +#define xtoa(c) "0123456789abcdef"[c] + +#define MAXEXTRAS 5 + + +#define MAKEEXTRALIST(flag, extra, orig) \ +do { \ + const char *o = orig; \ + char *e; \ + while (*o++) \ + continue; \ + extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ + if (!extra) break; \ + for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ + continue; \ + e--; \ + if (flag & VIS_SP) *e++ = ' '; \ + if (flag & VIS_TAB) *e++ = '\t'; \ + if (flag & VIS_NL) *e++ = '\n'; \ + if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ + *e = '\0'; \ +} while (/*CONSTCOND*/0) + + +/* + * This is HVIS, the macro of vis used to HTTP style (RFC 1808) + */ +#define HVIS(dst, c, flag, nextc, extra) \ +do \ + if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \ + *dst++ = '%'; \ + *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \ + *dst++ = xtoa((unsigned int)c & 0xf); \ + } else { \ + SVIS(dst, c, flag, nextc, extra); \ + } \ +while (/*CONSTCOND*/0) + +/* + * This is SVIS, the central macro of vis. + * dst: Pointer to the destination buffer + * c: Character to encode + * flag: Flag word + * nextc: The character following 'c' + * extra: Pointer to the list of extra characters to be + * backslash-protected. + */ +#define SVIS(dst, c, flag, nextc, extra) \ +do { \ + int isextra; \ + isextra = strchr(extra, c) != NULL; \ + if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \ + ((flag & VIS_SAFE) && issafe(c)))) { \ + *dst++ = c; \ + break; \ + } \ + if (flag & VIS_CSTYLE) { \ + switch (c) { \ + case '\n': \ + *dst++ = '\\'; *dst++ = 'n'; \ + continue; \ + case '\r': \ + *dst++ = '\\'; *dst++ = 'r'; \ + continue; \ + case '\b': \ + *dst++ = '\\'; *dst++ = 'b'; \ + continue; \ + case BELL: \ + *dst++ = '\\'; *dst++ = 'a'; \ + continue; \ + case '\v': \ + *dst++ = '\\'; *dst++ = 'v'; \ + continue; \ + case '\t': \ + *dst++ = '\\'; *dst++ = 't'; \ + continue; \ + case '\f': \ + *dst++ = '\\'; *dst++ = 'f'; \ + continue; \ + case ' ': \ + *dst++ = '\\'; *dst++ = 's'; \ + continue; \ + case '\0': \ + *dst++ = '\\'; *dst++ = '0'; \ + if (isoctal(nextc)) { \ + *dst++ = '0'; \ + *dst++ = '0'; \ + } \ + continue; \ + default: \ + if (isgraph(c)) { \ + *dst++ = '\\'; *dst++ = c; \ + continue; \ + } \ + } \ + } \ + if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \ + *dst++ = '\\'; \ + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \ + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \ + *dst++ = (c & 07) + '0'; \ + } else { \ + if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \ + if (c & 0200) { \ + c &= 0177; *dst++ = 'M'; \ + } \ + if (iscntrl(c)) { \ + *dst++ = '^'; \ + if (c == 0177) \ + *dst++ = '?'; \ + else \ + *dst++ = c + '@'; \ + } else { \ + *dst++ = '-'; *dst++ = c; \ + } \ + } \ +} while (/*CONSTCOND*/0) + + +/* + * svis - visually encode characters, also encoding the characters + * pointed to by `extra' + */ +char * +svis(char *dst, int c, int flag, int nextc, const char *extra) +{ + char *nextra = NULL; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return dst; + } + if (flag & VIS_HTTPSTYLE) + HVIS(dst, c, flag, nextc, nextra); + else + SVIS(dst, c, flag, nextc, nextra); + free(nextra); + *dst = '\0'; + return dst; +} + + +/* + * strsvis, strsvisx - visually encode characters from src into dst + * + * Extra is a pointer to a \0-terminated list of characters to + * be encoded, too. These functions are useful e. g. to + * encode strings in such a way so that they are not interpreted + * by a shell. + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strsvisx encodes exactly len bytes from src into dst. + * This is useful for encoding a block of data. + */ +int +strsvis(char *dst, const char *csrc, int flag, const char *extra) +{ + int c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + if (flag & VIS_HTTPSTYLE) { + for (start = dst; (c = *src++) != '\0'; /* empty */) + HVIS(dst, c, flag, *src, nextra); + } else { + for (start = dst; (c = *src++) != '\0'; /* empty */) + SVIS(dst, c, flag, *src, nextra); + } + free(nextra); + *dst = '\0'; + return (dst - start); +} + + +int +strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) +{ + unsigned char c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (! nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + + if (flag & VIS_HTTPSTYLE) { + for (start = dst; len > 0; len--) { + c = *src++; + HVIS(dst, c, flag, len ? *src : '\0', nextra); + } + } else { + for (start = dst; len > 0; len--) { + c = *src++; + SVIS(dst, c, flag, len ? *src : '\0', nextra); + } + } + free(nextra); + *dst = '\0'; + return (dst - start); +} +#endif + +#if !HAVE_VIS +/* + * vis - visually encode characters + */ +char * +vis(char *dst, int c, int flag, int nextc) +{ + char *extra = NULL; + unsigned char uc = (unsigned char)c; + + _DIAGASSERT(dst != NULL); + + MAKEEXTRALIST(flag, extra, ""); + if (! extra) { + *dst = '\0'; /* can't create extra, return "" */ + return dst; + } + if (flag & VIS_HTTPSTYLE) + HVIS(dst, uc, flag, nextc, extra); + else + SVIS(dst, uc, flag, nextc, extra); + free(extra); + *dst = '\0'; + return dst; +} + + +/* + * strvis, strvisx - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strvisx encodes exactly len bytes from src into dst. + * This is useful for encoding a block of data. + */ +int +strvis(char *dst, const char *src, int flag) +{ + char *extra = NULL; + int rv; + + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvis(dst, src, flag, extra); + free(extra); + return rv; +} + + +int +strvisx(char *dst, const char *src, size_t len, int flag) +{ + char *extra = NULL; + int rv; + + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvisx(dst, src, len, flag, extra); + free(extra); + return rv; +} +#endif diff --git a/cpukit/libmisc/shell/vis.h b/cpukit/libmisc/shell/vis.h new file mode 100644 index 0000000000..fb0aa6dc2a --- /dev/null +++ b/cpukit/libmisc/shell/vis.h @@ -0,0 +1,91 @@ +/* $NetBSD: vis.h,v 1.16 2005/09/13 01:44:32 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vis.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _VIS_H_ +#define _VIS_H_ + +#include <sys/types.h> + +/* + * to select alternate encoding format + */ +#define VIS_OCTAL 0x01 /* use octal \ddd format */ +#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */ + +/* + * to alter set of characters encoded (default is to encode all + * non-graphic except space, tab, and newline). + */ +#define VIS_SP 0x04 /* also encode space */ +#define VIS_TAB 0x08 /* also encode tab */ +#define VIS_NL 0x10 /* also encode newline */ +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#define VIS_SAFE 0x20 /* only encode "unsafe" characters */ + +/* + * other + */ +#define VIS_NOSLASH 0x40 /* inhibit printing '\' */ +#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */ + +/* + * unvis return codes + */ +#define UNVIS_VALID 1 /* character valid */ +#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ +#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ +#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ +#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ + +/* + * unvis flags + */ +#define UNVIS_END 1 /* no more characters */ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +char *vis(char *, int, int, int); +char *svis(char *, int, int, int, const char *); +int strvis(char *, const char *, int); +int strsvis(char *, const char *, int, const char *); +int strvisx(char *, const char *, size_t, int); +int strsvisx(char *, const char *, size_t, int, const char *); +int strunvis(char *, const char *); +int strunvisx(char *, const char *, int); +#ifndef __LIBC12_SOURCE__ +//int unvis(char *, int, int *, int) __RENAME(__unvis13); +#endif +__END_DECLS + +#endif /* !_VIS_H_ */ |