GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/misc.c Lines: 446 512 87.1 %
Date: 2017-11-07 Branches: 395 507 77.9 %

Line Branch Exec Source
1
/*	$OpenBSD: misc.c,v 1.59 2017/08/30 17:15:36 jca Exp $	*/
2
3
/*
4
 * Miscellaneous functions
5
 */
6
7
#include <ctype.h>
8
#include <errno.h>
9
#include <fcntl.h>
10
#include <limits.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <unistd.h>
14
15
#include "sh.h"
16
#include "charclass.h"
17
18
short ctypes [UCHAR_MAX+1];	/* type bits for unsigned char */
19
20
static int	do_gmatch(const unsigned char *, const unsigned char *,
21
		    const unsigned char *, const unsigned char *);
22
static const unsigned char *cclass(const unsigned char *, int);
23
24
/*
25
 * Fast character classes
26
 */
27
void
28
setctypes(const char *s, int t)
29
{
30
	int i;
31
32
3474060
	if (t & C_IFS) {
33
221230740
		for (i = 0; i < UCHAR_MAX+1; i++)
34
110184960
			ctypes[i] &= ~C_IFS;
35
430410
		ctypes[0] |= C_IFS; /* include \0 in C_IFS */
36
430410
	}
37
23709910
	while (*s != 0)
38
10986440
		ctypes[(unsigned char) *s++] |= t;
39
1737030
}
40
41
void
42
initctypes(void)
43
{
44
	int c;
45
46
11977350
	for (c = 'a'; c <= 'z'; c++)
47
5662020
		ctypes[c] |= C_ALPHA;
48
11759580
	for (c = 'A'; c <= 'Z'; c++)
49
5662020
		ctypes[c] |= C_ALPHA;
50
217770
	ctypes['_'] |= C_ALPHA;
51
217770
	setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */
52
217770
	setctypes("*@#!$-?", C_VAR1);
53
217770
	setctypes(" \t\n", C_IFSWS);
54
217770
	setctypes("=-+?", C_SUBOP1);
55
217770
	setctypes("#%", C_SUBOP2);
56
217770
	setctypes(" \n\t\"#$&'()*;<>?[\\`|", C_QUOTE);
57
217770
}
58
59
/* convert unsigned long to base N string */
60
61
char *
62
ulton(long unsigned int n, int base)
63
{
64
	char *p;
65
	static char buf [20];
66
67
	p = &buf[sizeof(buf)];
68
290
	*--p = '\0';
69
145
	do {
70
145
		*--p = "0123456789ABCDEF"[n%base];
71
145
		n /= base;
72
145
	} while (n != 0);
73
145
	return p;
74
}
75
76
char *
77
str_save(const char *s, Area *ap)
78
{
79
	size_t len;
80
	char *p;
81
82
43583030
	if (!s)
83
3029614
		return NULL;
84
18761901
	len = strlen(s)+1;
85
18761901
	p = alloc(len, ap);
86
18761901
	strlcpy(p, s, len);
87
18761901
	return (p);
88
21791515
}
89
90
/* Allocate a string of size n+1 and copy upto n characters from the possibly
91
 * null terminated string s into it.  Always returns a null terminated string
92
 * (unless n < 0).
93
 */
94
char *
95
str_nsave(const char *s, int n, Area *ap)
96
{
97
	char *ns;
98
99
53998866
	if (n < 0)
100
		return 0;
101
26999433
	ns = alloc(n + 1, ap);
102
26999433
	ns[0] = '\0';
103
26999433
	return strncat(ns, s, n);
104
26999433
}
105
106
/* called from expand.h:XcheckN() to grow buffer */
107
char *
108
Xcheck_grow_(XString *xsp, char *xp, int more)
109
{
110
6777866
	char *old_beg = xsp->beg;
111
112
10166799
	xsp->len += more > xsp->len ? more : xsp->len;
113
3388933
	xsp->beg = aresize(xsp->beg, xsp->len + 8, xsp->areap);
114
3388933
	xsp->end = xsp->beg + xsp->len;
115
3388933
	return xsp->beg + (xp - old_beg);
116
}
117
118
const struct option options[] = {
119
	/* Special cases (see parse_args()): -A, -o, -s.
120
	 * Options are sorted by their longnames - the order of these
121
	 * entries MUST match the order of sh_flag F* enumerations in sh.h.
122
	 */
123
	{ "allexport",	'a',		OF_ANY },
124
#ifdef BRACE_EXPAND
125
	{ "braceexpand",  0,		OF_ANY }, /* non-standard */
126
#endif
127
	{ "bgnice",	  0,		OF_ANY },
128
	{ NULL,	'c',	    OF_CMDLINE },
129
	{ "csh-history",  0,		OF_ANY }, /* non-standard */
130
#ifdef EMACS
131
	{ "emacs",	  0,		OF_ANY },
132
	{ "emacs-usemeta",  0,		OF_ANY }, /* XXX delete after 6.2 */
133
#endif
134
	{ "errexit",	'e',		OF_ANY },
135
#ifdef EMACS
136
	{ "gmacs",	  0,		OF_ANY },
137
#endif
138
	{ "ignoreeof",	  0,		OF_ANY },
139
	{ "interactive",'i',	    OF_CMDLINE },
140
	{ "keyword",	'k',		OF_ANY },
141
	{ "login",	'l',	    OF_CMDLINE },
142
	{ "markdirs",	'X',		OF_ANY },
143
#ifdef JOBS
144
	{ "monitor",	'm',		OF_ANY },
145
#else /* JOBS */
146
	{ NULL,	'm',		     0 }, /* so FMONITOR not ifdef'd */
147
#endif /* JOBS */
148
	{ "noclobber",	'C',		OF_ANY },
149
	{ "noexec",	'n',		OF_ANY },
150
	{ "noglob",	'f',		OF_ANY },
151
	{ "nohup",	  0,		OF_ANY },
152
	{ "nolog",	  0,		OF_ANY }, /* no effect */
153
#ifdef	JOBS
154
	{ "notify",	'b',		OF_ANY },
155
#endif	/* JOBS */
156
	{ "nounset",	'u',		OF_ANY },
157
	{ "physical",	  0,		OF_ANY }, /* non-standard */
158
	{ "posix",	  0,		OF_ANY }, /* non-standard */
159
	{ "privileged",	'p',		OF_ANY },
160
	{ "restricted",	'r',	    OF_CMDLINE },
161
	{ "sh",		  0,		OF_ANY }, /* non-standard */
162
	{ "stdin",	's',	    OF_CMDLINE }, /* pseudo non-standard */
163
	{ "trackall",	'h',		OF_ANY },
164
	{ "verbose",	'v',		OF_ANY },
165
#ifdef VI
166
	{ "vi",		  0,		OF_ANY },
167
	{ "viraw",	  0,		OF_ANY }, /* no effect */
168
	{ "vi-show8",	  0,		OF_ANY }, /* non-standard */
169
	{ "vi-tabcomplete",  0,		OF_ANY }, /* non-standard */
170
	{ "vi-esccomplete",  0,		OF_ANY }, /* non-standard */
171
#endif
172
	{ "xtrace",	'x',		OF_ANY },
173
	/* Anonymous flags: used internally by shell only
174
	 * (not visible to user)
175
	 */
176
	{ NULL,	0,		OF_INTERNAL }, /* FTALKING_I */
177
};
178
179
/*
180
 * translate -o option into F* constant (also used for test -o option)
181
 */
