123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * File: filegen.C $TOG: filegen.C /main/7 1999/10/14 15:05:25 mgreess $
- *
- * (c) Copyright 1993, 1994 Hewlett-Packard Company
- * (c) Copyright 1993, 1994 International Business Machines Corp.
- * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- * (c) Copyright 1993, 1994 Novell, Inc.
- */
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #define X_INCLUDE_DIRENT_H
- #define XOS_USE_XT_LOCKING
- #include <X11/Xos_r.h>
- #include <codelibs/stringx.h>
- #include <codelibs/nl_hack.h>
- #include "buf.h"
- #include "DtSvcLock.h"
- #ifndef MAXPATHLEN
- # define MAXPATHLEN 1024
- #endif
- #ifdef XTHREADS
- extern "C" {
- extern void XtProcessLock(void);
- extern void XtProcessUnlock(void);
- }
- #endif
- struct _SHXcomponent
- {
- boolean is_pattern;
- long offset; // subscript in path buffer
- char *ptr; // pointer into path buffer
- };
- declare_array(_SHXcomponents, _SHXcomponent, 4)
- // recursive routine to expand the wildcard path represented in stack into
- // all possible expansions. The expansions are appended to _SHXbuf::vec.
- // filebuf is a scratch buffer passed in by the caller and is used to build
- // intermediate paths. end is a pointer to the position in filebuf where
- // the calling routine left off.
- void
- _SHXbuf::expand(_SHXcomponents &stack,
- char *const filebuf, char *end, int compnum)
- {
- *end = '\0';
- if (compnum == stack.size())
- return;
- _SHXcomponent &comp = stack[compnum];
- // double-slash?
- if (comp.ptr[0] == '\0')
- {
- if (compnum + 1 == stack.size())
- append(filebuf, EXPANDQUOTE);
- else
- {
- *end++ = '/';
- expand(stack, filebuf, end, compnum + 1);
- }
- return;
- }
- // performance optimization: if this path component
- // doesn't contain a wildcard, avoid doing an opendir()
- if (!comp.is_pattern)
- {
- strcpy(end, comp.ptr);
- if (compnum + 1 == stack.size())
- {
- // last component, just see if the path really points to something
- if (access(filebuf, F_OK) != -1)
- append(filebuf, EXPANDQUOTE);
- }
- else
- {
- // intermediate directory just append this component and keep going
- char *end2 = strend(end);
- *end2++ = '/';
- expand(stack, filebuf, end2, compnum + 1);
- }
- return;
- }
- // We have a wildcard component, open and scan its parent directory
- // and look for matches.
- DIR *dir = opendir(filebuf[0] == '\0' ? "." : filebuf);
- if (dir == NULL)
- return;
- _Xreaddirparams dir_buf;
- struct dirent *ent;
- memset((char*) &dir_buf, 0, sizeof(_Xreaddirparams));
- while ((ent = _XReaddir(dir, dir_buf)) != NULL)
- {
- // deleted file?
- if (ent->d_ino == 0 || ent->d_name[0] == '\0')
- continue;
- // right name?
- if (comp.is_pattern)
- {
- wchar_t __nlh_char[1];
- // Must have explicit match for leading '.'
- if (CHARAT(ent->d_name) == '.' && CHARAT(comp.ptr) != '.')
- continue;
- if (strwcmp(comp.ptr, ent->d_name) != 0)
- continue;
- }
- else if (strcmp(comp.ptr, ent->d_name) != 0)
- continue;
- strcpy(end, ent->d_name);
- if (compnum + 1 == stack.size())
- append(filebuf, EXPANDQUOTE);
- else
- {
- char *end2 = end + strlen (ent->d_name);
- *end2++ = '/';
- expand(stack, filebuf, end2, compnum + 1);
- }
- }
- closedir(dir);
- }
- //extern "C" { void qsort(void *, unsigned, int, ...); };
- static char *bufptr;
- static int
- //compar(int &v1, int &v2)
- compar(const void *v1, const void *v2)
- {
- int result;
- _DtSvcProcessLock();
- result = strcmp(&bufptr[*(int*)v1], &bufptr[*(int*)v2]);
- _DtSvcProcessUnlock();
- return (result);
- }
- void
- _SHXbuf::filegen()
- {
- privbuf_charbuf path;
- _SHXcomponents stack;
- long vecstart = vec.size() - 1;
- if (vecstart < 0)
- return;
- long bufstart = long(vec[vecstart]);
- // Parse the file path, breaking it up into individual components.
- // Each component is marked as being either a wildcard component
- // or not. The wildcard components will have a '\' placed before
- // any quoted wildcard characters. The non-wildcard components
- // will be left unchanged.
- int bufpos = (int) bufstart;
- while (bufpos < buf.size())
- {
- _SHXcomponent & comp = stack[stack.size()];
- comp.is_pattern = FALSE;
- comp.offset = path.size();
- comp.ptr = NULL;
- int startpos = bufpos;
- int ch;
- do
- {
- ch = buf[bufpos];
- switch (ch)
- {
- case '/':
- ch = '\0';
- break;
- case '*':
- case '?':
- case '[':
- if (flags[bufpos] == NOQUOTE)
- comp.is_pattern = TRUE;
- else
- path[path.size()] = '\\';
- break;
- }
- path[path.size()] = ch;
- bufpos++;
- } while (ch != '\0');
- // Add a '*' to the end of the last component if needed
- // for completion.
- if (bufpos >= buf.size()) // last component?
- if (bufpos > bufstart + 1) // non-null string?
- if (completion && !is_pattern)
- {
- path[path.size() - 1] = '*';
- path[path.size()] = '\0';
- comp.is_pattern = TRUE;
- break;
- }
- // If it wasn't a pattern, remove all of the '\' characters
- // that were added.
- if (!comp.is_pattern)
- {
- int len = bufpos - startpos - 1;
- strncpy(&path[comp.offset], &buf[startpos], len);
- path[comp.offset + len] = '\0';
- }
- }
- // Fill in the character pointer values for all of the components.
- // We couldn't do this in the first pass because path is a
- // dynamic array.
- char *pathbuf = path.getarr();
- for (int i = 0; i < stack.size(); i++)
- stack[i].ptr = &pathbuf[stack[i].offset];
- // Remove the token that we just copied from the return vector
- // so that we can replace it with its expansion.
- vec.reset(vecstart);
- char filebuf[MAXPATHLEN];
- expand(stack, filebuf, filebuf, 0);
- if (vec.size() == vecstart) // no matches?
- {
- vec[vecstart] = (char *)bufstart; // restore orig. token
- return;
- }
- // alphabetize the expansion to make it look pretty like ksh does.
- _DtSvcProcessLock();
- bufptr = buf.getarr();
- qsort(&vec[vecstart], (unsigned int)(vec.size() - vecstart),
- sizeof (char *), compar);
- // Find the longest match if we are doing completion:
- if (completion)
- {
- long i;
- // compare all entries to a copy of the first entry
- snprintf(filebuf, sizeof(filebuf), "%s", &bufptr[long(vec[0])]);
- for (i = 1; i < vec.size(); i++)
- {
- char *ref = filebuf;
- char *ptr = &bufptr[long(vec[i])];
- while (*ref == *ptr && *ref != '\0' && *ptr != '\0')
- ref++, ptr++;
- *ref = '\0'; // shorten the reference copy
- }
- // Now store the best match as the first token. We will
- // have to shift the expansion vector down by one to
- // make room.
- for (i = vec.size(); i > 0; --i)
- {
- char *val = vec[i - 1];
- vec[i] = val;
- }
- vec[0] = (char *)buf.size();
- append(filebuf, EXPANDQUOTE);
- vec.reset(vec.size() - 1); // adjust for the append
- }
- _DtSvcProcessUnlock();
- }
- implement_array(_SHXcomponents, _SHXcomponent, 4)
|