Home | History | Annotate | Line # | Download | only in csh
glob.c revision 1.1.1.2
      1      1.1      cgd /*-
      2  1.1.1.2  mycroft  * Copyright (c) 1980, 1991, 1993
      3  1.1.1.2  mycroft  *	The Regents of the University of California.  All rights reserved.
      4      1.1      cgd  *
      5      1.1      cgd  * Redistribution and use in source and binary forms, with or without
      6      1.1      cgd  * modification, are permitted provided that the following conditions
      7      1.1      cgd  * are met:
      8      1.1      cgd  * 1. Redistributions of source code must retain the above copyright
      9      1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     10      1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     11      1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     12      1.1      cgd  *    documentation and/or other materials provided with the distribution.
     13      1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     14      1.1      cgd  *    must display the following acknowledgement:
     15      1.1      cgd  *	This product includes software developed by the University of
     16      1.1      cgd  *	California, Berkeley and its contributors.
     17      1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     18      1.1      cgd  *    may be used to endorse or promote products derived from this software
     19      1.1      cgd  *    without specific prior written permission.
     20      1.1      cgd  *
     21      1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22      1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23      1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24      1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25      1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26      1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27      1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28      1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29      1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30      1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31      1.1      cgd  * SUCH DAMAGE.
     32      1.1      cgd  */
     33      1.1      cgd 
     34      1.1      cgd #ifndef lint
     35  1.1.1.2  mycroft static char sccsid[] = "@(#)glob.c	8.1 (Berkeley) 5/31/93";
     36      1.1      cgd #endif /* not lint */
     37      1.1      cgd 
     38      1.1      cgd #include <sys/param.h>
     39      1.1      cgd #include <glob.h>
     40      1.1      cgd #include <errno.h>
     41      1.1      cgd #include <stdlib.h>
     42      1.1      cgd #include <string.h>
     43      1.1      cgd #include <unistd.h>
     44      1.1      cgd #if __STDC__
     45      1.1      cgd # include <stdarg.h>
     46      1.1      cgd #else
     47      1.1      cgd # include <varargs.h>
     48      1.1      cgd #endif
     49      1.1      cgd 
     50      1.1      cgd #include "csh.h"
     51      1.1      cgd #include "extern.h"
     52      1.1      cgd 
     53  1.1.1.2  mycroft static int noglob;
     54      1.1      cgd static int pargsiz, gargsiz;
     55      1.1      cgd 
     56      1.1      cgd /*
     57      1.1      cgd  * Values for gflag
     58      1.1      cgd  */
     59      1.1      cgd #define	G_NONE	0		/* No globbing needed			*/
     60      1.1      cgd #define	G_GLOB	1		/* string contains *?[] characters	*/
     61      1.1      cgd #define	G_CSH	2		/* string contains ~`{ characters	*/
     62      1.1      cgd 
     63      1.1      cgd #define	GLOBSPACE	100	/* Alloc increment			*/
     64      1.1      cgd 
     65      1.1      cgd #define LBRC '{'
     66      1.1      cgd #define RBRC '}'
     67      1.1      cgd #define LBRK '['
     68      1.1      cgd #define RBRK ']'
     69      1.1      cgd #define EOS '\0'
     70      1.1      cgd 
     71      1.1      cgd Char  **gargv = NULL;
     72      1.1      cgd long    gargc = 0;
     73      1.1      cgd Char  **pargv = NULL;
     74      1.1      cgd long    pargc = 0;
     75      1.1      cgd 
     76      1.1      cgd /*
     77      1.1      cgd  * globbing is now done in two stages. In the first pass we expand
     78      1.1      cgd  * csh globbing idioms ~`{ and then we proceed doing the normal
     79      1.1      cgd  * globbing if needed ?*[
     80      1.1      cgd  *
     81      1.1      cgd  * Csh type globbing is handled in globexpand() and the rest is
     82      1.1      cgd  * handled in glob() which is part of the 4.4BSD libc.
     83      1.1      cgd  *
     84      1.1      cgd  */
     85      1.1      cgd static Char	*globtilde __P((Char **, Char *));
     86      1.1      cgd static Char	**libglob __P((Char **));
     87      1.1      cgd static Char	**globexpand __P((Char **));
     88      1.1      cgd static int	globbrace __P((Char *, Char *, Char ***));
     89  1.1.1.2  mycroft static void	expbrace __P((Char ***, Char ***, int));
     90  1.1.1.2  mycroft static int	pmatch __P((Char *, Char *));
     91      1.1      cgd static void	pword __P((void));
     92      1.1      cgd static void	psave __P((int));
     93      1.1      cgd static void	backeval __P((Char *, bool));
     94      1.1      cgd 
     95      1.1      cgd 
     96      1.1      cgd static Char *
     97      1.1      cgd globtilde(nv, s)
     98      1.1      cgd     Char  **nv, *s;
     99      1.1      cgd {
    100      1.1      cgd     Char    gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
    101      1.1      cgd 
    102      1.1      cgd     gstart = gbuf;
    103      1.1      cgd     *gstart++ = *s++;
    104      1.1      cgd     u = s;
    105  1.1.1.2  mycroft     for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
    106  1.1.1.2  mycroft 	 *s && *s != '/' && *s != ':' && b < e;
    107  1.1.1.2  mycroft 	 *b++ = *s++)
    108  1.1.1.2  mycroft 	 continue;
    109      1.1      cgd     *b = EOS;
    110      1.1      cgd     if (gethdir(gstart)) {
    111      1.1      cgd 	blkfree(nv);
    112      1.1      cgd 	if (*gstart)
    113  1.1.1.2  mycroft 	    stderror(ERR_UNKUSER, vis_str(gstart));
    114      1.1      cgd 	else
    115      1.1      cgd 	    stderror(ERR_NOHOME);
    116      1.1      cgd     }
    117      1.1      cgd     b = &gstart[Strlen(gstart)];
    118      1.1      cgd     while (*s)
    119      1.1      cgd 	*b++ = *s++;
    120      1.1      cgd     *b = EOS;
    121      1.1      cgd     --u;
    122      1.1      cgd     xfree((ptr_t) u);
    123      1.1      cgd     return (Strsave(gstart));
    124      1.1      cgd }
    125      1.1      cgd 
    126      1.1      cgd static int
    127      1.1      cgd globbrace(s, p, bl)
    128      1.1      cgd     Char   *s, *p, ***bl;
    129      1.1      cgd {
    130      1.1      cgd     int     i, len;
    131      1.1      cgd     Char   *pm, *pe, *lm, *pl;
    132      1.1      cgd     Char  **nv, **vl;
    133      1.1      cgd     Char    gbuf[MAXPATHLEN];
    134      1.1      cgd     int     size = GLOBSPACE;
    135      1.1      cgd 
    136      1.1      cgd     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
    137      1.1      cgd     *vl = NULL;
    138      1.1      cgd 
    139      1.1      cgd     len = 0;
    140      1.1      cgd     /* copy part up to the brace */
    141      1.1      cgd     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
    142      1.1      cgd 	continue;
    143      1.1      cgd 
    144      1.1      cgd     /* check for balanced braces */
    145      1.1      cgd     for (i = 0, pe = ++p; *pe; pe++)
    146      1.1      cgd 	if (*pe == LBRK) {
    147      1.1      cgd 	    /* Ignore everything between [] */
    148      1.1      cgd 	    for (++pe; *pe != RBRK && *pe != EOS; pe++)
    149      1.1      cgd 		continue;
    150      1.1      cgd 	    if (*pe == EOS) {
    151      1.1      cgd 		blkfree(nv);
    152  1.1.1.2  mycroft 		return (-RBRK);
    153      1.1      cgd 	    }
    154      1.1      cgd 	}
    155      1.1      cgd 	else if (*pe == LBRC)
    156      1.1      cgd 	    i++;
    157      1.1      cgd 	else if (*pe == RBRC) {
    158      1.1      cgd 	    if (i == 0)
    159      1.1      cgd 		break;
    160      1.1      cgd 	    i--;
    161      1.1      cgd 	}
    162      1.1      cgd 
    163  1.1.1.2  mycroft     if (i != 0 || *pe == '\0') {
    164      1.1      cgd 	blkfree(nv);
    165  1.1.1.2  mycroft 	return (-RBRC);
    166      1.1      cgd     }
    167      1.1      cgd 
    168      1.1      cgd     for (i = 0, pl = pm = p; pm <= pe; pm++)
    169      1.1      cgd 	switch (*pm) {
    170      1.1      cgd 	case LBRK:
    171      1.1      cgd 	    for (++pm; *pm != RBRK && *pm != EOS; pm++)
    172      1.1      cgd 		continue;
    173      1.1      cgd 	    if (*pm == EOS) {
    174      1.1      cgd 		*vl = NULL;
    175      1.1      cgd 		blkfree(nv);
    176      1.1      cgd 		return (-RBRK);
    177      1.1      cgd 	    }
    178      1.1      cgd 	    break;
    179      1.1      cgd 	case LBRC:
    180      1.1      cgd 	    i++;
    181      1.1      cgd 	    break;
    182      1.1      cgd 	case RBRC:
    183      1.1      cgd 	    if (i) {
    184      1.1      cgd 		i--;
    185      1.1      cgd 		break;
    186      1.1      cgd 	    }
    187      1.1      cgd 	    /* FALLTHROUGH */
    188      1.1      cgd 	case ',':
    189      1.1      cgd 	    if (i && *pm == ',')
    190      1.1      cgd 		break;
    191      1.1      cgd 	    else {
    192      1.1      cgd 		Char    savec = *pm;
    193      1.1      cgd 
    194      1.1      cgd 		*pm = EOS;
    195      1.1      cgd 		(void) Strcpy(lm, pl);
    196      1.1      cgd 		(void) Strcat(gbuf, pe + 1);
    197      1.1      cgd 		*pm = savec;
    198      1.1      cgd 		*vl++ = Strsave(gbuf);
    199      1.1      cgd 		len++;
    200      1.1      cgd 		pl = pm + 1;
    201      1.1      cgd 		if (vl == &nv[size]) {
    202      1.1      cgd 		    size += GLOBSPACE;
    203      1.1      cgd 		    nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    204      1.1      cgd 					    size * sizeof(Char *));
    205      1.1      cgd 		    vl = &nv[size - GLOBSPACE];
    206      1.1      cgd 		}
    207      1.1      cgd 	    }
    208      1.1      cgd 	    break;
    209  1.1.1.2  mycroft 	default:
    210  1.1.1.2  mycroft 	    break;
    211      1.1      cgd 	}
    212      1.1      cgd     *vl = NULL;
    213      1.1      cgd     *bl = nv;
    214      1.1      cgd     return (len);
    215      1.1      cgd }
    216      1.1      cgd 
    217  1.1.1.2  mycroft 
    218  1.1.1.2  mycroft static void
    219  1.1.1.2  mycroft expbrace(nvp, elp, size)
    220  1.1.1.2  mycroft     Char ***nvp, ***elp;
    221  1.1.1.2  mycroft     int size;
    222  1.1.1.2  mycroft {
    223  1.1.1.2  mycroft     Char **vl, **el, **nv, *s;
    224  1.1.1.2  mycroft 
    225  1.1.1.2  mycroft     vl = nv = *nvp;
    226  1.1.1.2  mycroft     if (elp != NULL)
    227  1.1.1.2  mycroft 	el = *elp;
    228  1.1.1.2  mycroft     else
    229  1.1.1.2  mycroft 	for (el = vl; *el; el++)
    230  1.1.1.2  mycroft 	    continue;
    231  1.1.1.2  mycroft 
    232  1.1.1.2  mycroft     for (s = *vl; s; s = *++vl) {
    233  1.1.1.2  mycroft 	Char   *b;
    234  1.1.1.2  mycroft 	Char  **vp, **bp;
    235  1.1.1.2  mycroft 
    236  1.1.1.2  mycroft 	/* leave {} untouched for find */
    237  1.1.1.2  mycroft 	if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
    238  1.1.1.2  mycroft 	    continue;
    239  1.1.1.2  mycroft 	if ((b = Strchr(s, '{')) != NULL) {
    240  1.1.1.2  mycroft 	    Char  **bl;
    241  1.1.1.2  mycroft 	    int     len;
    242  1.1.1.2  mycroft 
    243  1.1.1.2  mycroft 	    if ((len = globbrace(s, b, &bl)) < 0) {
    244  1.1.1.2  mycroft 		xfree((ptr_t) nv);
    245  1.1.1.2  mycroft 		stderror(ERR_MISSING, -len);
    246  1.1.1.2  mycroft 	    }
    247  1.1.1.2  mycroft 	    xfree((ptr_t) s);
    248  1.1.1.2  mycroft 	    if (len == 1) {
    249  1.1.1.2  mycroft 		*vl-- = *bl;
    250  1.1.1.2  mycroft 		xfree((ptr_t) bl);
    251  1.1.1.2  mycroft 		continue;
    252  1.1.1.2  mycroft 	    }
    253  1.1.1.2  mycroft 	    len = blklen(bl);
    254  1.1.1.2  mycroft 	    if (&el[len] >= &nv[size]) {
    255  1.1.1.2  mycroft 		int     l, e;
    256  1.1.1.2  mycroft 
    257  1.1.1.2  mycroft 		l = &el[len] - &nv[size];
    258  1.1.1.2  mycroft 		size += GLOBSPACE > l ? GLOBSPACE : l;
    259  1.1.1.2  mycroft 		l = vl - nv;
    260  1.1.1.2  mycroft 		e = el - nv;
    261  1.1.1.2  mycroft 		nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    262  1.1.1.2  mycroft 					size * sizeof(Char *));
    263  1.1.1.2  mycroft 		vl = nv + l;
    264  1.1.1.2  mycroft 		el = nv + e;
    265  1.1.1.2  mycroft 	    }
    266  1.1.1.2  mycroft 	    vp = vl--;
    267  1.1.1.2  mycroft 	    *vp = *bl;
    268  1.1.1.2  mycroft 	    len--;
    269  1.1.1.2  mycroft 	    for (bp = el; bp != vp; bp--)
    270  1.1.1.2  mycroft 		bp[len] = *bp;
    271  1.1.1.2  mycroft 	    el += len;
    272  1.1.1.2  mycroft 	    vp++;
    273  1.1.1.2  mycroft 	    for (bp = bl + 1; *bp; *vp++ = *bp++)
    274  1.1.1.2  mycroft 		continue;
    275  1.1.1.2  mycroft 	    xfree((ptr_t) bl);
    276  1.1.1.2  mycroft 	}
    277  1.1.1.2  mycroft 
    278  1.1.1.2  mycroft     }
    279  1.1.1.2  mycroft     if (elp != NULL)
    280  1.1.1.2  mycroft 	*elp = el;
    281  1.1.1.2  mycroft     *nvp = nv;
    282  1.1.1.2  mycroft }
    283  1.1.1.2  mycroft 
    284      1.1      cgd static Char **
    285      1.1      cgd globexpand(v)
    286      1.1      cgd     Char  **v;
    287      1.1      cgd {
    288      1.1      cgd     Char   *s;
    289      1.1      cgd     Char  **nv, **vl, **el;
    290      1.1      cgd     int     size = GLOBSPACE;
    291      1.1      cgd 
    292      1.1      cgd 
    293      1.1      cgd     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
    294      1.1      cgd     *vl = NULL;
    295      1.1      cgd 
    296      1.1      cgd     /*
    297      1.1      cgd      * Step 1: expand backquotes.
    298      1.1      cgd      */
    299  1.1.1.2  mycroft     while ((s = *v++) != NULL) {
    300      1.1      cgd 	if (Strchr(s, '`')) {
    301      1.1      cgd 	    int     i;
    302      1.1      cgd 
    303      1.1      cgd 	    (void) dobackp(s, 0);
    304      1.1      cgd 	    for (i = 0; i < pargc; i++) {
    305      1.1      cgd 		*vl++ = pargv[i];
    306      1.1      cgd 		if (vl == &nv[size]) {
    307      1.1      cgd 		    size += GLOBSPACE;
    308      1.1      cgd 		    nv = (Char **) xrealloc((ptr_t) nv,
    309      1.1      cgd 					    (size_t) size * sizeof(Char *));
    310      1.1      cgd 		    vl = &nv[size - GLOBSPACE];
    311      1.1      cgd 		}
    312      1.1      cgd 	    }
    313      1.1      cgd 	    xfree((ptr_t) pargv);
    314      1.1      cgd 	    pargv = NULL;
    315      1.1      cgd 	}
    316      1.1      cgd 	else {
    317      1.1      cgd 	    *vl++ = Strsave(s);
    318      1.1      cgd 	    if (vl == &nv[size]) {
    319      1.1      cgd 		size += GLOBSPACE;
    320      1.1      cgd 		nv = (Char **) xrealloc((ptr_t) nv, (size_t)
    321      1.1      cgd 					size * sizeof(Char *));
    322      1.1      cgd 		vl = &nv[size - GLOBSPACE];
    323      1.1      cgd 	    }
    324      1.1      cgd 	}
    325      1.1      cgd     }
    326      1.1      cgd     *vl = NULL;
    327      1.1      cgd 
    328      1.1      cgd     if (noglob)
    329      1.1      cgd 	return (nv);
    330      1.1      cgd 
    331      1.1      cgd     /*
    332      1.1      cgd      * Step 2: expand braces
    333      1.1      cgd      */
    334      1.1      cgd     el = vl;
    335  1.1.1.2  mycroft     expbrace(&nv, &el, size);
    336      1.1      cgd 
    337      1.1      cgd     /*
    338      1.1      cgd      * Step 3: expand ~
    339      1.1      cgd      */
    340      1.1      cgd     vl = nv;
    341      1.1      cgd     for (s = *vl; s; s = *++vl)
    342      1.1      cgd 	if (*s == '~')
    343      1.1      cgd 	    *vl = globtilde(nv, s);
    344      1.1      cgd     vl = nv;
    345      1.1      cgd     return (vl);
    346      1.1      cgd }
    347      1.1      cgd 
    348      1.1      cgd static Char *
    349      1.1      cgd handleone(str, vl, action)
    350      1.1      cgd     Char   *str, **vl;
    351      1.1      cgd     int     action;
    352      1.1      cgd {
    353      1.1      cgd 
    354      1.1      cgd     Char   *cp, **vlp = vl;
    355      1.1      cgd 
    356      1.1      cgd     switch (action) {
    357      1.1      cgd     case G_ERROR:
    358  1.1.1.2  mycroft 	setname(vis_str(str));
    359      1.1      cgd 	blkfree(vl);
    360      1.1      cgd 	stderror(ERR_NAME | ERR_AMBIG);
    361      1.1      cgd 	break;
    362      1.1      cgd     case G_APPEND:
    363      1.1      cgd 	trim(vlp);
    364      1.1      cgd 	str = Strsave(*vlp++);
    365      1.1      cgd 	do {
    366      1.1      cgd 	    cp = Strspl(str, STRspace);
    367      1.1      cgd 	    xfree((ptr_t) str);
    368      1.1      cgd 	    str = Strspl(cp, *vlp);
    369      1.1      cgd 	    xfree((ptr_t) cp);
    370      1.1      cgd 	}
    371      1.1      cgd 	while (*++vlp);
    372      1.1      cgd 	blkfree(vl);
    373      1.1      cgd 	break;
    374      1.1      cgd     case G_IGNORE:
    375      1.1      cgd 	str = Strsave(strip(*vlp));
    376      1.1      cgd 	blkfree(vl);
    377      1.1      cgd 	break;
    378  1.1.1.2  mycroft     default:
    379  1.1.1.2  mycroft 	break;
    380      1.1      cgd     }
    381      1.1      cgd     return (str);
    382      1.1      cgd }
    383      1.1      cgd 
    384      1.1      cgd static Char **
    385      1.1      cgd libglob(vl)
    386      1.1      cgd     Char  **vl;
    387      1.1      cgd {
    388  1.1.1.2  mycroft     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
    389      1.1      cgd     glob_t  globv;
    390      1.1      cgd     char   *ptr;
    391  1.1.1.2  mycroft     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
    392  1.1.1.2  mycroft 
    393  1.1.1.2  mycroft     if (!vl || !vl[0])
    394  1.1.1.2  mycroft 	return (vl);
    395      1.1      cgd 
    396      1.1      cgd     globv.gl_offs = 0;
    397      1.1      cgd     globv.gl_pathv = 0;
    398      1.1      cgd     globv.gl_pathc = 0;
    399  1.1.1.2  mycroft 
    400  1.1.1.2  mycroft     if (nonomatch)
    401  1.1.1.2  mycroft 	gflgs |= GLOB_NOCHECK;
    402  1.1.1.2  mycroft 
    403      1.1      cgd     do {
    404      1.1      cgd 	ptr = short2qstr(*vl);
    405      1.1      cgd 	switch (glob(ptr, gflgs, 0, &globv)) {
    406      1.1      cgd 	case GLOB_ABEND:
    407  1.1.1.2  mycroft 	    setname(vis_str(*vl));
    408      1.1      cgd 	    stderror(ERR_NAME | ERR_GLOB);
    409      1.1      cgd 	    /* NOTREACHED */
    410      1.1      cgd 	case GLOB_NOSPACE:
    411      1.1      cgd 	    stderror(ERR_NOMEM);
    412      1.1      cgd 	    /* NOTREACHED */
    413      1.1      cgd 	default:
    414      1.1      cgd 	    break;
    415      1.1      cgd 	}
    416  1.1.1.2  mycroft 	if (globv.gl_flags & GLOB_MAGCHAR) {
    417  1.1.1.2  mycroft 	    match |= (globv.gl_matchc != 0);
    418  1.1.1.2  mycroft 	    magic = 1;
    419      1.1      cgd 	}
    420      1.1      cgd 	gflgs |= GLOB_APPEND;
    421      1.1      cgd     }
    422      1.1      cgd     while (*++vl);
    423  1.1.1.2  mycroft     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
    424  1.1.1.2  mycroft 	NULL : blk2short(globv.gl_pathv);
    425      1.1      cgd     globfree(&globv);
    426      1.1      cgd     return (vl);
    427      1.1      cgd }
    428      1.1      cgd 
    429      1.1      cgd Char   *
    430      1.1      cgd globone(str, action)
    431      1.1      cgd     Char   *str;
    432      1.1      cgd     int     action;
    433      1.1      cgd {
    434      1.1      cgd     Char   *v[2], **vl, **vo;
    435  1.1.1.2  mycroft     int    gflg;
    436      1.1      cgd 
    437      1.1      cgd     noglob = adrof(STRnoglob) != 0;
    438      1.1      cgd     gflag = 0;
    439      1.1      cgd     v[0] = str;
    440      1.1      cgd     v[1] = 0;
    441      1.1      cgd     tglob(v);
    442  1.1.1.2  mycroft     gflg = gflag;
    443  1.1.1.2  mycroft     if (gflg == G_NONE)
    444      1.1      cgd 	return (strip(Strsave(str)));
    445      1.1      cgd 
    446  1.1.1.2  mycroft     if (gflg & G_CSH) {
    447      1.1      cgd 	/*
    448      1.1      cgd 	 * Expand back-quote, tilde and brace
    449      1.1      cgd 	 */
    450      1.1      cgd 	vo = globexpand(v);
    451  1.1.1.2  mycroft 	if (noglob || (gflg & G_GLOB) == 0) {
    452      1.1      cgd 	    if (vo[0] == NULL) {
    453      1.1      cgd 		xfree((ptr_t) vo);
    454      1.1      cgd 		return (Strsave(STRNULL));
    455      1.1      cgd 	    }
    456      1.1      cgd 	    if (vo[1] != NULL)
    457      1.1      cgd 		return (handleone(str, vo, action));
    458      1.1      cgd 	    else {
    459      1.1      cgd 		str = strip(vo[0]);
    460      1.1      cgd 		xfree((ptr_t) vo);
    461      1.1      cgd 		return (str);
    462      1.1      cgd 	    }
    463      1.1      cgd 	}
    464      1.1      cgd     }
    465  1.1.1.2  mycroft     else if (noglob || (gflg & G_GLOB) == 0)
    466      1.1      cgd 	return (strip(Strsave(str)));
    467      1.1      cgd     else
    468      1.1      cgd 	vo = v;
    469      1.1      cgd 
    470      1.1      cgd     vl = libglob(vo);
    471  1.1.1.2  mycroft     if ((gflg & G_CSH) && vl != vo)
    472      1.1      cgd 	blkfree(vo);
    473      1.1      cgd     if (vl == NULL) {
    474  1.1.1.2  mycroft 	setname(vis_str(str));
    475      1.1      cgd 	stderror(ERR_NAME | ERR_NOMATCH);
    476      1.1      cgd     }
    477      1.1      cgd     if (vl[0] == NULL) {
    478      1.1      cgd 	xfree((ptr_t) vl);
    479      1.1      cgd 	return (Strsave(STRNULL));
    480      1.1      cgd     }
    481      1.1      cgd     if (vl[1] != NULL)
    482      1.1      cgd 	return (handleone(str, vl, action));
    483      1.1      cgd     else {
    484      1.1      cgd 	str = strip(*vl);
    485      1.1      cgd 	xfree((ptr_t) vl);
    486      1.1      cgd 	return (str);
    487      1.1      cgd     }
    488      1.1      cgd }
    489      1.1      cgd 
    490      1.1      cgd Char  **
    491      1.1      cgd globall(v)
    492      1.1      cgd     Char  **v;
    493      1.1      cgd {
    494      1.1      cgd     Char  **vl, **vo;
    495  1.1.1.2  mycroft     int   gflg = gflag;
    496      1.1      cgd 
    497      1.1      cgd     if (!v || !v[0]) {
    498      1.1      cgd 	gargv = saveblk(v);
    499      1.1      cgd 	gargc = blklen(gargv);
    500      1.1      cgd 	return (gargv);
    501      1.1      cgd     }
    502      1.1      cgd 
    503      1.1      cgd     noglob = adrof(STRnoglob) != 0;
    504      1.1      cgd 
    505  1.1.1.2  mycroft     if (gflg & G_CSH)
    506      1.1      cgd 	/*
    507      1.1      cgd 	 * Expand back-quote, tilde and brace
    508      1.1      cgd 	 */
    509      1.1      cgd 	vl = vo = globexpand(v);
    510      1.1      cgd     else
    511      1.1      cgd 	vl = vo = saveblk(v);
    512      1.1      cgd 
    513  1.1.1.2  mycroft     if (!noglob && (gflg & G_GLOB)) {
    514      1.1      cgd 	vl = libglob(vo);
    515  1.1.1.2  mycroft 	if ((gflg & G_CSH) && vl != vo)
    516      1.1      cgd 	    blkfree(vo);
    517      1.1      cgd     }
    518  1.1.1.2  mycroft     else
    519  1.1.1.2  mycroft 	trim(vl);
    520      1.1      cgd 
    521      1.1      cgd     gargc = vl ? blklen(vl) : 0;
    522      1.1      cgd     return (gargv = vl);
    523      1.1      cgd }
    524      1.1      cgd 
    525      1.1      cgd void
    526      1.1      cgd ginit()
    527      1.1      cgd {
    528      1.1      cgd     gargsiz = GLOBSPACE;
    529      1.1      cgd     gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
    530      1.1      cgd     gargv[0] = 0;
    531      1.1      cgd     gargc = 0;
    532      1.1      cgd }
    533      1.1      cgd 
    534      1.1      cgd void
    535      1.1      cgd rscan(t, f)
    536      1.1      cgd     register Char **t;
    537      1.1      cgd     void    (*f) ();
    538      1.1      cgd {
    539      1.1      cgd     register Char *p;
    540      1.1      cgd 
    541  1.1.1.2  mycroft     while ((p = *t++) != NULL)
    542      1.1      cgd 	while (*p)
    543      1.1      cgd 	    (*f) (*p++);
    544      1.1      cgd }
    545      1.1      cgd 
    546      1.1      cgd void
    547      1.1      cgd trim(t)
    548      1.1      cgd     register Char **t;
    549      1.1      cgd {
    550      1.1      cgd     register Char *p;
    551      1.1      cgd 
    552  1.1.1.2  mycroft     while ((p = *t++) != NULL)
    553      1.1      cgd 	while (*p)
    554      1.1      cgd 	    *p++ &= TRIM;
    555      1.1      cgd }
    556      1.1      cgd 
    557      1.1      cgd void
    558      1.1      cgd tglob(t)
    559      1.1      cgd     register Char **t;
    560      1.1      cgd {
    561      1.1      cgd     register Char *p, c;
    562      1.1      cgd 
    563  1.1.1.2  mycroft     while ((p = *t++) != NULL) {
    564      1.1      cgd 	if (*p == '~' || *p == '=')
    565      1.1      cgd 	    gflag |= G_CSH;
    566      1.1      cgd 	else if (*p == '{' &&
    567  1.1.1.2  mycroft 		 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
    568      1.1      cgd 	    continue;
    569  1.1.1.2  mycroft 	while ((c = *p++) != '\0') {
    570  1.1.1.2  mycroft 	    /*
    571  1.1.1.2  mycroft 	     * eat everything inside the matching backquotes
    572  1.1.1.2  mycroft 	     */
    573  1.1.1.2  mycroft 	    if (c == '`') {
    574  1.1.1.2  mycroft 		gflag |= G_CSH;
    575  1.1.1.2  mycroft 		while (*p && *p != '`')
    576  1.1.1.2  mycroft 		    if (*p++ == '\\') {
    577  1.1.1.2  mycroft 			if (*p)		/* Quoted chars */
    578  1.1.1.2  mycroft 			    p++;
    579  1.1.1.2  mycroft 			else
    580  1.1.1.2  mycroft 			    break;
    581  1.1.1.2  mycroft 		    }
    582  1.1.1.2  mycroft 		if (*p)			/* The matching ` */
    583  1.1.1.2  mycroft 		    p++;
    584  1.1.1.2  mycroft 		else
    585  1.1.1.2  mycroft 		    break;
    586  1.1.1.2  mycroft 	    }
    587  1.1.1.2  mycroft 	    else if (c == '{')
    588  1.1.1.2  mycroft 		gflag |= G_CSH;
    589  1.1.1.2  mycroft 	    else if (isglob(c))
    590  1.1.1.2  mycroft 		gflag |= G_GLOB;
    591  1.1.1.2  mycroft 	}
    592      1.1      cgd     }
    593      1.1      cgd }
    594      1.1      cgd 
    595      1.1      cgd /*
    596      1.1      cgd  * Command substitute cp.  If literal, then this is a substitution from a
    597      1.1      cgd  * << redirection, and so we should not crunch blanks and tabs, separating
    598      1.1      cgd  * words only at newlines.
    599      1.1      cgd  */
    600      1.1      cgd Char  **
    601      1.1      cgd dobackp(cp, literal)
    602      1.1      cgd     Char   *cp;
    603      1.1      cgd     bool    literal;
    604      1.1      cgd {
    605      1.1      cgd     register Char *lp, *rp;
    606      1.1      cgd     Char   *ep, word[MAXPATHLEN];
    607      1.1      cgd 
    608      1.1      cgd     if (pargv) {
    609  1.1.1.2  mycroft #ifdef notdef
    610      1.1      cgd 	abort();
    611  1.1.1.2  mycroft #endif
    612      1.1      cgd 	blkfree(pargv);
    613      1.1      cgd     }
    614      1.1      cgd     pargsiz = GLOBSPACE;
    615      1.1      cgd     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
    616      1.1      cgd     pargv[0] = NULL;
    617      1.1      cgd     pargcp = pargs = word;
    618      1.1      cgd     pargc = 0;
    619      1.1      cgd     pnleft = MAXPATHLEN - 4;
    620      1.1      cgd     for (;;) {
    621      1.1      cgd 	for (lp = cp; *lp != '`'; lp++) {
    622      1.1      cgd 	    if (*lp == 0) {
    623      1.1      cgd 		if (pargcp != pargs)
    624      1.1      cgd 		    pword();
    625      1.1      cgd 		return (pargv);
    626      1.1      cgd 	    }
    627      1.1      cgd 	    psave(*lp);
    628      1.1      cgd 	}
    629      1.1      cgd 	lp++;
    630      1.1      cgd 	for (rp = lp; *rp && *rp != '`'; rp++)
    631      1.1      cgd 	    if (*rp == '\\') {
    632      1.1      cgd 		rp++;
    633      1.1      cgd 		if (!*rp)
    634      1.1      cgd 		    goto oops;
    635      1.1      cgd 	    }
    636      1.1      cgd 	if (!*rp)
    637      1.1      cgd     oops:  stderror(ERR_UNMATCHED, '`');
    638      1.1      cgd 	ep = Strsave(lp);
    639      1.1      cgd 	ep[rp - lp] = 0;
    640      1.1      cgd 	backeval(ep, literal);
    641      1.1      cgd 	cp = rp + 1;
    642      1.1      cgd     }
    643      1.1      cgd }
    644      1.1      cgd 
    645      1.1      cgd static void
    646      1.1      cgd backeval(cp, literal)
    647      1.1      cgd     Char   *cp;
    648      1.1      cgd     bool    literal;
    649      1.1      cgd {
    650      1.1      cgd     register int icnt, c;
    651      1.1      cgd     register Char *ip;
    652      1.1      cgd     struct command faket;
    653      1.1      cgd     bool    hadnl;
    654      1.1      cgd     int     pvec[2], quoted;
    655      1.1      cgd     Char   *fakecom[2], ibuf[BUFSIZ];
    656      1.1      cgd     char    tibuf[BUFSIZ];
    657      1.1      cgd 
    658      1.1      cgd     hadnl = 0;
    659      1.1      cgd     icnt = 0;
    660      1.1      cgd     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
    661      1.1      cgd     faket.t_dtyp = NODE_COMMAND;
    662      1.1      cgd     faket.t_dflg = 0;
    663      1.1      cgd     faket.t_dlef = 0;
    664      1.1      cgd     faket.t_drit = 0;
    665      1.1      cgd     faket.t_dspr = 0;
    666      1.1      cgd     faket.t_dcom = fakecom;
    667      1.1      cgd     fakecom[0] = STRfakecom1;
    668      1.1      cgd     fakecom[1] = 0;
    669      1.1      cgd 
    670      1.1      cgd     /*
    671      1.1      cgd      * We do the psave job to temporarily change the current job so that the
    672      1.1      cgd      * following fork is considered a separate job.  This is so that when
    673      1.1      cgd      * backquotes are used in a builtin function that calls glob the "current
    674      1.1      cgd      * job" is not corrupted.  We only need one level of pushed jobs as long as
    675      1.1      cgd      * we are sure to fork here.
    676      1.1      cgd      */
    677      1.1      cgd     psavejob();
    678      1.1      cgd 
    679      1.1      cgd     /*
    680      1.1      cgd      * It would be nicer if we could integrate this redirection more with the
    681      1.1      cgd      * routines in sh.sem.c by doing a fake execute on a builtin function that
    682      1.1      cgd      * was piped out.
    683      1.1      cgd      */
    684      1.1      cgd     mypipe(pvec);
    685      1.1      cgd     if (pfork(&faket, -1) == 0) {
    686      1.1      cgd 	struct wordent paraml;
    687      1.1      cgd 	struct command *t;
    688      1.1      cgd 
    689      1.1      cgd 	(void) close(pvec[0]);
    690      1.1      cgd 	(void) dmove(pvec[1], 1);
    691  1.1.1.2  mycroft 	(void) dmove(SHERR, 2);
    692      1.1      cgd 	initdesc();
    693      1.1      cgd 	/*
    694      1.1      cgd 	 * Bugfix for nested backquotes by Michael Greim <greim (at) sbsvax.UUCP>,
    695      1.1      cgd 	 * posted to comp.bugs.4bsd 12 Sep. 1989.
    696      1.1      cgd 	 */
    697      1.1      cgd 	if (pargv)		/* mg, 21.dec.88 */
    698      1.1      cgd 	    blkfree(pargv), pargv = 0, pargsiz = 0;
    699      1.1      cgd 	/* mg, 21.dec.88 */
    700      1.1      cgd 	arginp = cp;
    701      1.1      cgd 	while (*cp)
    702      1.1      cgd 	    *cp++ &= TRIM;
    703  1.1.1.2  mycroft 
    704  1.1.1.2  mycroft         /*
    705  1.1.1.2  mycroft 	 * In the child ``forget'' everything about current aliases or
    706  1.1.1.2  mycroft 	 * eval vectors.
    707  1.1.1.2  mycroft 	 */
    708  1.1.1.2  mycroft 	alvec = NULL;
    709  1.1.1.2  mycroft 	evalvec = NULL;
    710  1.1.1.2  mycroft 	alvecp = NULL;
    711  1.1.1.2  mycroft 	evalp = NULL;
    712      1.1      cgd 	(void) lex(&paraml);
    713      1.1      cgd 	if (seterr)
    714      1.1      cgd 	    stderror(ERR_OLD);
    715      1.1      cgd 	alias(&paraml);
    716      1.1      cgd 	t = syntax(paraml.next, &paraml, 0);
    717      1.1      cgd 	if (seterr)
    718      1.1      cgd 	    stderror(ERR_OLD);
    719      1.1      cgd 	if (t)
    720      1.1      cgd 	    t->t_dflg |= F_NOFORK;
    721      1.1      cgd 	(void) signal(SIGTSTP, SIG_IGN);
    722      1.1      cgd 	(void) signal(SIGTTIN, SIG_IGN);
    723      1.1      cgd 	(void) signal(SIGTTOU, SIG_IGN);
    724      1.1      cgd 	execute(t, -1, NULL, NULL);
    725      1.1      cgd 	exitstat();
    726      1.1      cgd     }
    727      1.1      cgd     xfree((ptr_t) cp);
    728      1.1      cgd     (void) close(pvec[1]);
    729      1.1      cgd     c = 0;
    730      1.1      cgd     ip = NULL;
    731      1.1      cgd     do {
    732      1.1      cgd 	int     cnt = 0;
    733      1.1      cgd 
    734      1.1      cgd 	for (;;) {
    735      1.1      cgd 	    if (icnt == 0) {
    736      1.1      cgd 		int     i;
    737      1.1      cgd 
    738      1.1      cgd 		ip = ibuf;
    739      1.1      cgd 		do
    740      1.1      cgd 		    icnt = read(pvec[0], tibuf, BUFSIZ);
    741      1.1      cgd 		while (icnt == -1 && errno == EINTR);
    742      1.1      cgd 		if (icnt <= 0) {
    743      1.1      cgd 		    c = -1;
    744      1.1      cgd 		    break;
    745      1.1      cgd 		}
    746      1.1      cgd 		for (i = 0; i < icnt; i++)
    747      1.1      cgd 		    ip[i] = (unsigned char) tibuf[i];
    748      1.1      cgd 	    }
    749      1.1      cgd 	    if (hadnl)
    750      1.1      cgd 		break;
    751      1.1      cgd 	    --icnt;
    752      1.1      cgd 	    c = (*ip++ & TRIM);
    753      1.1      cgd 	    if (c == 0)
    754      1.1      cgd 		break;
    755      1.1      cgd 	    if (c == '\n') {
    756      1.1      cgd 		/*
    757      1.1      cgd 		 * Continue around the loop one more time, so that we can eat
    758      1.1      cgd 		 * the last newline without terminating this word.
    759      1.1      cgd 		 */
    760      1.1      cgd 		hadnl = 1;
    761      1.1      cgd 		continue;
    762      1.1      cgd 	    }
    763      1.1      cgd 	    if (!quoted && (c == ' ' || c == '\t'))
    764      1.1      cgd 		break;
    765      1.1      cgd 	    cnt++;
    766      1.1      cgd 	    psave(c | quoted);
    767      1.1      cgd 	}
    768      1.1      cgd 	/*
    769      1.1      cgd 	 * Unless at end-of-file, we will form a new word here if there were
    770      1.1      cgd 	 * characters in the word, or in any case when we take text literally.
    771      1.1      cgd 	 * If we didn't make empty words here when literal was set then we
    772      1.1      cgd 	 * would lose blank lines.
    773      1.1      cgd 	 */
    774      1.1      cgd 	if (c != -1 && (cnt || literal))
    775      1.1      cgd 	    pword();
    776      1.1      cgd 	hadnl = 0;
    777      1.1      cgd     } while (c >= 0);
    778      1.1      cgd     (void) close(pvec[0]);
    779      1.1      cgd     pwait();
    780      1.1      cgd     prestjob();
    781      1.1      cgd }
    782      1.1      cgd 
    783      1.1      cgd static void
    784      1.1      cgd psave(c)
    785      1.1      cgd     int    c;
    786      1.1      cgd {
    787      1.1      cgd     if (--pnleft <= 0)
    788      1.1      cgd 	stderror(ERR_WTOOLONG);
    789      1.1      cgd     *pargcp++ = c;
    790      1.1      cgd }
    791      1.1      cgd 
    792      1.1      cgd static void
    793      1.1      cgd pword()
    794      1.1      cgd {
    795      1.1      cgd     psave(0);
    796      1.1      cgd     if (pargc == pargsiz - 1) {
    797      1.1      cgd 	pargsiz += GLOBSPACE;
    798      1.1      cgd 	pargv = (Char **) xrealloc((ptr_t) pargv,
    799      1.1      cgd 				   (size_t) pargsiz * sizeof(Char *));
    800      1.1      cgd     }
    801      1.1      cgd     pargv[pargc++] = Strsave(pargs);
    802      1.1      cgd     pargv[pargc] = NULL;
    803      1.1      cgd     pargcp = pargs;
    804      1.1      cgd     pnleft = MAXPATHLEN - 4;
    805      1.1      cgd }
    806      1.1      cgd 
    807  1.1.1.2  mycroft int
    808      1.1      cgd Gmatch(string, pattern)
    809  1.1.1.2  mycroft     Char *string, *pattern;
    810  1.1.1.2  mycroft {
    811  1.1.1.2  mycroft     Char **blk, **p;
    812  1.1.1.2  mycroft     int	   gpol = 1, gres = 0;
    813  1.1.1.2  mycroft 
    814  1.1.1.2  mycroft     if (*pattern == '^') {
    815  1.1.1.2  mycroft 	gpol = 0;
    816  1.1.1.2  mycroft 	pattern++;
    817  1.1.1.2  mycroft     }
    818  1.1.1.2  mycroft 
    819  1.1.1.2  mycroft     blk = (Char **) xmalloc(GLOBSPACE * sizeof(Char *));
    820  1.1.1.2  mycroft     blk[0] = Strsave(pattern);
    821  1.1.1.2  mycroft     blk[1] = NULL;
    822  1.1.1.2  mycroft 
    823  1.1.1.2  mycroft     expbrace(&blk, NULL, GLOBSPACE);
    824  1.1.1.2  mycroft 
    825  1.1.1.2  mycroft     for (p = blk; *p; p++)
    826  1.1.1.2  mycroft 	gres |= pmatch(string, *p);
    827  1.1.1.2  mycroft 
    828  1.1.1.2  mycroft     blkfree(blk);
    829  1.1.1.2  mycroft     return(gres == gpol);
    830  1.1.1.2  mycroft }
    831  1.1.1.2  mycroft 
    832  1.1.1.2  mycroft static int
    833  1.1.1.2  mycroft pmatch(string, pattern)
    834      1.1      cgd     register Char *string, *pattern;
    835      1.1      cgd {
    836      1.1      cgd     register Char stringc, patternc;
    837  1.1.1.2  mycroft     int     match, negate_range;
    838      1.1      cgd     Char    rangec;
    839      1.1      cgd 
    840      1.1      cgd     for (;; ++string) {
    841      1.1      cgd 	stringc = *string & TRIM;
    842      1.1      cgd 	patternc = *pattern++;
    843      1.1      cgd 	switch (patternc) {
    844      1.1      cgd 	case 0:
    845      1.1      cgd 	    return (stringc == 0);
    846      1.1      cgd 	case '?':
    847      1.1      cgd 	    if (stringc == 0)
    848      1.1      cgd 		return (0);
    849      1.1      cgd 	    break;
    850      1.1      cgd 	case '*':
    851      1.1      cgd 	    if (!*pattern)
    852      1.1      cgd 		return (1);
    853      1.1      cgd 	    while (*string)
    854      1.1      cgd 		if (Gmatch(string++, pattern))
    855      1.1      cgd 		    return (1);
    856      1.1      cgd 	    return (0);
    857      1.1      cgd 	case '[':
    858      1.1      cgd 	    match = 0;
    859  1.1.1.2  mycroft 	    if ((negate_range = (*pattern == '^')) != 0)
    860  1.1.1.2  mycroft 		pattern++;
    861  1.1.1.2  mycroft 	    while ((rangec = *pattern++) != '\0') {
    862      1.1      cgd 		if (rangec == ']')
    863  1.1.1.2  mycroft 		    break;
    864      1.1      cgd 		if (match)
    865      1.1      cgd 		    continue;
    866  1.1.1.2  mycroft 		if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
    867      1.1      cgd 		    match = (stringc <= (*pattern & TRIM) &&
    868  1.1.1.2  mycroft 			      (*(pattern-2) & TRIM) <= stringc);
    869      1.1      cgd 		    pattern++;
    870      1.1      cgd 		}
    871  1.1.1.2  mycroft 		else
    872  1.1.1.2  mycroft 		    match = (stringc == (rangec & TRIM));
    873      1.1      cgd 	    }
    874      1.1      cgd 	    if (rangec == 0)
    875      1.1      cgd 		stderror(ERR_NAME | ERR_MISSING, ']');
    876  1.1.1.2  mycroft 	    if (match == negate_range)
    877  1.1.1.2  mycroft 		return (0);
    878      1.1      cgd 	    break;
    879      1.1      cgd 	default:
    880      1.1      cgd 	    if ((patternc & TRIM) != stringc)
    881      1.1      cgd 		return (0);
    882      1.1      cgd 	    break;
    883      1.1      cgd 
    884      1.1      cgd 	}
    885      1.1      cgd     }
    886      1.1      cgd }
    887      1.1      cgd 
    888      1.1      cgd void
    889      1.1      cgd Gcat(s1, s2)
    890      1.1      cgd     Char   *s1, *s2;
    891      1.1      cgd {
    892      1.1      cgd     register Char *p, *q;
    893      1.1      cgd     int     n;
    894      1.1      cgd 
    895  1.1.1.2  mycroft     for (p = s1; *p++;)
    896  1.1.1.2  mycroft 	continue;
    897  1.1.1.2  mycroft     for (q = s2; *q++;)
    898  1.1.1.2  mycroft 	continue;
    899      1.1      cgd     n = (p - s1) + (q - s2) - 1;
    900      1.1      cgd     if (++gargc >= gargsiz) {
    901      1.1      cgd 	gargsiz += GLOBSPACE;
    902      1.1      cgd 	gargv = (Char **) xrealloc((ptr_t) gargv,
    903      1.1      cgd 				   (size_t) gargsiz * sizeof(Char *));
    904      1.1      cgd     }
    905      1.1      cgd     gargv[gargc] = 0;
    906      1.1      cgd     p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
    907  1.1.1.2  mycroft     for (q = s1; (*p++ = *q++) != '\0';)
    908  1.1.1.2  mycroft 	continue;
    909  1.1.1.2  mycroft     for (p--, q = s2; (*p++ = *q++) != '\0';)
    910  1.1.1.2  mycroft 	continue;
    911      1.1      cgd }
    912      1.1      cgd 
    913      1.1      cgd #ifdef FILEC
    914      1.1      cgd int
    915      1.1      cgd sortscmp(a, b)
    916  1.1.1.2  mycroft     register const ptr_t a, b;
    917      1.1      cgd {
    918      1.1      cgd #if defined(NLS) && !defined(NOSTRCOLL)
    919      1.1      cgd     char    buf[2048];
    920      1.1      cgd #endif
    921      1.1      cgd 
    922      1.1      cgd     if (!a)			/* check for NULL */
    923      1.1      cgd 	return (b ? 1 : 0);
    924      1.1      cgd     if (!b)
    925      1.1      cgd 	return (-1);
    926      1.1      cgd 
    927  1.1.1.2  mycroft     if (!*(Char **)a)			/* check for NULL */
    928  1.1.1.2  mycroft 	return (*(Char **)b ? 1 : 0);
    929  1.1.1.2  mycroft     if (!*(Char **)b)
    930      1.1      cgd 	return (-1);
    931      1.1      cgd 
    932      1.1      cgd #if defined(NLS) && !defined(NOSTRCOLL)
    933  1.1.1.2  mycroft     (void) strcpy(buf, short2str(*(Char **)a));
    934  1.1.1.2  mycroft     return ((int) strcoll(buf, short2str(*(Char **)b)));
    935      1.1      cgd #else
    936  1.1.1.2  mycroft     return ((int) Strcmp(*(Char **)a, *(Char **)b));
    937      1.1      cgd #endif
    938      1.1      cgd }
    939      1.1      cgd #endif /* FILEC */
    940