182
int
183
option(const char *n)
184
{
185
	int i;
186
187
158437
	for (i = 0; i < NELEM(options); i++)
188

151936
		if (options[i].name && strcmp(options[i].name, n) == 0) {
189
#ifdef EMACS
190
3263
			if (i == FEMACSUSEMETA)
191
				warningf(true, "%s: deprecated option", n);
192
#endif
193
3263
			return i;
194
		}
195
196
	return -1;
197
3263
}
198
199
struct options_info {
200
	int opt_width;
201
	struct {
202
		const char *name;
203
		int	flag;
204
	} opts[NELEM(options)];
205
};
206
207
static char *options_fmt_entry(void *arg, int i, char *buf, int buflen);
208
static void printoptions(int verbose);
209
210
/* format a single select menu item */
211
static char *
212
options_fmt_entry(void *arg, int i, char *buf, int buflen)
213
{
214
2652
	struct options_info *oi = (struct options_info *) arg;
215
216
1326
	shf_snprintf(buf, buflen, "%-*s %s",
217
1326
	    oi->opt_width, oi->opts[i].name,
218
1326
	    Flag(oi->opts[i].flag) ? "on" : "off");
219
1326
	return buf;
220
}
221
222
static void
223
printoptions(int verbose)
224
{
225
	int i;
226
227
78
	if (verbose) {
228
39
		struct options_info oi;
229
		int n, len;
230
231
		/* verbose version */
232
39
		shprintf("Current option settings\n");
233
234
2964
		for (i = n = oi.opt_width = 0; i < NELEM(options); i++) {
235
#ifdef EMACS
236
1443
			if (i == FEMACSUSEMETA)
237
				continue;
238
#endif
239
1404
			if (options[i].name) {
240
1326
				len = strlen(options[i].name);
241
1326
				oi.opts[n].name = options[i].name;
242
1326
				oi.opts[n++].flag = i;
243
1326
				if (len > oi.opt_width)
244
117
					oi.opt_width = len;
245
			}
246
		}
247
39
		print_columns(shl_stdout, n, options_fmt_entry, &oi,
248
39
		    oi.opt_width + 5, 1);
249
39
	} else {
250
		/* short version ala ksh93 */
251
		shprintf("set");
252
		for (i = 0; i < NELEM(options); i++) {
253
#ifdef EMACS
254
			if (i == FEMACSUSEMETA)
255
				continue;
256
#endif
257
			if (options[i].name)
258
				shprintf(" %co %s",
259
					 Flag(i) ? '-' : '+',
260
					 options[i].name);
261
		}
262
		shprintf("\n");
263
	}
264
39
}
265
266
char *
267
getoptions(void)
268
{
269
	int i;
270
120
	char m[(int) FNFLAGS + 1];
271
60
	char *cp = m;
272
273
4560
	for (i = 0; i < NELEM(options); i++)
274

3360
		if (options[i].c && Flag(i))
275
168
			*cp++ = options[i].c;
276
60
	*cp = 0;
277
120
	return str_save(m, ATEMP);
278
60
}
279
280
/* change a Flag(*) value; takes care of special actions */
281
void
282
change_flag(enum sh_flag f,
283
    int what,		/* flag to change */
284
    int newval)		/* what is changing the flag (command line vs set) */
