Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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