home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / scan / part01 / fileops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-21  |  13.4 KB  |  471 lines

  1. /*
  2.  *    fileops.c - display directory menu
  3.  *
  4.  * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
  5.  *
  6.  * Permission is hereby granted to copy, distribute or otherwise 
  7.  * use any part of this package as long as you do not try to make 
  8.  * money from it or pretend that you wrote it.  This copyright 
  9.  * notice must be maintained in any copy made.
  10.  *
  11.  * Use of this software constitutes acceptance for use in an AS IS 
  12.  * condition. There are NO warranties with regard to this software.  
  13.  * In no event shall the author be liable for any damages whatsoever 
  14.  * arising out of or in connection with the use or performance of this 
  15.  * software.  Any use of this software is at the user's own risk.
  16.  *
  17.  * If you make modifications to this software that you feel 
  18.  * increases it usefulness for the rest of the community, please 
  19.  * email the changes, enhancements, bug fixes as well as any and 
  20.  * all ideas to me. This software is going to be maintained and 
  21.  * enhanced as deemed necessary by the community.
  22.  *              
  23.  *              Patrick J. Wolfe
  24.  *              uunet!uiucuxc!kailand!pwolfe
  25.  *              pwolfe@kailand.kai.com
  26.  */
  27.  
  28. #include "config.h"
  29.  
  30. extern long sixmonthsago;
  31. extern int opt_dot_order, opt_dotdir_order, opt_dir_order, opt_hide_dotdot,
  32.     opt_show_filetype, opt_show_symlinks;
  33. extern int topptr, curptr, lastptr, COLS, namebufleft;
  34. extern char *sys_errlist[], errormsg[], *namebuf, *monthtable[];
  35.  
  36. extern WINDOW *headwin, *datawin, *helpwin;
  37.  
  38. struct stat sb;
  39. struct dblock cwd[MAXDIRSIZE];
  40. struct namelist lidlist[MAXLID];
  41. struct namelist gidlist[MAXGID];
  42. int lidend = -1, gidend = -1, hidden_ctr;
  43. char currdir[MAXPATHLEN], prevdir[MAXPATHLEN];
  44. char *emptystring = "", *nbptr;
  45.  
  46.  
  47. void
  48. statfile (ctr)
  49. int    ctr;
  50. {
  51. struct passwd *pb;
  52. struct group *gb;
  53. struct tm *tb;
  54. struct stat sb2;
  55. int ctr2, permend = 0;
  56. #ifdef sequent
  57. int ctr3;
  58. #endif
  59. #ifdef S_IFLNK
  60. char ucblink[MAXPATHLEN];
  61. #ifdef sequent
  62. char attlink[MAXPATHLEN];
  63. #endif
  64. #endif
  65. char *ptr2;
  66.  
  67.  
  68. #ifdef S_IFLNK
  69. if (opt_show_symlinks)
  70.     ctr2 = lstat (cwd[ctr].name, &sb);    /* if showing links, then use "lstat()" to get status of the link */
  71. else
  72. #endif
  73.     ctr2 = stat (cwd[ctr].name, &sb);
  74.  
  75. if (ctr2 != 0) {
  76.     cwd[ctr].size = -1;
  77.     cwd[ctr].selected = 0;    /* unselect it */
  78.     if (errno == ENOENT) {    /* store error message for display */
  79.         for (cwd[ctr].link = nbptr, ptr2 = "deleted";
  80.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  81.             namebufleft--, nbptr++, ptr2++);
  82.         /* move to the next character in the file name buffer */
  83.         namebufleft--;
  84.         nbptr++;
  85.         }
  86.     else    {
  87.         for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
  88.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  89.             namebufleft--, nbptr++, ptr2++);
  90.  
  91.         /* move to the next character in the file name buffer */
  92.         namebufleft--;
  93.         nbptr++;
  94.         }
  95.     if (namebufleft <= 0) {
  96.         fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
  97.         die ();
  98.         }
  99.     return;
  100.     }
  101.  
  102. /* if this hasn't changed - don't waste any more time */
  103. if ((cwd[ctr].size != -1) && (cwd[ctr].ctime == sb.st_ctime)) {
  104.     return;    
  105.     }
  106.  
  107. /* make link point to an empty string, so we don't have to check for NULL */
  108. cwd[ctr].link = emptystring;
  109.  
  110. /*
  111.  * determine filetype - we want to do this first, because if it's a symbolic
  112.  * link, we would prefer info about the file being pointed to
  113.  */
  114. cwd[ctr].type = sb.st_mode & S_IFMT;
  115.  
  116. if (cwd[ctr].type == S_IFREG) {
  117.     cwd[ctr].perms[0] = '-';
  118.     }
  119. else if (cwd[ctr].type == S_IFDIR) {
  120.     cwd[ctr].perms[0] = 'd';
  121.     }
  122. else if (cwd[ctr].type == S_IFBLK) {
  123.     cwd[ctr].perms[0] = 'b';
  124.     }
  125. else if (cwd[ctr].type == S_IFCHR) {
  126.     cwd[ctr].perms[0] = 'c';
  127.     }
  128.  
  129. #ifdef S_IFSOCK
  130. else if (cwd[ctr].type == S_IFSOCK) {
  131.     cwd[ctr].perms[0] = 's';
  132.     }
  133. #endif /* S_IFSOCK */
  134.  
  135. #ifdef S_IFIFO
  136. else if (cwd[ctr].type == S_IFIFO) {
  137.     cwd[ctr].perms[0] = 'f';
  138.     }
  139. #endif /* S_IFIFO */
  140.  
  141. #ifdef S_IFLNK
  142.  
  143. #ifdef sequent
  144. /* check for conditional symbolic link before regular symbolic link */
  145. else if ((cwd[ctr].type == S_IFLNK) && (sb.st_spare4[0] == 1)) {
  146.     if (stat (cwd[ctr].name, &sb2) == 0) {
  147.         BCOPY ((char *) &sb2, (char *)&sb, sizeof (struct stat));    /* use stats of the pointed at thing */
  148.         cwd[ctr].type = sb.st_mode & S_IFMT;    /* get the actual file type */
  149.         }
  150.     cwd[ctr].perms[0] = 'l';
  151.     if (((ctr2 = readclink (cwd[ctr].name, ucblink, MAXPATHLEN, U_UCB)) == -1) 
  152.      || ((ctr3 = readclink (cwd[ctr].name, attlink, MAXPATHLEN, U_ATT)) == -1)) {
  153.         for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
  154.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  155.             namebufleft--, nbptr++, ptr2++);
  156.  
  157.         /* move to the next character in the file name buffer */
  158.         namebufleft--;
  159.         nbptr++;
  160.         }
  161.     else    {
  162.         ucblink[ctr2] = '\0';    /* readclink does not null terminate it's filename */
  163.         attlink[ctr3] = '\0';    /* readclink does not null terminate it's filename */
  164.         for (cwd[lastptr].link = nbptr, ptr2 = " -> ucb=";
  165.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  166.             namebufleft--, nbptr++, ptr2++);
  167.         for (ptr2 = ucblink;
  168.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  169.             namebufleft--, nbptr++, ptr2++);
  170.         for (ptr2 = " att=";
  171.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  172.             namebufleft--, nbptr++, ptr2++);
  173.         for (ptr2 = attlink;
  174.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  175.             namebufleft--, nbptr++, ptr2++);
  176.         namebufleft--;
  177.         nbptr++;
  178.         }
  179.     if (namebufleft <= 0) {
  180.         fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
  181.         die ();
  182.         }
  183.     }
  184. #endif /* sequent */
  185.  
  186. else if (cwd[ctr].type == S_IFLNK) {
  187.     if (stat (cwd[ctr].name, &sb2) == 0) {
  188.         BCOPY ((char *) &sb2, (char *)&sb, sizeof (struct stat));    /* use stats of the pointed at thing */
  189.         cwd[ctr].type = sb.st_mode & S_IFMT;    /* get the actual file type */
  190.         }
  191.     cwd[ctr].perms[0] = 'l';
  192.     if ((ctr2 = readlink (cwd[ctr].name, ucblink, MAXPATHLEN)) == -1) {
  193.         for (cwd[lastptr].link = nbptr, ptr2 = sys_errlist[errno];
  194.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  195.             namebufleft--, nbptr++, ptr2++);
  196.  
  197.         /* move to the next character in the file name buffer */
  198.         namebufleft--;
  199.         nbptr++;
  200.         }
  201.     else    {
  202.         ucblink[ctr2] = '\0';    /* readlink does not null terminate it's filename */
  203.         for (cwd[lastptr].link = nbptr, ptr2 = " -> ";
  204.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  205.             namebufleft--, nbptr++, ptr2++);
  206.         for (ptr2 = ucblink;
  207.             (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  208.             namebufleft--, nbptr++, ptr2++);
  209.         namebufleft--;
  210.         nbptr++;
  211.         }
  212.     if (namebufleft <= 0) {
  213.         fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
  214.         die ();
  215.         }
  216.     }
  217. #endif /* S_IFLNK */
  218.  
  219. else    {
  220.     cwd[ctr].perms[0] = '?';    /* unknown */
  221.     }
  222.  
  223. cwd[ctr].perms[++permend] = (sb.st_mode & 0400 ? 'r' : '-');        /* owners permissions */
  224. cwd[ctr].perms[++permend] = (sb.st_mode & 0200 ? 'w' : '-');
  225. cwd[ctr].perms[++permend] = ((sb.st_mode & 04000) && (sb.st_mode & 0100) ? 's' :
  226.             sb.st_mode & 04000 ? 'S' : sb.st_mode & 0100 ? 'x' : '-');
  227. cwd[ctr].perms[++permend] = (sb.st_mode & 040 ? 'r' : '-');            /* group permissions */
  228. cwd[ctr].perms[++permend] = (sb.st_mode & 020 ? 'w' : '-');
  229. cwd[ctr].perms[++permend] = ((sb.st_mode & 02000) && (sb.st_mode & 010) ? 's' :
  230.             sb.st_mode & 02000 ? 'S' : sb.st_mode & 010 ? 'x' : '-');
  231. cwd[ctr].perms[++permend] = (sb.st_mode & 04 ? 'r' : '-');            /* others permissions */
  232. cwd[ctr].perms[++permend] = (sb.st_mode & 02 ? 'w' : '-');
  233. cwd[ctr].perms[++permend] = ((sb.st_mode & 01000) && (sb.st_mode & 01) ? 't' :
  234.             sb.st_mode & 01000 ? 'T' : sb.st_mode & 01 ? 'x' : '-');
  235. cwd[ctr].perms[++permend] = '\0';
  236.  
  237. if (opt_show_filetype && (cwd[ctr].link[0] == '\0')) {
  238.     if (cwd[ctr].perms[0] == 'd') {
  239.         cwd[ctr].link = "/";
  240.         }
  241.     else if ((cwd[ctr].perms[0] == '-') && ((sb.st_mode & 0111) != 0)) {
  242.         cwd[ctr].link = "*";
  243.         }
  244.     }
  245.  
  246. if ((cwd[ctr].owner == -1) || (lidlist[cwd[ctr].owner].number != sb.st_uid)) {
  247.     for (ctr2 = 0; (cwd[ctr].owner == -1) && (ctr2 <= lidend); ctr2++) {
  248.         if (lidlist[ctr2].number == sb.st_uid) {
  249.             cwd[ctr].owner = ctr2;
  250.             }
  251.         }
  252.     if (cwd[ctr].owner == -1) {                /* didn't already have user name */
  253.         if (lidend >= MAXLID) {                /* store for future files */
  254.             fprintf (stderr, "MAXLID is too low - reset and recompile\n");
  255.             die ();
  256.             }
  257.         lidend++;
  258.         cwd[ctr].owner = lidend;
  259.         lidlist[lidend].number = sb.st_uid;
  260.         if ((pb = getpwuid(sb.st_uid)) == NULL) {
  261.             sprintf (lidlist[lidend].name, "%d", sb.st_uid);
  262.             }
  263.         else    {
  264.             strcpy (lidlist[lidend].name, pb->pw_name);
  265.             }
  266.         }
  267.     }
  268.  
  269. if ((cwd[ctr].group == -1) || (gidlist[cwd[ctr].group].number != sb.st_gid)) {
  270.     for (ctr2 = 0; (cwd[ctr].group == -1) && (ctr2 <= gidend); ctr2++) {
  271.         if (gidlist[ctr2].number == sb.st_gid) {
  272.             cwd[ctr].group = ctr2;
  273.             }
  274.         }
  275.     if (cwd[ctr].group == -1) {                /* didn't already have group name */
  276.         if (gidend >= MAXGID) {                /* store for future files */
  277.             fprintf (stderr, "MAXGID is too low - reset and recompile\n");
  278.             die ();
  279.             }
  280.         gidend++;
  281.         cwd[ctr].group = gidend;
  282.         gidlist[gidend].number = sb.st_gid;
  283.         if ((gb = (struct group *) getgrgid(sb.st_gid)) == (struct group *) NULL) {
  284.             sprintf (gidlist[gidend].name, "%d", sb.st_gid);
  285.             }
  286.         else    {
  287.             strcpy (gidlist[gidend].name, gb->gr_name);
  288.             }
  289.         }
  290.     }
  291.  
  292. /* like ls, if it's over six months old, display the year instead of the time */
  293. tb = localtime (&sb.st_mtime);
  294. if (sb.st_mtime < sixmonthsago)
  295.     sprintf (cwd[ctr].modtime, "%3s %02d %04d ", monthtable[tb->tm_mon], tb->tm_mday, 1900 + tb->tm_year);
  296. else
  297.     sprintf (cwd[ctr].modtime, "%3s %02d %02d:%02d", monthtable[tb->tm_mon], tb->tm_mday, tb->tm_hour, tb->tm_min); 
  298.  
  299. cwd[ctr].size = sb.st_size;
  300. cwd[ctr].ctime = sb.st_ctime;
  301. }
  302.  
  303.  
  304. int
  305. sortdirfirst (a, b)
  306. struct    dblock    *a, *b;
  307. {
  308. int aisdir, bisdir;
  309.  
  310. if (opt_dir_order != DIR_SORT) {    /* if not mixing dirs and files, sort between dirs and files */
  311.     if (a->size != -1)
  312.         aisdir = (a->type == S_IFDIR);
  313.     else if (stat (a->name, &sb) == 0) 
  314.         aisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
  315.     else
  316.         aisdir = 0;
  317.     if (b->size != -1)
  318.         bisdir = (b->type == S_IFDIR);
  319.     else if (stat (b->name, &sb) == 0) 
  320.         bisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
  321.     else
  322.         bisdir = 0;
  323.     if (aisdir && ! bisdir) {
  324.         return (opt_dir_order == DIR_LAST ? 1 : -1);
  325.         }
  326.     if (! aisdir && bisdir) {
  327.         return (opt_dir_order == DIR_LAST ? -1 : 1);
  328.         }
  329.     }
  330.  
  331. if (opt_dot_order != DOT_HIDE) {    /* if not hiding dot files, sort between dot and non-dot files now */
  332.     if ((a->name[0] == '.') && (b->name[0] != '.')) {
  333.         return (opt_dot_order == DOT_LAST ? 1 : -1);
  334.         }
  335.     else if ((a->name[0] != '.') && (b->name[0] == '.')) {
  336.         return (opt_dot_order == DOT_LAST ? -1 : 1);
  337.         }
  338.     }
  339.  
  340. return (strncmp (a->name, b->name, 16));    /* sort alphabetically by name */
  341. }
  342.  
  343.  
  344. int
  345. sortdotfirst (a, b)
  346. struct    dblock    *a, *b;
  347. {
  348. int aisdir, bisdir;
  349.  
  350. if (opt_dot_order != DOT_HIDE) {    /* if not hiding dot files, sort between dot and non-dot files now */
  351.     if ((a->name[0] == '.') && (b->name[0] != '.')) {
  352.         return (opt_dot_order == DOT_LAST ? 1 : -1);
  353.         }
  354.     else if ((a->name[0] != '.') && (b->name[0] == '.')) {
  355.         return (opt_dot_order == DOT_LAST ? -1 : 1);
  356.         }
  357.     }
  358.  
  359. if (opt_dir_order != DIR_SORT) {    /* if not mixing dirs and files, sort between dirs and files */
  360.     if (a->size != -1)
  361.         aisdir = (a->type == S_IFDIR);
  362.     else if (stat (a->name, &sb) == 0) 
  363.         aisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
  364.     else
  365.         aisdir = 0;
  366.     if (b->size != -1)
  367.         bisdir = (b->type == S_IFDIR);
  368.     else if (stat (b->name, &sb) == 0) 
  369.         bisdir = ((sb.st_mode & S_IFMT) == S_IFDIR);
  370.     else
  371.         bisdir = 0;
  372.     if (aisdir && ! bisdir) {
  373.         return (opt_dir_order == DIR_LAST ? 1 : -1);
  374.         }
  375.     if (! aisdir && bisdir) {
  376.         return (opt_dir_order == DIR_LAST ? -1 : 1);
  377.         }
  378.     }
  379.  
  380. return (strncmp (a->name, b->name, 16));    /* sort alphabetically by name */
  381. }
  382.  
  383.  
  384. void
  385. do_chdir (dirname)
  386. char    *dirname;
  387. {
  388. DIR    *dirp;
  389. struct timeval tp;
  390. struct    direct    *dp;
  391. Function *sortroutine;
  392. char *ptr2;
  393.  
  394. gettimeofday (&tp, 0);
  395. sixmonthsago = tp.tv_sec - (60 * 60 * 24 * 180);        /* time 180 days (6 months) ago */
  396.  
  397. hidden_ctr = 0;
  398.  
  399. if ((chdir (dirname) == -1) || ((dirp = opendir(".")) == NULL)) {
  400.     strcpy (errormsg, "could not cd to \"");
  401.     strcat (errormsg, dirname);
  402.     strcat (errormsg, "\": ");
  403.     strcat (errormsg, sys_errlist[errno]);
  404.     msgupdate ();
  405.     if (chdir (currdir) != -1) {
  406.         return;
  407.         }
  408.     if (chdir ("/") == -1) {
  409.         fprintf (stderr, "\r\nscan: fatal error - couldn't cd to %s, %s or /\n",
  410.             dirname, currdir);
  411.         die ();
  412.         }
  413.     }
  414.  
  415. /* save previous directory name, get current directory name */
  416. strcpy (prevdir, currdir);
  417. #ifdef SYSVgetcwd
  418. getcwd (currdir, MAXPATHLEN);
  419. #else
  420. getwd (currdir);
  421. #endif /* SYSVgetcwd */
  422.  
  423. /* start over at beginning of the name buffer */
  424. namebufleft = BUFSIZE;
  425. nbptr = namebuf;
  426.  
  427. for (lastptr = 0, dp = readdir(dirp); (lastptr < MAXDIRSIZE) && (dp != NULL); dp = readdir(dirp)) {
  428.     if (opt_hide_dotdot && (((NAMELEN(dp) == 1) && (dp->d_name[0] == '.'))    /* check if hiding just "." and ".." */
  429.       || ((NAMELEN(dp) == 2) && (dp->d_name[0] == '.') && (dp->d_name[1] == '.')) )) {
  430.         continue;
  431.         }
  432.     if ((opt_dot_order == DOT_HIDE) && (dp->d_name[0] == '.')) {    /* check if hiding dot files */
  433.         hidden_ctr++;
  434.         continue;
  435.         }
  436.  
  437.     /* add filename to file name buffer */
  438.     for (cwd[lastptr].name = nbptr, ptr2 = dp->d_name;
  439.         (namebufleft > 0) && ((*nbptr = *ptr2) != '\0');
  440.         namebufleft--, nbptr++, ptr2++);
  441.  
  442.     /* move to the next character in the file name buffer */
  443.     namebufleft--;
  444.     nbptr++;
  445.     if (namebufleft <= 0) {
  446.         fprintf (stderr, "file name buffer is too small - raise and recompile scan\n");
  447.         die ();
  448.         }
  449.  
  450.     /* get status of file now */
  451.     cwd[lastptr].size = cwd[lastptr].owner = cwd[lastptr].group = -1;
  452.     statfile (lastptr);
  453.  
  454.     cwd[lastptr].selected = 0;
  455.     lastptr++;
  456.     }
  457.  
  458. closedir (dirp);
  459.  
  460. if (opt_dotdir_order == WITH_DIR)
  461.     sortroutine = sortdirfirst;
  462. else
  463.     sortroutine = sortdotfirst;
  464.  
  465. qsort ((char *) cwd, lastptr, sizeof (struct dblock), sortroutine);
  466. lastptr--;
  467.  
  468. topptr = curptr = 0;
  469. redraw_menu ();
  470. }
  471.