285
{
286
	int oldval;
287
288
1075552
	oldval = Flag(f);
289
537776
	Flag(f) = newval;
290
#ifdef JOBS
291
537776
	if (f == FMONITOR) {
292
		if (what != OF_CMDLINE && newval != oldval)
293
			j_change();
294
	} else
295
#endif /* JOBS */
296
#ifdef EDIT
297
	if (0
298
# ifdef VI
299
537776
	    || f == FVI
300
# endif /* VI */
301
# ifdef EMACS
302
537776
	    || f == FEMACS || f == FGMACS
303
# endif /* EMACS */
304
	   )
305
	{
306
225995
		if (newval) {
307
# ifdef VI
308
225995
			Flag(FVI) = 0;
309
# endif /* VI */
310
# ifdef EMACS
311
225995
			Flag(FEMACS) = Flag(FGMACS) = 0;
312
# endif /* EMACS */
313
225995
			Flag(f) = newval;
314
225995
		}
315
	} else
316
#endif /* EDIT */
317
	/* Turning off -p? */
318
311781
	if (f == FPRIVILEGED && oldval && !newval) {
319
		gid_t gid = getgid();
320
321
		setresgid(gid, gid, gid);
322
		setgroups(1, &gid);
323
		setresuid(ksheuid, ksheuid, ksheuid);
324
311781
	} else if (f == FPOSIX && newval) {
325
#ifdef BRACE_EXPAND
326
3256
		Flag(FBRACEEXPAND) = 0
327
#endif /* BRACE_EXPAND */
328
		;
329
3256
	}
330
	/* Changing interactive flag? */
331
537776
	if (f == FTALKING) {
332

1750
		if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid)
333
875
			Flag(FTALKING_I) = newval;
334
	}
335
537776
}
336
337
/* parse command line & set command arguments.  returns the index of
338
 * non-option arguments, -1 if there is an error.
339
 */
340
int
341
parse_args(char **argv,
342
    int what,			/* OF_CMDLINE or OF_SET */
343
    int *setargsp)
344
{
345
	static char cmd_opts[NELEM(options) + 3]; /* o:\0 */
346
	static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */
347
	char *opts;
348
	char *array = NULL;
349
620790
	Getopt go;
350
	int i, optc, set, sortargs = 0, arrayset = 0;
351
352
	/* First call?  Build option strings... */
353
310395
	if (cmd_opts[0] == '\0') {
354
		char *p, *q;
355
356
		/* see cmd_opts[] declaration */
357
217770
		strlcpy(cmd_opts, "o:", sizeof cmd_opts);
358
217770
		p = cmd_opts + strlen(cmd_opts);
359
		/* see set_opts[] declaration */
360
217770
		strlcpy(set_opts, "A:o;s", sizeof set_opts);
361
217770
		q = set_opts + strlen(set_opts);
362
16550520
		for (i = 0; i < NELEM(options); i++) {
363
8057490
			if (options[i].c) {
364
4137630
				if (options[i].flags & OF_CMDLINE)
365
4137630
					*p++ = options[i].c;
366
4137630
				if (options[i].flags & OF_SET)
367
3048780
					*q++ = options[i].c;
368
			}
369
		}
370
217770
		*p = '\0';
371
217770
		*q = '\0';
372
217770
	}
373
374
310395
	if (what == OF_CMDLINE) {
375
		char *p;
376
		/* Set FLOGIN before parsing options so user can clear
377
		 * flag using +l.
378
		 */
379
435540
		Flag(FLOGIN) = (argv[0][0] == '-' ||
380
392646
		    ((p = strrchr(argv[0], '/')) && *++p == '-'));
381
		opts = cmd_opts;
382
217770
	} else
383
		opts = set_opts;
384
310395
	ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT);
385
982660
	while ((optc = ksh_getopt(argv, &go, opts)) != -1) {
386
361870
		set = (go.info & GI_PLUS) ? 0 : 1;
387

361870
		switch (optc) {
388
		case 'A':
389
50043
			arrayset = set ? 1 : -1;
390
50043
			array = go.optarg;
391
50043
			break;
392
393
		case 'o':
394
3302
			if (go.optarg == NULL) {
395
				/* lone -o: print options
396
				 *
397
				 * Note that on the command line, -o requires
398
				 * an option (ie, can't get here if what is
399
				 * OF_CMDLINE).
400
				 */
401
39
				printoptions(set);
402
39
				break;
403
			}
404
3263
			i = option(go.optarg);
405

6526
			if (i >= 0 && set == Flag(i))
406
				/* Don't check the context if the flag
407
				 * isn't changing - makes "set -o interactive"
408
				 * work if you're already interactive.  Needed
409
				 * if the output of "set +o" is to be used.
410
				 */
411
				;
412

6476
			else if (i >= 0 && (options[i].flags & what))
413
3238
				change_flag((enum sh_flag) i, what, set);
414
			else {
415
				bi_errorf("%s: bad option", go.optarg);
416
				return -1;
417
			}
418
			break;
419
420
		case '?':
421
			return -1;
422
423
		default:
424
			/* -s: sort positional params (at&t ksh stupidity) */
425
308525
			if (what == OF_SET && optc == 's') {
426
				sortargs = 1;
427
25
				break;
428
			}
429
3825032
			for (i = 0; i < NELEM(options); i++)
430

2221016
				if (optc == options[i].c &&
431
308500
				    (what & options[i].flags)) {
432
308500
					change_flag((enum sh_flag) i, what,
433
					    set);
434
308500
					break;
435
				}
436
308500
			if (i == NELEM(options)) {
437
				internal_errorf(1, "parse_args: `%c'", optc);
438
				return -1; /* not reached */
439
			}
440
		}
441
	}
442

