|
Packit |
992a25 |
/***********************************************************************
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* This software is part of the ast package *
|
|
Packit |
992a25 |
* Copyright (c) 1982-2012 AT&T Intellectual Property *
|
|
Packit |
992a25 |
* and is licensed under the *
|
|
Packit |
992a25 |
* Eclipse Public License, Version 1.0 *
|
|
Packit |
992a25 |
* by AT&T Intellectual Property *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* A copy of the License is available at *
|
|
Packit |
992a25 |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit |
992a25 |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* Information and Software Systems Research *
|
|
Packit |
992a25 |
* AT&T Research *
|
|
Packit |
992a25 |
* Florham Park NJ *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* David Korn <dgk@research.att.com> *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
***********************************************************************/
|
|
Packit |
992a25 |
#pragma prototyped
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* David Korn
|
|
Packit |
992a25 |
* AT&T Labs
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#include "defs.h"
|
|
Packit |
992a25 |
#include <fcin.h>
|
|
Packit |
992a25 |
#include <ls.h>
|
|
Packit |
992a25 |
#include <nval.h>
|
|
Packit |
992a25 |
#include "variables.h"
|
|
Packit |
992a25 |
#include "path.h"
|
|
Packit |
992a25 |
#include "io.h"
|
|
Packit |
992a25 |
#include "jobs.h"
|
|
Packit |
992a25 |
#include "history.h"
|
|
Packit |
992a25 |
#include "test.h"
|
|
Packit |
992a25 |
#include "FEATURE/dynamic"
|
|
Packit |
992a25 |
#include "FEATURE/externs"
|
|
Packit |
992a25 |
#if SHOPT_PFSH
|
|
Packit |
992a25 |
# ifdef _hdr_exec_attr
|
|
Packit |
992a25 |
# include <exec_attr.h>
|
|
Packit |
992a25 |
# endif
|
|
Packit |
992a25 |
# if _lib_vfork
|
|
Packit |
992a25 |
# include <ast_vfork.h>
|
|
Packit |
992a25 |
# else
|
|
Packit |
992a25 |
# define vfork() fork()
|
|
Packit |
992a25 |
# endif
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
|
|
Packit |
992a25 |
#define LIBCMD "cmd"
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static int canexecute(Shell_t*,char*,int);
|
|
Packit |
992a25 |
static void funload(Shell_t*,int,const char*);
|
|
Packit |
992a25 |
static void exscript(Shell_t*,char*, char*[], char**);
|
|
Packit |
992a25 |
static int path_chkpaths(Shell_t*,Pathcomp_t*,Pathcomp_t*,Pathcomp_t*,int);
|
|
Packit |
992a25 |
static void path_checkdup(Shell_t *shp,register Pathcomp_t*);
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static const char *std_path;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static int onstdpath(const char *name)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register const char *cp = std_path, *sp;
|
|
Packit |
992a25 |
if(cp)
|
|
Packit |
992a25 |
while(*cp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
for(sp=name; *sp && (*cp == *sp); sp++,cp++);
|
|
Packit |
992a25 |
if(*sp==0 && (*cp==0 || *cp==':'))
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
while(*cp && *cp++!=':');
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#if SHOPT_PFSH
|
|
Packit |
992a25 |
int path_xattr(Shell_t *shp, const char *path, char *rpath)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
char resolvedpath[PATH_MAX + 1];
|
|
Packit |
992a25 |
if (shp->gd->user && *shp->gd->user)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
execattr_t *pf;
|
|
Packit |
992a25 |
if(!rpath)
|
|
Packit |
992a25 |
rpath = resolvedpath;
|
|
Packit |
992a25 |
if (!realpath(path, resolvedpath))
|
|
Packit |
992a25 |
return -1;
|
|
Packit |
992a25 |
if(pf=getexecuser(shp->gd->user, KV_COMMAND, resolvedpath, GET_ONE))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (!pf->attr || pf->attr->length == 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
free_execattr(pf);
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
free_execattr(pf);
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
errno = ENOENT;
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif /* SHOPT_PFSH */
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static pid_t path_pfexecve(Shell_t *shp,const char *path, char *argv[],char *const envp[],int spawn)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
#if SHOPT_PFSH
|
|
Packit |
992a25 |
char resolvedpath[PATH_MAX + 1];
|
|
Packit |
992a25 |
pid_t pid;
|
|
Packit |
992a25 |
if(spawn)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
while((pid = vfork()) < 0)
|
|
Packit |
992a25 |
_sh_fork(shp,pid, 0, (int*)0);
|
|
Packit |
992a25 |
if(pid)
|
|
Packit |
992a25 |
return(pid);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!sh_isoption(SH_PFSH))
|
|
Packit |
992a25 |
return(execve(path, argv, envp));
|
|
Packit |
992a25 |
/* Solaris implements realpath(3C) using the resolvepath(2) */
|
|
Packit |
992a25 |
/* system call so we can save us to call access(2) first */
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/* we can exec the command directly instead of via pfexec(1) if */
|
|
Packit |
992a25 |
/* there is a matching entry without attributes in exec_attr(4) */
|
|
Packit |
992a25 |
if(!path_xattr(shp,path,resolvedpath))
|
|
Packit |
992a25 |
return(execve(path, argv, envp));
|
|
Packit |
992a25 |
--argv;
|
|
Packit |
992a25 |
argv[0] = argv[1];
|
|
Packit |
992a25 |
argv[1] = resolvedpath;
|
|
Packit |
992a25 |
return(execve("/usr/bin/pfexec", argv, envp));
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
return(execve(path, argv, envp));
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static pid_t _spawnveg(Shell_t *shp,const char *path, char* const argv[], char* const envp[], pid_t pgid)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pid_t pid;
|
|
Packit |
992a25 |
while(1)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sh_stats(STAT_SPAWN);
|
|
Packit |
992a25 |
pid = spawnveg(path,argv,envp,pgid);
|
|
Packit |
992a25 |
if(pid>=0 || errno!=EAGAIN)
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(pid);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* used with command -x to run the command in multiple passes
|
|
Packit |
992a25 |
* spawn is non-zero when invoked via spawn
|
|
Packit |
992a25 |
* the exitval is set to the maximum for each execution
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static pid_t path_xargs(Shell_t *shp,const char *path, char *argv[],char *const envp[], int spawn)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char *cp, **av, **xv;
|
|
Packit |
992a25 |
char **avlast= &argv[shp->xargmax], **saveargs=0;
|
|
Packit |
992a25 |
char *const *ev;
|
|
Packit |
992a25 |
long size, left;
|
|
Packit |
992a25 |
int nlast=1,n,exitval=0;
|
|
Packit |
992a25 |
pid_t pid;
|
|
Packit |
992a25 |
if(shp->xargmin < 0)
|
|
Packit |
992a25 |
return((pid_t)-1);
|
|
Packit |
992a25 |
size = shp->gd->lim.arg_max-1024;
|
|
Packit |
992a25 |
for(ev=envp; cp= *ev; ev++)
|
|
Packit |
992a25 |
size -= strlen(cp)-1;
|
|
Packit |
992a25 |
for(av=argv; (cp= *av) && av< &argv[shp->xargmin]; av++)
|
|
Packit |
992a25 |
size -= strlen(cp)-1;
|
|
Packit |
992a25 |
for(av=avlast; cp= *av; av++,nlast++)
|
|
Packit |
992a25 |
size -= strlen(cp)-1;
|
|
Packit |
992a25 |
av = &argv[shp->xargmin];
|
|
Packit |
992a25 |
if(!spawn)
|
|
Packit |
992a25 |
job_clear();
|
|
Packit |
992a25 |
shp->exitval = 0;
|
|
Packit |
992a25 |
while(av
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
for(xv=av,left=size; left>0 && av
|
|
Packit |
992a25 |
left -= strlen(*av++)+1;
|
|
Packit |
992a25 |
/* leave at least two for last */
|
|
Packit |
992a25 |
if(left<0 && (avlast-av)<2)
|
|
Packit |
992a25 |
av--;
|
|
Packit |
992a25 |
if(xv==&argv[shp->xargmin])
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
n = nlast*sizeof(char*);
|
|
Packit |
992a25 |
saveargs = (char**)malloc(n);
|
|
Packit |
992a25 |
memcpy((void*)saveargs, (void*)av, n);
|
|
Packit |
992a25 |
memcpy((void*)av,(void*)avlast,n);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
for(n=shp->xargmin; xv < av; xv++)
|
|
Packit |
992a25 |
argv[n++] = *xv;
|
|
Packit |
992a25 |
for(xv=avlast; cp= *xv; xv++)
|
|
Packit |
992a25 |
argv[n++] = cp;
|
|
Packit |
992a25 |
argv[n] = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(saveargs || av
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if((pid=_spawnveg(shp,path,argv,envp,0)) < 0)
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
job_post(shp,pid,0);
|
|
Packit |
992a25 |
job_wait(pid);
|
|
Packit |
992a25 |
if(shp->exitval>exitval)
|
|
Packit |
992a25 |
exitval = shp->exitval;
|
|
Packit |
992a25 |
if(saveargs)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
memcpy((void*)av,saveargs,n);
|
|
Packit |
992a25 |
free((void*)saveargs);
|
|
Packit |
992a25 |
saveargs = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(spawn && !sh_isoption(SH_PFSH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shp->xargexit = exitval;
|
|
Packit |
992a25 |
if(saveargs)
|
|
Packit |
992a25 |
free((void*)saveargs);
|
|
Packit |
992a25 |
return(_spawnveg(shp,path,argv,envp,spawn>>1));
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(saveargs)
|
|
Packit |
992a25 |
free((void*)saveargs);
|
|
Packit |
992a25 |
return(path_pfexecve(shp,path,argv,envp,spawn));
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!spawn)
|
|
Packit |
992a25 |
exit(exitval);
|
|
Packit |
992a25 |
return((pid_t)-1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* make sure PWD is set up correctly
|
|
Packit |
992a25 |
* Return the present working directory
|
|
Packit |
992a25 |
* Invokes getcwd() if necessary
|
|
Packit |
992a25 |
* Sets the PWD variable to this value
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
char *path_pwd(Shell_t *shp,int flag)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char *cp;
|
|
Packit |
992a25 |
register int count = 0;
|
|
Packit |
992a25 |
if(shp->pwd)
|
|
Packit |
992a25 |
return((char*)shp->pwd);
|
|
Packit |
992a25 |
while(1)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/* try from lowest to highest */
|
|
Packit |
992a25 |
switch(count++)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 0:
|
|
Packit |
992a25 |
cp = nv_getval(PWDNOD);
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 1:
|
|
Packit |
992a25 |
cp = nv_getval(HOME);
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 2:
|
|
Packit |
992a25 |
cp = "/";
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 3:
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(cp=getcwd(NIL(char*),0))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
nv_offattr(PWDNOD,NV_NOFREE);
|
|
Packit |
992a25 |
_nv_unset(PWDNOD,0);
|
|
Packit |
992a25 |
PWDNOD->nvalue.cp = cp;
|
|
Packit |
992a25 |
goto skip;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
case 4:
|
|
Packit |
992a25 |
return((char*)e_dot);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(cp && *cp=='/' && test_inode(cp,e_dot))
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(count>1)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
nv_offattr(PWDNOD,NV_NOFREE);
|
|
Packit |
992a25 |
nv_putval(PWDNOD,cp,NV_RDONLY);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
skip:
|
|
Packit |
992a25 |
nv_onattr(PWDNOD,NV_NOFREE|NV_EXPORT);
|
|
Packit |
992a25 |
shp->pwd = (char*)(PWDNOD->nvalue.cp);
|
|
Packit |
992a25 |
return(cp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* delete current Pathcomp_t structure
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void path_delete(Pathcomp_t *first)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp=first, *old=0, *ppnext;
|
|
Packit |
992a25 |
while(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
ppnext = pp->next;
|
|
Packit |
992a25 |
if(--pp->refcount<=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->lib)
|
|
Packit |
992a25 |
free((void*)pp->lib);
|
|
Packit |
992a25 |
if(pp->bbuf)
|
|
Packit |
992a25 |
free((void*)pp->bbuf);
|
|
Packit |
992a25 |
free((void*)pp);
|
|
Packit |
992a25 |
if(old)
|
|
Packit |
992a25 |
old->next = ppnext;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
old = pp;
|
|
Packit |
992a25 |
pp = ppnext;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* returns library variable from .paths
|
|
Packit |
992a25 |
* The value might be returned on the stack overwriting path
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static char *path_lib(Shell_t *shp,Pathcomp_t *pp, char *path)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char *last = strrchr(path,'/');
|
|
Packit |
992a25 |
register int r;
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
if(last)
|
|
Packit |
992a25 |
*last = 0;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
path = ".";
|
|
Packit |
992a25 |
r = stat(path,&statb);
|
|
Packit |
992a25 |
if(last)
|
|
Packit |
992a25 |
*last = '/';
|
|
Packit |
992a25 |
if(r>=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t pcomp;
|
|
Packit |
992a25 |
char save[8];
|
|
Packit |
992a25 |
for( ;pp; pp=pp->next)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
path_checkdup(shp,pp);
|
|
Packit |
992a25 |
if(pp->ino==statb.st_ino && pp->dev==statb.st_dev && pp->mtime==statb.st_mtime)
|
|
Packit |
992a25 |
return(pp->lib);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
pcomp.len = 0;
|
|
Packit |
992a25 |
if(last)
|
|
Packit |
992a25 |
pcomp.len = last-path;
|
|
Packit |
992a25 |
memcpy((void*)save, (void*)stakptr(PATH_OFFSET+pcomp.len),sizeof(save));
|
|
Packit |
992a25 |
if(path_chkpaths(shp,(Pathcomp_t*)0,(Pathcomp_t*)0,&pcomp,PATH_OFFSET))
|
|
Packit |
992a25 |
return(stakfreeze(1));
|
|
Packit |
992a25 |
memcpy((void*)stakptr(PATH_OFFSET+pcomp.len),(void*)save,sizeof(save));
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#if 0
|
|
Packit |
992a25 |
void path_dump(register Pathcomp_t *pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sfprintf(sfstderr,"dump\n");
|
|
Packit |
992a25 |
while(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sfprintf(sfstderr,"pp=%x dev=%d ino=%d len=%d flags=%o name=%.*s\n",
|
|
Packit |
992a25 |
pp,pp->dev,pp->ino,pp->len,pp->flags,pp->len,pp->name);
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* check for duplicate directories on PATH
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static void path_checkdup(Shell_t *shp,register Pathcomp_t *pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char *name = pp->name;
|
|
Packit |
992a25 |
register Pathcomp_t *oldpp,*first;
|
|
Packit |
992a25 |
register int flag=0;
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
if(stat(name,&statb)<0 || !S_ISDIR(statb.st_mode))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->flags |= PATH_SKIP;
|
|
Packit |
992a25 |
pp->dev = *name=='/';
|
|
Packit |
992a25 |
return;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
pp->mtime = statb.st_mtime;
|
|
Packit |
992a25 |
pp->ino = statb.st_ino;
|
|
Packit |
992a25 |
pp->dev = statb.st_dev;
|
|
Packit |
992a25 |
if(*name=='/' && onstdpath(name))
|
|
Packit |
992a25 |
flag = PATH_STD_DIR;
|
|
Packit |
992a25 |
first = (pp->flags&PATH_CDPATH)?(Pathcomp_t*)shp->cdpathlist:path_get(shp,"");
|
|
Packit |
992a25 |
for(oldpp=first; oldpp && oldpp!=pp; oldpp=oldpp->next)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->ino==oldpp->ino && pp->dev==oldpp->dev && pp->mtime==oldpp->mtime)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
flag |= PATH_SKIP;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
pp->flags |= flag;
|
|
Packit |
992a25 |
if(((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int offset = staktell();
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
path_chkpaths(shp,first,0,pp,offset);
|
|
Packit |
992a25 |
stakseek(offset);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* write the next path to search on the current stack
|
|
Packit |
992a25 |
* if last is given, all paths that come before <last> are skipped
|
|
Packit |
992a25 |
* the next pathcomp is returned.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
Pathcomp_t *path_nextcomp(Shell_t *shp,register Pathcomp_t *pp, const char *name, Pathcomp_t *last)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *ppnext;
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
if(*name=='/')
|
|
Packit |
992a25 |
pp = 0;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
for(;pp && pp!=last;pp=ppnext)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
ppnext = pp->next;
|
|
Packit |
992a25 |
if(!pp->dev && !pp->ino)
|
|
Packit |
992a25 |
path_checkdup(shp,pp);
|
|
Packit |
992a25 |
if(pp->flags&PATH_SKIP)
|
|
Packit |
992a25 |
return(ppnext);
|
|
Packit |
992a25 |
if(!last || *pp->name!='/')
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!pp) /* this should not happen */
|
|
Packit |
992a25 |
pp = last;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(pp && (pp->name[0]!='.' || pp->name[1]))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(*pp->name!='/')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakputs(path_pwd(shp,1));
|
|
Packit |
992a25 |
if(*stakptr(staktell()-1)!='/')
|
|
Packit |
992a25 |
stakputc('/');
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakwrite(pp->name,pp->len);
|
|
Packit |
992a25 |
if(pp->name[pp->len-1]!='/')
|
|
Packit |
992a25 |
stakputc('/');
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
while(pp && pp!=last && (pp=pp->next))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!(pp->flags&PATH_SKIP))
|
|
Packit |
992a25 |
return(pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return((Pathcomp_t*)0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static Pathcomp_t* defpath_init(Shell_t *shp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *pp = (void*)path_addpath(shp,(Pathcomp_t*)0,(std_path),PATH_PATH);
|
|
Packit |
992a25 |
return(pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static void path_init(Shell_t *shp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
const char *val;
|
|
Packit |
992a25 |
Pathcomp_t *pp;
|
|
Packit |
992a25 |
if(!std_path && !(std_path=astconf("PATH",NIL(char*),NIL(char*))))
|
|
Packit |
992a25 |
std_path = e_defpath;
|
|
Packit |
992a25 |
if(val=sh_scoped(shp,(PATHNOD))->nvalue.cp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shp->pathlist = pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!(pp=(Pathcomp_t*)shp->defpathlist))
|
|
Packit |
992a25 |
pp = defpath_init(shp);
|
|
Packit |
992a25 |
shp->pathlist = (void*)path_dup(pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(val=sh_scoped(shp,(FPATHNOD))->nvalue.cp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* returns that pathlist to search
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
Pathcomp_t *path_get(register Shell_t *shp,register const char *name)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp=0;
|
|
Packit |
992a25 |
if(*name && strchr(name,'/'))
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
if(!sh_isstate(SH_DEFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!shp->pathlist)
|
|
Packit |
992a25 |
path_init(shp);
|
|
Packit |
992a25 |
pp = (Pathcomp_t*)shp->pathlist;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!pp && (!(sh_scoped(shp,PATHNOD)->nvalue.cp)) || sh_isstate(SH_DEFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!(pp=(Pathcomp_t*)shp->defpathlist))
|
|
Packit |
992a25 |
pp = defpath_init(shp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* open file corresponding to name using path give by <pp>
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, int fun)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register int fd= -1;
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
Pathcomp_t *oldpp;
|
|
Packit |
992a25 |
if(!pp && !shp->pathlist)
|
|
Packit |
992a25 |
path_init(shp);
|
|
Packit |
992a25 |
if(!fun && strchr(name,'/'))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(sh_isoption(SH_RESTRICTED))
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_exit(1),e_restricted,name);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
do
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp = path_nextcomp(shp,oldpp=pp,name,0);
|
|
Packit |
992a25 |
while(oldpp && (oldpp->flags&PATH_SKIP))
|
|
Packit |
992a25 |
oldpp = oldpp->next;
|
|
Packit |
992a25 |
if(fun && (!oldpp || !(oldpp->flags&PATH_FPATH)))
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(fstat(fd,&statb)<0 || S_ISDIR(statb.st_mode))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
errno = EISDIR;
|
|
Packit |
992a25 |
sh_close(fd);
|
|
Packit |
992a25 |
fd = -1;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while( fd<0 && pp);
|
|
Packit |
992a25 |
if(fd>=0 && (fd = sh_iomovefd(fd)) > 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
fcntl(fd,F_SETFD,FD_CLOEXEC);
|
|
Packit |
992a25 |
shp->fdstatus[fd] |= IOCLEX;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(fd);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* open file corresponding to name using path give by <pp>
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
int path_open(Shell_t *shp,const char *name, register Pathcomp_t *pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
return(path_opentype(shp,name,pp,0));
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* given a pathname return the base name
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
char *path_basename(register const char *name)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register const char *start = name;
|
|
Packit |
992a25 |
while (*name)
|
|
Packit |
992a25 |
if ((*name++ == '/') && *name) /* don't trim trailing / */
|
|
Packit |
992a25 |
start = name;
|
|
Packit |
992a25 |
return ((char*)start);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
char *path_fullname(Shell_t *shp,const char *name)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int len=strlen(name)+1,dirlen=0;
|
|
Packit |
992a25 |
char *path,*pwd;
|
|
Packit |
992a25 |
if(*name!='/')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pwd = path_pwd(shp,1);
|
|
Packit |
992a25 |
dirlen = strlen(pwd)+1;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
path = (char*)malloc(len+dirlen);
|
|
Packit |
992a25 |
if(dirlen)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
memcpy((void*)path,(void*)pwd,dirlen);
|
|
Packit |
992a25 |
path[dirlen-1] = '/';
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
memcpy((void*)&path[dirlen],(void*)name,len);
|
|
Packit |
992a25 |
pathcanon(path,0);
|
|
Packit |
992a25 |
return(path);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* load functions from file <fno>
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static void funload(Shell_t *shp,int fno, const char *name)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
char *pname,*oldname=shp->st.filename, buff[IOBSIZE+1];
|
|
Packit |
992a25 |
Namval_t *np;
|
|
Packit |
992a25 |
struct Ufunction *rp,*rpfirst;
|
|
Packit |
992a25 |
int savestates = sh_getstate(), oldload=shp->funload;
|
|
Packit |
992a25 |
pname = path_fullname(shp,stakptr(PATH_OFFSET));
|
|
Packit |
992a25 |
if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Dt_t *funtree = sh_subfuntree(1);
|
|
Packit |
992a25 |
while(1)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
rpfirst = dtprev(shp->fpathdict,rp);
|
|
Packit |
992a25 |
if(!rpfirst || strcmp(pname,rpfirst->fname))
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
rp = rpfirst;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
do
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if((np = dtsearch(funtree,rp->np)) && is_afunction(np))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(np->nvalue.rp)
|
|
Packit |
992a25 |
np->nvalue.rp->fdict = 0;
|
|
Packit |
992a25 |
nv_delete(np,funtree,NV_NOFREE);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
dtinsert(funtree,rp->np);
|
|
Packit |
992a25 |
rp->fdict = funtree;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while((rp=dtnext(shp->fpathdict,rp)) && strcmp(pname,rp->fname)==0);
|
|
Packit |
992a25 |
sh_close(fno);
|
|
Packit |
992a25 |
free((void*)pname);
|
|
Packit |
992a25 |
return;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
sh_onstate(SH_NOLOG);
|
|
Packit |
992a25 |
sh_onstate(SH_NOALIAS);
|
|
Packit |
992a25 |
shp->readscript = (char*)name;
|
|
Packit |
992a25 |
shp->st.filename = pname;
|
|
Packit |
992a25 |
shp->funload = 1;
|
|
Packit |
992a25 |
error_info.line = 0;
|
|
Packit |
992a25 |
sh_eval(sfnew(NIL(Sfio_t*),buff,IOBSIZE,fno,SF_READ),SH_FUNEVAL);
|
|
Packit |
992a25 |
sh_close(fno);
|
|
Packit |
992a25 |
shp->readscript = 0;
|
|
Packit |
992a25 |
#if SHOPT_NAMESPACE
|
|
Packit |
992a25 |
if(shp->namespace)
|
|
Packit |
992a25 |
np = sh_fsearch(shp,name,0);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
#endif /* SHOPT_NAMESPACE */
|
|
Packit |
992a25 |
np = nv_search(name,shp->fun_tree,0);
|
|
Packit |
992a25 |
if(!np || !np->nvalue.ip)
|
|
Packit |
992a25 |
pname = stakcopy(shp->st.filename);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
pname = 0;
|
|
Packit |
992a25 |
free((void*)shp->st.filename);
|
|
Packit |
992a25 |
shp->funload = oldload;
|
|
Packit |
992a25 |
shp->st.filename = oldname;
|
|
Packit |
992a25 |
sh_setstate(savestates);
|
|
Packit |
992a25 |
if(pname)
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_exit(ERROR_NOEXEC),e_funload,name,pname);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* do a path search and track alias if requested
|
|
Packit |
992a25 |
* if flag is 0, or if name not found, then try autoloading function
|
|
Packit |
992a25 |
* if flag==2 or 3, returns 1 if name found on FPATH
|
|
Packit |
992a25 |
* if flag==3 no tracked alias will be set
|
|
Packit |
992a25 |
* returns 1, if function was autoloaded.
|
|
Packit |
992a25 |
* If oldpp is not NULL, it will contain a pointer to the path component
|
|
Packit |
992a25 |
* where it was found.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
int path_search(Shell_t *shp,register const char *name,Pathcomp_t **oldpp, int flag)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Namval_t *np;
|
|
Packit |
992a25 |
register int fno;
|
|
Packit |
992a25 |
Pathcomp_t *pp=0;
|
|
Packit |
992a25 |
if(name && strchr(name,'/'))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
if(canexecute(shp,stakptr(PATH_OFFSET),0)<0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*stakptr(PATH_OFFSET) = 0;
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(*name=='/')
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
stakputs(path_pwd(shp,1));
|
|
Packit |
992a25 |
stakputc('/');
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(sh_isstate(SH_DEFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!shp->defpathlist)
|
|
Packit |
992a25 |
defpath_init(shp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(!shp->pathlist)
|
|
Packit |
992a25 |
path_init(shp);
|
|
Packit |
992a25 |
if(flag)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!(flag&1) && (np=nv_search(name,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && (pp=(Pathcomp_t*)np->nvalue.cp))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
path_nextcomp(shp,pp,name,pp);
|
|
Packit |
992a25 |
if(oldpp)
|
|
Packit |
992a25 |
*oldpp = pp;
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
pp = path_absolute(shp,name,oldpp?*oldpp:NIL(Pathcomp_t*));
|
|
Packit |
992a25 |
if(oldpp)
|
|
Packit |
992a25 |
*oldpp = pp;
|
|
Packit |
992a25 |
if(!pp && (np=nv_search(name,shp->fun_tree,0))&&np->nvalue.ip)
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
if(!pp)
|
|
Packit |
992a25 |
*stakptr(PATH_OFFSET) = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(flag==0 || !pp || (pp->flags&PATH_FPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!pp)
|
|
Packit |
992a25 |
pp=sh_isstate(SH_DEFPATH)?shp->defpathlist:shp->pathlist;
|
|
Packit |
992a25 |
if(pp && strmatch(name,e_alphanum) && (fno=path_opentype(shp,name,pp,1))>=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(flag==2)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sh_close(fno);
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
funload(shp,fno,name);
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
*stakptr(PATH_OFFSET) = 0;
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(pp && !sh_isstate(SH_DEFPATH) && *name!='/' && flag<3)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(np=nv_search(name,shp->track_tree,NV_ADD))
|
|
Packit |
992a25 |
path_alias(np,pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* do a path search and find the full pathname of file name
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
Pathcomp_t *path_absolute(Shell_t *shp,register const char *name, Pathcomp_t *pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register int f,isfun;
|
|
Packit |
992a25 |
int noexec=0;
|
|
Packit |
992a25 |
Pathcomp_t *oldpp;
|
|
Packit |
992a25 |
Namval_t *np;
|
|
Packit |
992a25 |
char *cp;
|
|
Packit |
992a25 |
char *bp;
|
|
Packit |
992a25 |
shp->path_err = ENOENT;
|
|
Packit |
992a25 |
if(!pp && !(pp=path_get(shp,"")))
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
shp->path_err = 0;
|
|
Packit |
992a25 |
while(1)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sh_sigcheck(shp);
|
|
Packit |
992a25 |
shp->bltin_dir = 0;
|
|
Packit |
992a25 |
while(oldpp=pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp = path_nextcomp(shp,pp,name,0);
|
|
Packit |
992a25 |
if(!(oldpp->flags&PATH_SKIP))
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!oldpp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shp->path_err = ENOENT;
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
isfun = (oldpp->flags&PATH_FPATH);
|
|
Packit |
992a25 |
if(!isfun && !sh_isoption(SH_RESTRICTED))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
#if SHOPT_DYNAMIC
|
|
Packit |
992a25 |
Shbltin_f addr;
|
|
Packit |
992a25 |
int n;
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),shp->bltin_tree,0))
|
|
Packit |
992a25 |
return(oldpp);
|
|
Packit |
992a25 |
#if SHOPT_DYNAMIC
|
|
Packit |
992a25 |
n = staktell();
|
|
Packit |
992a25 |
stakputs("b_");
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
if((addr = sh_getlib(shp, stakptr(n), oldpp)) &&
|
|
Packit |
992a25 |
(np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)) &&
|
|
Packit |
992a25 |
nv_isattr(np,NV_BLTINOPT))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shp->bltin_dir = 0;
|
|
Packit |
992a25 |
return(oldpp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakseek(n);
|
|
Packit |
992a25 |
while(bp = oldpp->blib)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
char *fp;
|
|
Packit |
992a25 |
void *dll;
|
|
Packit |
992a25 |
int m;
|
|
Packit |
992a25 |
if(fp = strchr(bp, ':'))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*fp++ = 0;
|
|
Packit |
992a25 |
oldpp->blib = fp;
|
|
Packit |
992a25 |
fp = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
fp = oldpp->bbuf;
|
|
Packit |
992a25 |
oldpp->blib = oldpp->bbuf = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
n = staktell();
|
|
Packit |
992a25 |
stakputs("b_");
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
m = staktell();
|
|
Packit |
992a25 |
shp->bltin_dir = oldpp->name;
|
|
Packit |
992a25 |
if(*bp!='/')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakputs(oldpp->name);
|
|
Packit |
992a25 |
stakputc('/');
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakputs(bp);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
if(cp = strrchr(stakptr(m),'/'))
|
|
Packit |
992a25 |
cp++;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
cp = stakptr(m);
|
|
Packit |
992a25 |
if(!strcmp(cp,LIBCMD) &&
|
|
Packit |
992a25 |
(addr=(Shbltin_f)dlllook((void*)0,stakptr(n))) &&
|
|
Packit |
992a25 |
(np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)) &&
|
|
Packit |
992a25 |
nv_isattr(np,NV_BLTINOPT))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
found:
|
|
Packit |
992a25 |
if(fp)
|
|
Packit |
992a25 |
free(fp);
|
|
Packit |
992a25 |
shp->bltin_dir = 0;
|
|
Packit |
992a25 |
return(oldpp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#ifdef SH_PLUGIN_VERSION
|
|
Packit |
992a25 |
if (dll = dllplugin(SH_ID, stakptr(m), NiL, SH_PLUGIN_VERSION, NiL, RTLD_LAZY, NiL, 0))
|
|
Packit |
992a25 |
sh_addlib(shp,dll,stakptr(m),oldpp);
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
#if (_AST_VERSION>=20040404)
|
|
Packit |
992a25 |
if (dll = dllplug(SH_ID, stakptr(m), NiL, RTLD_LAZY, NiL, 0))
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
if (dll = dllfind(stakptr(m), NiL, RTLD_LAZY, NiL, 0))
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* this detects the 2007-05-11 builtin context change and also
|
|
Packit |
992a25 |
* the 2008-03-30 opt_info.num change that hit libcmd::b_head
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
if (libcmd && !dlllook(dll, "b_pids"))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
dlclose(dll);
|
|
Packit |
992a25 |
dll = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
sh_addlib(shp,dll,stakptr(m),oldpp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
if(dll &&
|
|
Packit |
992a25 |
(addr=(Shbltin_f)dlllook(dll,stakptr(n))) &&
|
|
Packit |
992a25 |
(!(np = sh_addbuiltin(stakptr(PATH_OFFSET),NiL,NiL)) || np->nvalue.bfp!=(Nambfp_f)addr) &&
|
|
Packit |
992a25 |
(np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
np->nvenv = dll;
|
|
Packit |
992a25 |
goto found;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),shp->bltin_tree,0))
|
|
Packit |
992a25 |
goto found;
|
|
Packit |
992a25 |
if(fp)
|
|
Packit |
992a25 |
free(fp);
|
|
Packit |
992a25 |
stakseek(n);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif /* SHOPT_DYNAMIC */
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
shp->bltin_dir = 0;
|
|
Packit |
992a25 |
sh_stats(STAT_PATHS);
|
|
Packit |
992a25 |
f = canexecute(shp,stakptr(PATH_OFFSET),isfun);
|
|
Packit |
992a25 |
if(isfun && f>=0 && (cp = strrchr(name,'.')))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*cp = 0;
|
|
Packit |
992a25 |
if(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
|
|
Packit |
992a25 |
f = -1;
|
|
Packit |
992a25 |
*cp = '.';
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(isfun && f>=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
nv_onattr(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
|
|
Packit |
992a25 |
funload(shp,f,name);
|
|
Packit |
992a25 |
close(f);
|
|
Packit |
992a25 |
f = -1;
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(f>=0 && (oldpp->flags & PATH_STD_DIR))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int n = staktell();
|
|
Packit |
992a25 |
stakputs("/bin/");
|
|
Packit |
992a25 |
stakputs(name);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
np = nv_search(stakptr(n),shp->bltin_tree,0);
|
|
Packit |
992a25 |
stakseek(n);
|
|
Packit |
992a25 |
if(np)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
n = np->nvflag;
|
|
Packit |
992a25 |
np = sh_addbuiltin(stakptr(PATH_OFFSET),(Shbltin_f)np->nvalue.bfp,nv_context(np));
|
|
Packit |
992a25 |
np->nvflag = n;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!pp || f>=0)
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
if(errno!=ENOENT)
|
|
Packit |
992a25 |
noexec = errno;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(f<0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shp->path_err = (noexec?noexec:ENOENT);
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
return(oldpp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* returns 0 if path can execute
|
|
Packit |
992a25 |
* sets exec_err if file is found but can't be executable
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
#undef S_IXALL
|
|
Packit |
992a25 |
#ifdef S_IXUSR
|
|
Packit |
992a25 |
# define S_IXALL (S_IXUSR|S_IXGRP|S_IXOTH)
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
# ifdef S_IEXEC
|
|
Packit |
992a25 |
# define S_IXALL (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))
|
|
Packit |
992a25 |
# else
|
|
Packit |
992a25 |
# define S_IXALL 0111
|
|
Packit |
992a25 |
# endif /*S_EXEC */
|
|
Packit |
992a25 |
#endif /* S_IXUSR */
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static int canexecute(Shell_t *shp,register char *path, int isfun)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
register int fd=0;
|
|
Packit |
992a25 |
path = path_relative(shp,path);
|
|
Packit |
992a25 |
if(isfun)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if((fd=open(path,O_RDONLY,0))<0 || fstat(fd,&statb)<0)
|
|
Packit |
992a25 |
goto err;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(stat(path,&statb) < 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
#if _WINIX
|
|
Packit |
992a25 |
/* check for .exe or .bat suffix */
|
|
Packit |
992a25 |
char *cp;
|
|
Packit |
992a25 |
if(errno==ENOENT && (!(cp=strrchr(path,'.')) || strlen(cp)>4 || strchr(cp,'/')))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int offset = staktell()-1;
|
|
Packit |
992a25 |
stakseek(offset);
|
|
Packit |
992a25 |
stakputs(".bat");
|
|
Packit |
992a25 |
path = stakptr(PATH_OFFSET);
|
|
Packit |
992a25 |
if(stat(path,&statb) < 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(errno!=ENOENT)
|
|
Packit |
992a25 |
goto err;
|
|
Packit |
992a25 |
memcpy(stakptr(offset),".sh",4);
|
|
Packit |
992a25 |
if(stat(path,&statb) < 0)
|
|
Packit |
992a25 |
goto err;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
#endif /* _WINIX */
|
|
Packit |
992a25 |
goto err;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
errno = EPERM;
|
|
Packit |
992a25 |
if(S_ISDIR(statb.st_mode))
|
|
Packit |
992a25 |
errno = EISDIR;
|
|
Packit |
992a25 |
else if((statb.st_mode&S_IXALL)==S_IXALL || sh_access(path,X_OK)>=0)
|
|
Packit |
992a25 |
return(fd);
|
|
Packit |
992a25 |
if(isfun && fd>=0)
|
|
Packit |
992a25 |
sh_close(fd);
|
|
Packit |
992a25 |
err:
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* Return path relative to present working directory
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
char *path_relative(Shell_t *shp,register const char* file)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register const char *pwd;
|
|
Packit |
992a25 |
register const char *fp = file;
|
|
Packit |
992a25 |
/* can't relpath when shp->pwd not set */
|
|
Packit |
992a25 |
if(!(pwd=shp->pwd))
|
|
Packit |
992a25 |
return((char*)fp);
|
|
Packit |
992a25 |
while(*pwd==*fp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(*pwd++==0)
|
|
Packit |
992a25 |
return((char*)e_dot);
|
|
Packit |
992a25 |
fp++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(*pwd==0 && *fp == '/')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
while(*++fp=='/');
|
|
Packit |
992a25 |
if(*fp)
|
|
Packit |
992a25 |
return((char*)fp);
|
|
Packit |
992a25 |
return((char*)e_dot);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return((char*)file);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
void path_exec(Shell_t *shp,register const char *arg0,register char *argv[],struct argnod *local)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
char **envp;
|
|
Packit |
992a25 |
const char *opath;
|
|
Packit |
992a25 |
Pathcomp_t *libpath, *pp=0;
|
|
Packit |
992a25 |
int slash=0;
|
|
Packit |
992a25 |
nv_setlist(local,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
|
|
Packit |
992a25 |
envp = sh_envgen();
|
|
Packit |
992a25 |
if(strchr(arg0,'/'))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
slash=1;
|
|
Packit |
992a25 |
/* name containing / not allowed for restricted shell */
|
|
Packit |
992a25 |
if(sh_isoption(SH_RESTRICTED))
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_exit(1),e_restricted,arg0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
pp=path_get(shp,arg0);
|
|
Packit |
992a25 |
shp->path_err= ENOENT;
|
|
Packit |
992a25 |
sfsync(NIL(Sfio_t*));
|
|
Packit |
992a25 |
timerdel(NIL(void*));
|
|
Packit |
992a25 |
/* find first path that has a library component */
|
|
Packit |
992a25 |
while(pp && (pp->flags&PATH_SKIP))
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
if(pp || slash) do
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sh_sigcheck(shp);
|
|
Packit |
992a25 |
if(libpath=pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp = path_nextcomp(shp,pp,arg0,0);
|
|
Packit |
992a25 |
opath = stakfreeze(1)+PATH_OFFSET;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
opath = arg0;
|
|
Packit |
992a25 |
path_spawn(shp,opath,argv,envp,libpath,0);
|
|
Packit |
992a25 |
while(pp && (pp->flags&PATH_FPATH))
|
|
Packit |
992a25 |
pp = path_nextcomp(shp,pp,arg0,0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while(pp);
|
|
Packit |
992a25 |
/* force an exit */
|
|
Packit |
992a25 |
((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
|
|
Packit |
992a25 |
if((errno=shp->path_err)==ENOENT)
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_found,arg0);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arg0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
pid_t path_spawn(Shell_t *shp,const char *opath,register char **argv, char **envp, Pathcomp_t *libpath, int spawn)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char *path;
|
|
Packit |
992a25 |
char **xp=0, *xval, *libenv = (libpath?libpath->lib:0);
|
|
Packit |
992a25 |
Namval_t* np;
|
|
Packit |
992a25 |
char *s, *v;
|
|
Packit |
992a25 |
int r, n, pidsize;
|
|
Packit |
992a25 |
pid_t pid= -1;
|
|
Packit |
992a25 |
/* leave room for inserting _= pathname in environment */
|
|
Packit |
992a25 |
envp--;
|
|
Packit |
992a25 |
#if _lib_readlink
|
|
Packit |
992a25 |
/* save original pathname */
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
pidsize = sfprintf(stkstd,"*%d*",spawn?getpid():getppid());
|
|
Packit |
992a25 |
stakputs(opath);
|
|
Packit |
992a25 |
opath = stakfreeze(1)+PATH_OFFSET+pidsize;
|
|
Packit |
992a25 |
np=nv_search(argv[0],shp->track_tree,0);
|
|
Packit |
992a25 |
while(libpath && !libpath->lib)
|
|
Packit |
992a25 |
libpath=libpath->next;
|
|
Packit |
992a25 |
if(libpath && (!np || nv_size(np)>0))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/* check for symlink and use symlink name */
|
|
Packit |
992a25 |
char buff[PATH_MAX+1];
|
|
Packit |
992a25 |
char save[PATH_MAX+1];
|
|
Packit |
992a25 |
stakseek(PATH_OFFSET);
|
|
Packit |
992a25 |
stakputs(opath);
|
|
Packit |
992a25 |
path = stakptr(PATH_OFFSET);
|
|
Packit |
992a25 |
while((n=readlink(path,buff,PATH_MAX))>0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
buff[n] = 0;
|
|
Packit |
992a25 |
n = PATH_OFFSET;
|
|
Packit |
992a25 |
r = 0;
|
|
Packit |
992a25 |
if((v=strrchr(path,'/')) && *buff!='/')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(buff[0]=='.' && buff[1]=='.' && (r = strlen(path) + 1) <= PATH_MAX)
|
|
Packit |
992a25 |
memcpy(save, path, r);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
r = 0;
|
|
Packit |
992a25 |
n += (v+1-path);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakseek(n);
|
|
Packit |
992a25 |
stakputs(buff);
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
path = stakptr(PATH_OFFSET);
|
|
Packit |
992a25 |
if(v && buff[0]=='.' && buff[1]=='.')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pathcanon(path, 0);
|
|
Packit |
992a25 |
if(r && access(path,X_OK))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
memcpy(path, save, r);
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(libenv = path_lib(shp,libpath,path))
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
stakseek(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
if(libenv && (v = strchr(libenv,'=')))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
n = v - libenv;
|
|
Packit |
992a25 |
*v = 0;
|
|
Packit |
992a25 |
np = nv_open(libenv,shp->var_tree,0);
|
|
Packit |
992a25 |
*v = '=';
|
|
Packit |
992a25 |
s = nv_getval(np);
|
|
Packit |
992a25 |
stakputs(libenv);
|
|
Packit |
992a25 |
if(s)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakputc(':');
|
|
Packit |
992a25 |
stakputs(s);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
v = stakfreeze(1);
|
|
Packit |
992a25 |
r = 1;
|
|
Packit |
992a25 |
xp = envp + 1;
|
|
Packit |
992a25 |
while (s = *xp++)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (strneq(s, v, n) && s[n] == '=')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
xval = *--xp;
|
|
Packit |
992a25 |
*xp = v;
|
|
Packit |
992a25 |
r = 0;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (r)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*envp-- = v;
|
|
Packit |
992a25 |
xp = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(!opath)
|
|
Packit |
992a25 |
opath = stakptr(PATH_OFFSET);
|
|
Packit |
992a25 |
envp[0] = (char*)opath-(PATH_OFFSET+pidsize);
|
|
Packit |
992a25 |
envp[0][0] = '_';
|
|
Packit |
992a25 |
envp[0][1] = '=';
|
|
Packit |
992a25 |
sfsync(sfstderr);
|
|
Packit |
992a25 |
sh_sigcheck(shp);
|
|
Packit |
992a25 |
path = path_relative(shp,opath);
|
|
Packit |
992a25 |
#ifdef SHELLMAGIC
|
|
Packit |
992a25 |
if(*path!='/' && path!=opath)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* The following code because execv(foo,) and execv(./foo,)
|
|
Packit |
992a25 |
* may not yield the same results
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
char *sp = (char*)malloc(strlen(path)+3);
|
|
Packit |
992a25 |
sp[0] = '.';
|
|
Packit |
992a25 |
sp[1] = '/';
|
|
Packit |
992a25 |
strcpy(sp+2,path);
|
|
Packit |
992a25 |
path = sp;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif /* SHELLMAGIC */
|
|
Packit |
992a25 |
if(spawn && !sh_isoption(SH_PFSH))
|
|
Packit |
992a25 |
pid = _spawnveg(shp,opath, &argv[0],envp, spawn>>1);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
pid = path_pfexecve(shp,opath, &argv[0] ,envp,spawn);
|
|
Packit |
992a25 |
if(xp)
|
|
Packit |
992a25 |
*xp = xval;
|
|
Packit |
992a25 |
#ifdef SHELLMAGIC
|
|
Packit |
992a25 |
if(*path=='.' && path!=opath)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
free(path);
|
|
Packit |
992a25 |
path = path_relative(shp,opath);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif /* SHELLMAGIC */
|
|
Packit |
992a25 |
if(pid>0)
|
|
Packit |
992a25 |
return(pid);
|
|
Packit |
992a25 |
retry:
|
|
Packit |
992a25 |
switch(shp->path_err = errno)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
#ifdef apollo
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* On apollo's execve will fail with eacces when
|
|
Packit |
992a25 |
* file has execute but not read permissions. So,
|
|
Packit |
992a25 |
* for now we will pretend that EACCES and ENOEXEC
|
|
Packit |
992a25 |
* mean the same thing.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
case EACCES:
|
|
Packit |
992a25 |
#endif /* apollo */
|
|
Packit |
992a25 |
case ENOEXEC:
|
|
Packit |
992a25 |
#if SHOPT_SUID_EXEC
|
|
Packit |
992a25 |
case EPERM:
|
|
Packit |
992a25 |
/* some systems return EPERM if setuid bit is on */
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
errno = ENOEXEC;
|
|
Packit |
992a25 |
if(spawn)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
#ifdef _lib_fork
|
|
Packit |
992a25 |
if(shp->subshell)
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
do
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if((pid=fork())>0)
|
|
Packit |
992a25 |
return(pid);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while(_sh_fork(shp,pid,0,(int*)0) < 0);
|
|
Packit |
992a25 |
((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
exscript(shp,path,argv,envp);
|
|
Packit |
992a25 |
#ifndef apollo
|
|
Packit |
992a25 |
case EACCES:
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
if(stat(path,&statb)>=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(S_ISDIR(statb.st_mode))
|
|
Packit |
992a25 |
errno = EISDIR;
|
|
Packit |
992a25 |
#ifdef S_ISSOCK
|
|
Packit |
992a25 |
if(S_ISSOCK(statb.st_mode))
|
|
Packit |
992a25 |
exscript(shp,path,argv,envp);
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
/* FALL THROUGH */
|
|
Packit |
992a25 |
#endif /* !apollo */
|
|
Packit |
992a25 |
#ifdef ENAMETOOLONG
|
|
Packit |
992a25 |
case ENAMETOOLONG:
|
|
Packit |
992a25 |
#endif /* ENAMETOOLONG */
|
|
Packit |
992a25 |
#if !SHOPT_SUID_EXEC
|
|
Packit |
992a25 |
case EPERM:
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
shp->path_err = errno;
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
case ENOTDIR:
|
|
Packit |
992a25 |
case ENOENT:
|
|
Packit |
992a25 |
case EINTR:
|
|
Packit |
992a25 |
#ifdef EMLINK
|
|
Packit |
992a25 |
case EMLINK:
|
|
Packit |
992a25 |
#endif /* EMLINK */
|
|
Packit |
992a25 |
return(-1);
|
|
Packit |
992a25 |
case E2BIG:
|
|
Packit |
992a25 |
if(shp->xargmin)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pid = path_xargs(shp,opath, &argv[0] ,envp,spawn);
|
|
Packit |
992a25 |
if(pid<0)
|
|
Packit |
992a25 |
goto retry;
|
|
Packit |
992a25 |
return(pid);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
default:
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* File is executable but not machine code.
|
|
Packit |
992a25 |
* Assume file is a Shell script and execute it.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static void exscript(Shell_t *shp,register char *path,register char *argv[],char **envp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Sfio_t *sp;
|
|
Packit |
992a25 |
path = path_relative(shp,path);
|
|
Packit |
992a25 |
shp->comdiv=0;
|
|
Packit |
992a25 |
shp->bckpid = 0;
|
|
Packit |
992a25 |
shp->coshell = 0;
|
|
Packit |
992a25 |
shp->st.ioset=0;
|
|
Packit |
992a25 |
/* clean up any cooperating processes */
|
|
Packit |
992a25 |
if(shp->cpipe[0]>0)
|
|
Packit |
992a25 |
sh_pclose(shp->cpipe);
|
|
Packit |
992a25 |
if(shp->cpid && shp->outpipe)
|
|
Packit |
992a25 |
sh_close(*shp->outpipe);
|
|
Packit |
992a25 |
shp->cpid = 0;
|
|
Packit |
992a25 |
if(sp=fcfile())
|
|
Packit |
992a25 |
while(sfstack(sp,SF_POPSTACK));
|
|
Packit |
992a25 |
job_clear();
|
|
Packit |
992a25 |
if(shp->infd>0 && (shp->fdstatus[shp->infd]&IOCLEX))
|
|
Packit |
992a25 |
sh_close(shp->infd);
|
|
Packit |
992a25 |
sh_setstate(sh_state(SH_FORKED));
|
|
Packit |
992a25 |
sfsync(sfstderr);
|
|
Packit |
992a25 |
#if SHOPT_SUID_EXEC && !SHOPT_PFSH
|
|
Packit |
992a25 |
/* check if file cannot open for read or script is setuid/setgid */
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
static char name[] = "/tmp/euidXXXXXXXXXX";
|
|
Packit |
992a25 |
register int n;
|
|
Packit |
992a25 |
register uid_t euserid;
|
|
Packit |
992a25 |
char *savet=0;
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
if((n=sh_open(path,O_RDONLY,0)) >= 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/* move <n> if n=0,1,2 */
|
|
Packit |
992a25 |
n = sh_iomovefd(n);
|
|
Packit |
992a25 |
if(fstat(n,&statb)>=0 && !(statb.st_mode&(S_ISUID|S_ISGID)))
|
|
Packit |
992a25 |
goto openok;
|
|
Packit |
992a25 |
sh_close(n);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if((euserid=geteuid()) != shp->gd->userid)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
strncpy(name+9,fmtbase((long)getpid(),10,0),sizeof(name)-10);
|
|
Packit |
992a25 |
/* create a suid open file with owner equal effective uid */
|
|
Packit |
992a25 |
if((n=open(name,O_CREAT|O_TRUNC|O_WRONLY,S_ISUID|S_IXUSR)) < 0)
|
|
Packit |
992a25 |
goto fail;
|
|
Packit |
992a25 |
unlink(name);
|
|
Packit |
992a25 |
/* make sure that file has right owner */
|
|
Packit |
992a25 |
if(fstat(n,&statb)<0 || statb.st_uid != euserid)
|
|
Packit |
992a25 |
goto fail;
|
|
Packit |
992a25 |
if(n!=10)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sh_close(10);
|
|
Packit |
992a25 |
fcntl(n, F_DUPFD, 10);
|
|
Packit |
992a25 |
sh_close(n);
|
|
Packit |
992a25 |
n=10;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
savet = *--argv;
|
|
Packit |
992a25 |
*argv = path;
|
|
Packit |
992a25 |
path_pfexecve(shp,e_suidexec,argv,envp,0);
|
|
Packit |
992a25 |
fail:
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* The following code is just for compatibility
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
if((n=open(path,O_RDONLY,0)) < 0)
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
|
|
Packit |
992a25 |
if(savet)
|
|
Packit |
992a25 |
*argv++ = savet;
|
|
Packit |
992a25 |
openok:
|
|
Packit |
992a25 |
shp->infd = n;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#else
|
|
Packit |
992a25 |
if((shp->infd = sh_open(path,O_RDONLY,0)) < 0)
|
|
Packit |
992a25 |
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
shp->infd = sh_iomovefd(shp->infd);
|
|
Packit |
992a25 |
#if SHOPT_ACCT
|
|
Packit |
992a25 |
sh_accbegin(path) ; /* reset accounting */
|
|
Packit |
992a25 |
#endif /* SHOPT_ACCT */
|
|
Packit |
992a25 |
shp->arglist = sh_argcreate(argv);
|
|
Packit |
992a25 |
shp->lastarg = strdup(path);
|
|
Packit |
992a25 |
/* save name of calling command */
|
|
Packit |
992a25 |
shp->readscript = error_info.id;
|
|
Packit |
992a25 |
/* close history file if name has changed */
|
|
Packit |
992a25 |
if(shp->gd->hist_ptr && (path=nv_getval(HISTFILE)) && strcmp(path,shp->gd->hist_ptr->histname))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
hist_close(shp->gd->hist_ptr);
|
|
Packit |
992a25 |
(HISTCUR)->nvalue.lp = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
sh_offstate(SH_FORKED);
|
|
Packit |
992a25 |
if(shp->sigflag[SIGCHLD]==SH_SIGOFF)
|
|
Packit |
992a25 |
shp->sigflag[SIGCHLD] = SH_SIGFAULT;
|
|
Packit |
992a25 |
siglongjmp(*shp->jmplist,SH_JMPSCRIPT);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#if SHOPT_ACCT
|
|
Packit |
992a25 |
# include <sys/acct.h>
|
|
Packit |
992a25 |
# include "FEATURE/time"
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static struct acct sabuf;
|
|
Packit |
992a25 |
static struct tms buffer;
|
|
Packit |
992a25 |
static clock_t before;
|
|
Packit |
992a25 |
static char *SHACCT; /* set to value of SHACCT environment variable */
|
|
Packit |
992a25 |
static shaccton; /* non-zero causes accounting record to be written */
|
|
Packit |
992a25 |
static int compress(time_t);
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* initialize accounting, i.e., see if SHACCT variable set
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void sh_accinit(void)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
SHACCT = getenv("SHACCT");
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* suspend accounting until turned on by sh_accbegin()
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void sh_accsusp(void)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
shaccton=0;
|
|
Packit |
992a25 |
#ifdef AEXPAND
|
|
Packit |
992a25 |
sabuf.ac_flag |= AEXPND;
|
|
Packit |
992a25 |
#endif /* AEXPAND */
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* begin an accounting record by recording start time
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void sh_accbegin(const char *cmdname)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(SHACCT)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sabuf.ac_btime = time(NIL(time_t *));
|
|
Packit |
992a25 |
before = times(&buffer);
|
|
Packit |
992a25 |
sabuf.ac_uid = getuid();
|
|
Packit |
992a25 |
sabuf.ac_gid = getgid();
|
|
Packit |
992a25 |
strncpy(sabuf.ac_comm, (char*)path_basename(cmdname),
|
|
Packit |
992a25 |
sizeof(sabuf.ac_comm));
|
|
Packit |
992a25 |
shaccton = 1;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* terminate an accounting record and append to accounting file
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void sh_accend(void)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int fd;
|
|
Packit |
992a25 |
clock_t after;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
if(shaccton)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
after = times(&buffer);
|
|
Packit |
992a25 |
sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
|
|
Packit |
992a25 |
sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
|
|
Packit |
992a25 |
sabuf.ac_etime = compress( (time_t)(after-before));
|
|
Packit |
992a25 |
fd = open( SHACCT , O_WRONLY | O_APPEND | O_CREAT,RW_ALL);
|
|
Packit |
992a25 |
write(fd, (const char*)&sabuf, sizeof( sabuf ));
|
|
Packit |
992a25 |
close( fd);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* Produce a pseudo-floating point representation
|
|
Packit |
992a25 |
* with 3 bits base-8 exponent, 13 bits fraction.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static int compress(register time_t t)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register int exp = 0, rund = 0;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
while (t >= 8192)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
exp++;
|
|
Packit |
992a25 |
rund = t&0;;
|
|
Packit |
992a25 |
t >>= 3;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (rund)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
t++;
|
|
Packit |
992a25 |
if (t >= 8192)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
t >>= 3;
|
|
Packit |
992a25 |
exp++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return((exp<<13) + t);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#endif /* SHOPT_ACCT */
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* add a pathcomponent to the path search list and eliminate duplicates
|
|
Packit |
992a25 |
* and non-existing absolute paths.
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static Pathcomp_t *path_addcomp(Shell_t *shp,Pathcomp_t *first, Pathcomp_t *old,const char *name, int flag)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp, *oldpp;
|
|
Packit |
992a25 |
int len, offset=staktell();
|
|
Packit |
992a25 |
if(!(flag&PATH_BFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register const char *cp = name;
|
|
Packit |
992a25 |
while(*cp && *cp!=':')
|
|
Packit |
992a25 |
stakputc(*cp++);
|
|
Packit |
992a25 |
len = staktell()-offset;
|
|
Packit |
992a25 |
stakputc(0);
|
|
Packit |
992a25 |
stakseek(offset);
|
|
Packit |
992a25 |
name = (const char*)stakptr(offset);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
len = strlen(name);
|
|
Packit |
992a25 |
for(pp=first; pp; pp=pp->next)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(len == pp->len && memcmp(name,pp->name,len)==0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->flags |= flag;
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
for(pp=first, oldpp=0; pp; oldpp=pp, pp=pp->next);
|
|
Packit |
992a25 |
pp = newof((Pathcomp_t*)0,Pathcomp_t,1,len+1);
|
|
Packit |
992a25 |
pp->shp = shp;
|
|
Packit |
992a25 |
pp->refcount = 1;
|
|
Packit |
992a25 |
memcpy((char*)(pp+1),name,len+1);
|
|
Packit |
992a25 |
pp->name = (char*)(pp+1);
|
|
Packit |
992a25 |
pp->len = len;
|
|
Packit |
992a25 |
if(oldpp)
|
|
Packit |
992a25 |
oldpp->next = pp;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
first = pp;
|
|
Packit |
992a25 |
pp->flags = flag;
|
|
Packit |
992a25 |
if(strcmp(name,SH_CMDLIB_DIR)==0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->dev = 1;
|
|
Packit |
992a25 |
pp->flags |= PATH_BUILTIN_LIB;
|
|
Packit |
992a25 |
pp->blib = pp->bbuf = malloc(sizeof(LIBCMD));
|
|
Packit |
992a25 |
strcpy(pp->blib,LIBCMD);
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if((old||shp->pathinit) && ((flag&(PATH_PATH|PATH_SKIP))==PATH_PATH))
|
|
Packit |
992a25 |
path_chkpaths(shp,first,old,pp,offset);
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* This function checks for the .paths file in directory in <pp>
|
|
Packit |
992a25 |
* it assumes that the directory is on the stack at <offset>
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static int path_chkpaths(Shell_t *shp,Pathcomp_t *first, Pathcomp_t* old,Pathcomp_t *pp, int offset)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
int k,m,n,fd;
|
|
Packit |
992a25 |
char *sp,*cp,*ep;
|
|
Packit |
992a25 |
stakseek(offset+pp->len);
|
|
Packit |
992a25 |
if(pp->len==1 && *stakptr(offset)=='/')
|
|
Packit |
992a25 |
stakseek(offset);
|
|
Packit |
992a25 |
stakputs("/.paths");
|
|
Packit |
992a25 |
if((fd=open(stakptr(offset),O_RDONLY))>=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
fstat(fd,&statb);
|
|
Packit |
992a25 |
n = statb.st_size;
|
|
Packit |
992a25 |
stakseek(offset+pp->len+n+2);
|
|
Packit |
992a25 |
sp = stakptr(offset+pp->len);
|
|
Packit |
992a25 |
*sp++ = '/';
|
|
Packit |
992a25 |
n=read(fd,cp=sp,n);
|
|
Packit |
992a25 |
sp[n] = 0;
|
|
Packit |
992a25 |
close(fd);
|
|
Packit |
992a25 |
for(ep=0; n--; cp++)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(*cp=='=')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
ep = cp+1;
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(*cp!='\r' && *cp!='\n')
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
if(*sp=='#' || sp==cp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
sp = cp+1;
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
*cp = 0;
|
|
Packit |
992a25 |
m = ep ? (ep-sp) : 0;
|
|
Packit |
992a25 |
if(m==0 || m==6 && memcmp((void*)sp,(void*)"FPATH=",m)==0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(first)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
char *ptr = stakptr(offset+pp->len+1);
|
|
Packit |
992a25 |
if(ep)
|
|
Packit |
992a25 |
strcpy(ptr,ep);
|
|
Packit |
992a25 |
path_addcomp(shp,first,old,stakptr(offset),PATH_FPATH|PATH_BFPATH);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(m==11 && memcmp((void*)sp,(void*)"PLUGIN_LIB=",m)==0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->bbuf)
|
|
Packit |
992a25 |
free(pp->bbuf);
|
|
Packit |
992a25 |
pp->blib = pp->bbuf = strdup(ep);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if(m)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->lib = (char*)malloc(cp-sp+pp->len+2);
|
|
Packit |
992a25 |
memcpy((void*)pp->lib,(void*)sp,m);
|
|
Packit |
992a25 |
memcpy((void*)&pp->lib[m],stakptr(offset),pp->len);
|
|
Packit |
992a25 |
pp->lib[k=m+pp->len] = '/';
|
|
Packit |
992a25 |
strcpy((void*)&pp->lib[k+1],ep);
|
|
Packit |
992a25 |
pathcanon(&pp->lib[m],0);
|
|
Packit |
992a25 |
if(!first)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
stakseek(0);
|
|
Packit |
992a25 |
stakputs(pp->lib);
|
|
Packit |
992a25 |
free((void*)pp->lib);
|
|
Packit |
992a25 |
return(1);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
sp = cp+1;
|
|
Packit |
992a25 |
ep = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
Pathcomp_t *path_addpath(Shell_t *shp,Pathcomp_t *first, register const char *path,int type)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register const char *cp;
|
|
Packit |
992a25 |
Pathcomp_t *old=0;
|
|
Packit |
992a25 |
int offset = staktell();
|
|
Packit |
992a25 |
char *savptr;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
if(!path && type!=PATH_PATH)
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
if(type!=PATH_FPATH)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
old = first;
|
|
Packit |
992a25 |
first = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(offset)
|
|
Packit |
992a25 |
savptr = stakfreeze(0);
|
|
Packit |
992a25 |
if(path) while(*(cp=path))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(*cp==':')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(type!=PATH_FPATH)
|
|
Packit |
992a25 |
first = path_addcomp(shp,first,old,".",type);
|
|
Packit |
992a25 |
while(*++path == ':');
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
int c;
|
|
Packit |
992a25 |
while(*path && *path!=':')
|
|
Packit |
992a25 |
path++;
|
|
Packit |
992a25 |
c = *path++;
|
|
Packit |
992a25 |
first = path_addcomp(shp,first,old,cp,type);
|
|
Packit |
992a25 |
if(c==0)
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
if(*path==0)
|
|
Packit |
992a25 |
path--;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(old)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!first && !path)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *pp = (Pathcomp_t*)shp->defpathlist;
|
|
Packit |
992a25 |
if(!pp)
|
|
Packit |
992a25 |
pp = defpath_init(shp);
|
|
Packit |
992a25 |
first = path_dup(pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(cp=(sh_scoped(shp,FPATHNOD))->nvalue.cp)
|
|
Packit |
992a25 |
first = (void*)path_addpath(shp,(Pathcomp_t*)first,cp,PATH_FPATH);
|
|
Packit |
992a25 |
path_delete(old);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(offset)
|
|
Packit |
992a25 |
stakset(savptr,offset);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
stakseek(0);
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* duplicate the path give by <first> by incremented reference counts
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
Pathcomp_t *path_dup(Pathcomp_t *first)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp=first;
|
|
Packit |
992a25 |
while(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->refcount++;
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* called whenever the directory is changed
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void path_newdir(Shell_t *shp,Pathcomp_t *first)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp=first, *next, *pq;
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
for(pp=first; pp; pp=pp->next)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->flags &= ~PATH_SKIP;
|
|
Packit |
992a25 |
if(*pp->name=='/')
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
/* delete .paths component */
|
|
Packit |
992a25 |
if((next=pp->next) && (next->flags&PATH_BFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->next = next->next;
|
|
Packit |
992a25 |
if(--next->refcount<=0)
|
|
Packit |
992a25 |
free((void*)next);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if(stat(pp->name,&statb)<0 || !S_ISDIR(statb.st_mode))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
pp->dev = 0;
|
|
Packit |
992a25 |
pp->ino = 0;
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
pp->dev = statb.st_dev;
|
|
Packit |
992a25 |
pp->ino = statb.st_ino;
|
|
Packit |
992a25 |
pp->mtime = statb.st_mtime;
|
|
Packit |
992a25 |
for(pq=first;pq!=pp;pq=pq->next)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->ino==pq->ino && pp->dev==pq->dev)
|
|
Packit |
992a25 |
pp->flags |= PATH_SKIP;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
for(pq=pp;pq=pq->next;)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->ino==pq->ino && pp->dev==pq->dev)
|
|
Packit |
992a25 |
pq->flags |= PATH_SKIP;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
/* try to insert .paths component */
|
|
Packit |
992a25 |
int offset = staktell();
|
|
Packit |
992a25 |
stakputs(pp->name);
|
|
Packit |
992a25 |
stakseek(offset);
|
|
Packit |
992a25 |
next = pp->next;
|
|
Packit |
992a25 |
pp->next = 0;
|
|
Packit |
992a25 |
path_chkpaths(shp,first,(Pathcomp_t*)0,pp,offset);
|
|
Packit |
992a25 |
if(pp->next)
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
pp->next = next;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
#if 0
|
|
Packit |
992a25 |
path_dump(first);
|
|
Packit |
992a25 |
#endif
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
Pathcomp_t *path_unsetfpath(Shell_t *shp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *first = (Pathcomp_t*)shp->pathlist;
|
|
Packit |
992a25 |
register Pathcomp_t *pp=first, *old=0;
|
|
Packit |
992a25 |
if(shp->fpathdict)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
struct Ufunction *rp, *rpnext;
|
|
Packit |
992a25 |
for(rp=(struct Ufunction*)dtfirst(shp->fpathdict);rp;rp=rpnext)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
rpnext = (struct Ufunction*)dtnext(shp->fpathdict,rp);
|
|
Packit |
992a25 |
if(rp->fdict)
|
|
Packit |
992a25 |
nv_delete(rp->np,rp->fdict,NV_NOFREE);
|
|
Packit |
992a25 |
rp->fdict = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if((pp->flags&PATH_FPATH) && !(pp->flags&PATH_BFPATH))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp->flags&PATH_PATH)
|
|
Packit |
992a25 |
pp->flags &= ~PATH_FPATH;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *ppsave=pp;
|
|
Packit |
992a25 |
if(old)
|
|
Packit |
992a25 |
old->next = pp->next;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
first = pp->next;
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
if(--ppsave->refcount<=0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(ppsave->lib)
|
|
Packit |
992a25 |
free((void*)ppsave->lib);
|
|
Packit |
992a25 |
free((void*)ppsave);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
old = pp;
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(first);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
Pathcomp_t *path_dirfind(Pathcomp_t *first,const char *name,int c)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register Pathcomp_t *pp=first;
|
|
Packit |
992a25 |
while(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(memcmp(name,pp->name,pp->len)==0 && name[pp->len]==c)
|
|
Packit |
992a25 |
return(pp);
|
|
Packit |
992a25 |
pp = pp->next;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
return(0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* get discipline for tracked alias
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
static char *talias_get(Namval_t *np, Namfun_t *nvp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
|
|
Packit |
992a25 |
char *ptr;
|
|
Packit |
992a25 |
if(!pp)
|
|
Packit |
992a25 |
return(NULL);
|
|
Packit |
992a25 |
pp->shp->last_table = 0;
|
|
Packit |
992a25 |
path_nextcomp(pp->shp,pp,nv_name(np),pp);
|
|
Packit |
992a25 |
ptr = stakfreeze(0);
|
|
Packit |
992a25 |
return(ptr+PATH_OFFSET);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static void talias_put(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(!val && np->nvalue.cp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
|
|
Packit |
992a25 |
if(--pp->refcount<=0)
|
|
Packit |
992a25 |
free((void*)pp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
nv_putv(np,val,flags,fp);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static const Namdisc_t talias_disc = { 0, talias_put, talias_get };
|
|
Packit |
992a25 |
static Namfun_t talias_init = { &talias_disc, 1 };
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* set tracked alias node <np> to value <pp>
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
void path_alias(register Namval_t *np,register Pathcomp_t *pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if(pp)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
struct stat statb;
|
|
Packit |
992a25 |
char *sp;
|
|
Packit |
992a25 |
Pathcomp_t *old = 0;
|
|
Packit |
992a25 |
nv_offattr(np,NV_NOPRINT);
|
|
Packit |
992a25 |
nv_stack(np,&talias_init);
|
|
Packit |
992a25 |
old = (Pathcomp_t*)np->nvalue.cp;
|
|
Packit |
992a25 |
if (old && (--old->refcount <= 0))
|
|
Packit |
992a25 |
free((void*)old);
|
|
Packit |
992a25 |
np->nvalue.cp = (char*)pp;
|
|
Packit |
992a25 |
pp->refcount++;
|
|
Packit |
992a25 |
nv_setattr(np,NV_TAGGED|NV_NOFREE);
|
|
Packit |
992a25 |
path_nextcomp(pp->shp,pp,nv_name(np),pp);
|
|
Packit |
992a25 |
sp = stakptr(PATH_OFFSET);
|
|
Packit |
992a25 |
if(sp && lstat(sp,&statb)>=0 && S_ISLNK(statb.st_mode))
|
|
Packit |
992a25 |
nv_setsize(np,statb.st_size+1);
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
nv_setsize(np,0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
_nv_unset(np,0);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|