Simple embedded shell with runtime pluggable commands.

Dependents:   DataBus2018

Implements a simple unix-like shell for embedded systems with a pluggable command architecture.

Committer:
shimniok
Date:
Fri Dec 28 17:10:31 2018 +0000
Revision:
31:27e8130a0d8f
began wildcard implementation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shimniok 31:27e8130a0d8f 1 /*
shimniok 31:27e8130a0d8f 2 * Copyright (c) 1989, 1993, 1994
shimniok 31:27e8130a0d8f 3 * The Regents of the University of California. All rights reserved.
shimniok 31:27e8130a0d8f 4 *
shimniok 31:27e8130a0d8f 5 * This code is derived from software contributed to Berkeley by
shimniok 31:27e8130a0d8f 6 * Guido van Rossum.
shimniok 31:27e8130a0d8f 7 *
shimniok 31:27e8130a0d8f 8 * Redistribution and use in source and binary forms, with or without
shimniok 31:27e8130a0d8f 9 * modification, are permitted provided that the following conditions
shimniok 31:27e8130a0d8f 10 * are met:
shimniok 31:27e8130a0d8f 11 * 1. Redistributions of source code must retain the above copyright
shimniok 31:27e8130a0d8f 12 * notice, this list of conditions and the following disclaimer.
shimniok 31:27e8130a0d8f 13 * 2. Redistributions in binary form must reproduce the above copyright
shimniok 31:27e8130a0d8f 14 * notice, this list of conditions and the following disclaimer in the
shimniok 31:27e8130a0d8f 15 * documentation and/or other materials provided with the distribution.
shimniok 31:27e8130a0d8f 16 * 3. All advertising materials mentioning features or use of this software
shimniok 31:27e8130a0d8f 17 * must display the following acknowledgement:
shimniok 31:27e8130a0d8f 18 * This product includes software developed by the University of
shimniok 31:27e8130a0d8f 19 * California, Berkeley and its contributors.
shimniok 31:27e8130a0d8f 20 * 4. Neither the name of the University nor the names of its contributors
shimniok 31:27e8130a0d8f 21 * may be used to endorse or promote products derived from this software
shimniok 31:27e8130a0d8f 22 * without specific prior written permission.
shimniok 31:27e8130a0d8f 23 *
shimniok 31:27e8130a0d8f 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
shimniok 31:27e8130a0d8f 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
shimniok 31:27e8130a0d8f 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
shimniok 31:27e8130a0d8f 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
shimniok 31:27e8130a0d8f 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
shimniok 31:27e8130a0d8f 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
shimniok 31:27e8130a0d8f 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
shimniok 31:27e8130a0d8f 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
shimniok 31:27e8130a0d8f 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
shimniok 31:27e8130a0d8f 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
shimniok 31:27e8130a0d8f 34 * SUCH DAMAGE.
shimniok 31:27e8130a0d8f 35 *
shimniok 31:27e8130a0d8f 36 * From FreeBSD fnmatch.c 1.11
shimniok 31:27e8130a0d8f 37 * $Id: fnmatch.c,v 1.3 1997/08/19 02:34:30 jdp Exp $
shimniok 31:27e8130a0d8f 38 */
shimniok 31:27e8130a0d8f 39
shimniok 31:27e8130a0d8f 40 #if defined(LIBC_SCCS) && !defined(lint)
shimniok 31:27e8130a0d8f 41 static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
shimniok 31:27e8130a0d8f 42 #endif /* LIBC_SCCS and not lint */
shimniok 31:27e8130a0d8f 43
shimniok 31:27e8130a0d8f 44 /*
shimniok 31:27e8130a0d8f 45 * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
shimniok 31:27e8130a0d8f 46 * Compares a filename or pathname to a pattern.
shimniok 31:27e8130a0d8f 47 */
shimniok 31:27e8130a0d8f 48
shimniok 31:27e8130a0d8f 49 #include <ctype.h>
shimniok 31:27e8130a0d8f 50 #include <string.h>
shimniok 31:27e8130a0d8f 51 #include <stdio.h>
shimniok 31:27e8130a0d8f 52
shimniok 31:27e8130a0d8f 53 #include "fnmatch.h"
shimniok 31:27e8130a0d8f 54
shimniok 31:27e8130a0d8f 55 #define EOS '\0'
shimniok 31:27e8130a0d8f 56
shimniok 31:27e8130a0d8f 57 static const char *rangematch(const char *, char, int);
shimniok 31:27e8130a0d8f 58
shimniok 31:27e8130a0d8f 59 int fnmatch(const char *pattern, const char *string, int flags)
shimniok 31:27e8130a0d8f 60 {
shimniok 31:27e8130a0d8f 61 const char *stringstart;
shimniok 31:27e8130a0d8f 62 char c, test;
shimniok 31:27e8130a0d8f 63
shimniok 31:27e8130a0d8f 64 for (stringstart = string;;)
shimniok 31:27e8130a0d8f 65 switch (c = *pattern++) {
shimniok 31:27e8130a0d8f 66 case EOS:
shimniok 31:27e8130a0d8f 67 if ((flags & FNM_LEADING_DIR) && *string == '/')
shimniok 31:27e8130a0d8f 68 return (0);
shimniok 31:27e8130a0d8f 69 return (*string == EOS ? 0 : FNM_NOMATCH);
shimniok 31:27e8130a0d8f 70 case '?':
shimniok 31:27e8130a0d8f 71 if (*string == EOS)
shimniok 31:27e8130a0d8f 72 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 73 if (*string == '/' && (flags & FNM_PATHNAME))
shimniok 31:27e8130a0d8f 74 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 75 if (*string == '.' && (flags & FNM_PERIOD) &&
shimniok 31:27e8130a0d8f 76 (string == stringstart ||
shimniok 31:27e8130a0d8f 77 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
shimniok 31:27e8130a0d8f 78 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 79 ++string;
shimniok 31:27e8130a0d8f 80 break;
shimniok 31:27e8130a0d8f 81 case '*':
shimniok 31:27e8130a0d8f 82 c = *pattern;
shimniok 31:27e8130a0d8f 83 /* Collapse multiple stars. */
shimniok 31:27e8130a0d8f 84 while (c == '*')
shimniok 31:27e8130a0d8f 85 c = *++pattern;
shimniok 31:27e8130a0d8f 86
shimniok 31:27e8130a0d8f 87 if (*string == '.' && (flags & FNM_PERIOD) &&
shimniok 31:27e8130a0d8f 88 (string == stringstart ||
shimniok 31:27e8130a0d8f 89 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
shimniok 31:27e8130a0d8f 90 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 91
shimniok 31:27e8130a0d8f 92 /* Optimize for pattern with * at end or before /. */
shimniok 31:27e8130a0d8f 93 if (c == EOS)
shimniok 31:27e8130a0d8f 94 if (flags & FNM_PATHNAME)
shimniok 31:27e8130a0d8f 95 return ((flags & FNM_LEADING_DIR) ||
shimniok 31:27e8130a0d8f 96 strchr(string, '/') == NULL ?
shimniok 31:27e8130a0d8f 97 0 : FNM_NOMATCH);
shimniok 31:27e8130a0d8f 98 else
shimniok 31:27e8130a0d8f 99 return (0);
shimniok 31:27e8130a0d8f 100 else if (c == '/' && flags & FNM_PATHNAME) {
shimniok 31:27e8130a0d8f 101 if ((string = strchr(string, '/')) == NULL)
shimniok 31:27e8130a0d8f 102 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 103 break;
shimniok 31:27e8130a0d8f 104 }
shimniok 31:27e8130a0d8f 105
shimniok 31:27e8130a0d8f 106 /* General case, use recursion. */
shimniok 31:27e8130a0d8f 107 while ((test = *string) != EOS) {
shimniok 31:27e8130a0d8f 108 if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
shimniok 31:27e8130a0d8f 109 return (0);
shimniok 31:27e8130a0d8f 110 if (test == '/' && flags & FNM_PATHNAME)
shimniok 31:27e8130a0d8f 111 break;
shimniok 31:27e8130a0d8f 112 ++string;
shimniok 31:27e8130a0d8f 113 }
shimniok 31:27e8130a0d8f 114 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 115 case '[':
shimniok 31:27e8130a0d8f 116 if (*string == EOS)
shimniok 31:27e8130a0d8f 117 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 118 if (*string == '/' && flags & FNM_PATHNAME)
shimniok 31:27e8130a0d8f 119 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 120 if ((pattern =
shimniok 31:27e8130a0d8f 121 rangematch(pattern, *string, flags)) == NULL)
shimniok 31:27e8130a0d8f 122 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 123 ++string;
shimniok 31:27e8130a0d8f 124 break;
shimniok 31:27e8130a0d8f 125 case '\\':
shimniok 31:27e8130a0d8f 126 if (!(flags & FNM_NOESCAPE)) {
shimniok 31:27e8130a0d8f 127 if ((c = *pattern++) == EOS) {
shimniok 31:27e8130a0d8f 128 c = '\\';
shimniok 31:27e8130a0d8f 129 --pattern;
shimniok 31:27e8130a0d8f 130 }
shimniok 31:27e8130a0d8f 131 }
shimniok 31:27e8130a0d8f 132 /* FALLTHROUGH */
shimniok 31:27e8130a0d8f 133 default:
shimniok 31:27e8130a0d8f 134 if (c == *string)
shimniok 31:27e8130a0d8f 135 ;
shimniok 31:27e8130a0d8f 136 else if ((flags & FNM_CASEFOLD) &&
shimniok 31:27e8130a0d8f 137 (tolower((unsigned char)c) ==
shimniok 31:27e8130a0d8f 138 tolower((unsigned char)*string)))
shimniok 31:27e8130a0d8f 139 ;
shimniok 31:27e8130a0d8f 140 else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
shimniok 31:27e8130a0d8f 141 ((c == '/' && string != stringstart) ||
shimniok 31:27e8130a0d8f 142 (string == stringstart+1 && *stringstart == '/')))
shimniok 31:27e8130a0d8f 143 return (0);
shimniok 31:27e8130a0d8f 144 else
shimniok 31:27e8130a0d8f 145 return (FNM_NOMATCH);
shimniok 31:27e8130a0d8f 146 string++;
shimniok 31:27e8130a0d8f 147 break;
shimniok 31:27e8130a0d8f 148 }
shimniok 31:27e8130a0d8f 149 /* NOTREACHED */
shimniok 31:27e8130a0d8f 150 }
shimniok 31:27e8130a0d8f 151
shimniok 31:27e8130a0d8f 152 static const char *
shimniok 31:27e8130a0d8f 153 rangematch(const char *pattern, char test, int flags)
shimniok 31:27e8130a0d8f 154 {
shimniok 31:27e8130a0d8f 155 int negate, ok;
shimniok 31:27e8130a0d8f 156 char c, c2;
shimniok 31:27e8130a0d8f 157
shimniok 31:27e8130a0d8f 158 /*
shimniok 31:27e8130a0d8f 159 * A bracket expression starting with an unquoted circumflex
shimniok 31:27e8130a0d8f 160 * character produces unspecified results (IEEE 1003.2-1992,
shimniok 31:27e8130a0d8f 161 * 3.13.2). This implementation treats it like '!', for
shimniok 31:27e8130a0d8f 162 * consistency with the regular expression syntax.
shimniok 31:27e8130a0d8f 163 * J.T. Conklin (conklin@ngai.kaleida.com)
shimniok 31:27e8130a0d8f 164 */
shimniok 31:27e8130a0d8f 165 if ( (negate = (*pattern == '!' || *pattern == '^')) )
shimniok 31:27e8130a0d8f 166 ++pattern;
shimniok 31:27e8130a0d8f 167
shimniok 31:27e8130a0d8f 168 if (flags & FNM_CASEFOLD)
shimniok 31:27e8130a0d8f 169 test = tolower((unsigned char)test);
shimniok 31:27e8130a0d8f 170
shimniok 31:27e8130a0d8f 171 for (ok = 0; (c = *pattern++) != ']';) {
shimniok 31:27e8130a0d8f 172 if (c == '\\' && !(flags & FNM_NOESCAPE))
shimniok 31:27e8130a0d8f 173 c = *pattern++;
shimniok 31:27e8130a0d8f 174 if (c == EOS)
shimniok 31:27e8130a0d8f 175 return (NULL);
shimniok 31:27e8130a0d8f 176
shimniok 31:27e8130a0d8f 177 if (flags & FNM_CASEFOLD)
shimniok 31:27e8130a0d8f 178 c = tolower((unsigned char)c);
shimniok 31:27e8130a0d8f 179
shimniok 31:27e8130a0d8f 180 if (*pattern == '-'
shimniok 31:27e8130a0d8f 181 && (c2 = *(pattern+1)) != EOS && c2 != ']') {
shimniok 31:27e8130a0d8f 182 pattern += 2;
shimniok 31:27e8130a0d8f 183 if (c2 == '\\' && !(flags & FNM_NOESCAPE))
shimniok 31:27e8130a0d8f 184 c2 = *pattern++;
shimniok 31:27e8130a0d8f 185 if (c2 == EOS)
shimniok 31:27e8130a0d8f 186 return (NULL);
shimniok 31:27e8130a0d8f 187
shimniok 31:27e8130a0d8f 188 if (flags & FNM_CASEFOLD)
shimniok 31:27e8130a0d8f 189 c2 = tolower((unsigned char)c2);
shimniok 31:27e8130a0d8f 190
shimniok 31:27e8130a0d8f 191 if ((unsigned char)c <= (unsigned char)test &&
shimniok 31:27e8130a0d8f 192 (unsigned char)test <= (unsigned char)c2)
shimniok 31:27e8130a0d8f 193 ok = 1;
shimniok 31:27e8130a0d8f 194 } else if (c == test)
shimniok 31:27e8130a0d8f 195 ok = 1;
shimniok 31:27e8130a0d8f 196 }
shimniok 31:27e8130a0d8f 197 return (ok == negate ? NULL : pattern);
shimniok 31:27e8130a0d8f 198 }