570245
	if (!(go.info & GI_MINUSMINUS) && argv[go.optind] &&
443

458379
	    (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') &&
444
323
	    argv[go.optind][1] == '\0') {
445
		/* lone - clears -v and -x flags */
446
323
		if (argv[go.optind][0] == '-' && !Flag(FPOSIX))
447
323
			Flag(FVERBOSE) = Flag(FXTRACE) = 0;
448
		/* set skips lone - or + option */
449
323
		go.optind++;
450
323
	}
451
310395
	if (setargsp)
452
		/* -- means set $#/$* even if there are no arguments */
453

269504
		*setargsp = !arrayset && ((go.info & GI_MINUSMINUS) ||
454
41672
		    argv[go.optind]);
455
456

410481
	if (arrayset && (!*array || *skip_varname(array, false))) {
457
		bi_errorf("%s: is not an identifier", array);
458
		return -1;
459
	}
460
310395
	if (sortargs) {
461
250
		for (i = go.optind; argv[i]; i++)
462
			;
463
25
		qsortp((void **) &argv[go.optind], (size_t) (i - go.optind),
464
		    xstrcmp);
465
25
	}
466
310395
	if (arrayset) {
467
50043
		set_array(array, arrayset, argv + go.optind);
468
213586
		for (; argv[go.optind]; go.optind++)
469
			;
470
	}
471
472
310395
	return go.optind;
473
310395
}
474
475
/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */
476
int
477
getn(const char *as, int *ai)
478
{
479
648570
	char *p;
480
	long n;
481
482
324285
	n = strtol(as, &p, 10);
483
484

648570
	if (!*as || *p || INT_MIN >= n || n >= INT_MAX)
485
150
		return 0;
486
487
324135
	*ai = (int)n;
488
324135
	return 1;
489
324285
}
490
491
/* getn() that prints error */
492
int
493
bi_getn(const char *as, int *ai)
494
{
495
12070
	int rv = getn(as, ai);
496
497
6035
	if (!rv)
498
50
		bi_errorf("%s: bad number", as);
499
5985
	return rv;
500
}
501
502
/* -------- gmatch.c -------- */
503
504
/*
505
 * int gmatch(string, pattern)
506
 * char *string, *pattern;
507
 *
508
 * Match a pattern as in sh(1).
509
 * pattern character are prefixed with MAGIC by expand.
510
 */
511
512
int
513
gmatch(const char *s, const char *p, int isfile)
514
{
515
	const char *se, *pe;
516
517
34957962
	if (s == NULL || p == NULL)
518
		return 0;
519
17478981
	se = s + strlen(s);
520
17478981
	pe = p + strlen(p);
521
	/* isfile is false iff no syntax check has been done on
522
	 * the pattern.  If check fails, just to a strcmp().
523
	 */
524

26860663
	if (!isfile && !has_globbing(p, pe)) {
525
3905897
		int len = pe - p + 1;
526
3905897
		char tbuf[64];
527
11717691
		char *t = len <= sizeof(tbuf) ? tbuf :
528
		    alloc(len, ATEMP);
529
3905897
		debunk(t, p, len);
530
3905897
		return !strcmp(t, s);
531
3905897
	}
532
13573084
	return do_gmatch((const unsigned char *) s, (const unsigned char *) se,
533
	    (const unsigned char *) p, (const unsigned char *) pe);
534
17478981
}
535
536
/* Returns if p is a syntacticly correct globbing pattern, false
537
 * if it contains no pattern characters or if there is a syntax error.
538
 * Syntax errors are:
539
 *	- [ with no closing ]
540
 *	- imbalanced $(...) expression
541
 *	- [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d))
542
 */
543
/*XXX
544
- if no magic,
545
	if dest given, copy to dst
546
	return ?
547
- if magic && (no globbing || syntax error)
548
	debunk to dst
549
	return ?
550
- return ?
551
*/
552
int
553
has_globbing(const char *xp, const char *xpe)
554
{
555
	const unsigned char *p = (const unsigned char *) xp;
556
	const unsigned char *pe = (const unsigned char *) xpe;
557
	int c;
558
	int nest = 0, bnest = 0;
559
	int saw_glob = 0;
560
	int in_bracket = 0; /* inside [...] */
561
562
233400929
	for (; p < pe; p++) {
563
98150032
		if (!ISMAGIC(*p))
564
			continue;
565
35807588
		if ((c = *++p) == '*' || c == '?')
566
5062744
			saw_glob = 1;
567
30744844
		else if (c == '[') {
568
6383289
			if (!in_bracket) {
569
				saw_glob = 1;
570
				in_bracket = 1;
571

7100248
				if (ISMAGIC(p[1]) && p[2] == '!')
572
716945
					p += 2;
573

6383328
				if (ISMAGIC(p[1]) && p[2] == ']')
574
25
					p += 2;
575
			}
576
			/* XXX Do we need to check ranges here? POSIX Q */
577
24361555
		} else if (c == ']') {
578
3483794
			if (in_bracket) {
579
2149322
				if (bnest)		/* [a*(b]) */
580
25
					return 0;
581
				in_bracket = 0;
582
2149297
			}
583

24621284
		} else if ((c & 0x80) && strchr("*+?@! ", c & 0x7f)) {
584
			saw_glob = 1;
585
3743523
			if (in_bracket)
586
50
				bnest++;
587
			else
588
3743473
				nest++;
589
17134238
		} else if (c == '|') {
590
194968
			if (in_bracket && !bnest)	/* *(a[foo|bar]) */
591
				return 0;
592
16939270
		} else if (c == /*(*/ ')') {
593
3743498
			if (in_bracket) {
594
150
				if (!bnest--)		/* *(a[b)c] */
595
125
					return 0;
596
3743348
			} else if (nest)
597
3743348
				nest--;
598
		}
599
		/* else must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, MAGIC-]
600
			 MAGIC-{, MAGIC-,, MAGIC-} */
601
	}
602
30260475
	return saw_glob && !in_bracket && !nest;
603
12367055
}
604
605
/* Function must return either 0 or 1 (assumed by code for 0x80|'!') */
606
static int
607
do_gmatch(const unsigned char *s, const unsigned char *se,
608
    const unsigned char *p, const unsigned char *pe)
