Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[half-patch][feedback?] exec compatibility

ksh93's manual-page states:

----------------------------8< cut here >8------------------------------
       - exec [ -c ] [ -a name ] [ arg ... ]
              If  arg is given, the command specified by the arguments is exe-
              cuted in place of this shell without  creating  a  new  process.
              The -c option causes the environment to be cleared before apply-
              ing variable assignments associated with  the  exec  invocation.
              The  -a  option causes name rather than the first arg, to become
              argv[0] for the new process.  Input/output arguments may  appear
              and affect the current process.  If arg is not given, the effect
              of this command is to modify file descriptors as  prescribed  by
              the  input/output  redirection  list.   In  this  case, any file
              descriptor numbers greater than 2  that  are  opened  with  this
              mechanism are closed when invoking another program.
----------------------------8< cut here >8------------------------------

Bash implements this, and the -l option too.

I suspect that a lot of the time, these exec options will be used for
remote commands, as a recent poster encountered, and being incompatible
with bash will just cause growing pain for users in this special case.
(I'm not setting out to dup bash).

I've started implementing the compatibility; I've documented all three,
implemented -l and -a.  I'd like feedback before continuing:

 (1) is this worth doing at all, or should I stop?
 (2) to implement -c, is it best to change the interface to execute()?
     Are there any compability issues with modules if I do that?  I was
     thinking of changing the second parameter from "dash" to "flags"
     and using the same BINF_ option-space, but with a BINF_CLEARENV
     flag added; just clear the env _after_ checking for ARGV0 and it
     looks valid to me.
 (3) am I going about all this the wrong way?

diff -ur zsh-head/Doc/Zsh/builtins.yo zsh-exec/Doc/Zsh/builtins.yo
--- zsh-head/Doc/Zsh/builtins.yo	Fri Mar 23 10:14:05 2007
+++ zsh-exec/Doc/Zsh/builtins.yo	Sun Apr 29 21:17:32 2007
@@ -375,7 +375,24 @@
 Read the arguments as input to the shell and execute the resulting
 command in the current shell process.
+item(tt(exec) [ tt(-cl) ] [ tt(-a) var(argv0) ] var(simple command))(
+The simple command argument is run in place of the current process,
+rather than as a sub-process.  The shell does not fork and is replaced.
+The shell does not invoke tT(TRAPEXIT), nor does it source tt(zlogout)
+The options are provided for compatibility with other shells.
+The tt(-c) flag clears the environment.
+The tt(-l) flag is equivalent to the tt(-) precommand modifier, to
+treat the replacement command as a login shell; the command is executed
+with a tt(-) prepended to its argv[0] string.  This flag has no effect
+if used together with the tt(-a) option.
+The tt(-a) option is used to explicitly specify the argv[0] string to be
+used by the replacement command and is directly equivalent to putting
+the tt($ARGV0) variable into the environment.
+See also noderef(Precommand Modifiers).
 item(tt(exit) [ var(n) ])(
 Exit the shell with the exit status specified by var(n); if none
diff -ur zsh-head/Src/exec.c zsh-exec/Src/exec.c
--- zsh-head/Src/exec.c	Wed Feb 14 00:21:58 2007
+++ zsh-exec/Src/exec.c	Sun Apr 29 22:17:20 2007
@@ -2026,6 +2026,49 @@
 		if (!strcmp(next, "--"))
 		     uremnode(args, firstnode(args));   
+	    if (cflags & BINF_EXEC && nextnode(firstnode(args))) {
+		/* check for compatibility options to exec builtin */
+		char *next = (char *) getdata(nextnode(firstnode(args)));
+		char *cmdopt, *exec_argv0 = NULL;
+		while (next && *next == '-' && strlen(next) >= 2) {
+		    uremnode(args, firstnode(args));
+		    if (!strcmp(next, "--"))
+			break;
+		    for (cmdopt = &next[1]; *cmdopt; ++cmdopt) {
+			switch (*cmdopt) {
+			case 'a':
+			    exec_argv0 = (char *) getdata(nextnode(firstnode(args)));
+			    if (!exec_argv0) {
+				zerr("exec flag -a requires a parameter");
+				errflag = lastval = 1;
+				return;
+			    }
+			    uremnode(args, firstnode(args));
+			    break;
+			case 'c':
+			    zerr("exec -c not implemented");
+			    break;
+			case 'l':
+			    cflags |= BINF_DASH;
+			    break;
+			default:
+			    zerr("unknown exec flag -%c", *cmdopt);
+			    errflag = lastval = 1;
+			    return;
+			}
+		    }
+		    next = (char *) getdata(nextnode(firstnode(args)));
+		}
+		if (exec_argv0) {
+		    char *str, *s;
+		    size_t sz = strlen(exec_argv0);
+		    str = s = zalloc(5 + 1 + sz + 1);
+		    strcpy(s, "ARGV0=");
+		    s+=6;
+		    strcpy(s, exec_argv0);
+		    zputenv(str);
+		}
+	    }
 	    uremnode(args, firstnode(args));
 	    hn = NULL;
 	    if ((cflags & BINF_COMMAND) && unset(POSIXBUILTINS))

Messages sorted by: Reverse Date, Date, Thread, Author