xref: /openbsd/bin/ksh/misc.c (revision 404b540a)
1 /*	$OpenBSD: misc.c,v 1.37 2009/04/19 20:34:05 sthen Exp $	*/
2 
3 /*
4  * Miscellaneous functions
5  */
6 
7 #include "sh.h"
8 #include <ctype.h>
9 #include <sys/param.h>	/* for MAXPATHLEN */
10 #include "charclass.h"
11 
12 short ctypes [UCHAR_MAX+1];	/* type bits for unsigned char */
13 
14 static int	do_gmatch(const unsigned char *, const unsigned char *,
15 		    const unsigned char *, const unsigned char *);
16 static const unsigned char *cclass(const unsigned char *, int);
17 
18 /*
19  * Fast character classes
20  */
21 void
22 setctypes(const char *s, int t)
23 {
24 	int i;
25 
26 	if (t & C_IFS) {
27 		for (i = 0; i < UCHAR_MAX+1; i++)
28 			ctypes[i] &= ~C_IFS;
29 		ctypes[0] |= C_IFS; /* include \0 in C_IFS */
30 	}
31 	while (*s != 0)
32 		ctypes[(unsigned char) *s++] |= t;
33 }
34 
35 void
36 initctypes(void)
37 {
38 	int c;
39 
40 	for (c = 'a'; c <= 'z'; c++)
41 		ctypes[c] |= C_ALPHA;
42 	for (c = 'A'; c <= 'Z'; c++)
43 		ctypes[c] |= C_ALPHA;
44 	ctypes['_'] |= C_ALPHA;
45 	setctypes("0123456789", C_DIGIT);
46 	setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */
47 	setctypes("*@#!$-?", C_VAR1);
48 	setctypes(" \t\n", C_IFSWS);
49 	setctypes("=-+?", C_SUBOP1);
50 	setctypes("#%", C_SUBOP2);
51 	setctypes(" \n\t\"#$&'()*;<>?[\\`|", C_QUOTE);
52 }
53 
54 /* convert unsigned long to base N string */
55 
56 char *
57 ulton(long unsigned int n, int base)
58 {
59 	char *p;
60 	static char buf [20];
61 
62 	p = &buf[sizeof(buf)];
63 	*--p = '\0';
64 	do {
65 		*--p = "0123456789ABCDEF"[n%base];
66 		n /= base;
67 	} while (n != 0);
68 	return p;
69 }
70 
71 char *
72 str_save(const char *s, Area *ap)
73 {
74 	size_t len;
75 	char *p;
76 
77 	if (!s)
78 		return NULL;
79 	len = strlen(s)+1;
80 	p = alloc(len, ap);
81 	strlcpy(p, s, len);
82 	return (p);
83 }
84 
85 /* Allocate a string of size n+1 and copy upto n characters from the possibly
86  * null terminated string s into it.  Always returns a null terminated string
87  * (unless n < 0).
88  */
89 char *
90 str_nsave(const char *s, int n, Area *ap)
91 {
92 	char *ns;
93 
94 	if (n < 0)
95 		return 0;
96 	ns = alloc(n + 1, ap);
97 	ns[0] = '\0';
98 	return strncat(ns, s, n);
99 }
100 
101 /* called from expand.h:XcheckN() to grow buffer */
102 char *
103 Xcheck_grow_(XString *xsp, char *xp, int more)
104 {
105 	char *old_beg = xsp->beg;
106 
107 	xsp->len += more > xsp->len ? more : xsp->len;
108 	xsp->beg = aresize(xsp->beg, xsp->len + 8, xsp->areap);
109 	xsp->end = xsp->beg + xsp->len;
110 	return xsp->beg + (xp - old_beg);
111 }
112 
113 const struct option options[] = {
114 	/* Special cases (see parse_args()): -A, -o, -s.
115 	 * Options are sorted by their longnames - the order of these
116 	 * entries MUST match the order of sh_flag F* enumerations in sh.h.
117 	 */
118 	{ "allexport",	'a',		OF_ANY },
119 #ifdef BRACE_EXPAND
120 	{ "braceexpand",  0,		OF_ANY }, /* non-standard */
121 #endif
122 	{ "bgnice",	  0,		OF_ANY },
123 	{ (char *) 0,	'c',	    OF_CMDLINE },
124 	{ "csh-history",  0,		OF_ANY }, /* non-standard */
125 #ifdef EMACS
126 	{ "emacs",	  0,		OF_ANY },
127 	{ "emacs-usemeta",  0,		OF_ANY }, /* non-standard */
128 #endif
129 	{ "errexit",	'e',		OF_ANY },
130 #ifdef EMACS
131 	{ "gmacs",	  0,		OF_ANY },
132 #endif
133 	{ "ignoreeof",	  0,		OF_ANY },
134 	{ "interactive",'i',	    OF_CMDLINE },
135 	{ "keyword",	'k',		OF_ANY },
136 	{ "login",	'l',	    OF_CMDLINE },
137 	{ "markdirs",	'X',		OF_ANY },
138 #ifdef JOBS
139 	{ "monitor",	'm',		OF_ANY },
140 #else /* JOBS */
141 	{ (char *) 0,	'm',		     0 }, /* so FMONITOR not ifdef'd */
142 #endif /* JOBS */
143 	{ "noclobber",	'C',		OF_ANY },
144 	{ "noexec",	'n',		OF_ANY },
145 	{ "noglob",	'f',		OF_ANY },
146 	{ "nohup",	  0,		OF_ANY },
147 	{ "nolog",	  0,		OF_ANY }, /* no effect */
148 #ifdef	JOBS
149 	{ "notify",	'b',		OF_ANY },
150 #endif	/* JOBS */
151 	{ "nounset",	'u',		OF_ANY },
152 	{ "physical",	  0,		OF_ANY }, /* non-standard */
153 	{ "posix",	  0,		OF_ANY }, /* non-standard */
154 	{ "privileged",	'p',		OF_ANY },
155 	{ "restricted",	'r',	    OF_CMDLINE },
156 	{ "sh",		  0,		OF_ANY }, /* non-standard */
157 	{ "stdin",	's',	    OF_CMDLINE }, /* pseudo non-standard */
158 	{ "trackall",	'h',		OF_ANY },
159 	{ "verbose",	'v',		OF_ANY },
160 #ifdef VI
161 	{ "vi",		  0,		OF_ANY },
162 	{ "viraw",	  0,		OF_ANY }, /* no effect */
163 	{ "vi-show8",	  0,		OF_ANY }, /* non-standard */
164 	{ "vi-tabcomplete",  0,		OF_ANY }, /* non-standard */
165 	{ "vi-esccomplete",  0,		OF_ANY }, /* non-standard */
166 #endif
167 	{ "xtrace",	'x',		OF_ANY },
168 	/* Anonymous flags: used internally by shell only
169 	 * (not visible to user)
170 	 */
171 	{ (char *) 0,	0,		OF_INTERNAL }, /* FTALKING_I */
172 };
173 
174 /*
175  * translate -o option into F* constant (also used for test -o option)
176  */
177 int
178 option(const char *n)
179 {
180 	int i;
181 
182 	for (i = 0; i < NELEM(options); i++)
183 		if (options[i].name && strcmp(options[i].name, n) == 0)
184 			return i;
185 
186 	return -1;
187 }
188 
189 struct options_info {
190 	int opt_width;
191 	struct {
192 		const char *name;
193 		int	flag;
194 	} opts[NELEM(options)];
195 };
196 
197 static char *options_fmt_entry(void *arg, int i, char *buf, int buflen);
198 static void printoptions(int verbose);
199 
200 /* format a single select menu item */
201 static char *
202 options_fmt_entry(void *arg, int i, char *buf, int buflen)
203 {
204 	struct options_info *oi = (struct options_info *) arg;
205 
206 	shf_snprintf(buf, buflen, "%-*s %s",
207 	    oi->opt_width, oi->opts[i].name,
208 	    Flag(oi->opts[i].flag) ? "on" : "off");
209 	return buf;
210 }
211 
212 static void
213 printoptions(int verbose)
214 {
215 	int i;
216 
217 	if (verbose) {
218 		struct options_info oi;
219 		int n, len;
220 
221 		/* verbose version */
222 		shprintf("Current option settings\n");
223 
224 		for (i = n = oi.opt_width = 0; i < NELEM(options); i++)
225 			if (options[i].name) {
226 				len = strlen(options[i].name);
227 				oi.opts[n].name = options[i].name;
228 				oi.opts[n++].flag = i;
229 				if (len > oi.opt_width)
230 					oi.opt_width = len;
231 			}
232 		print_columns(shl_stdout, n, options_fmt_entry, &oi,
233 		    oi.opt_width + 5, 1);
234 	} else {
235 		/* short version ala ksh93 */
236 		shprintf("set");
237 		for (i = 0; i < NELEM(options); i++)
238 			if (Flag(i) && options[i].name)
239 				shprintf(" -o %s", options[i].name);
240 		shprintf(newline);
241 	}
242 }
243 
244 char *
245 getoptions(void)
246 {
247 	int i;
248 	char m[(int) FNFLAGS + 1];
249 	char *cp = m;
250 
251 	for (i = 0; i < NELEM(options); i++)
252 		if (options[i].c && Flag(i))
253 			*cp++ = options[i].c;
254 	*cp = 0;
255 	return str_save(m, ATEMP);
256 }
257 
258 /* change a Flag(*) value; takes care of special actions */
259 void
260 change_flag(enum sh_flag f,
261     int what,		/* flag to change */
262     int newval)		/* what is changing the flag (command line vs set) */
263 {
264 	int oldval;
265 
266 	oldval = Flag(f);
267 	Flag(f) = newval;
268 #ifdef JOBS
269 	if (f == FMONITOR) {
270 		if (what != OF_CMDLINE && newval != oldval)
271 			j_change();
272 	} else
273 #endif /* JOBS */
274 #ifdef EDIT
275 	if (0
276 # ifdef VI
277 	    || f == FVI
278 # endif /* VI */
279 # ifdef EMACS
280 	    || f == FEMACS || f == FGMACS
281 # endif /* EMACS */
282 	   )
283 	{
284 		if (newval) {
285 # ifdef VI
286 			Flag(FVI) = 0;
287 # endif /* VI */
288 # ifdef EMACS
289 			Flag(FEMACS) = Flag(FGMACS) = 0;
290 # endif /* EMACS */
291 			Flag(f) = newval;
292 		}
293 	} else
294 #endif /* EDIT */
295 	/* Turning off -p? */
296 	if (f == FPRIVILEGED && oldval && !newval) {
297 		gid_t gid = getgid();
298 
299 		setresgid(gid, gid, gid);
300 		setgroups(1, &gid);
301 		setresuid(ksheuid, ksheuid, ksheuid);
302 	} else if (f == FPOSIX && newval) {
303 #ifdef BRACE_EXPAND
304 		Flag(FBRACEEXPAND) = 0
305 #endif /* BRACE_EXPAND */
306 		;
307 	}
308 	/* Changing interactive flag? */
309 	if (f == FTALKING) {
310 		if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid)
311 			Flag(FTALKING_I) = newval;
312 	}
313 }
314 
315 /* parse command line & set command arguments.  returns the index of
316  * non-option arguments, -1 if there is an error.
317  */
318 int
319 parse_args(char **argv,
320     int what,			/* OF_CMDLINE or OF_SET */
321     int *setargsp)
322 {
323 	static char cmd_opts[NELEM(options) + 3]; /* o:\0 */
324 	static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */
325 	char *opts;
326 	char *array = (char *) 0;
327 	Getopt go;
328 	int i, optc, set, sortargs = 0, arrayset = 0;
329 
330 	/* First call?  Build option strings... */
331 	if (cmd_opts[0] == '\0') {
332 		char *p, *q;
333 
334 		/* see cmd_opts[] declaration */
335 		strlcpy(cmd_opts, "o:", sizeof cmd_opts);
336 		p = cmd_opts + strlen(cmd_opts);
337 		/* see set_opts[] declaration */
338 		strlcpy(set_opts, "A:o;s", sizeof set_opts);
339 		q = set_opts + strlen(set_opts);
340 		for (i = 0; i < NELEM(options); i++) {
341 			if (options[i].c) {
342 				if (options[i].flags & OF_CMDLINE)
343 					*p++ = options[i].c;
344 				if (options[i].flags & OF_SET)
345 					*q++ = options[i].c;
346 			}
347 		}
348 		*p = '\0';
349 		*q = '\0';
350 	}
351 
352 	if (what == OF_CMDLINE) {
353 		char *p;
354 		/* Set FLOGIN before parsing options so user can clear
355 		 * flag using +l.
356 		 */
357 		Flag(FLOGIN) = (argv[0][0] == '-' ||
358 		    ((p = strrchr(argv[0], '/')) && *++p == '-'));
359 		opts = cmd_opts;
360 	} else
361 		opts = set_opts;
362 	ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT);
363 	while ((optc = ksh_getopt(argv, &go, opts)) != -1) {
364 		set = (go.info & GI_PLUS) ? 0 : 1;
365 		switch (optc) {
366 		case 'A':
367 			arrayset = set ? 1 : -1;
368 			array = go.optarg;
369 			break;
370 
371 		case 'o':
372 			if (go.optarg == (char *) 0) {
373 				/* lone -o: print options
374 				 *
375 				 * Note that on the command line, -o requires
376 				 * an option (ie, can't get here if what is
377 				 * OF_CMDLINE).
378 				 */
379 				printoptions(set);
380 				break;
381 			}
382 			i = option(go.optarg);
383 			if (i >= 0 && set == Flag(i))
384 				/* Don't check the context if the flag
385 				 * isn't changing - makes "set -o interactive"
386 				 * work if you're already interactive.  Needed
387 				 * if the output of "set +o" is to be used.
388 				 */
389 				;
390 			else if (i >= 0 && (options[i].flags & what))
391 				change_flag((enum sh_flag) i, what, set);
392 			else {
393 				bi_errorf("%s: bad option", go.optarg);
394 				return -1;
395 			}
396 			break;
397 
398 		case '?':
399 			return -1;
400 
401 		default:
402 			/* -s: sort positional params (at&t ksh stupidity) */
403 			if (what == OF_SET && optc == 's') {
404 				sortargs = 1;
405 				break;
406 			}
407 			for (i = 0; i < NELEM(options); i++)
408 				if (optc == options[i].c &&
409 				    (what & options[i].flags)) {
410 					change_flag((enum sh_flag) i, what,
411 					    set);
412 					break;
413 				}
414 			if (i == NELEM(options)) {
415 				internal_errorf(1, "parse_args: `%c'", optc);
416 				return -1; /* not reached */
417 			}
418 		}
419 	}
420 	if (!(go.info & GI_MINUSMINUS) && argv[go.optind] &&
421 	    (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') &&
422 	    argv[go.optind][1] == '\0') {
423 		/* lone - clears -v and -x flags */
424 		if (argv[go.optind][0] == '-' && !Flag(FPOSIX))
425 			Flag(FVERBOSE) = Flag(FXTRACE) = 0;
426 		/* set skips lone - or + option */
427 		go.optind++;
428 	}
429 	if (setargsp)
430 		/* -- means set $#/$* even if there are no arguments */
431 		*setargsp = !arrayset && ((go.info & GI_MINUSMINUS) ||
432 		    argv[go.optind]);
433 
434 	if (arrayset && (!*array || *skip_varname(array, false))) {
435 		bi_errorf("%s: is not an identifier", array);
436 		return -1;
437 	}
438 	if (sortargs) {
439 		for (i = go.optind; argv[i]; i++)
440 			;
441 		qsortp((void **) &argv[go.optind], (size_t) (i - go.optind),
442 		    xstrcmp);
443 	}
444 	if (arrayset) {
445 		set_array(array, arrayset, argv + go.optind);
446 		for (; argv[go.optind]; go.optind++)
447 			;
448 	}
449 
450 	return go.optind;
451 }
452 
453 /* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */
454 int
455 getn(const char *as, int *ai)
456 {
457 	char *p;
458 	long n;
459 
460 	n = strtol(as, &p, 10);
461 
462 	if (!*as || *p || INT_MIN >= n || n >= INT_MAX)
463 		return 0;
464 
465 	*ai = (int)n;
466 	return 1;
467 }
468 
469 /* getn() that prints error */
470 int
471 bi_getn(const char *as, int *ai)
472 {
473 	int rv = getn(as, ai);
474 
475 	if (!rv)
476 		bi_errorf("%s: bad number", as);
477 	return rv;
478 }
479 
480 /* -------- gmatch.c -------- */
481 
482 /*
483  * int gmatch(string, pattern)
484  * char *string, *pattern;
485  *
486  * Match a pattern as in sh(1).
487  * pattern character are prefixed with MAGIC by expand.
488  */
489 
490 int
491 gmatch(const char *s, const char *p, int isfile)
492 {
493 	const char *se, *pe;
494 
495 	if (s == NULL || p == NULL)
496 		return 0;
497 	se = s + strlen(s);
498 	pe = p + strlen(p);
499 	/* isfile is false iff no syntax check has been done on
500 	 * the pattern.  If check fails, just to a strcmp().
501 	 */
502 	if (!isfile && !has_globbing(p, pe)) {
503 		int len = pe - p + 1;
504 		char tbuf[64];
505 		char *t = len <= sizeof(tbuf) ? tbuf :
506 		    (char *) alloc(len, ATEMP);
507 		debunk(t, p, len);
508 		return !strcmp(t, s);
509 	}
510 	return do_gmatch((const unsigned char *) s, (const unsigned char *) se,
511 	    (const unsigned char *) p, (const unsigned char *) pe);
512 }
513 
514 /* Returns if p is a syntacticly correct globbing pattern, false
515  * if it contains no pattern characters or if there is a syntax error.
516  * Syntax errors are:
517  *	- [ with no closing ]
518  *	- imbalanced $(...) expression
519  *	- [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d))
520  */
521 /*XXX
522 - if no magic,
523 	if dest given, copy to dst
524 	return ?
525 - if magic && (no globbing || syntax error)
526 	debunk to dst
527 	return ?
528 - return ?
529 */
530 int
531 has_globbing(const char *xp, const char *xpe)
532 {
533 	const unsigned char *p = (const unsigned char *) xp;
534 	const unsigned char *pe = (const unsigned char *) xpe;
535 	int c;
536 	int nest = 0, bnest = 0;
537 	int saw_glob = 0;
538 	int in_bracket = 0; /* inside [...] */
539 
540 	for (; p < pe; p++) {
541 		if (!ISMAGIC(*p))
542 			continue;
543 		if ((c = *++p) == '*' || c == '?')
544 			saw_glob = 1;
545 		else if (c == '[') {
546 			if (!in_bracket) {
547 				saw_glob = 1;
548 				in_bracket = 1;
549 				if (ISMAGIC(p[1]) && p[2] == NOT)
550 					p += 2;
551 				if (ISMAGIC(p[1]) && p[2] == ']')
552 					p += 2;
553 			}
554 			/* XXX Do we need to check ranges here? POSIX Q */
555 		} else if (c == ']') {
556 			if (in_bracket) {
557 				if (bnest)		/* [a*(b]) */
558 					return 0;
559 				in_bracket = 0;
560 			}
561 		} else if ((c & 0x80) && strchr("*+?@! ", c & 0x7f)) {
562 			saw_glob = 1;
563 			if (in_bracket)
564 				bnest++;
565 			else
566 				nest++;
567 		} else if (c == '|') {
568 			if (in_bracket && !bnest)	/* *(a[foo|bar]) */
569 				return 0;
570 		} else if (c == /*(*/ ')') {
571 			if (in_bracket) {
572 				if (!bnest--)		/* *(a[b)c] */
573 					return 0;
574 			} else if (nest)
575 				nest--;
576 		}
577 		/* else must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, MAGIC-]
578 			 MAGIC-{, MAGIC-,, MAGIC-} */
579 	}
580 	return saw_glob && !in_bracket && !nest;
581 }
582 
583 /* Function must return either 0 or 1 (assumed by code for 0x80|'!') */
584 static int
585 do_gmatch(const unsigned char *s, const unsigned char *se,
586     const unsigned char *p, const unsigned char *pe)
587 {
588 	int sc, pc;
589 	const unsigned char *prest, *psub, *pnext;
590 	const unsigned char *srest;
591 
592 	if (s == NULL || p == NULL)
593 		return 0;
594 	while (p < pe) {
595 		pc = *p++;
596 		sc = s < se ? *s : '\0';
597 		s++;
598 		if (!ISMAGIC(pc)) {
599 			if (sc != pc)
600 				return 0;
601 			continue;
602 		}
603 		switch (*p++) {
604 		case '[':
605 			if (sc == 0 || (p = cclass(p, sc)) == NULL)
606 				return 0;
607 			break;
608 
609 		case '?':
610 			if (sc == 0)
611 				return 0;
612 			break;
613 
614 		case '*':
615 			if (p == pe)
616 				return 1;
617 			s--;
618 			do {
619 				if (do_gmatch(s, se, p, pe))
620 					return 1;
621 			} while (s++ < se);
622 			return 0;
623 
624 		  /*
625 		   * [*+?@!](pattern|pattern|..)
626 		   *
627 		   * Not ifdef'd KSH as this is needed for ${..%..}, etc.
628 		   */
629 		case 0x80|'+': /* matches one or more times */
630 		case 0x80|'*': /* matches zero or more times */
631 			if (!(prest = pat_scan(p, pe, 0)))
632 				return 0;
633 			s--;
634 			/* take care of zero matches */
635 			if (p[-1] == (0x80 | '*') &&
636 			    do_gmatch(s, se, prest, pe))
637 				return 1;
638 			for (psub = p; ; psub = pnext) {
639 				pnext = pat_scan(psub, pe, 1);
640 				for (srest = s; srest <= se; srest++) {
641 					if (do_gmatch(s, srest, psub, pnext - 2) &&
642 					    (do_gmatch(srest, se, prest, pe) ||
643 					    (s != srest && do_gmatch(srest,
644 					    se, p - 2, pe))))
645 						return 1;
646 				}
647 				if (pnext == prest)
648 					break;
649 			}
650 			return 0;
651 
652 		case 0x80|'?': /* matches zero or once */
653 		case 0x80|'@': /* matches one of the patterns */
654 		case 0x80|' ': /* simile for @ */
655 			if (!(prest = pat_scan(p, pe, 0)))
656 				return 0;
657 			s--;
658 			/* Take care of zero matches */
659 			if (p[-1] == (0x80 | '?') &&
660 			    do_gmatch(s, se, prest, pe))
661 				return 1;
662 			for (psub = p; ; psub = pnext) {
663 				pnext = pat_scan(psub, pe, 1);
664 				srest = prest == pe ? se : s;
665 				for (; srest <= se; srest++) {
666 					if (do_gmatch(s, srest, psub, pnext - 2) &&
667 					    do_gmatch(srest, se, prest, pe))
668 						return 1;
669 				}
670 				if (pnext == prest)
671 					break;
672 			}
673 			return 0;
674 
675 		case 0x80|'!': /* matches none of the patterns */
676 			if (!(prest = pat_scan(p, pe, 0)))
677 				return 0;
678 			s--;
679 			for (srest = s; srest <= se; srest++) {
680 				int matched = 0;
681 
682 				for (psub = p; ; psub = pnext) {
683 					pnext = pat_scan(psub, pe, 1);
684 					if (do_gmatch(s, srest, psub,
685 					    pnext - 2)) {
686 						matched = 1;
687 						break;
688 					}
689 					if (pnext == prest)
690 						break;
691 				}
692 				if (!matched &&
693 				    do_gmatch(srest, se, prest, pe))
694 					return 1;
695 			}
696 			return 0;
697 
698 		default:
699 			if (sc != p[-1])
700 				return 0;
701 			break;
702 		}
703 	}
704 	return s == se;
705 }
706 
707 static int
708 posix_cclass(const unsigned char *pattern, int test, const unsigned char **ep)
709 {
710 	struct cclass *cc;
711 	const unsigned char *colon;
712 	size_t len;
713 	int rval = 0;
714 
715 	if ((colon = strchr(pattern, ':')) == NULL || colon[1] != MAGIC) {
716 		*ep = pattern - 2;
717 		return -1;
718 	}
719 	*ep = colon + 3; /* skip MAGIC */
720 	len = (size_t)(colon - pattern);
721 
722 	for (cc = cclasses; cc->name != NULL; cc++) {
723 		if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
724 			if (cc->isctype(test))
725 				rval = 1;
726 			break;
727 		}
728 	}
729 	if (cc->name == NULL) {
730 		rval = -2;	/* invalid character class */
731 	}
732 	return rval;
733 }
734 
735 static const unsigned char *
736 cclass(const unsigned char *p, int sub)
737 {
738 	int c, d, rv, not, found = 0;
739 	const unsigned char *orig_p = p;
740 
741 	if ((not = (ISMAGIC(*p) && *++p == NOT)))
742 		p++;
743 	do {
744 		/* check for POSIX character class (e.g. [[:alpha:]]) */
745 		if ((p[0] == MAGIC && p[1] == '[' && p[2] == ':') ||
746 		    (p[0] == '[' && p[1] == ':')) {
747 			do {
748 				const char *pp = p + (*p == MAGIC) + 2;
749 				rv = posix_cclass(pp, sub, &p);
750 				switch (rv) {
751 				case 1:
752 					found = 1;
753 					break;
754 				case -2:
755 					return NULL;
756 				}
757 			} while (rv != -1 && p[0] == MAGIC && p[1] == '[' && p[2] == ':');
758 			if (p[0] == MAGIC && p[1] == ']')
759 				break;
760 		}
761 
762 		c = *p++;
763 		if (ISMAGIC(c)) {
764 			c = *p++;
765 			if ((c & 0x80) && !ISMAGIC(c)) {
766 				c &= 0x7f;/* extended pattern matching: *+?@! */
767 				/* XXX the ( char isn't handled as part of [] */
768 				if (c == ' ') /* simile for @: plain (..) */
769 					c = '(' /*)*/;
770 			}
771 		}
772 		if (c == '\0')
773 			/* No closing ] - act as if the opening [ was quoted */
774 			return sub == '[' ? orig_p : NULL;
775 		if (ISMAGIC(p[0]) && p[1] == '-' &&
776 		    (!ISMAGIC(p[2]) || p[3] != ']')) {
777 			p += 2; /* MAGIC- */
778 			d = *p++;
779 			if (ISMAGIC(d)) {
780 				d = *p++;
781 				if ((d & 0x80) && !ISMAGIC(d))
782 					d &= 0x7f;
783 			}
784 			/* POSIX says this is an invalid expression */
785 			if (c > d)
786 				return NULL;
787 		} else
788 			d = c;
789 		if (c == sub || (c <= sub && sub <= d))
790 			found = 1;
791 	} while (!(ISMAGIC(p[0]) && p[1] == ']'));
792 
793 	return (found != not) ? p+2 : NULL;
794 }
795 
796 /* Look for next ) or | (if match_sep) in *(foo|bar) pattern */
797 const unsigned char *
798 pat_scan(const unsigned char *p, const unsigned char *pe, int match_sep)
799 {
800 	int nest = 0;
801 
802 	for (; p < pe; p++) {
803 		if (!ISMAGIC(*p))
804 			continue;
805 		if ((*++p == /*(*/ ')' && nest-- == 0) ||
806 		    (*p == '|' && match_sep && nest == 0))
807 			return ++p;
808 		if ((*p & 0x80) && strchr("*+?@! ", *p & 0x7f))
809 			nest++;
810 	}
811 	return (const unsigned char *) 0;
812 }
813 
814 /*
815  * quick sort of array of generic pointers to objects.
816  */
817 void
818 qsortp(void **base,			/* base address */
819     size_t n,				/* elements */
820     int (*f) (const void *, const void *)) /* compare function */
821 {
822 	qsort(base, n, sizeof(char *), f);
823 }
824 
825 int
826 xstrcmp(const void *p1, const void *p2)
827 {
828 	return (strcmp(*(char **)p1, *(char **)p2));
829 }
830 
831 /* Initialize a Getopt structure */
832 void
833 ksh_getopt_reset(Getopt *go, int flags)
834 {
835 	go->optind = 1;
836 	go->optarg = (char *) 0;
837 	go->p = 0;
838 	go->flags = flags;
839 	go->info = 0;
840 	go->buf[1] = '\0';
841 }
842 
843 
844 /* getopt() used for shell built-in commands, the getopts command, and
845  * command line options.
846  * A leading ':' in options means don't print errors, instead return '?'
847  * or ':' and set go->optarg to the offending option character.
848  * If GF_ERROR is set (and option doesn't start with :), errors result in
849  * a call to bi_errorf().
850  *
851  * Non-standard features:
852  *	- ';' is like ':' in options, except the argument is optional
853  *	  (if it isn't present, optarg is set to 0).
854  *	  Used for 'set -o'.
855  *	- ',' is like ':' in options, except the argument always immediately
856  *	  follows the option character (optarg is set to the null string if
857  *	  the option is missing).
858  *	  Used for 'read -u2', 'print -u2' and fc -40.
859  *	- '#' is like ':' in options, expect that the argument is optional
860  *	  and must start with a digit or be the string "unlimited".  If the
861  *	  argument doesn't match, it is assumed to be missing and normal option
862  *	  processing continues (optarg is set to 0 if the option is missing).
863  *	  Used for 'typeset -LZ4' and 'ulimit -adunlimited'.
864  *	- accepts +c as well as -c IF the GF_PLUSOPT flag is present.  If an
865  *	  option starting with + is accepted, the GI_PLUS flag will be set
866  *	  in go->info.
867  */
868 int
869 ksh_getopt(char **argv, Getopt *go, const char *options)
870 {
871 	char c;
872 	char *o;
873 
874 	if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') {
875 		char *arg = argv[go->optind], flag = arg ? *arg : '\0';
876 
877 		go->p = 1;
878 		if (flag == '-' && arg[1] == '-' && arg[2] == '\0') {
879 			go->optind++;
880 			go->p = 0;
881 			go->info |= GI_MINUSMINUS;
882 			return -1;
883 		}
884 		if (arg == (char *) 0 ||
885 		    ((flag != '-' ) && /* neither a - nor a + (if + allowed) */
886 		    (!(go->flags & GF_PLUSOPT) || flag != '+')) ||
887 		    (c = arg[1]) == '\0') {
888 			go->p = 0;
889 			return -1;
890 		}
891 		go->optind++;
892 		go->info &= ~(GI_MINUS|GI_PLUS);
893 		go->info |= flag == '-' ? GI_MINUS : GI_PLUS;
894 	}
895 	go->p++;
896 	if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#' ||
897 	    !(o = strchr(options, c))) {
898 		if (options[0] == ':') {
899 			go->buf[0] = c;
900 			go->optarg = go->buf;
901 		} else {
902 			warningf(true, "%s%s-%c: unknown option",
903 			    (go->flags & GF_NONAME) ? "" : argv[0],
904 			    (go->flags & GF_NONAME) ? "" : ": ", c);
905 			if (go->flags & GF_ERROR)
906 				bi_errorf(null);
907 		}
908 		return '?';
909 	}
910 	/* : means argument must be present, may be part of option argument
911 	 *   or the next argument
912 	 * ; same as : but argument may be missing
913 	 * , means argument is part of option argument, and may be null.
914 	 */
915 	if (*++o == ':' || *o == ';') {
916 		if (argv[go->optind - 1][go->p])
917 			go->optarg = argv[go->optind - 1] + go->p;
918 		else if (argv[go->optind])
919 			go->optarg = argv[go->optind++];
920 		else if (*o == ';')
921 			go->optarg = (char *) 0;
922 		else {
923 			if (options[0] == ':') {
924 				go->buf[0] = c;
925 				go->optarg = go->buf;
926 				return ':';
927 			}
928 			warningf(true, "%s%s-`%c' requires argument",
929 			    (go->flags & GF_NONAME) ? "" : argv[0],
930 			    (go->flags & GF_NONAME) ? "" : ": ", c);
931 			if (go->flags & GF_ERROR)
932 				bi_errorf(null);
933 			return '?';
934 		}
935 		go->p = 0;
936 	} else if (*o == ',') {
937 		/* argument is attached to option character, even if null */
938 		go->optarg = argv[go->optind - 1] + go->p;
939 		go->p = 0;
940 	} else if (*o == '#') {
941 		/* argument is optional and may be attached or unattached
942 		 * but must start with a digit.  optarg is set to 0 if the
943 		 * argument is missing.
944 		 */
945 		if (argv[go->optind - 1][go->p]) {
946 			if (digit(argv[go->optind - 1][go->p]) ||
947 			    !strcmp(&argv[go->optind - 1][go->p], "unlimited")) {
948 				go->optarg = argv[go->optind - 1] + go->p;
949 				go->p = 0;
950 			} else
951 				go->optarg = (char *) 0;
952 		} else {
953 			if (argv[go->optind] && (digit(argv[go->optind][0]) ||
954 			    !strcmp(argv[go->optind], "unlimited"))) {
955 				go->optarg = argv[go->optind++];
956 				go->p = 0;
957 			} else
958 				go->optarg = (char *) 0;
959 		}
960 	}
961 	return c;
962 }
963 
964 /* print variable/alias value using necessary quotes
965  * (POSIX says they should be suitable for re-entry...)
966  * No trailing newline is printed.
967  */
968 void
969 print_value_quoted(const char *s)
970 {
971 	const char *p;
972 	int inquote = 0;
973 
974 	/* Test if any quotes are needed */
975 	for (p = s; *p; p++)
976 		if (ctype(*p, C_QUOTE))
977 			break;
978 	if (!*p) {
979 		shprintf("%s", s);
980 		return;
981 	}
982 	for (p = s; *p; p++) {
983 		if (*p == '\'') {
984 			shprintf("'\\'" + 1 - inquote);
985 			inquote = 0;
986 		} else {
987 			if (!inquote) {
988 				shprintf("'");
989 				inquote = 1;
990 			}
991 			shf_putc(*p, shl_stdout);
992 		}
993 	}
994 	if (inquote)
995 		shprintf("'");
996 }
997 
998 /* Print things in columns and rows - func() is called to format the ith
999  * element
1000  */
1001 void
1002 print_columns(struct shf *shf, int n, char *(*func) (void *, int, char *, int),
1003     void *arg, int max_width, int prefcol)
1004 {
1005 	char *str = (char *) alloc(max_width + 1, ATEMP);
1006 	int i;
1007 	int r, c;
1008 	int rows, cols;
1009 	int nspace;
1010 	int col_width;
1011 
1012 	/* max_width + 1 for the space.  Note that no space
1013 	 * is printed after the last column to avoid problems
1014 	 * with terminals that have auto-wrap.
1015 	 */
1016 	cols = x_cols / (max_width + 1);
1017 	if (!cols)
1018 		cols = 1;
1019 	rows = (n + cols - 1) / cols;
1020 	if (prefcol && n && cols > rows) {
1021 		int tmp = rows;
1022 
1023 		rows = cols;
1024 		cols = tmp;
1025 		if (rows > n)
1026 			rows = n;
1027 	}
1028 
1029 	col_width = max_width;
1030 	if (cols == 1)
1031 		col_width = 0; /* Don't pad entries in single column output. */
1032 	nspace = (x_cols - max_width * cols) / cols;
1033 	if (nspace <= 0)
1034 		nspace = 1;
1035 	for (r = 0; r < rows; r++) {
1036 		for (c = 0; c < cols; c++) {
1037 			i = c * rows + r;
1038 			if (i < n) {
1039 				shf_fprintf(shf, "%-*s",
1040 				    col_width,
1041 				    (*func)(arg, i, str, max_width + 1));
1042 				if (c + 1 < cols)
1043 					shf_fprintf(shf, "%*s", nspace, null);
1044 			}
1045 		}
1046 		shf_putchar('\n', shf);
1047 	}
1048 	afree(str, ATEMP);
1049 }
1050 
1051 /* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */
1052 int
1053 strip_nuls(char *buf, int nbytes)
1054 {
1055 	char *dst;
1056 
1057 	/* nbytes check because some systems (older freebsd's) have a buggy
1058 	 * memchr()
1059 	 */
1060 	if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
1061 		char *end = buf + nbytes;
1062 		char *p, *q;
1063 
1064 		for (p = dst; p < end; p = q) {
1065 			/* skip a block of nulls */
1066 			while (++p < end && *p == '\0')
1067 				;
1068 			/* find end of non-null block */
1069 			if (!(q = memchr(p, '\0', end - p)))
1070 				q = end;
1071 			memmove(dst, p, q - p);
1072 			dst += q - p;
1073 		}
1074 		*dst = '\0';
1075 		return dst - buf;
1076 	}
1077 	return nbytes;
1078 }
1079 
1080 /* Like read(2), but if read fails due to non-blocking flag, resets flag
1081  * and restarts read.
1082  */
1083 int
1084 blocking_read(int fd, char *buf, int nbytes)
1085 {
1086 	int ret;
1087 	int tried_reset = 0;
1088 
1089 	while ((ret = read(fd, buf, nbytes)) < 0) {
1090 		if (!tried_reset && errno == EAGAIN) {
1091 			int oerrno = errno;
1092 			if (reset_nonblock(fd) > 0) {
1093 				tried_reset = 1;
1094 				continue;
1095 			}
1096 			errno = oerrno;
1097 		}
1098 		break;
1099 	}
1100 	return ret;
1101 }
1102 
1103 /* Reset the non-blocking flag on the specified file descriptor.
1104  * Returns -1 if there was an error, 0 if non-blocking wasn't set,
1105  * 1 if it was.
1106  */
1107 int
1108 reset_nonblock(int fd)
1109 {
1110 	int flags;
1111 
1112 	if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
1113 		return -1;
1114 	if (!(flags & O_NONBLOCK))
1115 		return 0;
1116 	flags &= ~O_NONBLOCK;
1117 	if (fcntl(fd, F_SETFL, flags) < 0)
1118 		return -1;
1119 	return 1;
1120 }
1121 
1122 
1123 /* Like getcwd(), except bsize is ignored if buf is 0 (MAXPATHLEN is used) */
1124 char *
1125 ksh_get_wd(char *buf, int bsize)
1126 {
1127 	char *b;
1128 	char *ret;
1129 
1130 	/* Note: we could just use plain getcwd(), but then we'd had to
1131 	 * inject possibly allocated space into the ATEMP area. */
1132 	/* Assume getcwd() available */
1133 	if (!buf) {
1134 		bsize = MAXPATHLEN;
1135 		b = alloc(MAXPATHLEN + 1, ATEMP);
1136 	} else
1137 		b = buf;
1138 
1139 	ret = getcwd(b, bsize);
1140 
1141 	if (!buf) {
1142 		if (ret)
1143 			ret = aresize(b, strlen(b) + 1, ATEMP);
1144 		else
1145 			afree(b, ATEMP);
1146 	}
1147 
1148 	return ret;
1149 }
1150