609
{
610
	int sc, pc;
611
	const unsigned char *prest, *psub, *pnext;
612
	const unsigned char *srest;
613
614
794129412
	if (s == NULL || p == NULL)
615
		return 0;
616
646089089
	while (p < pe) {
617
424629994
		pc = *p++;
618
1261600068
		sc = s < se ? *s : '\0';
619
424629994
		s++;
620
424629994
		if (!ISMAGIC(pc)) {
621
125160765
			if (sc != pc)
622
95389699
				return 0;
623
			continue;
624
		}
625


299469229
		switch (*p++) {
626
		case '[':
627

537920134
			if (sc == 0 || (p = cclass(p, sc)) == NULL)
628
60437897
				return 0;
629
			break;
630
631
		case '?':
632
22674
			if (sc == 0)
633
5842
				return 0;
634
			break;
635
636
		case '*':
637
7111087
			if (p == pe)
638
450283
				return 1;
639
6660804
			s--;
640
6660804
			do {
641
80827046
				if (do_gmatch(s, se, p, pe))
642
5302085
					return 1;
643
75524961
			} while (s++ < se);
644
1358719
			return 0;
645
646
		  /*
647
		   * [*+?@!](pattern|pattern|..)
648
		   *
649
		   * Not ifdef'd KSH as this is needed for ${..%..}, etc.
650
		   */
651
		case 0x80|'+': /* matches one or more times */
652
		case 0x80|'*': /* matches zero or more times */
653
10592002
			if (!(prest = pat_scan(p, pe, 0)))
654
				return 0;
655
10592002
			s--;
656
			/* take care of zero matches */
657

21182996
			if (p[-1] == (0x80 | '*') &&
658
10590994
			    do_gmatch(s, se, prest, pe))
659
117646
				return 1;
660
10475446
			for (psub = p; ; psub = pnext) {
661
10475446
				pnext = pat_scan(psub, pe, 1);
662
567912224
				for (srest = s; srest <= se; srest++) {
663

282002075
					if (do_gmatch(s, srest, psub, pnext - 2) &&
664
8046965
					    (do_gmatch(srest, se, prest, pe) ||
665
15977573
					    (s != srest && do_gmatch(srest,
666
7988379
					    se, p - 2, pe))))
667
533030
						return 1;
668
				}
669
9942416
				if (pnext == prest)
670
					break;
671
			}
672
9941326
			return 0;
673
674
		case 0x80|'?': /* matches zero or once */
675
		case 0x80|'@': /* matches one of the patterns */
676
		case 0x80|' ': /* simile for @ */
677
1750208
			if (!(prest = pat_scan(p, pe, 0)))
678
				return 0;
679
1750208
			s--;
680
			/* Take care of zero matches */
681

1750208
			if (p[-1] == (0x80 | '?') &&
682
			    do_gmatch(s, se, prest, pe))
683
				return 1;
684
1821631
			for (psub = p; ; psub = pnext) {
685
1821631
				pnext = pat_scan(psub, pe, 1);
686
1821631
				srest = prest == pe ? se : s;
687
6882552
				for (; srest <= se; srest++) {
688

2023617
					if (do_gmatch(s, srest, psub, pnext - 2) &&
689
201986
					    do_gmatch(srest, se, prest, pe))
690
201986
						return 1;
691
				}
692
1619645
				if (pnext == prest)
693
					break;
694
			}
695
1548222
			return 0;
696
697
		case 0x80|'!': /* matches none of the patterns */
698
125
			if (!(prest = pat_scan(p, pe, 0)))
699
				return 0;
700
125
			s--;
701
1050
			for (srest = s; srest <= se; srest++) {
702
				int matched = 0;
703
704
600
				for (psub = p; ; psub = pnext) {
705
600
					pnext = pat_scan(psub, pe, 1);
706
600
					if (do_gmatch(s, srest, psub,
707
600
					    pnext - 2)) {
708
						matched = 1;
709
100
						break;
710
					}
711
500
					if (pnext == prest)
712
						break;
713
				}
714

750
				if (!matched &&
715
325
				    do_gmatch(srest, se, prest, pe))
716
25
					return 1;
717
400
			}
718
100
			return 0;
719
720
		default:
721
5791942
			if (sc != p[-1])
722
318751
				return 0;
723
			break;
724
		}
725
	}
726
221459095
	return s == se;
727
397064706
}
728
729
static int
730
posix_cclass(const unsigned char *pattern, int test, const unsigned char **ep)
731
{
732
	struct cclass *cc;
733
	const unsigned char *colon;
734
	size_t len;
735
	int rval = 0;
736
737

139499247
	if ((colon = strchr(pattern, ':')) == NULL || colon[1] != MAGIC) {
738
		*ep = pattern - 2;
739
		return -1;
740
	}
741
46499749
	*ep = colon + 3; /* skip MAGIC */
742
46499749
	len = (size_t)(colon - pattern);
743
744
278996248
	for (cc = cclasses; cc->name != NULL; cc++) {
745

185997873
		if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
746
46499749
			if (cc->isctype(test))
747
10087502
				rval = 1;
748
			break;
749
		}
750
	}
