home *** CD-ROM | disk | FTP | other *** search
- /*
- * fileops.c - display directory menu
- *
- * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
- *
- * Permission is hereby granted to copy, distribute or otherwise
- * use any part of this package as long as you do not try to make
- * money from it or pretend that you wrote it. This copyright
- * notice must be maintained in any copy made.
- *
- * Use of this software constitutes acceptance for use in an AS IS
- * condition. There are NO warranties with regard to this software.
- * In no event shall the author be liable for any damages whatsoever
- * arising out of or in connection with the use or performance of this
- * software. Any use of this software is at the user's own risk.
- *
- * If you make modifications to this software that you feel
- * increases it usefulness for the rest of the community, please
- * email the changes, enhancements, bug fixes as well as any and
- * all ideas to me. This software is going to be maintained and
- * enhanced as deemed necessary by the community.
- *
- * Patrick J. Wolfe
- * uunet!uiucuxc!kailand!pwolfe
- * pwolfe@kailand.kai.com
- */
-
- #include "config.h"
-
- extern long sixmonthsago;
- extern int opt_dot_order, opt_dotdir_order, opt_dir_order, opt_hide_dotdot,
- opt_show_filetype, opt_show_symlinks;
- extern int topptr, curptr, lastptr, COLS, namebufleft;
- extern char *sys_errlist[], errormsg[], *namebuf, *monthtable[];
-
- extern WINDOW *headwin, *datawin, *helpwin;
-
- struct stat sb;
- struct dblock cwd[MAXDIRSIZE];
- struct namelist lidlist[MAXLID];
- struct namelist gidlist[MAXGID];
- int lidend = -1, gidend = -1, hidden_ctr;
- char currdir[MAXPATHLEN], prevdir[MAXPATHLEN];
- char *emptystring = "", *nbptr;
-
-
- void
- statfile (ctr)
- int ctr;
- {
- struct passwd *pb;
- struct group *gb;
- struct tm *tb;
- struct stat sb2;
- int ctr2, permend = 0;
- #ifdef sequent
- int ctr3;
- #endif
- #ifdef S_IFLNK
- char ucblink[MAXPATHLEN];
- #ifdef sequent
- char attlink[MAXPATHLEN];
- #endif
- #endif
- char *ptr2;
-
-
- #ifdef S_IFLNK
- if (opt_show_symlinks)
- ctr2 = lstat (cwd[ctr].name, &sb); /* if showing links, then use "lstat()" to get status of the link */
- else
- #endif
- ctr2 = stat (cwd[ctr].name, &sb);
-
- if (ctr2 != 0) {
- cwd[ctr].size = -1;
- cwd[ctr].selected = 0; /* unselect it */
- if (errno == ENOENT) { /* store error message for display */
- for (cwd[ctr].link = nbptr, ptr2 = "deleted";
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- /* move to the next character in the file name buffer */
- namebufleft--;
- nbptr++;
- }
- else {
- for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
-
- /* move to the next character in the file name buffer */
- namebufleft--;
- nbptr++;
- }
- if (namebufleft <= 0) {
- fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
- die ();
- }
- return;
- }
-
- /* if this hasn't changed - don't waste any more time */
- if ((cwd[ctr].size != -1) && (cwd[ctr].ctime == sb.st_ctime)) {
- return;
- }
-
- /* make link point to an empty string, so we don't have to check for NULL */
- cwd[ctr].link = emptystring;
-
- /*
- * determine filetype - we want to do this first, because if it's a symbolic
- * link, we would prefer info about the file being pointed to
- */
- cwd[ctr].type = sb.st_mode & S_IFMT;
-
- if (cwd[ctr].type == S_IFREG) {
- cwd[ctr].perms[0] = '-';
- }
- else if (cwd[ctr].type == S_IFDIR) {
- cwd[ctr].perms[0] = 'd';
- }
- else if (cwd[ctr].type == S_IFBLK) {
- cwd[ctr].perms[0] = 'b';
- }
- else if (cwd[ctr].type == S_IFCHR) {
- cwd[ctr].perms[0] = 'c';
- }
-
- #ifdef S_IFSOCK
- else if (cwd[ctr].type == S_IFSOCK) {
- cwd[ctr].perms[0] = 's';
- }
- #endif /* S_IFSOCK */
-
- #ifdef S_IFIFO
- else if (cwd[ctr].type == S_IFIFO) {
- cwd[ctr].perms[0] = 'f';
- }
- #endif /* S_IFIFO */
-
- #ifdef S_IFLNK
-
- #ifdef sequent
- /* check for conditional symbolic link before regular symbolic link */
- else if ((cwd[ctr].type == S_IFLNK) && (sb.st_spare4[0] == 1)) {
- if (stat (cwd[ctr].name, &sb2) == 0) {
- BCOPY ((char *) &sb2, (char *)&sb, sizeof (struct stat)); /* use stats of the pointed at thing */
- cwd[ctr].type = sb.st_mode & S_IFMT; /* get the actual file type */
- }
- cwd[ctr].perms[0] = 'l';
- if (((ctr2 = readclink (cwd[ctr].name, ucblink, MAXPATHLEN, U_UCB)) == -1)
- || ((ctr3 = readclink (cwd[ctr].name, attlink, MAXPATHLEN, U_ATT)) == -1)) {
- for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
-
- /* move to the next character in the file name buffer */
- namebufleft--;
- nbptr++;
- }
- else {
- ucblink[ctr2] = '\0'; /* readclink does not null terminate it's filename */
- attlink[ctr3] = '\0'; /* readclink does not null terminate it's filename */
- for (cwd[lastptr].link = nbptr, ptr2 = " -> ucb=";
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- for (ptr2 = ucblink;
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- for (ptr2 = " att=";
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- for (ptr2 = attlink;
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- namebufleft--;
- nbptr++;
- }
- if (namebufleft <= 0) {
- fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
- die ();
- }
- }
- #endif /* sequent */
-
- else if (cwd[ctr].type == S_IFLNK) {
- if (stat (cwd[ctr].name, &sb2) == 0) {
- BCOPY ((char *) &sb2, (char *)&sb, sizeof (struct stat)); /* use stats of the pointed at thing */
- cwd[ctr].type = sb.st_mode & S_IFMT; /* get the actual file type */
- }
- cwd[ctr].perms[0] = 'l';
- if ((ctr2 = readlink (cwd[ctr].name, ucblink, MAXPATHLEN)) == -1) {
- for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
-
- /* move to the next character in the file name buffer */
- namebufleft--;
- nbptr++;
- }
- else {
- ucblink[ctr2] = '\0'; /* readlink does not null terminate it's filename */
- for (cwd[lastptr].link = nbptr, ptr2 = " -> ";
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- for (ptr2 = ucblink;
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
- namebufleft--;
- nbptr++;
- }
- if (namebufleft <= 0) {
- fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
- die ();
- }
- }
- #endif /* S_IFLNK */
-
- else {
- cwd[ctr].perms[0] = '?'; /* unknown */
- }
-
- cwd[ctr].perms[++permend] = (sb.st_mode & 0400 ? 'r' : '-'); /* owners permissions */
- cwd[ctr].perms[++permend] = (sb.st_mode & 0200 ? 'w' : '-');
- cwd[ctr].perms[++permend] = ((sb.st_mode & 04000) && (sb.st_mode & 0100) ? 's' :
- sb.st_mode & 04000 ? 'S' : sb.st_mode & 0100 ? 'x' : '-');
- cwd[ctr].perms[++permend] = (sb.st_mode & 040 ? 'r' : '-'); /* group permissions */
- cwd[ctr].perms[++permend] = (sb.st_mode & 020 ? 'w' : '-');
- cwd[ctr].perms[++permend] = ((sb.st_mode & 02000) && (sb.st_mode & 010) ? 's' :
- sb.st_mode & 02000 ? 'S' : sb.st_mode & 010 ? 'x' : '-');
- cwd[ctr].perms[++permend] = (sb.st_mode & 04 ? 'r' : '-'); /* others permissions */
- cwd[ctr].perms[++permend] = (sb.st_mode & 02 ? 'w' : '-');
- cwd[ctr].perms[++permend] = ((sb.st_mode & 01000) && (sb.st_mode & 01) ? 't' :
- sb.st_mode & 01000 ? 'T' : sb.st_mode & 01 ? 'x' : '-');
- cwd[ctr].perms[++permend] = '\0';
-
- if (opt_show_filetype && (cwd[ctr].link[0] == '\0')) {
- if (cwd[ctr].perms[0] == 'd') {
- cwd[ctr].link = "/";
- }
- else if ((cwd[ctr].perms[0] == '-') && ((sb.st_mode & 0111) != 0)) {
- cwd[ctr].link = "*";
- }
- }
-
- if ((cwd[ctr].owner == -1) || (lidlist[cwd[ctr].owner].number != sb.st_uid)) {
- for (ctr2 = 0; (cwd[ctr].owner == -1) && (ctr2 <= lidend); ctr2++) {
- if (lidlist[ctr2].number == sb.st_uid) {
- cwd[ctr].owner = ctr2;
- }
- }
- if (cwd[ctr].owner == -1) { /* didn't already have user name */
- if (lidend >= MAXLID) { /* store for future files */
- fprintf (stderr, "MAXLID is too low - reset and recompile\n");
- die ();
- }
- lidend++;
- cwd[ctr].owner = lidend;
- lidlist[lidend].number = sb.st_uid;
- if ((pb = getpwuid(sb.st_uid)) == NULL) {
- sprintf (lidlist[lidend].name, "%d", sb.st_uid);
- }
- else {
- strcpy (lidlist[lidend].name, pb->pw_name);
- }
- }
- }
-
- if ((cwd[ctr].group == -1) || (gidlist[cwd[ctr].group].number != sb.st_gid)) {
- for (ctr2 = 0; (cwd[ctr].group == -1) && (ctr2 <= gidend); ctr2++) {
- if (gidlist[ctr2].number == sb.st_gid) {
- cwd[ctr].group = ctr2;
- }
- }
- if (cwd[ctr].group == -1) { /* didn't already have group name */
- if (gidend >= MAXGID) { /* store for future files */
- fprintf (stderr, "MAXGID is too low - reset and recompile\n");
- die ();
- }
- gidend++;
- cwd[ctr].group = gidend;
- gidlist[gidend].number = sb.st_gid;
- if ((gb = (struct group *) getgrgid(sb.st_gid)) == (struct group *) NULL) {
- sprintf (gidlist[gidend].name, "%d", sb.st_gid);
- }
- else {
- strcpy (gidlist[gidend].name, gb->gr_name);
- }
- }
- }
-
- /* like ls, if it's over six months old, display the year instead of the time */
- tb = localtime (&sb.st_mtime);
- if (sb.st_mtime < sixmonthsago)
- sprintf (cwd[ctr].modtime, "%3s %02d %04d ", monthtable[tb->tm_mon], tb->tm_mday, 1900 + tb->tm_year);
- else
- sprintf (cwd[ctr].modtime, "%3s %02d %02d:%02d", monthtable[tb->tm_mon], tb->tm_mday, tb->tm_hour, tb->tm_min);
-
- cwd[ctr].size = sb.st_size;
- cwd[ctr].ctime = sb.st_ctime;
- }
-
-
- int
- sortdirfirst (a, b)
- struct dblock *a, *b;
- {
- int aisdir, bisdir;
-
- if (opt_dir_order != DIR_SORT) { /* if not mixing dirs and files, sort between dirs and files */
- if (a->size != -1)
- aisdir = (a->type == S_IFDIR);
- else if (stat (a->name, &sb) == 0)
- aisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
- else
- aisdir = 0;
- if (b->size != -1)
- bisdir = (b->type == S_IFDIR);
- else if (stat (b->name, &sb) == 0)
- bisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
- else
- bisdir = 0;
- if (aisdir && ! bisdir) {
- return (opt_dir_order == DIR_LAST ? 1 : -1);
- }
- if (! aisdir && bisdir) {
- return (opt_dir_order == DIR_LAST ? -1 : 1);
- }
- }
-
- if (opt_dot_order != DOT_HIDE) { /* if not hiding dot files, sort between dot and non-dot files now */
- if ((a->name[0] == '.') && (b->name[0] != '.')) {
- return (opt_dot_order == DOT_LAST ? 1 : -1);
- }
- else if ((a->name[0] != '.') && (b->name[0] == '.')) {
- return (opt_dot_order == DOT_LAST ? -1 : 1);
- }
- }
-
- return (strncmp (a->name, b->name, 16)); /* sort alphabetically by name */
- }
-
-
- int
- sortdotfirst (a, b)
- struct dblock *a, *b;
- {
- int aisdir, bisdir;
-
- if (opt_dot_order != DOT_HIDE) { /* if not hiding dot files, sort between dot and non-dot files now */
- if ((a->name[0] == '.') && (b->name[0] != '.')) {
- return (opt_dot_order == DOT_LAST ? 1 : -1);
- }
- else if ((a->name[0] != '.') && (b->name[0] == '.')) {
- return (opt_dot_order == DOT_LAST ? -1 : 1);
- }
- }
-
- if (opt_dir_order != DIR_SORT) { /* if not mixing dirs and files, sort between dirs and files */
- if (a->size != -1)
- aisdir = (a->type == S_IFDIR);
- else if (stat (a->name, &sb) == 0)
- aisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
- else
- aisdir = 0;
- if (b->size != -1)
- bisdir = (b->type == S_IFDIR);
- else if (stat (b->name, &sb) == 0)
- bisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
- else
- bisdir = 0;
- if (aisdir && ! bisdir) {
- return (opt_dir_order == DIR_LAST ? 1 : -1);
- }
- if (! aisdir && bisdir) {
- return (opt_dir_order == DIR_LAST ? -1 : 1);
- }
- }
-
- return (strncmp (a->name, b->name, 16)); /* sort alphabetically by name */
- }
-
-
- void
- do_chdir (dirname)
- char *dirname;
- {
- DIR *dirp;
- struct timeval tp;
- struct direct *dp;
- Function *sortroutine;
- char *ptr2;
-
- gettimeofday (&tp, 0);
- sixmonthsago = tp.tv_sec - (60 * 60 * 24 * 180); /* time 180 days (6 months) ago */
-
- hidden_ctr = 0;
-
- if ((chdir (dirname) == -1) || ((dirp = opendir(".")) == NULL)) {
- strcpy (errormsg, "could not cd to \"");
- strcat (errormsg, dirname);
- strcat (errormsg, "\": ");
- strcat (errormsg, sys_errlist[errno]);
- msgupdate ();
- if (chdir (currdir) != -1) {
- return;
- }
- if (chdir ("/") == -1) {
- fprintf (stderr, "\r\nscan: fatal error - couldn't cd to %s, %s or /\n",
- dirname, currdir);
- die ();
- }
- }
-
- /* save previous directory name, get current directory name */
- strcpy (prevdir, currdir);
- #ifdef SYSVgetcwd
- getcwd (currdir, MAXPATHLEN);
- #else
- getwd (currdir);
- #endif /* SYSVgetcwd */
-
- /* start over at beginning of the name buffer */
- namebufleft = BUFSIZE;
- nbptr = namebuf;
-
- for (lastptr = 0, dp = readdir(dirp); (lastptr < MAXDIRSIZE) && (dp != NULL); dp = readdir(dirp)) {
- if (opt_hide_dotdot && (((NAMELEN(dp) == 1) && (dp->d_name[0] == '.')) /* check if hiding just "." and ".." */
- || ((NAMELEN(dp) == 2) && (dp->d_name[0] == '.') && (dp->d_name[1] == '.')) )) {
- continue;
- }
- if ((opt_dot_order == DOT_HIDE) && (dp->d_name[0] == '.')) { /* check if hiding dot files */
- hidden_ctr++;
- continue;
- }
-
- /* add filename to file name buffer */
- for (cwd[lastptr].name = nbptr, ptr2 = dp->d_name;
- (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
- namebufleft--, nbptr++, ptr2++);
-
- /* move to the next character in the file name buffer */
- namebufleft--;
- nbptr++;
- if (namebufleft <= 0) {
- fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
- die ();
- }
-
- /* get status of file now */
- cwd[lastptr].size = cwd[lastptr].owner = cwd[lastptr].group = -1;
- statfile (lastptr);
-
- cwd[lastptr].selected = 0;
- lastptr++;
- }
-
- closedir (dirp);
-
- if (opt_dotdir_order == WITH_DIR)
- sortroutine = sortdirfirst;
- else
- sortroutine = sortdotfirst;
-
- qsort ((char *) cwd, lastptr, sizeof (struct dblock), sortroutine);
- lastptr--;
-
- topptr = curptr = 0;
- redraw_menu ();
- }
-