elks-enhanced
public
Read
Owner: themaster
Branch: master
Commits: 6893
Updated: 2026-04-19 00:15
Git CLI clone URL
git clone https://www.xt-emporium.com/git/elks-enhanced.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
elks-enhanced
/
libc
/
misc
/
wildcard.c
File editor
/* * Copyright (c) 1993 by David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Wildcard name expansion, borrowed from sash. */ #include <regex.h> #include <dirent.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define FALSE 0 #define TRUE 1 typedef struct chunk CHUNK; #define CHUNKINITSIZE 4 struct chunk { CHUNK *next; char data[CHUNKINITSIZE]; /* actually of varying length */ }; static int chunkmaxmem = 2048; /* maximum memory used in wildcard expansion */ static int chunkmemused = 0; static CHUNK * chunklist; /* * Allocate a chunk of memory (like malloc). * The difference, though, is that the memory allocated is put on a * list of chunks which can be freed all at one time. You CAN NOT free * an individual chunk. */ static char * getchunk(int size) { CHUNK *chunk; if (size < CHUNKINITSIZE) size = CHUNKINITSIZE; size += sizeof(CHUNK) - CHUNKINITSIZE; if (chunkmemused + size > chunkmaxmem) return NULL; chunk = (CHUNK *) malloc(size); if (chunk == NULL) return NULL; chunkmemused += size; chunk->next = chunklist; chunklist = chunk; return chunk->data; } /* * Free all chunks of memory that had been allocated since the last * call to this routine. */ void freewildcards(void) { CHUNK *chunk; while (chunklist) { chunk = chunklist; chunklist = chunk->next; free((char *) chunk); } chunkmemused = 0; } /* * Routine to see if a text string is matched by a wildcard pattern. * Returns TRUE if the text is matched, or FALSE if it is not matched * or if the pattern is invalid. * * matches zero or more characters * ? matches a single character * [abc] matches 'a', 'b' or 'c' * \c quotes character c * Adapted from code written by Ingo Wilken. */ static int match(char *text, char *pattern) { char *retrypat; char *retrytxt; int ch; int found; retrypat = NULL; retrytxt = NULL; while (*text || *pattern) { ch = *pattern++; switch (ch) { case '*': retrypat = pattern; retrytxt = text; break; case '[': found = FALSE; while ((ch = *pattern++) != ']') { if (ch == '\\') ch = *pattern++; if (ch == '\0') return FALSE; if (*text == ch) found = TRUE; } if (!found) { pattern = retrypat; if (pattern == NULL) break; text = ++retrytxt; } /* fall into next case */ case '?': if (*text++ == '\0') return FALSE; break; case '\\': ch = *pattern++; if (ch == '\0') return FALSE; /* fall into next case */ default: if (*text == ch) { if (*text) text++; break; } if (*text) { pattern = retrypat; text = ++retrytxt; break; } return FALSE; } if (pattern == NULL) return FALSE; } return TRUE; } /* * Sort routine for list of filenames. */ static int namesort(char **p1, char **p2) { return strcmp(*p1, *p2); } /* * Expand the wildcards in a filename, if any. * Returns an argument list with matching filenames in sorted order. * The expanded names are stored in memory chunks which can later all * be freed at once. Returns zero if the name is not a wildcard, or * returns the count of matched files if the name is a wildcard and * there was at least one match, or returns < 0 if either no filenames * matched (-ENOENT), too many filenames matched (-ENOBUFS), no memory * available (-ENOMEM), or bad regular expression (-EINVAL). */ int expandwildcards(char *name, int maxargc, char **retargv) { char *last; char *cp1, *cp2, *cp3; DIR *dirp; struct dirent *dp; int dirlen; int matches; char dirname[256]; last = strrchr(name, '/'); if (last) last++; else last = name; cp1 = strchr(name, '*'); cp2 = strchr(name, '?'); cp3 = strchr(name, '['); if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL)) return 0; if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) || (cp3 && (cp3 < last))) return -EINVAL; /* Wildcards only implemented for last filename component*/ dirname[0] = '.'; dirname[1] = '\0'; if (last != name) { memcpy(dirname, name, last - name); dirname[last - name - 1] = '\0'; if (dirname[0] == '\0') { dirname[0] = '/'; dirname[1] = '\0'; } } dirp = opendir(dirname); if (dirp == NULL) return -ENOENT; dirlen = strlen(dirname); if (last == name) { dirlen = 0; dirname[0] = '\0'; } else if (dirname[dirlen - 1] != '/') { dirname[dirlen++] = '/'; dirname[dirlen] = '\0'; } matches = 0; while ((dp = readdir(dirp)) != NULL) { if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0)) continue; if (!match(dp->d_name, last)) continue; if (matches >= maxargc) { freewildcards(); closedir(dirp); return -ENOBUFS; /* Too many filename matches*/ } cp1 = getchunk(dirlen + strlen(dp->d_name) + 1); if (cp1 == NULL) { freewildcards(); closedir(dirp); return -ENOMEM; /* No memory for filenames*/ } if (dirlen) memcpy(cp1, dirname, dirlen); strcpy(cp1 + dirlen, dp->d_name); retargv[matches++] = cp1; } closedir(dirp); if (matches == 0) return -ENOENT; /* No matches*/ qsort((char *) retargv, matches, sizeof(char *), namesort); return matches; }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
master
Visibility
public
Your access
Read
Remote
Configured
File activity
View file history