751
46499749
	if (cc->name == NULL) {
752
		rval = -2;	/* invalid character class */
753
	}
754
46499749
	return rval;
755
46499749
}
756
757
static const unsigned char *
758
cclass(const unsigned char *p, int sub)
759
{
760
	int c, d, rv, not, found = 0;
761
	const unsigned char *orig_p = p;
762
763

791028753
	if ((not = (ISMAGIC(*p) && *++p == '!')))
764
217091526
		p++;
765
	do {
766
		/* check for POSIX character class (e.g. [[:alpha:]]) */
767


310454855
		if ((p[0] == MAGIC && p[1] == '[' && p[2] == ':') ||
768
310452456
		    (p[0] == '[' && p[1] == ':')) {
769
			do {
770
56587251
				const char *pp = p + (*p == MAGIC) + 2;
771
56587251
				rv = posix_cclass(pp, sub, &p);
772
56587251
				switch (rv) {
773
				case 1:
774
					found = 1;
775
10087502
					break;
776
				case -2:
777
					return NULL;
778
				}
779


185998996
			} while (rv != -1 && p[0] == MAGIC && p[1] == '[' && p[2] == ':');
780

92999498
			if (p[0] == MAGIC && p[1] == ']')
781
				break;
782
		}
783
784
217454174
		c = *p++;
785
217454174
		if (ISMAGIC(c)) {
786
575
			c = *p++;
787

650
			if ((c & 0x80) && !ISMAGIC(c)) {
788
75
				c &= 0x7f;/* extended pattern matching: *+?@! */
789
				/* XXX the ( char isn't handled as part of [] */
790
75
				if (c == ' ') /* simile for @: plain (..) */
791
					c = '(' /*)*/;
792
75
			}
793
		}
794
217454174
		if (c == '\0')
795
			/* No closing ] - act as if the opening [ was quoted */
796
			return sub == '[' ? orig_p : NULL;
797

434674576
		if (ISMAGIC(p[0]) && p[1] == '-' &&
798
659
		    (!ISMAGIC(p[2]) || p[3] != ']')) {
799
434
			p += 2; /* MAGIC- */
800
434
			d = *p++;
801
434
			if (ISMAGIC(d)) {
802
25
				d = *p++;
803

25
				if ((d & 0x80) && !ISMAGIC(d))
804
					d &= 0x7f;
805
			}
806
			/* POSIX says this is an invalid expression */
807
434
			if (c > d)
808
25
				return NULL;
809
		} else
810
			d = c;
811

624267152
		if (c == sub || (c <= sub && sub <= d))
812
13557034
			found = 1;
813

652128550
	} while (!(ISMAGIC(p[0]) && p[1] == ']'));
814
815
263718918
	return (found != not) ? p+2 : NULL;
816
263718943
}
817
818
/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */
819
const unsigned char *
820
pat_scan(const unsigned char *p, const unsigned char *pe, int match_sep)
821
{
822
	int nest = 0;
823
824
410469926
	for (; p < pe; p++) {
825
192914957
		if (!ISMAGIC(*p))
826
			continue;
827

145439629
		if ((*++p == /*(*/ ')' && nest-- == 0) ||
828
92400733
		    (*p == '|' && match_sep && nest == 0))
829
24640012
			return ++p;
830

96271273
		if ((*p & 0x80) && strchr("*+?@! ", *p & 0x7f))
831
3982208
			nest++;
832
	}
833
	return NULL;
834
24640012
}
835
836
/*
837
 * quick sort of array of generic pointers to objects.
838
 */
839
void
840
qsortp(void **base,			/* base address */
841
    size_t n,				/* elements */
842
    int (*f) (const void *, const void *)) /* compare function */
843
{
844
5852392
	qsort(base, n, sizeof(char *), f);
845
2926196
}
846
847
int
848
xstrcmp(const void *p1, const void *p2)
849
{
850
84219478
	return (strcmp(*(char **)p1, *(char **)p2));
851
}
852
853
/* Initialize a Getopt structure */
854
void
855
ksh_getopt_reset(Getopt *go, int flags)
856
{
857
22376556
	go->optind = 1;
858
11188278
	go->optarg = NULL;
859
11188278
	go->p = 0;
860
11188278
	go->flags = flags;
861
11188278
	go->info = 0;
862
11188278
	go->buf[1] = '\0';
863
11188278
}
864
865
866
/* getopt() used for shell built-in commands, the getopts command, and
867
 * command line options.
868
 * A leading ':' in options means don't print errors, instead return '?'
869
 * or ':' and set go->optarg to the offending option character.
870
 * If GF_ERROR is set (and option doesn't start with :), errors result in
871
 * a call to bi_errorf().
872
 *
873
 * Non-standard features:
874
 *	- ';' is like ':' in options, except the argument is optional
875
 *	  (if it isn't present, optarg is set to 0).
876
 *	  Used for 'set -o'.
877
 *	- ',' is like ':' in options, except the argument always immediately
878
 *	  follows the option character (optarg is set to the null string if
879
 *	  the option is missing).
880
 *	  Used for 'read -u2', 'print -u2' and fc -40.
881
 *	- '#' is like ':' in options, expect that the argument is optional
882
 *	  and must start with a digit or be the string "unlimited".  If the
883
 *	  argument doesn't match, it is assumed to be missing and normal option
884
 *	  processing continues (optarg is set to 0 if the option is missing).
885
 *	  Used for 'typeset -LZ4' and 'ulimit -adunlimited'.
886
 *	- accepts +c as well as -c IF the GF_PLUSOPT flag is present.  If an
887
 *	  option starting with + is accepted, the GI_PLUS flag will be set
888
 *	  in go->info.
889
 */
