1
0
Files
irix-657m-src/eoe/cmd/sh/expand.c
2022-09-29 17:59:04 +03:00

282 lines
4.5 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)sh:expand.c 1.18.6.1"
/*
* UNIX shell
*
*/
#include "defs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
/*
* globals (file name generation)
*
* "*" in params matches r.e ".*"
* "?" in params matches r.e. "."
* "[...]" in params matches character class
* "[...a-z...]" in params matches a through z.
*
*/
static void addg();
#ifndef sgi
static DIR *_opendir();
static int _closedir();
#else
#define _opendir opendir
#define _closedir closedir
#endif
extern int gmatch();
expand(as, rcnt)
unsigned char *as;
{
int count;
DIR *dirf;
BOOL dir = 0;
unsigned char *rescan = 0;
unsigned char *slashsav = 0;
register unsigned char *s, *cs;
unsigned char *s2 = 0;
struct argnod *schain = gchain;
BOOL slash;
if (trapnote & SIGSET)
return(0);
s = cs = as;
/*
* check for meta chars
*/
{
register BOOL open;
slash = 0;
open = 0;
do
{
switch (*cs++)
{
case 0:
if (rcnt && slash)
break;
else
return(0);
case '/':
slash++;
open = 0;
continue;
case '[':
open++;
continue;
case ']':
if (open == 0)
continue;
case '?': /*FALLTHROUGH*/
case '*':
if (rcnt > slash)
continue;
else
cs--;
break;
case '\\':
cs++;
default: /*FALLTHROUGH*/
continue;
}
break;
} while (TRUE);
}
for (;;)
{
if (cs == s)
{
s = (unsigned char *)nullstr;
break;
}
else if (*--cs == '/')
{
*cs = 0;
if (s == cs)
s = (unsigned char *)"/";
else {
/* push trimmed copy of directory prefix
onto stack */
s2 = cpystak(s);
trim(s2);
s = s2;
}
break;
}
}
if ((dirf = _opendir((const char *)(*s ? s : (unsigned char *)"."))) != 0)
dir++;
/* Let s point to original string because it will be trimmed later */
if(s2)
s = as;
count = 0;
if (*cs == 0)
slashsav = cs++; /* remember where first slash in as is */
/* check for rescan */
if (dir)
{
register unsigned char *rs;
struct dirent *e;
rs = cs;
do /* find next / in as */
{
if (*rs == '/')
{
rescan = rs;
*rs = 0;
gchain = 0;
}
} while (*rs++);
while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0)
{
if (e->d_name[0] == '.' && *cs != '.')
continue;
if (gmatch(e->d_name, cs))
{
addg(s, e->d_name, rescan, slashsav);
count++;
}
}
(void)_closedir(dirf);
if (rescan)
{
register struct argnod *rchain;
rchain = gchain;
gchain = schain;
if (count)
{
count = 0;
while (rchain)
{
count += expand(rchain->argval, slash + 1);
rchain = rchain->argnxt;
}
}
*rescan = '/';
}
}
if(slashsav)
*slashsav = '/';
return(count);
}
#ifndef sgi
/*
opendir -- C library extension routine
*/
extern int open(), close(), fstat();
#define NULL 0
static DIR *
_opendir(filename)
char *filename; /* name of directory */
{
static DIR direct;
static char dirbuf[DIRBUF];
register DIR *dirp = &direct; /* static storage */
register int fd; /* file descriptor for read */
struct stat sbuf; /* result of fstat() */
if (stat(filename, &sbuf) < 0
|| (sbuf.st_mode & S_IFMT) != S_IFDIR
|| (fd = open(filename, 0)) < 0 )
return NULL;
dirp->dd_fd = fd;
dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
dirp->dd_buf = dirbuf;
return dirp;
}
/*
closedir -- C library extension routine
*/
extern int close();
static int
_closedir(dirp)
register DIR *dirp; /* stream from opendir() */
{
return close(dirp->dd_fd);
}
#endif
static void
addg(as1, as2, as3, as4)
unsigned char *as1, *as2, *as3, *as4;
{
register unsigned char *s1, *s2;
s2 = locstak() + BYTESPERWORD;
s1 = as1;
if(as4) {
while (*s2 = *s1++)
s2++;
/* Restore first slash before the first metacharacter if as1 is not "/" */
if(as4 + 1 == s1)
*s2++ = '/';
}
/* add matched entries, plus extra \\ to escape \\'s */
s1 = as2;
while (*s2 = *s1++) {
if(*s2 == '\\')
*++s2 = '\\';
s2++;
}
s1 = as3;
if (s1)
{
*s2++ = '/';
while (*s2++ = *++s1);
}
makearg(endstak(s2));
}
void
makearg(args)
register struct argnod *args;
{
args->argnxt = gchain;
gchain = args;
}