home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mm / mm-ccmd-0.91-20031009.tar.gz / mm-ccmd-0.91-20031009.tar / work / ccmd / filelist.c < prev    next >
C/C++ Source or Header  |  2002-02-20  |  22KB  |  820 lines

  1. /*
  2.  Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  the City of New York.  Permission is granted to any individual or
  4.  institution to use, copy, or redistribute this software so long as it
  5.  is not sold for profit, provided this copyright notice is retained.
  6.  
  7.  Author: Howie Kaye
  8. */
  9. /*
  10.  * Given a vector of directories, build a table of all files in those
  11.  * directories
  12.  * If the path passed here is the same as the previous one (help, and the 
  13.  * completion, uses previous listing for speed.
  14.  *
  15.  * All buffers are either malloc'ed or realloc'ed when needed.  If 
  16.  * these fail, bad things can happen -- i'm not yet sure what to do in this 
  17.  * case.
  18.  *
  19.  */
  20.  
  21. #include "ccmdlib.h"
  22. #include "filelist.h"
  23.  
  24.  
  25. /* Set up defs for type of directory access we have */
  26.  
  27. #if HAVE_DIRENTLIB
  28. #  include <dirent.h>
  29. #elif HAVE_NDIRLIB
  30. #  include <ndir.h>
  31. #elif HAVE_DIRLIB
  32. #  include <sys/dir.h>
  33. #elif HAVE_NODIRLIB
  34. #  if CCMD_OS_MSDOS
  35. #    include <dos.h>
  36. #    include <direct.h>
  37. #  endif
  38. #endif
  39.  
  40. #if HAVE_NODIRLIB
  41. typedef struct {
  42.     int size;
  43.     struct direct *files;
  44.     struct direct *current;
  45. } DIR;
  46. #endif
  47.  
  48. #if defined(ns32000) && CCMD_OS_BSD
  49. #  undef rewinddir
  50. #  define rewinddir(dirp) seekdir((dirp), (long)0)
  51. DIR *OPENDIR(fn) { DIR *d = opendir(fn); d->dd_hashed_dir = 0; return(d); }
  52. #else
  53. #  define OPENDIR opendir
  54. DIR *opendir();
  55. #endif
  56.  
  57. #if HAVE_DIRENTLIB
  58. #  define direct dirent            /* XXX kludge */
  59. #endif
  60.  
  61. #if CCMD_OS_UNIX
  62. # ifndef _CMUSR
  63. #  include <pwd.h>            /* for "~" completion */
  64. # endif /*  !_CMUSR */
  65. #endif /* CCMD_OS_UNIX */
  66.  
  67. /* make sure toupper does what we want */
  68. #undef toupper
  69. #define toupper(c) (islower(c) ? (c)-'a'+'A' : (c))
  70. #define BUFLEN 120
  71.  
  72. char *tilde_expand();
  73.  
  74. char *namebuf;                /* hold filenames here */
  75. char *prevnamebuf;            /* previous name buffer */
  76.  
  77. dirfile *files;                /* list of files */
  78. dirfile *prevfiles;            /* list from previous pass */
  79.  
  80. dirfile **fileindex;            /* vector of files for sorting */
  81. dirfile **previndex;            /* index from previous pass */
  82.  
  83. int filecount;                /* number of files entries used */
  84. int prevfilecount;            /* from previous pass */
  85. int maxfiles;                /* number of file entries malloc'ed */
  86.  
  87. char *curfile;                /* current file in namelist */
  88. int namelen;                /* used length of namebuf */
  89. int maxnamelen;                /* malloc'ed length of namebuf */
  90. char **prevpath=NULL;            /* previous search path  */
  91. char **usepath=NULL;            /* expanded path to use */
  92. int currentpath= 0;            /* current spot in usepath */
  93. int usepathlen=0;
  94. int redofiles = TRUE;
  95. int *modtimes = NULL;
  96. int suffix_modtime = 0;
  97. char *oldsuffix = NULL;
  98.  
  99. char *malloc(), *realloc(), *index();
  100. void qsort();                /* quick sort routine */
  101.  
  102. int dirfilecmp();            /* predicate for qsort */
  103.  
  104. /*
  105.  * chng_suffix:
  106.  * determine whether or not suffix has changed.  if it has, need
  107.  * to reread the directory.
  108.  * if suffix and oldsuffix are not equal, or they are equal but the modtimes
  109.  * are different, return TRUE, else return FALSE
  110.  */
  111.  
  112. chng_suffix (suffix, oldsuffix)
  113. char *suffix, *oldsuffix;
  114. {
  115.   struct stat sbuf;
  116.  
  117.   if (strcmp (suffix, oldsuffix) != 0)
  118.     return (TRUE);
  119.   if (stat (suffix, &sbuf) != 0)    /* don't know, be safe */
  120.     return (TRUE);
  121.   if (suffix_modtime == sbuf.st_mtime)
  122.     return (FALSE);
  123.   suffix_modtime = sbuf.st_mtime;
  124.   return (TRUE);
  125. }
  126.  
  127.  
  128. /*
  129.  * cmfileini:
  130.  * (re)initialize file vars.  Useful in making new file appear for
  131.  * file parse.
  132.  */
  133. cmfileini()
  134. {
  135.     redofiles = TRUE;
  136. }
  137.  
  138. /*
  139.  * search_path:
  140.  * takes a NULL terminated vector of directories.
  141.  * returns a pointer to a listing of the files.
  142.  * this listing is guaranteed to stay intact until the function is
  143.  * called again.
  144.  * fcount is set to the number of files returned
  145.  */
  146.  
  147. dirfile **
  148. search_path(path,suffix,fcount) char **path; char *suffix; int *fcount; {
  149.   int pathlen;                /* length of the path */
  150.   char **p;
  151.   int i;
  152.   register char **p1, **p2;        /* as last time */
  153.   struct stat sbuf;
  154.   int *m,goodlen = 0;
  155.  
  156.   p1 = path;
  157.   p2 = prevpath;
  158.   m = modtimes;
  159.  
  160.   if ((suffix == NULL && oldsuffix == NULL) ||
  161.       (suffix != NULL && oldsuffix != NULL 
  162.        && !chng_suffix (suffix, oldsuffix)))
  163.       {
  164.       for (;!redofiles;) {        /* check if it is same path */
  165.       if (p1 == NULL || p2 == NULL) break; /* NULL list? */
  166.       if (*p1 == NULL && *p2 != NULL) break; /* one null? */
  167.       if (*p1 != NULL && *p2 == NULL) break;
  168.       if ((*p1 != NULL) && (*p2 != NULL))
  169.           if (strcmp(*p1,*p2))
  170.           break;        /* or different entry...rebuild list */
  171.       if (*p1 == NULL) {        /* end of list?  they are the same */
  172.                     /* same list as last time...so */
  173.           namebuf = prevnamebuf;    /* make everything point to last set*/
  174.           *fcount = filecount = prevfilecount;
  175.           files = prevfiles;
  176.           fileindex = previndex;
  177.           return(previndex);    /* and return prev index */
  178.       }
  179.       if (stat(*p1,&sbuf) != 0)    /* if a directory changed, rebuild */
  180.           break;
  181.       if (sbuf.st_mtime != *m) break;
  182.       p1++,p2++;                /* keep walking the list */
  183.       }
  184.   }
  185.   redofiles = FALSE;
  186.                     /* different path...free up old */
  187.                     /* buffers */
  188.  
  189.   if (prevnamebuf != NULL)        /* free old name buffer */
  190.     free(prevnamebuf);
  191.   if (prevfiles != NULL)        /* and old file list */
  192.     free(prevfiles);
  193.   if (previndex != NULL)        /* old index */
  194.     free(previndex);
  195.   if (prevpath != NULL) {        /* and old path */
  196.     for (p = prevpath; *p != NULL; p++)    /* have to free each name in path */
  197.       free(*p);
  198.     free(prevpath);
  199.   }
  200.   if (modtimes != NULL)
  201.       free(modtimes);
  202.   filecount = prevfilecount = 0;    /* no previous files */
  203.   fileindex = NULL;            /* or current files */
  204.   files = NULL;
  205.   namebuf = NULL;
  206.   curfile = NULL;
  207.   namelen = 0;
  208.   maxnamelen = 0;
  209.   maxfiles = 0;
  210.                     /* now copy the current path */
  211.   pathlen = 0;
  212.   for (p = path; *p != NULL; p++)    /* first find it's length */
  213.     pathlen++;
  214.   prevpath = (char **) malloc((pathlen+1)*sizeof(char *)); /* build vector */
  215.   modtimes = (int *) malloc((pathlen)*sizeof(int));
  216.   for (i = 0,p = path; *p != NULL; i++,p++) { /* then copy the names */
  217.     prevpath[i] = malloc((1+strlen(*p)) * sizeof(char));
  218.     strcpy(prevpath[i],*p);
  219.     if (stat(*p,&sbuf) == 0)
  220.     modtimes[i] = sbuf.st_mtime;
  221.     else modtimes[i] = -1;
  222.   }
  223.   prevpath[pathlen] = NULL;        /* NULL termination */
  224.  
  225.   if (usepath != NULL) {        /* and expanded path */
  226.     for (i = 0,p = usepath; i < usepathlen;p++,i++) {
  227.       if (*p != NULL) free(*p);
  228.     }
  229.     free(usepath);
  230.   }
  231.   usepath = (char **) malloc((pathlen+1)*sizeof(char *)); /* build vector */
  232.   usepathlen=pathlen;            /* and remember length */
  233.  
  234.   goodlen = 0;
  235.   for (i = 0; i < usepathlen; i++) {
  236.     int xlen = 0;
  237.  
  238.     if (suffix) 
  239.     xlen = strlen(suffix);
  240.                     /* if it starts with a /, use */
  241.     if (suffix && (suffix[0] == '/' || strlen(suffix) == 0 ||
  242.            suffix[0] == '~' || (strcmp(suffix,".") == 0) ||
  243.            (strcmp(suffix,"..") == 0))) {    
  244.       int j;                /* as an absolute path */
  245.       char *term = "";
  246.       if (suffix[strlen(suffix)-1] != '/')
  247.     term = "/";
  248.       usepath[i] = malloc(xlen + 2);
  249.       sprintf(usepath[i],"%s%s",suffix,"/");
  250.       goodlen = 1;
  251.       for (j = 1; j < usepathlen; j++)
  252.     usepath[j] = NULL;
  253.       break;
  254.     }
  255.     else {
  256.       usepath[i] = malloc((1+xlen+sizeof("/")+
  257.                strlen(prevpath[i]))*sizeof(char));
  258.       strcpy(usepath[i],prevpath[i]);
  259.       if (suffix) {
  260.     if (usepath[i][strlen(usepath[i])-1] != '/')
  261.         strcat(usepath[i], "/");
  262.     strcat(usepath[i],suffix);
  263.       }
  264.       if (stat(usepath[i],&sbuf) == 0)
  265.       goodlen++;
  266.     }
  267.   }
  268.   usepath[usepathlen] = NULL;
  269.   for (i =0; i < usepathlen; i++) {    /* now build up list */
  270.     currentpath = i;
  271.     if (usepath[i] != NULL && modtimes[i] != -1) 
  272.     search_dir(usepath[i],goodlen <= 1);
  273.   }
  274.                     /* build up index into list */
  275.   if (oldsuffix)
  276.       free(oldsuffix);
  277.   if (suffix) {
  278.     struct stat sbuf;
  279.  
  280.     oldsuffix = malloc(strlen(suffix)+1);
  281.     strcpy(oldsuffix,suffix);
  282.     if (stat(suffix,&sbuf) == 0)
  283.       suffix_modtime = sbuf.st_mtime;
  284.   }
  285.   else oldsuffix = NULL;
  286.   fileindex = (dirfile **) malloc(sizeof(dirfile *) * filecount);
  287.   for (i = 0; i < filecount; i++) fileindex[i] = &files[i];
  288.                     /* and sort it */
  289.   qsort(fileindex,filecount,sizeof(dirfile *), dirfilecmp);
  290.  
  291.   previndex = fileindex;            /* save these for next time */
  292.   prevnamebuf = namebuf;
  293.   prevfiles = files;
  294.   *fcount = prevfilecount = filecount;
  295.   return(previndex);
  296. }
  297.  
  298. /*
  299.  * search_dir:
  300.  * builds up a file list for a single directory
  301.  * if a directory is wild, expands it.
  302.  * if directory is CWD, then includes ".", and ".."
  303.  */
  304.  
  305. search_dir(dirname,showdot) char *dirname; int showdot; {
  306.   struct stat sbuf;
  307.   DIR *dirp, *dotdirp;            /* directory pointers */
  308.   register struct direct *d;        /* file entries in a dir */
  309.   struct direct *dotd, *readdir();
  310.   int i;
  311.   char *dirr=dirname;            /* actual directory name to use */
  312.   struct passwd *user;            /* passwd structure for "~" files */
  313.   int ispwd;                /* flag if looking at connect dir */
  314.   register dirfile *f;
  315.   int dirstrlen;
  316. #if CCMD_OS_MSDOS
  317.   static char pwdbuf[51];
  318.   char *getcwd();
  319.   int ustrcmp();
  320. #endif
  321.   if (iswild(dirname)) {
  322.     expandwilddir(dirname);    
  323.     return;
  324.   }
  325. #if CCMD_OS_UNIX
  326.   if (dirname[0] == '~') {        /* "~user"? */ 
  327.     dirr = tilde_expand(dirname);    /* expand it */
  328.   }
  329. #endif
  330.   dirstrlen = strlen(dirr);
  331.   ispwd = !strcmp(dirr,".");        /* if looking at "." then pwd */
  332.  
  333.                     /* otherwise, we have to check */
  334.   if (stat(dirr,&sbuf) != 0)
  335.       return;
  336.   if (!((sbuf.st_mode & S_IFMT) == S_IFDIR)) {
  337.       return;
  338.   }
  339.   if (!ispwd) {
  340. #if CCMD_OS_MSDOS
  341.     if (index(STRUCTTERM,dirr[strlen(dirr)-1])) { /* on msdos, */
  342.       char buf[70];            /* check if the directory is */
  343.       int unit;                /* the same as the connected */
  344.       union REGS sregs, oregs;        /* by doing a DOS call to get the */
  345.       struct SREGS segregs;        /* connected dir */
  346.       int i;
  347.       
  348.       segread(&segregs);        /* set segment registers */
  349.       unit = 0;                /* use default structure */
  350.       if (isalpha(*dirr))
  351.     unit = toupper(*dirr) - 'A' + 1; /* no use the specified struct */
  352.  
  353.       strcpy(buf,dirr);            /* copy the directory name */
  354.       strcat(buf,"/");            /* add a "/" */
  355.       sregs.h.ah = 0x47;        /* DOS int get cwd */
  356.       sregs.x.si = (int) &buf[strlen(buf)];
  357.       sregs.h.dl = unit;
  358.       intdosx(&sregs, &oregs, & segregs); /* do the interrupt */
  359.       for (i = 0; i < strlen(buf); i++)    /* and lowercase the string */
  360.     if (isupper(buf[i])) buf[i] = tolower(buf[i]);
  361.       dirp = OPENDIR(buf);        /* open up directory */
  362.     }
  363.     else
  364.       dirp = OPENDIR(dirr);        /* open directory we are looking at */
  365. #else
  366.     dirp = OPENDIR(dirr);        /* open directory we are looking at */
  367. #endif
  368.     if (dirp == NULL) {
  369.     perror(dirr);
  370.     return;                /* can't...just return */
  371.     }
  372.     if (defstruct(dirr)) {        /* same structure? */
  373.       dotdirp = OPENDIR(".");        /* open up "." */
  374.       if (dotdirp != NULL) {
  375.     d = readdir(dirp);        /* read dir entries */
  376.     dotd = readdir(dotdirp);
  377.     if (d != NULL && dotd != NULL)
  378. #if CCMD_OS_UNIX
  379.       ispwd = (d->d_ino == dotd->d_ino); /* are they the same? */
  380. #elif CCMD_OS_MSDOS
  381.           ispwd = (!ustrcmp(d->d_name,getcwd(pwdbuf,50)));
  382. #endif
  383.     closedir(dotdirp);
  384.         rewinddir(dirp);
  385.       }
  386.       else {
  387.     perror(".");
  388.       }
  389.     }                    /* if different struct, different */
  390.   }
  391.   else {
  392.     dirp = OPENDIR(dirr);        /* open up directory */
  393.     if (dirp == NULL) { 
  394.       perror(dirr);
  395.       return;                /* couldn't...go home */
  396.     }
  397.   }
  398.                     /* directory is now open */
  399.   if (!ispwd && !showdot) {        /* if not CWD, skip ".", ".." */
  400.       do d = readdir (dirp);
  401.       while (d && d->d_name[0] == '.' &&
  402.          (d->d_name[1] == 0 ||
  403.           (d->d_name[1] == '.' && d->d_name[2] == 0)));
  404.   }
  405.   else {
  406.       d = readdir(dirp);
  407.   }
  408.   if (d == NULL) {
  409.       perror("readdir");
  410.   }
  411.   for (; d != NULL; d = readdir(dirp)) {
  412.     int fnlength;
  413.                     /* do we need more files? */
  414.  
  415.     if (filecount == maxfiles) {
  416.       maxfiles += FILEINCR;
  417.       files =(dirfile *)cmrealloc(files, sizeof(dirfile)*(maxfiles));
  418.     }
  419.                     /* do we need more name space  */
  420. #if (CCMD_OS_MSDOS || HAVE_NDIRLIB || HAVE_DIRENTLIB)
  421.     fnlength = strlen(d->d_name);
  422. #elif CCMD_OS_LINUX
  423.     fnlength = _D_EXACT_NAMLEN(d);
  424. #elif CCMD_OS_BSD
  425.     fnlength = d->d_namlen;
  426. #else
  427.     fnlength = strlen(d->d_name);
  428.     if (fnlength > 14)
  429.     fnlength = 14;
  430. #endif
  431.  
  432.     if (maxnamelen - (curfile - namebuf) < (fnlength + 1)) {
  433.       int offset = curfile - namebuf;
  434.       maxnamelen += NAMEINCR;
  435.       namebuf = cmrealloc(namebuf,sizeof(char)*maxnamelen);
  436.       curfile = namebuf + offset;
  437.     }
  438.     f = &files[filecount];        /* set up pointer to current file */
  439.     f->offset = curfile-namebuf;    /* it's offset into namebuf */
  440.  
  441.     strncpy(curfile, d->d_name, fnlength);
  442.     curfile[fnlength] = 0;
  443.     curfile += fnlength + 1;        /* bump current pointer by namelen */
  444.  
  445.     f->directory = dirname;        /* point to it's directory */
  446.     f->flags = 0;            /* no flags */
  447.     filecount++;
  448.   }
  449.   closedir(dirp);
  450. }
  451.   
  452.  
  453. /*
  454.  * dirfilecmp:
  455.  * predicate to compare two dirfile struct's for qsort
  456.  */
  457. dirfilecmp(a,b) register dirfile **a,**b; {
  458.   return(strcmp(&namebuf[(*a)->offset],&namebuf[(*b)->offset]));
  459. }
  460.  
  461.  
  462. /*
  463.  * ustrcmp:
  464.  * case insensitive string comparison
  465.  */
  466.  
  467. ustrcmp(s1,s2) char *s1, *s2; {
  468.   register char c1, c2;
  469.   for (;;s1++,s2++) {
  470.     c1 = toupper(*s1);
  471.     c2 = toupper(*s2);
  472.     if (c1 < c2) return(-1);
  473.     if (c1 > c2) return(1);
  474.     if (c1 == '\0') return(0);
  475.   }
  476. }
  477.  
  478. /* 
  479.  * expand the current directory, and place expansion in 
  480.  * usepath vector after current loc.
  481.  * expand usepath as we go.
  482.  */
  483.  
  484. expandwilddir(dirname) char *dirname; {
  485.   DIR *dirp;
  486.   struct direct *d;
  487.   static char basename[BUFLEN],fname[BUFLEN],rest[BUFLEN];
  488.   char c;
  489.   static char temp[BUFLEN];
  490.   
  491.   int i,base;
  492.   struct stat s;
  493.   
  494.   base = -1;                /* find the non wild base */
  495.   for (i = 0; i < strlen(dirname); i++) {
  496.     c=dirname[i];
  497.     if (index(DIRSEP,c)) {
  498.       base = i;
  499.       continue;
  500.     }
  501.     if (index(WILDCHARS,c)) break;
  502.   }
  503.   if (base == -1) {            /* no base dir.   use dot */
  504.     strcpy(basename,".");
  505.   }
  506.   else {                /* a base dir.  use it */
  507.     strncpy(temp,dirname,base);
  508.     temp[base] = '\0';
  509.     strcpy(basename,tilde_expand(temp));
  510.   }
  511.  
  512.   if (strlen(basename) == 0) strcpy(basename,"/");
  513.  
  514.   fname[0] = '\0';            /* the current wild part */
  515.   for (i = base+1; i < strlen(dirname); i++) {
  516.     if (index(DIRSEP,dirname[i])) break;
  517.     fname[i-(base+1)] = dirname[i];
  518.   }
  519.   fname[i-(base+1)] = '\0';
  520.  
  521.   i++;                    /* get past dirsep */
  522.   if (i < strlen(dirname))
  523.     strcpy(rest,&dirname[i]);        /* and the rest of the string */
  524.   else rest[0] =  '\0';
  525.   if (rest[strlen(rest)-1] == '/') rest[strlen(rest)-1] = '\0';
  526.  
  527.   if (strcmp(basename,"/") && strcmp(basename,".") && strcmp(basename,"..")) {
  528.                         /* we know these are dirs */
  529.     if (stat(basename,&s) == -1) {    /* and root breaks the msdos stat */
  530.       fprintf(stderr,"stat(%s) failed\n",basename); /* function */
  531.       return;
  532.     }
  533.     if (!((s.st_mode & S_IFMT) == S_IFDIR)) {
  534.       fprintf(stderr,"%s not a dir\n",basename);
  535.       return;
  536.     }
  537.   }
  538.   dirp = OPENDIR(basename);
  539.   if (dirp == NULL) return;
  540.                     /* insert directories into path */
  541.   d = readdir(dirp);            /* kill off . and .. */
  542.   if (!strcmp(d->d_name,"."))
  543.     readdir(dirp);
  544.   else rewinddir(dirp);
  545.   for(d = readdir(dirp); d!= NULL; d = readdir(dirp)) {
  546.     if ((d->d_name[0] != '.') || (d->d_name[0] == '.' && fname[0] == '.')) {
  547.       if (fmatch(d->d_name,fname)) {    /* if we match the wildcard */
  548.     static char buf[BUFLEN];
  549.     if (!strcmp(basename,".")) 
  550.       basename[0] = '\0';
  551.     else {
  552.       strcpy(buf,basename);
  553.     }
  554.     if (strlen(buf) > 0)
  555.       if (strcmp(buf,"/")) strcat(buf,"/");
  556.     strcat(buf,d->d_name);
  557.     if (strcmp(buf,".") && strcmp(buf,"..")) {
  558.       if (stat(buf,&s) == -1) continue;
  559.       if (!((s.st_mode & S_IFMT) == S_IFDIR)) continue;
  560.     }
  561.     if (strlen(rest) > 0) {
  562.       strcat(buf,"/");
  563.       strcat(buf,rest);
  564.     }
  565.     addtopath(buf);            /* add to the path vector */
  566.       }
  567.     }
  568.   }
  569.   closedir(dirp);            /* all done */
  570. }
  571.  
  572. /*
  573.  * actually add directories to the path in use.
  574.  */
  575. addtopath(dirname) char *dirname; {
  576.   int i;
  577.  
  578.                     /* grow the path */
  579.   usepath =(char**) cmrealloc(usepath,(usepathlen+2)*sizeof(char *));
  580.                     /* move everything else down one */
  581.   for (i = usepathlen; i > currentpath; i--) {
  582.     usepath[i+1] = usepath[i];
  583.   }
  584.   usepathlen++;                /* make space for this string */
  585.   usepath[currentpath+1] = malloc(strlen(dirname)+1);
  586.   strcpy(usepath[currentpath+1],dirname); /* and copy it in */
  587. }
  588.  
  589. #ifdef notdef
  590. /*
  591.  * index function
  592.  * returns index of char c in string s
  593.  */
  594. char *
  595. index(sp,c)                /* get index into a string */
  596. register char *sp, c;
  597. {
  598.   for (; *sp && *sp != c; sp++);
  599.   if (*sp == '\0') return(NULL);
  600.   else return(sp);
  601. }
  602. #endif
  603.  
  604. /*
  605.  * routine to check if a string is wild
  606.  * match all chars in string against all wild chars
  607.  */
  608.  
  609. iswild(str) char *str; {
  610.   int hit[128],i;
  611.   int len1, len2;
  612.   for (i = 0; i < 128; i++) hit[i] = 0;    /* no hits yet */
  613.   len1 = strlen(str);
  614.   for(i = 0; i < len1; i++)        /* mark hits */
  615.     hit[str[i]] = 1;
  616.   len2 = strlen(WILDCHARS);
  617.   for (i = 0; i < len2; i++)        /* and check for them */
  618.     if (hit[WILDCHARS[i]]) return(TRUE);
  619.   return(FALSE);
  620. }
  621.  
  622. /*
  623.  * check if directory is on connected structure
  624.  */
  625. defstruct(dirname)
  626. char *dirname;
  627. {
  628. #if CCMD_OS_MSDOS
  629.   int i;
  630.   char buf[100];
  631.   
  632.   getcwd(buf,100);            /* get connected dir */
  633.   for(i = 0; i < strlen(dirname); i++)
  634.     if (index(STRUCTTERM,dirname[i]))    /* a structure delimiter? */
  635.       return(toupper(dirname[i-1]) == toupper(buf[0]));
  636. #endif
  637.   return(TRUE);
  638. }
  639.  
  640.  
  641. #if CCMD_OS_UNIX
  642. /* 
  643.  * WHOAMI:
  644.  * 1) Get real uid
  645.  * 2) See if the $USER environment variable is set
  646.  * 3) If $USER's uid is the same as realuid, realname is $USER
  647.  * 4) Otherwise get logged in user's name
  648.  * 5) If that name has the same uid as the real uid realname is loginname
  649.  * 6) Otherwise, get a name for realuid from /etc/passwd
  650.  */
  651.  
  652. static char *
  653. whoami () {
  654.   static char realname[256];        /* user's name */
  655.   static int realuid = -1;        /* user's real uid */
  656.   char loginname[256], envname[256];    /* temp storage */
  657.   char *getlogin(), *getenv(), *c;
  658.   struct passwd *p, *getpwnam(), *getpwuid(), *getpwent();
  659.  
  660.   if (realuid != -1)
  661.     return(realname);
  662.  
  663.   realuid = getuid ();            /* get our uid */
  664.  
  665.   /* how about $USER? */
  666.   if ((c = getenv("USER")) != NULL) {    /* check the env variable */
  667.     strcpy (envname, c);        
  668.     p = getpwnam(envname);
  669.     if (p->pw_uid == realuid) { /* get passwd entry */
  670.                     /* for envname */
  671.       strcpy (realname, envname);    /* if the uid's are the same */
  672.       return(realname);
  673.     }
  674.   }
  675.  
  676.   /* can we use loginname() ? */
  677.   if ((c =  getlogin()) != NULL) {    /* name from utmp file */
  678.     strcpy (loginname, c);    
  679.     if ((p = getpwnam(loginname)) != NULL) /* get passwd entry */
  680.       if (p->pw_uid == realuid) {    /* for loginname */ 
  681.     strcpy (realname, loginname);    /* if the uid's are the same */
  682.     return(realname);
  683.       }
  684.   }
  685.  
  686.   /* Use first name we get for realuid */
  687.   if ((p = getpwuid(realuid)) == NULL) { /* name for uid */
  688.     realname[0] = '\0';            /* no user name */
  689.     realuid = -1;
  690.     return(NULL);
  691.   }
  692.   strcpy (realname, p->pw_name);    
  693.   return(realname);
  694. }
  695. #endif
  696.  
  697. /*
  698.  * expand ~user to the user's home directory.
  699.  */
  700. char *
  701. tilde_expand(dirname) char *dirname; {
  702. #if CCMD_OS_MSDOS
  703.   return(dirname);            /* no users in msdos */
  704. #elif CCMD_OS_UNIX
  705.   struct passwd *user, *getpwuid(), *getpwnam();
  706.   static char olddir[BUFLEN];
  707.   static char oldrealdir[BUFLEN];
  708.   static char temp[BUFLEN];
  709.   int i;
  710.  
  711.   if (dirname[0] != '~') return(dirname); /* not a tilde...return param */
  712.   if (!strcmp(olddir,dirname)) return(oldrealdir); /* same as last time. */
  713.                     /* so return old answer */
  714.   else {
  715.     for (i = 0; i < strlen(dirname); i++) /* find username part of string */
  716.       if (!index(DIRSEP,dirname[i]))
  717.     temp[i] = dirname[i];
  718.       else break;
  719.     temp[i] = '\0';            /* tie off with a NULL */
  720.     if (strlen(temp) == 1) {        /* if just a "~" */
  721.       user = getpwnam(whoami());    /*  get info on current user */
  722.     }
  723.     else {
  724.       user = getpwnam(&temp[1]);    /* otherwise on the specified user */
  725.     }
  726.   }
  727.   if (user != NULL) {            /* valid user? */
  728.     strcpy(olddir, dirname);        /* remember the directory */
  729.     strcpy(oldrealdir,user->pw_dir);    /* and their home directory */
  730.     strcat(oldrealdir,&dirname[i]);
  731.     return(oldrealdir);
  732.   }
  733.   else {                /* invalid? */
  734.     strcpy(olddir, dirname);        /* remember for next time */
  735.     strcpy(oldrealdir, dirname);
  736.     return(oldrealdir);
  737.   }
  738. #endif
  739. }
  740.  
  741. #ifdef notdef
  742. bcopy(src,dest,len)
  743. register char *src,*dest;
  744. register int len;
  745. {
  746.   if (src > dest)               /* Could source be overwritten? */
  747.     for(; len > 0; len--)       /* No */
  748.       *dest++ = *src++;         /* Simple forward copy */
  749.   else
  750.     for(; len >= 0; len--)       /* Yes */
  751.       *(dest+len) = *(src+len); /* Backwards copy */
  752. }
  753.  
  754. #endif
  755.  
  756. #if HAVE_NODIRLIB
  757.  
  758. #ifdef opendir
  759. #undef opendir
  760. #endif
  761. DIR *
  762. opendir(name) {
  763.     DIR *dir;
  764.     int fd,open();
  765.     struct stat sbuf;
  766.     int x;
  767.  
  768.     if (stat(name,&sbuf) != 0) return(NULL);
  769.     if (!(sbuf.st_mode & S_IFDIR)) {
  770.     errno = ENOTDIR;
  771.     return(NULL);
  772.     }
  773.     fd = open(name,O_RDONLY,0);
  774.     if (fd == -1)
  775.     perror("open");
  776.     if (fd == -1) return(NULL);
  777.     if ((dir = (DIR *)malloc(sizeof(DIR))) == NULL) {
  778.     close(fd);
  779.     return(NULL);
  780.     }
  781.     dir->size = sbuf.st_size;
  782.     if ((dir->files = (struct direct *) malloc(dir->size)) == 0) {
  783.     close(fd);
  784.     free(dir);
  785.     return(NULL);
  786.     }
  787.     x = read(fd,dir->files,dir->size);
  788.     if (x == -1) perror("read");
  789.     dir->current = dir->files;
  790.     close(fd);
  791.     return(dir);
  792. }
  793.  
  794. struct direct *
  795. readdir(dirp) DIR *dirp; {
  796.     int s = dirp->size / sizeof(struct direct);
  797.     struct direct *temp;
  798.     if (dirp->current >= dirp->files + s)
  799.     return(NULL);
  800.     while (dirp->current->d_ino == 0)
  801.     if (dirp->current >= dirp->files + s)
  802.         return(NULL);
  803.     else dirp->current++;
  804.         if (dirp->current >= dirp->files + s)
  805.     return(NULL);
  806.     temp = dirp->current++;
  807.     return(temp);
  808. }
  809.     
  810. rewinddir(dirp) DIR *dirp; {
  811.     dirp->current = dirp->files;
  812. }
  813.  
  814. closedir(dirp) DIR *dirp;
  815. {
  816.     free(dirp->files);
  817.     free(dirp);
  818. }
  819. #endif /* HAVE_NODIRLIB */
  820.