890
int
891
ksh_getopt(char **argv, Getopt *go, const char *options)
892
{
893
	char c;
894
	char *o;
895
896

17165541
	if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') {
897
19446638
		char *arg = argv[go->optind], flag = arg ? *arg : '\0';
898
899
6641437
		go->p = 1;
900

9676569
		if (flag == '-' && arg[1] == '-' && arg[2] == '\0') {
901
486680
			go->optind++;
902
486680
			go->p = 0;
903
486680
			go->info |= GI_MINUSMINUS;
904
486680
			return -1;
905
		}
906

8218523
		if (arg == NULL ||
907
5677084
		    ((flag != '-' ) && /* neither a - nor a + (if + allowed) */
908

5699196
		    (!(go->flags & GF_PLUSOPT) || flag != '+')) ||
909
2063766
		    (c = arg[1]) == '\0') {
910
4091427
			go->p = 0;
911
4091427
			return -1;
912
		}
913
2063330
		go->optind++;
914
2063330
		go->info &= ~(GI_MINUS|GI_PLUS);
915
2063330
		go->info |= flag == '-' ? GI_MINUS : GI_PLUS;
916
2063330
	}
917
2689128
	go->p++;
918



16134768
	if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#' ||
919
2689128
	    !(o = strchr(options, c))) {
920
625
		if (options[0] == ':') {
921
625
			go->buf[0] = c;
922
625
			go->optarg = go->buf;
923
625
		} else {
924
			warningf(true, "%s%s-%c: unknown option",
925
			    (go->flags & GF_NONAME) ? "" : argv[0],
926
			    (go->flags & GF_NONAME) ? "" : ": ", c);
927
			if (go->flags & GF_ERROR)
928
				bi_errorf(NULL);
929
		}
930
625
		return '?';
931
	}
932
	/* : means argument must be present, may be part of option argument
933
	 *   or the next argument
934
	 * ; same as : but argument may be missing
935
	 * , means argument is part of option argument, and may be null.
936
	 */
937

5326693
	if (*++o == ':' || *o == ';') {
938
53615
		if (argv[go->optind - 1][go->p])
939
			go->optarg = argv[go->optind - 1] + go->p;
940
53615
		else if (argv[go->optind])
941
53576
			go->optarg = argv[go->optind++];
942
39
		else if (*o == ';')
943
			go->optarg = NULL;
944
		else {
945
			if (options[0] == ':') {
946
				go->buf[0] = c;
947
				go->optarg = go->buf;
948
				return ':';
949
			}
950
			warningf(true, "%s%s-`%c' requires argument",
951
			    (go->flags & GF_NONAME) ? "" : argv[0],
952
			    (go->flags & GF_NONAME) ? "" : ": ", c);
953
			if (go->flags & GF_ERROR)
954
				bi_errorf(NULL);
955
			return '?';
956
		}
957
53615
		go->p = 0;
958
2688503
	} else if (*o == ',') {
959
		/* argument is attached to option character, even if null */
960
200
		go->optarg = argv[go->optind - 1] + go->p;
961
200
		go->p = 0;
962
2634888
	} else if (*o == '#') {
963
		/* argument is optional and may be attached or unattached
964
		 * but must start with a digit.  optarg is set to 0 if the
965
		 * argument is missing.
966
		 */
967
657802
		if (argv[go->optind - 1][go->p]) {
968

435815
			if (digit(argv[go->optind - 1][go->p]) ||
969
217770
			    !strcmp(&argv[go->optind - 1][go->p], "unlimited")) {
970
275
				go->optarg = argv[go->optind - 1] + go->p;
971
275
				go->p = 0;
972
275
			} else
973
217770
				go->optarg = NULL;
974
		} else {
975

1315779
			if (argv[go->optind] && (digit(argv[go->optind][0]) ||
976
436340
			    !strcmp(argv[go->optind], "unlimited"))) {
977
3342
				go->optarg = argv[go->optind++];
978
3342
				go->p = 0;
979
3342
			} else
980
436415
				go->optarg = NULL;
981
		}
982
	}
983
2688503
	return c;
984
7267235
}
985
986
/* print variable/alias value using necessary quotes
987
 * (POSIX says they should be suitable for re-entry...)
988
 * No trailing newline is printed.
989
 */
990
void
991
print_value_quoted(const char *s)
992
{
993
	const char *p;
994
	int inquote = 0;
995
996
	/* Test if any quotes are needed */
997
183186
	for (p = s; *p; p++)
998
74937
		if (ctype(*p, C_QUOTE))
999
			break;
1000
13516
	if (!*p) {
1001
9898
		shprintf("%s", s);
1002
9898
		return;
1003
	}
1004
369950
	for (p = s; *p; p++) {
1005
181357
		if (*p == '\'') {
1006
1053
			shprintf(inquote ? "'\\'" : "\\'");
1007
			inquote = 0;
1008
1053
		} else {
1009
180304
			if (!inquote) {
1010
4566
				shprintf("'");
1011
				inquote = 1;
1012
4566
			}
1013
360608
			shf_putc(*p, shl_stdout);
1014
		}
1015
	}
1016
3618
	if (inquote)
1017
3516
		shprintf("'");
1018
17134
}
1019
1020
/* Print things in columns and rows - func() is called to format the ith
1021
 * element
1022
 */
