diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h index d66821adb..1a577ad11 100644 --- a/src/cmd/ksh93/include/defs.h +++ b/src/cmd/ksh93/include/defs.h @@ -29,8 +29,8 @@ #define defs_h_defined #include -#if !defined(AST_VERSION) || AST_VERSION < 20220101 -#error libast version 20220101 or later is required +#if !defined(AST_VERSION) || AST_VERSION < 20220201 +#error libast version 20220201 or later is required #endif #if !_lib_fork #error In 2021, ksh joined the 21st century and started requiring fork(2). diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c index ab0a802c6..945f34a84 100644 --- a/src/cmd/ksh93/sh/path.c +++ b/src/cmd/ksh93/sh/path.c @@ -147,7 +147,7 @@ static pid_t _spawnveg(const char *path, char* const argv[], char* const envp[], while(1) { sh_stats(STAT_SPAWN); - pid = spawnveg(path,argv,envp,pgid); + pid = spawnveg(path,argv,envp,pgid,job.jobcontrol?job.fd:-1); if(pid>=0 || errno!=EAGAIN) break; } diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index d09a2f2eb..aeb7c3cf1 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -55,6 +55,10 @@ # include #endif +#if _lib_posix_spawn > 1 && _lib_posix_spawn_file_actions_addtcsetpgrp_np +#define _use_ntfork_tcpgrp 1 +#endif + #define SH_NTFORK SH_TIMING #define NV_BLTPFSH NV_ARRAY @@ -1613,7 +1617,11 @@ int sh_exec(register const Shnode_t *t, int flags) fifo_save_ppid = sh.current_pid; #endif #if SHOPT_SPAWN +#if _use_ntfork_tcpgrp + if(com) +#else if(com && !job.jobcontrol) +#endif /* _use_ntfork_tcpgrp */ { parent = sh_ntfork(t,com,&jobid,ntflag); if(parent<0) @@ -3449,7 +3457,8 @@ static void sigreset(int mode) /* * A combined fork/exec for systems with slow fork(). - * Incompatible with job control on interactive shells (job.jobcontrol). + * Incompatible with job control on interactive shells (job.jobcontrol) if + * the system does not support posix_spawn_file_actions_addtcsetpgrp_np(). */ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int flag) { @@ -3461,6 +3470,9 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int flag) char **arge, *path; volatile pid_t grp = 0; Pathcomp_t *pp; +#if _use_ntfork_tcpgrp + volatile int jobwasset=0; +#endif /* _use_ntfork_tcpgrp */ if(flag) { otype = savetype; @@ -3525,8 +3537,21 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int flag) } arge = sh_envgen(); sh.exitval = 0; +#if _use_ntfork_tcpgrp + if(job.jobcontrol) + { + signal(SIGTTIN,SIG_DFL); + signal(SIGTTOU,SIG_DFL); + signal(SIGTSTP,SIG_DFL); + jobwasset++; + } +#endif /* _use_ntfork_tcpgrp */ #ifdef JOBS +#if _use_ntfork_tcpgrp + if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP))) +#else if(sh_isstate(SH_MONITOR) && (otype&FAMP)) +#endif /* _use_ntfork_tcpgrp */ { if((otype&FAMP) || job.curpgid==0) grp = 1; @@ -3587,6 +3612,17 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int flag) sh_popcontext(buffp); if(buffp->olist) free_list(buffp->olist); +#if _use_ntfork_tcpgrp + if(jobwasset) + { + signal(SIGTTIN,SIG_IGN); + signal(SIGTTOU,SIG_IGN); + if(sh_isstate(SH_INTERACTIVE)) + signal(SIGTSTP,SIG_IGN); + else + signal(SIGTSTP,SIG_DFL); + } +#endif /* _use_ntfork_tcpgrp */ if(sigwasset) sigreset(1); /* restore ignored signals */ if(scope) diff --git a/src/lib/libast/comp/spawnveg.c b/src/lib/libast/comp/spawnveg.c index 20f880925..96e29f7f9 100644 --- a/src/lib/libast/comp/spawnveg.c +++ b/src/lib/libast/comp/spawnveg.c @@ -32,12 +32,6 @@ #include -#if _lib_spawnveg - -NoN(spawnveg) - -#else - #if _lib_posix_spawn > 1 /* reports underlying exec() errors */ #include @@ -45,20 +39,22 @@ NoN(spawnveg) #include pid_t -spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) +spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd) { - int err, flags = 0; - pid_t pid; - posix_spawnattr_t attr; + int err, flags = 0; + pid_t pid; + posix_spawnattr_t attr; +#if _lib_posix_spawn_file_actions_addtcsetpgrp_np + posix_spawn_file_actions_t actions; +#endif if (err = posix_spawnattr_init(&attr)) goto nope; #if POSIX_SPAWN_SETSID if (pgid == -1) flags |= POSIX_SPAWN_SETSID; - else #endif - if (pgid) + if (pgid && pgid != -1) flags |= POSIX_SPAWN_SETPGROUP; if (flags && (err = posix_spawnattr_setflags(&attr, flags))) goto bad; @@ -69,13 +65,33 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) if (err = posix_spawnattr_setpgroup(&attr, pgid)) goto bad; } +#if _lib_posix_spawn_file_actions_addtcsetpgrp_np + if (tcfd >= 0) + { + if (err = posix_spawn_file_actions_init(&actions)) + goto bad; + if (err = posix_spawn_file_actions_addtcsetpgrp_np(&actions, tcfd)) + goto fail; + } + if (err = posix_spawn(&pid, path, (tcfd >= 0) ? &actions : NiL, &attr, argv, envv ? envv : environ)) +#else if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ)) +#endif { if ((err != EPERM) || (err = posix_spawn(&pid, path, NiL, NiL, argv, envv ? envv : environ))) - goto bad; + goto fail; } +#if _lib_posix_spawn_file_actions_addtcsetpgrp_np + if (tcfd >= 0) + posix_spawn_file_actions_destroy(&actions); +#endif posix_spawnattr_destroy(&attr); return pid; + fail: +#if _lib_posix_spawn_file_actions_addtcsetpgrp_np + if (tcfd >= 0) + posix_spawn_file_actions_destroy(&actions); +#endif bad: posix_spawnattr_destroy(&attr); nope: @@ -97,8 +113,9 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) #endif pid_t -spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) +spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd) { + NOT_USED(tcfd); #if defined(P_DETACH) return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ); #else @@ -117,10 +134,11 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) */ pid_t -spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) +spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd) { struct inheritance inherit; + NOT_USED(tcfd); inherit.flags = 0; if (pgid) { @@ -154,7 +172,7 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) */ pid_t -spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) +spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd) { #if _lib_fork || _lib_vfork int n; @@ -169,6 +187,7 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) #endif #endif + NOT_USED(tcfd); if (!envv) envv = environ; #if _lib_spawnve @@ -214,11 +233,9 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) #if _lib_tcgetpgrp if (m) tcsetpgrp(2, pgid); -#else -#ifdef TIOCSPGRP +#elif defined(TIOCSPGRP) if (m) ioctl(2, TIOCSPGRP, &pgid); -#endif #endif } execve(path, argv, envv); @@ -289,5 +306,3 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) #endif #endif - -#endif diff --git a/src/lib/libast/features/api b/src/lib/libast/features/api index 5158228fd..edaf10f05 100644 --- a/src/lib/libast/features/api +++ b/src/lib/libast/features/api @@ -1,6 +1,6 @@ iff AST_API -ver ast 20220101 +ver ast 20220201 api ast 20120528 regexec regnexec regrexec regsubexec strgrpmatch diff --git a/src/lib/libast/features/lib b/src/lib/libast/features/lib index 7531b9383..8e42646a1 100644 --- a/src/lib/libast/features/lib +++ b/src/lib/libast/features/lib @@ -36,7 +36,7 @@ lib mount,onexit,opendir,pathconf lib readlink,remove,rename,rewinddir,rindex,rmdir,setlocale lib setpgid,setpgrp,setpgrp2,setreuid,setsid,setuid,sigaction lib sigprocmask,sigsetmask,sigunblock,sigvec,socketpair -lib spawn,spawnve,spawnveg +lib spawn,spawnve lib strchr,strcoll,strdup,strerror,strcasecmp,strncasecmp,strrchr,strstr lib strmode,strxfrm,strftime,swab,symlink,sysconf,sysinfo,syslog lib telldir,tmpnam,tzset,universe,unlink,utime,wctype @@ -343,6 +343,7 @@ tst lib_posix_spawn unistd.h stdlib.h spawn.h -Dfork=______fork note{ posix_spaw _exit(n); } }end +lib posix_spawn_file_actions_addtcsetpgrp_np tst lib_spawn_mode unistd.h stdlib.h note{ first spawn arg is mode and it works }end execute{ #include @@ -642,7 +643,7 @@ tst - output{ printf("\n"); #endif - #if _lib_spawnveg || _lib_posix_spawn || _lib_spawn_mode || _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance || _lib_vfork && _real_vfork + #if _lib_posix_spawn || _lib_spawn_mode || _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance || _lib_vfork && _real_vfork printf("#if !_AST_no_spawnveg\n"); printf("#define _use_spawnveg 1\n"); printf("#endif\n"); diff --git a/src/lib/libast/features/sys b/src/lib/libast/features/sys index 6bab48802..a07334037 100644 --- a/src/lib/libast/features/sys +++ b/src/lib/libast/features/sys @@ -195,7 +195,7 @@ extern setpgid int (pid_t, pid_t) extern setsid pid_t (void) extern setuid int (uid_t) extern sleep unsigned (unsigned int) -extern spawnveg pid_t (const char*, char* const[], char* const[], pid_t) +extern spawnveg pid_t (const char*, char* const[], char* const[], pid_t, int) extern srand void (unsigned int) extern strcasecmp int (const char*, const char*) extern strcat char* (char*, const char*) diff --git a/src/lib/libast/man/spawnveg.3 b/src/lib/libast/man/spawnveg.3 index 7778d82ba..4aa1549a8 100644 --- a/src/lib/libast/man/spawnveg.3 +++ b/src/lib/libast/man/spawnveg.3 @@ -42,7 +42,7 @@ spawnveg \- process spawn with process group and session control .SH SYNOPSIS .L "#include " .sp -.L "int spawnveg(const char* command, char** argv, char** envv, pid_t pgid);" +.L "int spawnveg(const char* command, char** argv, char** envv, pid_t pgid, int tcfd);" .SH DESCRIPTION .L spawnveg combines @@ -81,10 +81,24 @@ The new process becomes a process group leader. .L >1 The new process joins the process group .IR pgid . -.SH CAVEATS +.PP The +.L tcfd +argument is currently only used if the operating system supports the +.I posix_spawn_file_actions_addtcsetpgrp_np +function. +When +.L tcfd +is +.LR >=0 , +spawnveg will set the controlling terminal for the new process to +.IR tcfd . +.SH CAVEATS +If the +.I posix_spawn_file_actions_addtcsetpgrp_np +function is not available, then .L spawnveg -function cannot set the terminal process group. +cannot reliably set the terminal process group. As a result, it is incompatible with job control when used with terminals. Additionally, if the .L POSIX_SPAWN_SETSID diff --git a/src/lib/libast/misc/procopen.c b/src/lib/libast/misc/procopen.c index 2bced4de3..175c9d579 100644 --- a/src/lib/libast/misc/procopen.c +++ b/src/lib/libast/misc/procopen.c @@ -2,7 +2,7 @@ * * * This software is part of the ast package * * Copyright (c) 1985-2012 AT&T Intellectual Property * -* Copyright (c) 2020-2021 Contributors to ksh 93u+m * +* Copyright (c) 2020-2022 Contributors to ksh 93u+m * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -744,7 +744,7 @@ sfsync(sfstderr); if (forked || (flags & PROC_OVERLAY)) execve(path, p, environ); #if _use_spawnveg - else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1) + else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp, -1)) != -1) goto cleanup; #endif if (errno != ENOEXEC) @@ -773,7 +773,7 @@ sfsync(sfstderr); execve(env + 2, p, environ); #if _use_spawnveg else - proc->pid = spawnveg(env + 2, p, environ, proc->pgrp); + proc->pid = spawnveg(env + 2, p, environ, proc->pgrp, -1); #endif cleanup: if (forked)