diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2014-08-27 17:14:13 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2014-08-27 17:14:13 +0200 |
commit | 727dd67821e4581e4b61b30b79ca47c5bffc8497 (patch) | |
tree | d5be61f067a42b2633ef148f416f138e7c2f7da2 /package/sash/src/ls.c | |
parent | 683cf71a6ebccbd4f827ad4a6ac92dbbaf8f644d (diff) | |
parent | 008d0e157538e4a4c302dc79e6c28c9da615b527 (diff) |
Merge branch 'master' of git+ssh://openadk.org/git/openadk
Diffstat (limited to 'package/sash/src/ls.c')
-rw-r--r-- | package/sash/src/ls.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/package/sash/src/ls.c b/package/sash/src/ls.c new file mode 100644 index 000000000..9b337aeaa --- /dev/null +++ b/package/sash/src/ls.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 1993 by David I. Bell + * Permission is granted to use, distribute, or modify this source, + * provided that this copyright notice remains intact. + * + * The "ls" built-in command. + */ + +#include "sash.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <dirent.h> +#include <pwd.h> +#include <grp.h> +#include <time.h> + +#define LISTSIZE 256 + +#define COLWIDTH 20 + +#ifdef S_ISLNK +#define LSTAT lstat +#else +#define LSTAT stat +#endif + + +/* + * Flags for the LS command. + */ +#define LSF_LONG 0x01 +#define LSF_DIR 0x02 +#define LSF_INODE 0x04 +#define LSF_MULT 0x08 +#define LSF_ALL 0x10 +#define LSF_COMPACT 0x20 + + +static char **list; +static int listsize; +static int listused; +static int linelen = 0; + + +static void lsfile(); + + +void +do_ls(argc, argv) + int argc; + char **argv; +{ + char *cp; + char *name; + int flags; + int i; + DIR *dirp; + BOOL endslash; + char **newlist; + struct dirent *dp; + char fullname[PATHLEN]; + struct stat statbuf; + static char *def[2]; + + if (listsize == 0) { + list = (char **) malloc(LISTSIZE * sizeof(char *)); + if (list == NULL) { + fprintf(stderr, "No memory for ls buffer\n"); + return; + } + listsize = LISTSIZE; + } + listused = 0; + + flags = 0; + if ((argc > 1) && (argv[1][0] == '-')) + { + argc--; + cp = *(++argv) + 1; + + while (*cp) switch (*cp++) { + case 'l': flags |= LSF_LONG; break; + case 'd': flags |= LSF_DIR; break; + case 'i': flags |= LSF_INODE; break; + case 'a': flags |= LSF_ALL; break; + case 'C': flags |= LSF_COMPACT; break; + default: + fprintf(stderr, "Unknown option -%c\n", cp[-1]); + return; + } + } + + if ((flags & LSF_COMPACT) && (flags & ~LSF_COMPACT)) { + fprintf(stderr, "Cannot do compact list with other options\n"); + return; + } + + if (argc <= 1) { + argc = 2; + argv = def; + argv[0] = "ls"; + argv[1] = "."; + } + + if (argc > 2) + flags |= LSF_MULT; + + while (argc-- > 1) { + name = *(++argv); + endslash = (*name && (name[strlen(name) - 1] == '/')); + + if (LSTAT(name, &statbuf) < 0) { + perror(name); + continue; + } + + if ((flags & LSF_DIR) || (!S_ISDIR(statbuf.st_mode))) { + lsfile(name, &statbuf, flags); + continue; + } + + /* + * Do all the files in a directory. + */ + dirp = opendir(name); + if (dirp == NULL) { + perror(name); + continue; + } + + if (flags & LSF_MULT) + printf("\n%s:\n", name); + + while ((dp = readdir(dirp)) != NULL) { + + if ((dp->d_name[0] == '.') && !(flags & LSF_ALL)) + continue; + + fullname[0] = '\0'; + + if ((*name != '.') || (name[1] != '\0')) { + strcpy(fullname, name); + if (!endslash) + strcat(fullname, "/"); + } + + strcat(fullname, dp->d_name); + + if (listused >= listsize) { + newlist = malloc((sizeof(char **)) * (listsize + LISTSIZE)); + if (newlist == NULL) { + fprintf(stderr, "No memory for ls buffer\n"); + break; + } + memcpy(newlist, list, sizeof(char**) * listsize); + free(list); + listsize += LISTSIZE; + } + + list[listused] = strdup(fullname); + if (list[listused] == NULL) { + fprintf(stderr, "No memory for filenames\n"); + break; + } + listused++; + } + + closedir(dirp); + + /* + * Sort the files. + */ + qsort((char *) list, listused, sizeof(char *), namesort); + + /* + * Now finally list the filenames. + */ + for (i = 0; i < listused; i++) { + name = list[i]; + + if (LSTAT(name, &statbuf) < 0) { + perror(name); + free(name); + continue; + } + + cp = strrchr(name, '/'); + if (cp) + cp++; + else + cp = name; + + lsfile(cp, &statbuf, flags); + + free(name); + } + + listused = 0; + } + + if (linelen) + fputc('\n', stdout); +} + + +/* + * Do an LS of a particular file name according to the flags. + */ +static void +lsfile(name, statbuf, flags) + char *name; + struct stat *statbuf; +{ + char *cp; + struct passwd *pwd; + struct group *grp; + int len; + char buf[PATHLEN]; + static char username[12]; + static int userid; + static BOOL useridknown; + static char groupname[12]; + static int groupid; + static BOOL groupidknown; + + cp = buf; + *cp = '\0'; + + if (flags & LSF_INODE) { + sprintf(cp, "%5d ", statbuf->st_ino); + cp += strlen(cp); + } + + if (flags & LSF_LONG) { + strcpy(cp, modestring(statbuf->st_mode)); + cp += strlen(cp); + + sprintf(cp, "%3d ", statbuf->st_nlink); + cp += strlen(cp); + + if (!useridknown || (statbuf->st_uid != userid)) { + /*pwd = getpwuid(statbuf->st_uid); + if (pwd) + strcpy(username, pwd->pw_name); + else*/ + sprintf(username, "%d", statbuf->st_uid); + userid = statbuf->st_uid; + useridknown = TRUE; + } + + sprintf(cp, "%-8s ", username); + cp += strlen(cp); + + if (!groupidknown || (statbuf->st_gid != groupid)) { + /*grp = getgrgid(statbuf->st_gid); + if (grp) + strcpy(groupname, grp->gr_name); + else*/ + sprintf(groupname, "%d", statbuf->st_gid); + groupid = statbuf->st_gid; + groupidknown = TRUE; + } + + sprintf(cp, "%-8s ", groupname); + cp += strlen(cp); + + if (S_ISBLK(statbuf->st_mode) || S_ISCHR(statbuf->st_mode)) + sprintf(cp, "%3d, %3d ", major(statbuf->st_rdev), + minor(statbuf->st_rdev)); + else + sprintf(cp, "%8d ", statbuf->st_size); + cp += strlen(cp); + + sprintf(cp, " %-12s ", timestring(statbuf->st_mtime)); + } + + fputs(buf, stdout); + fputs(name, stdout); + +#ifdef S_ISLNK + if ((flags & LSF_LONG) && S_ISLNK(statbuf->st_mode)) { + len = readlink(name, buf, PATHLEN - 1); + if (len >= 0) { + buf[len] = '\0'; + printf(" -> %s", buf); + } + } +#endif + + if (flags & LSF_COMPACT) { + len = strlen(name); + if (len < COLWIDTH) { + for (; (len < COLWIDTH); len++) + fputc(' ', stdout); + linelen += COLWIDTH; + } else { + linelen = 80; + } + + if (linelen >= 80) { + fputc('\n', stdout); + linelen = 0; + } + } else { + fputc('\n', stdout); + } +} + +/* END CODE */ |