1023
void
1024
print_columns(struct shf *shf, int n, char *(*func) (void *, int, char *, int),
1025
    void *arg, int max_width, int prefcol)
1026
{
1027
206
	char *str = alloc(max_width + 1, ATEMP);
1028
	int i;
1029
	int r, c;
1030
	int rows, cols;
1031
	int nspace;
1032
	int col_width;
1033
1034
	/* max_width + 1 for the space.  Note that no space
1035
	 * is printed after the last column to avoid problems
1036
	 * with terminals that have auto-wrap.
1037
	 */
1038
103
	cols = x_cols / (max_width + 1);
1039
103
	if (!cols)
1040
		cols = 1;
1041
103
	rows = (n + cols - 1) / cols;
1042

142
	if (prefcol && n && cols > rows) {
1043
		int tmp = rows;
1044
1045
		rows = cols;
1046
		cols = tmp;
1047
		if (rows > n)
1048
			rows = n;
1049
	}
1050
1051
	col_width = max_width;
1052
103
	if (cols == 1)
1053
		col_width = 0; /* Don't pad entries in single column output. */
1054
103
	nspace = (x_cols - max_width * cols) / cols;
1055
103
	if (nspace <= 0)
1056
		nspace = 1;
1057
1084
	for (r = 0; r < rows; r++) {
1058
5454
		for (c = 0; c < cols; c++) {
1059
2288
			i = c * rows + r;
1060
2288
			if (i < n) {
1061
1778
				shf_fprintf(shf, "%-*s",
1062
				    col_width,
1063
1778
				    (*func)(arg, i, str, max_width + 1));
1064
1778
				if (c + 1 < cols)
1065
1485
					shf_fprintf(shf, "%*s", nspace, "");
1066
			}
1067
		}
1068
439
		shf_putchar('\n', shf);
1069
	}
1070
103
	afree(str, ATEMP);
1071
103
}
1072
1073
/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */
1074
int
1075
strip_nuls(char *buf, int nbytes)
1076
{
1077
	char *dst;
1078
1079
40146440
	if ((dst = memchr(buf, '\0', nbytes))) {
1080
23
		char *end = buf + nbytes;
1081
		char *p, *q;
1082
1083
92
		for (p = dst; p < end; p = q) {
1084
			/* skip a block of nulls */
1085

46
			while (++p < end && *p == '\0')
1086
				;
1087
			/* find end of non-null block */
1088
23
			if (!(q = memchr(p, '\0', end - p)))
1089
23
				q = end;
1090
23
			memmove(dst, p, q - p);
1091
23
			dst += q - p;
1092
		}
1093
23
		*dst = '\0';
1094
23
		return dst - buf;
1095
	}
1096
20073197
	return nbytes;
1097
20073220
}
1098
1099
/* Like read(2), but if read fails due to non-blocking flag, resets flag
1100
 * and restarts read.
1101
 */
1102
int
1103
blocking_read(int fd, char *buf, int nbytes)
1104
{
1105
	int ret;
1106
	int tried_reset = 0;
1107
1108
54317300
	while ((ret = read(fd, buf, nbytes)) < 0) {
1109
18720538
		if (!tried_reset && errno == EAGAIN) {
1110
			int oerrno = errno;
1111
			if (reset_nonblock(fd) > 0) {
1112
				tried_reset = 1;
1113
				continue;
1114
			}
1115
			errno = oerrno;
1116
		}
1117
		break;
1118
	}
1119
13579325
	return ret;
1120
}
1121
1122
/* Reset the non-blocking flag on the specified file descriptor.
1123
 * Returns -1 if there was an error, 0 if non-blocking wasn't set,
1124
 * 1 if it was.
1125
 */
1126
int
1127
reset_nonblock(int fd)
1128
{
1129
	int flags;
1130
1131
5498
	if ((flags = fcntl(fd, F_GETFL)) < 0)
1132
		return -1;
1133
2749
	if (!(flags & O_NONBLOCK))
1134
2749
		return 0;
1135
	flags &= ~O_NONBLOCK;
1136
	if (fcntl(fd, F_SETFL, flags) < 0)
1137
		return -1;
1138
	return 1;
1139
2749
}
1140
1141
1142
/* Like getcwd(), except bsize is ignored if buf is 0 (PATH_MAX is used) */
1143
char *
1144
ksh_get_wd(char *buf, int bsize)
1145
{
1146
	char *b;
1147
	char *ret;
1148
1149
	/* Note: we could just use plain getcwd(), but then we'd had to
1150
	 * inject possibly allocated space into the ATEMP area. */
1151
	/* Assume getcwd() available */
1152
17452
	if (!buf) {
1153
		bsize = PATH_MAX;
1154
8726
		b = alloc(PATH_MAX + 1, ATEMP);
1155
8726
	} else
1156
		b = buf;
1157
1158
8726
	ret = getcwd(b, bsize);
1159
1160
8726
	if (!buf) {
1161
8726
		if (ret)
1162
8726
			ret = aresize(b, strlen(b) + 1, ATEMP);
1163
		else
1164
			afree(b, ATEMP);
1165
	}
1166
1167
8726
	return ret;
1168
}