|
|
503c26 |
diff -up ksh20120801/src/cmd/ksh93/sh/subshell.c.orig ksh20120801/src/cmd/ksh93/sh/subshell.c
|
|
|
503c26 |
--- ksh20120801/src/cmd/ksh93/sh/subshell.c.orig 2012-07-17 23:54:21.000000000 +0200
|
|
|
503c26 |
+++ ksh20120801/src/cmd/ksh93/sh/subshell.c 2012-10-24 15:03:44.436870792 +0200
|
|
|
503c26 |
@@ -40,14 +40,6 @@
|
|
|
503c26 |
# define PIPE_BUF 512
|
|
|
503c26 |
#endif
|
|
|
503c26 |
|
|
|
503c26 |
-#ifndef O_SEARCH
|
|
|
503c26 |
-# ifdef O_PATH
|
|
|
503c26 |
-# define O_SEARCH O_PATH
|
|
|
503c26 |
-# else
|
|
|
503c26 |
-# define O_SEARCH 0
|
|
|
503c26 |
-# endif
|
|
|
503c26 |
-#endif
|
|
|
503c26 |
-
|
|
|
503c26 |
/*
|
|
|
503c26 |
* Note that the following structure must be the same
|
|
|
503c26 |
* size as the Dtlink_t structure
|
|
|
503c26 |
@@ -84,7 +76,7 @@ static struct subshell
|
|
|
503c26 |
char *pwd; /* present working directory */
|
|
|
503c26 |
const char *shpwd; /* saved pointer to sh.pwd */
|
|
|
503c26 |
void *jobs; /* save job info */
|
|
|
503c26 |
- int pwdfd; /* file descritor for pwd */
|
|
|
503c26 |
+ int shpwdfd;/* fd for present working directory */
|
|
|
503c26 |
mode_t mask; /* saved umask */
|
|
|
503c26 |
short tmpfd; /* saved tmp file descriptor */
|
|
|
503c26 |
short pipefd; /* read fd if pipe is created */
|
|
|
503c26 |
@@ -101,7 +93,6 @@ static struct subshell
|
|
|
503c26 |
int subdup;
|
|
|
503c26 |
char subshare;
|
|
|
503c26 |
char comsub;
|
|
|
503c26 |
- char pwdclose;
|
|
|
503c26 |
#if SHOPT_COSHELL
|
|
|
503c26 |
void *coshell;
|
|
|
503c26 |
#endif /* SHOPT_COSHELL */
|
|
|
503c26 |
@@ -518,7 +509,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
|
|
|
503c26 |
shp->pathinit = 0;
|
|
|
503c26 |
}
|
|
|
503c26 |
sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
|
|
|
503c26 |
- sp->pwdfd = -1;
|
|
|
503c26 |
if(!shp->pwd)
|
|
|
503c26 |
path_pwd(shp,0);
|
|
|
503c26 |
sp->bckpid = shp->bckpid;
|
|
|
503c26 |
@@ -531,39 +521,14 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
|
|
|
503c26 |
shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
|
|
|
503c26 |
if(comsub)
|
|
|
503c26 |
shp->comsub = comsub;
|
|
|
503c26 |
+ sp->shpwdfd=-1;
|
|
|
503c26 |
if(!comsub || !shp->subshare)
|
|
|
503c26 |
{
|
|
|
503c26 |
- struct subshell *xp;
|
|
|
503c26 |
sp->shpwd = shp->pwd;
|
|
|
503c26 |
-#ifdef _lib_fchdir
|
|
|
503c26 |
- for(xp=sp->prev; xp; xp=xp->prev)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- if(xp->pwdfd>0 && strcmp(xp->pwd,shp->pwd)==0)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- sp->pwdfd = xp->pwdfd;
|
|
|
503c26 |
- break;
|
|
|
503c26 |
- }
|
|
|
503c26 |
- }
|
|
|
503c26 |
- if(sp->pwdfd<0)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- int n = open(".",O_RDONLY);
|
|
|
503c26 |
- if(O_SEARCH && errno==EACCES)
|
|
|
503c26 |
- n = open(".",O_RDONLY);
|
|
|
503c26 |
- if(n>=0)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- sp->pwdfd = n;
|
|
|
503c26 |
- if(n<10)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- sp->pwdfd = sh_fcntl(n,F_DUPFD,10);
|
|
|
503c26 |
- close(n);
|
|
|
503c26 |
- }
|
|
|
503c26 |
- if(sp->pwdfd>0)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- fcntl(sp->pwdfd,F_SETFD,FD_CLOEXEC);
|
|
|
503c26 |
- sp->pwdclose = 1;
|
|
|
503c26 |
- }
|
|
|
503c26 |
- }
|
|
|
503c26 |
- }
|
|
|
503c26 |
+ sp->shpwdfd=((shp->pwdfd >= 0))?sh_fcntl(shp->pwdfd, F_dupfd_cloexec, 10):-1;
|
|
|
503c26 |
+#ifdef O_SEARCH
|
|
|
503c26 |
+ if(sp->shpwdfd<0)
|
|
|
503c26 |
+ errormsg(SH_DICT,ERROR_system(1), "Can't obtain directory fd.");
|
|
|
503c26 |
#endif
|
|
|
503c26 |
sp->pwd = (shp->pwd?strdup(shp->pwd):0);
|
|
|
503c26 |
sp->mask = shp->mask;
|
|
|
503c26 |
@@ -741,14 +706,11 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
|
|
|
503c26 |
Namval_t *pwdnod = sh_scoped(shp,PWDNOD);
|
|
|
503c26 |
if(shp->pwd)
|
|
|
503c26 |
{
|
|
|
503c26 |
- if(sp->pwdfd >=0)
|
|
|
503c26 |
- {
|
|
|
503c26 |
- if(fchdir(sp->pwdfd)<0)
|
|
|
503c26 |
- chdir(sp->pwd);
|
|
|
503c26 |
- }
|
|
|
503c26 |
- else
|
|
|
503c26 |
- chdir(sp->pwd);
|
|
|
503c26 |
shp->pwd=sp->pwd;
|
|
|
503c26 |
+#ifndef O_SEARCH
|
|
|
503c26 |
+ if (sp->shpwdfd < 0)
|
|
|
503c26 |
+ chdir(shp->pwd);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
path_newdir(shp,shp->pathlist);
|
|
|
503c26 |
}
|
|
|
503c26 |
if(nv_isattr(pwdnod,NV_NOFREE))
|
|
|
503c26 |
@@ -762,8 +724,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
|
|
|
503c26 |
}
|
|
|
503c26 |
else
|
|
|
503c26 |
free((void*)sp->pwd);
|
|
|
503c26 |
- if(sp->pwdclose)
|
|
|
503c26 |
- close(sp->pwdfd);
|
|
|
503c26 |
if(sp->mask!=shp->mask)
|
|
|
503c26 |
umask(shp->mask=sp->mask);
|
|
|
503c26 |
if(shp->coutpipe!=sp->coutpipe)
|
|
|
503c26 |
@@ -775,6 +735,13 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_
|
|
|
503c26 |
shp->cpipe[1] = sp->cpipe;
|
|
|
503c26 |
shp->coutpipe = sp->coutpipe;
|
|
|
503c26 |
}
|
|
|
503c26 |
+ if(sp->shpwdfd >=0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(shp->pwdfd >=0)
|
|
|
503c26 |
+ sh_close(shp->pwdfd);
|
|
|
503c26 |
+ shp->pwdfd=sp->shpwdfd;
|
|
|
503c26 |
+ fchdir(shp->pwdfd);
|
|
|
503c26 |
+ }
|
|
|
503c26 |
shp->subshare = sp->subshare;
|
|
|
503c26 |
shp->comsub = sp->comsub;
|
|
|
503c26 |
shp->subdup = sp->subdup;
|
|
|
503c26 |
diff -up ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.orig ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c
|
|
|
503c26 |
--- ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c.orig 2012-08-02 16:50:40.000000000 +0200
|
|
|
503c26 |
+++ ksh-20120801/src/cmd/ksh93/bltins/cd_pwd.c 2012-10-24 15:37:46.814469045 +0200
|
|
|
503c26 |
@@ -38,6 +38,10 @@
|
|
|
503c26 |
#include "builtins.h"
|
|
|
503c26 |
#include <ls.h>
|
|
|
503c26 |
|
|
|
503c26 |
+#ifndef EINTR_REPEAT
|
|
|
503c26 |
+# define EINTR_REPEAT(expr) while((expr) && (errno == EINTR)) errno=0;
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+
|
|
|
503c26 |
/*
|
|
|
503c26 |
* Invalidate path name bindings to relative paths
|
|
|
503c26 |
*/
|
|
|
503c26 |
@@ -49,6 +53,95 @@ static void rehash(register Namval_t *np
|
|
|
503c26 |
_nv_unset(np,0);
|
|
|
503c26 |
}
|
|
|
503c26 |
|
|
|
503c26 |
+/*
|
|
|
503c26 |
+ * Obtain a file handle to the directory "path" relative to directory
|
|
|
503c26 |
+ * "dir", or open a NFSv4 xattr directory handle for file dir/path.
|
|
|
503c26 |
+ */
|
|
|
503c26 |
+int sh_diropenat(Shell_t *shp, int dir, const char *path, bool xattr)
|
|
|
503c26 |
+{
|
|
|
503c26 |
+ int fd,shfd;
|
|
|
503c26 |
+ int savederrno=errno;
|
|
|
503c26 |
+#ifndef AT_FDCWD
|
|
|
503c26 |
+ NOT_USED(dir);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+#ifndef O_XATTR
|
|
|
503c26 |
+ NOT_USED(xattr);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+
|
|
|
503c26 |
+#ifdef O_XATTR
|
|
|
503c26 |
+ if(xattr)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ int apfd; /* attribute parent fd */
|
|
|
503c26 |
+ /* open parent node... */
|
|
|
503c26 |
+ EINTR_REPEAT((apfd = openat(dir, path, O_RDONLY|O_NONBLOCK|O_cloexec)) < 0);
|
|
|
503c26 |
+ if(apfd < 0)
|
|
|
503c26 |
+ return -1;
|
|
|
503c26 |
+
|
|
|
503c26 |
+ /* ... and then open a fd to the attribute directory */
|
|
|
503c26 |
+ EINTR_REPEAT((fd = openat(apfd, e_dot, O_XATTR|O_cloexec)) < 0);
|
|
|
503c26 |
+
|
|
|
503c26 |
+ savederrno = errno;
|
|
|
503c26 |
+ EINTR_REPEAT(close(apfd) < 0);
|
|
|
503c26 |
+ errno = savederrno;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ else
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+#ifdef AT_FDCWD
|
|
|
503c26 |
+ /*
|
|
|
503c26 |
+ * Open directory. First we try without |O_SEARCH| and
|
|
|
503c26 |
+ * if this fails with EACCESS we try with |O_SEARCH|
|
|
|
503c26 |
+ * again.
|
|
|
503c26 |
+ * This is required ...
|
|
|
503c26 |
+ * - ... because some platforms may require that it can
|
|
|
503c26 |
+ * only be used for directories while some filesystems
|
|
|
503c26 |
+ * (e.g. Reiser4 or HSM systems) allow a |fchdir()| into
|
|
|
503c26 |
+ * files, too)
|
|
|
503c26 |
+ * - ... to preserve the semantics of "cd", e.g.
|
|
|
503c26 |
+ * otherwise "cd" would return [No access] instead of
|
|
|
503c26 |
+ * [Not a directory] for files on filesystems which do
|
|
|
503c26 |
+ * not allow a "cd" into files.
|
|
|
503c26 |
+ * - ... to allow that a
|
|
|
503c26 |
+ * $ redirect {n}
|
|
|
503c26 |
+ * platforms.
|
|
|
503c26 |
+ */
|
|
|
503c26 |
+ EINTR_REPEAT((fd = openat(dir, path, O_RDONLY|O_NONBLOCK|O_cloexec)) < 0);
|
|
|
503c26 |
+# ifdef O_SEARCH
|
|
|
503c26 |
+ if((fd < 0) && (errno == EACCES))
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ EINTR_REPEAT((fd = openat(dir, path, O_SEARCH|O_cloexec)) < 0)
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+# endif
|
|
|
503c26 |
+#else
|
|
|
503c26 |
+ /*
|
|
|
503c26 |
+ * Version of openat() call above for systems without
|
|
|
503c26 |
+ * openat API. This only works because we basically
|
|
|
503c26 |
+ * gurantee that |dir| is always the same place as
|
|
|
503c26 |
+ * |cwd| on such machines (but this won't be the case
|
|
|
503c26 |
+ * in the future).
|
|
|
503c26 |
+ */
|
|
|
503c26 |
+ /*
|
|
|
503c26 |
+ * This |fchdir()| call is not needed (yet) since
|
|
|
503c26 |
+ * all consumers do not use |dir| when |AT_FDCWD|
|
|
|
503c26 |
+ * is not available.
|
|
|
503c26 |
+ *
|
|
|
503c26 |
+ * fchdir(dir);
|
|
|
503c26 |
+ */
|
|
|
503c26 |
+ EINTR_REPEAT((fd = open(path, O_cloexec)) < 0);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+
|
|
|
503c26 |
+ if(fd < 0)
|
|
|
503c26 |
+ return fd;
|
|
|
503c26 |
+
|
|
|
503c26 |
+ /* Move fd to a number > 10 and *register* the fd number with the shell */
|
|
|
503c26 |
+ shfd = sh_fcntl(fd, F_dupfd_cloexec, 10);
|
|
|
503c26 |
+ savederrno=errno;
|
|
|
503c26 |
+ sh_close(fd);
|
|
|
503c26 |
+ errno=savederrno;
|
|
|
503c26 |
+ return(shfd);
|
|
|
503c26 |
+}
|
|
|
503c26 |
+
|
|
|
503c26 |
int b_cd(int argc, char *argv[],Shbltin_t *context)
|
|
|
503c26 |
{
|
|
|
503c26 |
register char *dir;
|
|
|
503c26 |
@@ -56,18 +149,20 @@ int b_cd(int argc, char *argv[],Shbltin_
|
|
|
503c26 |
register const char *dp;
|
|
|
503c26 |
register Shell_t *shp = context->shp;
|
|
|
503c26 |
int saverrno=0;
|
|
|
503c26 |
- int rval,flag=0;
|
|
|
503c26 |
+ int rval;
|
|
|
503c26 |
+ bool flag=false,xattr=false;
|
|
|
503c26 |
char *oldpwd;
|
|
|
503c26 |
+ int newdirfd;
|
|
|
503c26 |
Namval_t *opwdnod, *pwdnod;
|
|
|
503c26 |
if(sh_isoption(SH_RESTRICTED))
|
|
|
503c26 |
errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
|
|
|
503c26 |
while((rval = optget(argv,sh_optcd))) switch(rval)
|
|
|
503c26 |
{
|
|
|
503c26 |
case 'L':
|
|
|
503c26 |
- flag = 0;
|
|
|
503c26 |
+ flag = false;
|
|
|
503c26 |
break;
|
|
|
503c26 |
case 'P':
|
|
|
503c26 |
- flag = 1;
|
|
|
503c26 |
+ flag = true;
|
|
|
503c26 |
break;
|
|
|
503c26 |
case ':':
|
|
|
503c26 |
errormsg(SH_DICT,2, "%s", opt_info.arg);
|
|
|
503c26 |
@@ -179,14 +274,72 @@ int b_cd(int argc, char *argv[],Shbltin_
|
|
|
503c26 |
continue;
|
|
|
503c26 |
#endif /* SHOPT_FS_3D */
|
|
|
503c26 |
}
|
|
|
503c26 |
+ rval = newdirfd = sh_diropenat(shp, shp->pwdfd,
|
|
|
503c26 |
+ path_relative(shp,stakptr(PATH_OFFSET)), xattr);
|
|
|
503c26 |
+ if(newdirfd >=0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ /* chdir for directories on HSM/tapeworms may take minutes */
|
|
|
503c26 |
+ if(fchdir(newdirfd) >= 0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(shp->pwdfd >= 0)
|
|
|
503c26 |
+ sh_close(shp->pwdfd);
|
|
|
503c26 |
+ shp->pwdfd=newdirfd;
|
|
|
503c26 |
+ goto success;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+#ifndef O_SEARCH
|
|
|
503c26 |
+ else
|
|
|
503c26 |
+ {
|
|
|
503c26 |
if((rval=chdir(path_relative(shp,stakptr(PATH_OFFSET)))) >= 0)
|
|
|
503c26 |
- goto success;
|
|
|
503c26 |
- if(errno!=ENOENT && saverrno==0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(shp->pwdfd >= 0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ sh_close(shp->pwdfd);
|
|
|
503c26 |
+#ifdef AT_FDCWD
|
|
|
503c26 |
+ shp->pwdfd = AT_FDCWD;
|
|
|
503c26 |
+#else
|
|
|
503c26 |
+ shp->pwdfd = -1;
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+ if(saverrno==0)
|
|
|
503c26 |
saverrno=errno;
|
|
|
503c26 |
+ if(newdirfd >=0)
|
|
|
503c26 |
+ sh_close(newdirfd);
|
|
|
503c26 |
}
|
|
|
503c26 |
while(cdpath);
|
|
|
503c26 |
if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
|
|
|
503c26 |
- rval = chdir(dir);
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ rval = newdirfd = sh_diropenat(shp,
|
|
|
503c26 |
+ shp->pwdfd,
|
|
|
503c26 |
+ dir, xattr);
|
|
|
503c26 |
+ if(newdirfd >=0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ /* chdir for directories on HSM/tapeworms may take minutes */
|
|
|
503c26 |
+ if(fchdir(newdirfd) >= 0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(shp->pwdfd >= 0)
|
|
|
503c26 |
+ sh_close(shp->pwdfd);
|
|
|
503c26 |
+ shp->pwdfd=newdirfd;
|
|
|
503c26 |
+ goto success;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+#ifndef O_SEARCH
|
|
|
503c26 |
+ else
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(chdir(dir) >=0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ if(shp->pwdfd >= 0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ sh_close(shp->pwdfd);
|
|
|
503c26 |
+ shp->pwdfd=-1;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+ }
|
|
|
503c26 |
/* use absolute chdir() if relative chdir() fails */
|
|
|
503c26 |
if(rval<0)
|
|
|
503c26 |
{
|
|
|
503c26 |
@@ -213,7 +366,7 @@ success:
|
|
|
503c26 |
if(*dir != '/')
|
|
|
503c26 |
return(0);
|
|
|
503c26 |
nv_putval(opwdnod,oldpwd,NV_RDONLY);
|
|
|
503c26 |
- flag = strlen(dir);
|
|
|
503c26 |
+ flag = (strlen(dir)>0)?true:false;
|
|
|
503c26 |
/* delete trailing '/' */
|
|
|
503c26 |
while(--flag>0 && dir[flag]=='/')
|
|
|
503c26 |
dir[flag] = 0;
|
|
|
503c26 |
diff -up ksh-20120801/src/cmd/ksh93/include/shell.h.orig ksh-20120801/src/cmd/ksh93/include/shell.h
|
|
|
503c26 |
--- ksh-20120801/src/cmd/ksh93/include/shell.h.orig 2012-07-17 22:07:40.000000000 +0200
|
|
|
503c26 |
+++ ksh-20120801/src/cmd/ksh93/include/shell.h 2012-10-24 15:42:10.756987230 +0200
|
|
|
503c26 |
@@ -145,6 +145,7 @@ struct Shell_s
|
|
|
503c26 |
unsigned char trapnote; /* set when trap/signal is pending */
|
|
|
503c26 |
char shcomp; /* set when runing shcomp */
|
|
|
503c26 |
short subshell; /* set for virtual subshell */
|
|
|
503c26 |
+ int pwdfd; /* file descriptor for pwd */
|
|
|
503c26 |
#ifdef _SH_PRIVATE
|
|
|
503c26 |
_SH_PRIVATE
|
|
|
503c26 |
#endif /* _SH_PRIVATE */
|
|
|
503c26 |
diff -up ksh-20120801/src/cmd/ksh93/sh/init.c.orig ksh-20120801/src/cmd/ksh93/sh/init.c
|
|
|
503c26 |
--- ksh-20120801/src/cmd/ksh93/sh/init.c.orig 2012-05-11 19:19:10.000000000 +0200
|
|
|
503c26 |
+++ ksh-20120801/src/cmd/ksh93/sh/init.c 2012-10-24 15:31:59.659485151 +0200
|
|
|
503c26 |
@@ -1365,6 +1365,18 @@ Shell_t *sh_init(register int argc,regis
|
|
|
503c26 |
}
|
|
|
503c26 |
}
|
|
|
503c26 |
sh_ioinit(shp);
|
|
|
503c26 |
+#ifdef AT_FDCWD
|
|
|
503c26 |
+ shp->pwdfd = sh_diropenat(shp, AT_FDCWD, e_dot, false);
|
|
|
503c26 |
+#else
|
|
|
503c26 |
+ /* Systems without AT_FDCWD/openat() do not use the |dir| argument */
|
|
|
503c26 |
+ shp->pwdfd = sh_diropenat(shp, -1, e_dot, false);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+#ifdef O_SEARCH
|
|
|
503c26 |
+ /* This should _never_ happen, guranteed by design and goat sacrifice */
|
|
|
503c26 |
+ if(shp->pwdfd < 0)
|
|
|
503c26 |
+ errormsg(SH_DICT,ERROR_system(1), "Can't obtain directory fd.");
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
+
|
|
|
503c26 |
/* initialize signal handling */
|
|
|
503c26 |
sh_siginit(shp);
|
|
|
503c26 |
stakinstall(NIL(Stak_t*),nospace);
|
|
|
503c26 |
diff -up ksh-20120801/src/cmd/ksh93/sh/xec.c.orig ksh-20120801/src/cmd/ksh93/sh/xec.c
|
|
|
503c26 |
--- ksh-20120801/src/cmd/ksh93/sh/xec.c.orig 2012-07-23 16:49:32.000000000 +0200
|
|
|
503c26 |
+++ ksh-20120801/src/cmd/ksh93/sh/xec.c 2012-10-24 15:35:02.209539671 +0200
|
|
|
503c26 |
@@ -1348,8 +1348,12 @@ int sh_exec(register const Shnode_t *t,
|
|
|
503c26 |
{
|
|
|
503c26 |
if(!shp->pwd)
|
|
|
503c26 |
path_pwd(shp,0);
|
|
|
503c26 |
- if(shp->pwd)
|
|
|
503c26 |
- stat(".",&statb);
|
|
|
503c26 |
+#ifndef O_SEARCH
|
|
|
503c26 |
+ else if (shp->pwdfd>=0)
|
|
|
503c26 |
+ fstat(shp->pwdfd,&statb);
|
|
|
503c26 |
+ else if (shp->pwd)
|
|
|
503c26 |
+ stat(e_dot,&statb);
|
|
|
503c26 |
+#endif
|
|
|
503c26 |
sfsync(NULL);
|
|
|
503c26 |
share = sfset(sfstdin,SF_SHARE,0);
|
|
|
503c26 |
sh_onstate(SH_STOPOK);
|
|
|
503c26 |
@@ -1428,14 +1432,32 @@ int sh_exec(register const Shnode_t *t,
|
|
|
503c26 |
sh_offstate(SH_NOFORK);
|
|
|
503c26 |
if(!(nv_isattr(np,BLT_ENV)))
|
|
|
503c26 |
{
|
|
|
503c26 |
- if(shp->pwd)
|
|
|
503c26 |
+#ifdef O_SEARCH
|
|
|
503c26 |
+ while((fchdir(shp->pwdfd) < 0) && errno==EINTR)
|
|
|
503c26 |
+ errno = 0;
|
|
|
503c26 |
+#else
|
|
|
503c26 |
+ if(shp->pwd || (shp->pwdfd >= 0))
|
|
|
503c26 |
{
|
|
|
503c26 |
struct stat stata;
|
|
|
503c26 |
stat(".",&stata);
|
|
|
503c26 |
/* restore directory changed */
|
|
|
503c26 |
if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
|
|
|
503c26 |
- chdir(shp->pwd);
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ /* chdir for directories on HSM/tapeworms may take minutes */
|
|
|
503c26 |
+ int err=errno;
|
|
|
503c26 |
+ if(shp->pwdfd >= 0)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ while((fchdir(shp->pwdfd) < 0) && errno==EINTR)
|
|
|
503c26 |
+ errno = err;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ else
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ while((chdir(shp->pwd) < 0) && errno==EINTR)
|
|
|
503c26 |
+ errno = err;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ }
|
|
|
503c26 |
}
|
|
|
503c26 |
+#endif /* O_SEARCH */
|
|
|
503c26 |
sh_offstate(SH_STOPOK);
|
|
|
503c26 |
if(share&SF_SHARE)
|
|
|
503c26 |
sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
|
|
|
503c26 |
diff -up ksh-20120801/src/lib/libast/features/common.orig ksh-20120801/src/lib/libast/features/common
|
|
|
503c26 |
--- ksh-20120801/src/lib/libast/features/common.orig 2011-12-12 20:55:33.000000000 +0100
|
|
|
503c26 |
+++ ksh-20120801/src/lib/libast/features/common 2012-10-24 15:54:35.433885131 +0200
|
|
|
503c26 |
@@ -463,6 +463,66 @@ typ uintptr_t stdint.h inttypes.h no{
|
|
|
503c26 |
typedef unsigned _ast_int4_t uintptr_t;
|
|
|
503c26 |
#endif
|
|
|
503c26 |
}end
|
|
|
503c26 |
+typ _Bool = uint8_t
|
|
|
503c26 |
+cat{
|
|
|
503c26 |
+ #if defined(_STDC_C99) || __STDC_VERSION__ >= 199901L
|
|
|
503c26 |
+ #include <stdbool.h>
|
|
|
503c26 |
+ #else
|
|
|
503c26 |
+ #define bool _Bool
|
|
|
503c26 |
+ #define false 0
|
|
|
503c26 |
+ #define true 1
|
|
|
503c26 |
+ #endif
|
|
|
503c26 |
+}end
|
|
|
503c26 |
+tst key __thread -lpthread note{ __thread keyword exists and works with -lpthread }end execute{
|
|
|
503c26 |
+ #include <pthread.h>
|
|
|
503c26 |
+
|
|
|
503c26 |
+ #define INITIAL 1
|
|
|
503c26 |
+ #define LOOP 100
|
|
|
503c26 |
+
|
|
|
503c26 |
+ static __thread int specific = INITIAL;
|
|
|
503c26 |
+ static int global = 0;
|
|
|
503c26 |
+
|
|
|
503c26 |
+ static void* worker(void* arg)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ int k;
|
|
|
503c26 |
+ int v;
|
|
|
503c26 |
+ v = (int)(arg - 0);
|
|
|
503c26 |
+ for (k = 0; k < LOOP; ++k)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ specific += v;
|
|
|
503c26 |
+ usleep(1);
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ if (specific != (INITIAL + LOOP * v))
|
|
|
503c26 |
+ global = 1;
|
|
|
503c26 |
+ return 0;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ int main()
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ pthread_t th[2];
|
|
|
503c26 |
+
|
|
|
503c26 |
+ if (pthread_create(&th[0], 0, worker, (void*)0 + 5) ||
|
|
|
503c26 |
+ pthread_create(&th[1], 0, worker, (void*)0 + 7))
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ NOTE("pthread_create failed");
|
|
|
503c26 |
+ return 1;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ pthread_join(th[0], 0);
|
|
|
503c26 |
+ pthread_join(th[1], 0);
|
|
|
503c26 |
+ if (global)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ NOTE("__thread variable not thread specific");
|
|
|
503c26 |
+ return 1;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ if (specific != INITIAL)
|
|
|
503c26 |
+ {
|
|
|
503c26 |
+ NOTE("main __thread variable changed by another thread");
|
|
|
503c26 |
+ return 1;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+ return 0;
|
|
|
503c26 |
+ }
|
|
|
503c26 |
+}end no{
|
|
|
503c26 |
+ #define __thread /* __thread keyword does not exist or does not work with -lpthread */
|
|
|
503c26 |
+}end
|
|
|
503c26 |
|
|
|
503c26 |
tst - -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{
|
|
|
503c26 |
#if _STD_ && _hdr_stdarg
|