/* ACK expects the caller to pop the hidden pointer on struct return. */
#define BYTES_TO_POP_ON_STRUCT_RETURN
+/*
+ * ACK doesn't move the last argument of a variadic arguments function
+ * anywhere, once it's on the stack as a function parameter. Thus, it is
+ * possible to make strong assumption on the immutability of the stack
+ * layout and use the address of that argument as the start of an array.
+ *
+ * If you're curious, just look at lib/libc/posix/_execl*.c ;-)
+ */
+
+#define FUNC_ARGS_ARRAY 1
+
#endif /* _MINIX_COMPILER_ACK_H */
#define _MINIX_COMPILER_H
/*===========================================================================*
- * Compiler overrides *
+ * Compiler overrides *
*===========================================================================*/
/* ACK */
#ifdef __ACK__
#endif
/*===========================================================================*
- * Default values *
+ * Default values *
*===========================================================================*/
/*
* cdecl calling convention expects the callee to pop the hidden pointer on
#define BYTES_TO_POP_ON_STRUCT_RETURN $4
#endif
+/*
+ * cdecl calling convention requires to push arguments on the stack in a
+ * reverse order to easily support variadic arguments. Thus, instead of
+ * using the proper stdarg.h macros (that nowadays are
+ * compiler-dependant), it may be tempting to directly take the address of
+ * the last argument and considering it as the start of an array. This is
+ * a shortcut that avoid looping to get all the arguments as the CPU
+ * already pushed them on the stack before the call to the function.
+ *
+ * Unfortunately, such an assumption is strictly compiler-dependant and
+ * compilers are free to move the last argument on the stack, as a local
+ * variable, and return the address of the location where the argument was
+ * stored, if asked for. This will break things as the rest of the array's
+ * argument are stored elsewhere (typically, a couple of words above the
+ * location where the argument was stored).
+ *
+ * Conclusion: if unsure on what the compiler may do, do not make any
+ * assumption and use the right (typically compiler-dependant) macros.
+ */
+
+#ifndef FUNC_ARGS_ARRAY
+#define FUNC_ARGS_ARRAY 0
+#endif
+
#endif /* _MINIX_COMPILER_H */
#else /* __GNUC__ >= 2 */
-#ifndef __sparc__
-#define va_start(AP, LASTARG) \
- (AP = ((char *) __builtin_next_arg ()))
-#else
-#define va_start(AP, LASTARG) \
- (__builtin_saveregs (), AP = ((char *) __builtin_next_arg ()))
-#endif
-
-void va_end (va_list); /* Defined in libgcc.a */
-#define va_end(AP)
-
-#define va_arg(AP, TYPE) \
- (AP = ((char *) (AP)) += __va_rounded_size (TYPE), \
- *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#define va_start(ap, last) __builtin_va_start((ap), (last))
+#define va_arg(ap, type) __builtin_va_arg((ap), type)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_copy(dest, src) __builtin_va_copy((dest), (src))
#endif /* __GNUC__ >= 2 */
-/* execl() - execute Author: Kees J. Bot
- * 21 Jan 1994
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+
#define execl _execl
#define execve _execve
#include <unistd.h>
+#include <minix/compiler.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <lib.h>
extern char * const **_penviron; /* The default environment. */
-int execl(const char *path, const char *arg1, ...)
+int
+execl(const char *path, const char *arg, ...)
/* execl("/bin/sh", "sh", "-c", "example", (char *) 0); */
{
- /* Assumption: The C-implementation for this machine pushes
+#if FUNC_ARGS_ARRAY
+ /*
+ * Assumption: The C-implementation for this machine pushes
* function arguments downwards on the stack making a perfect
* argument array. Luckily this is almost always so.
+ *
+ * execl() - execute Author: Kees J. Bot, 21 Jan 1994
+ */
+ return execve(path, (char * const *) &arg, *_penviron);
+#else
+ /*
+ * Indeed, GCC (4.4.1) behaves similarly to ACK. Nonetheless, let's
+ * stay the safe side. LLVM (llvm-gcc) doesn't make the aforementioned
+ * assumption.
*/
- return execve(path, (char * const *) &arg1, *_penviron);
+ va_list ap;
+ char **argv;
+ int i;
+
+ va_start(ap, arg);
+ for (i = 2; va_arg(ap, char *) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ if ((argv = alloca(i * sizeof (char *))) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ va_start(ap, arg);
+ argv[0] = __UNCONST(arg);
+ for (i = 1; (argv[i] = va_arg(ap, char *)) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ return execve(path, (char * const *) argv, *_penviron);
+#endif
}
+
-/* execle() - execute with a custom environment Author: Kees J. Bot
- * 21 Jan 1994
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#define nil 0
+
#define execle _execle
#define execve _execve
#include <unistd.h>
+#include <minix/compiler.h>
+#include <errno.h>
#include <stdarg.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <lib.h>
int execle(const char *path, const char *arg1, ...)
/* execle("/bin/sh", "sh", "-c", "example", (char *) 0, my_env_array); */
{
- char * const * envp;
- va_list ap;
-
+ char * const * envp;
+ va_list ap;
+#if FUNC_ARGS_ARRAY
+ /*
+ * execle() - execute with a custom environment
+ * Author: Kees J. Bot, 21 Jan 1994
+ */
va_start(ap, arg1);
/* Find the end of the argument array. */
- if (arg1 != nil) while (va_arg(ap, const char *) != nil) {}
+ if (arg1 != NULL) while (va_arg(ap, const char *) != NULL) {}
envp = va_arg(ap, char * const *);
va_end(ap);
return execve(path, (char * const *) &arg1, envp);
+#else
+ char **argv;
+ int i;
+
+ va_start(ap, arg1);
+ for (i = 2; va_arg(ap, char *) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ if ((argv = alloca(i * sizeof (char *))) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ va_start(ap, arg1);
+ argv[0] = __UNCONST(arg1);
+ for (i = 1; (argv[i] = va_arg(ap, char *)) != NULL; i++)
+ continue;
+ envp = va_arg(ap, char **);
+ va_end(ap);
+
+ return execve(path, (char * const *)argv, envp);
+#endif
}
-/* execlp() - execute with PATH search Author: Kees J. Bot
- * 22 Jan 1994
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+
#define execlp _execlp
#define execvp _execvp
#include <unistd.h>
+#include <minix/compiler.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <lib.h>
int execlp(const char *file, const char *arg1, ...)
/* execlp("sh", "sh", "-c", "example", (char *) 0); */
{
+#if FUNC_ARGS_ARRAY
+ /*
+ * execlp() - execute with PATH search
+ * Author: Kees J. Bot, 22 Jan 1994
+ */
return execvp(file, (char * const *) &arg1);
+#else
+ va_list ap;
+ char **argv;
+ int i;
+
+ va_start(ap, arg1);
+ for (i = 2; va_arg(ap, char *) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ if ((argv = alloca(i * sizeof (char *))) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ va_start(ap, arg1);
+ argv[0] = __UNCONST(arg1);
+ for (i = 1; (argv[i] = va_arg(ap, char *)) != NULL; i++)
+ continue;
+ va_end(ap);
+
+ return execvp(file, (char * const *)argv);
+#endif
}
#define _MINIX_SOURCE
-#define nil 0
#define execve _execve
#define sbrk _sbrk
#include <lib.h>
string_off= 0; /* Offset to start of the strings. */
argc= 0; /* Argument count. */
- for (ap= argv; *ap != nil; ap++) {
+ for (ap= argv; *ap != NULL; ap++) {
n = sizeof(*ap) + strlen(*ap) + 1;
frame_size+= n;
if (frame_size < n) ov= 1;
argc++;
}
- for (ep= envp; *ep != nil; ep++) {
+ for (ep= envp; *ep != NULL; ep++) {
n = sizeof(*ep) + strlen(*ep) + 1;
frame_size+= n;
if (frame_size < n) ov= 1;
sp = frame + string_off;
/* Load the argument vector and strings. */
- for (ap= argv; *ap != nil; ap++) {
+ for (ap= argv; *ap != NULL; ap++) {
*vp++= (char *) (sp - frame);
n= strlen(*ap) + 1;
memcpy(sp, *ap, n);
sp+= n;
}
- *vp++= nil;
+ *vp++= NULL;
/* Load the environment vector and strings. */
- for (ep= envp; *ep != nil; ep++) {
+ for (ep= envp; *ep != NULL; ep++) {
*vp++= (char *) (sp - frame);
n= strlen(*ep) + 1;
memcpy(sp, *ep, n);
sp+= n;
}
- *vp++= nil;
+ *vp++= NULL;
/* Padding. */
while (sp < frame + frame_size) *sp++= 0;
#define _MINIX_SOURCE
-#define nil 0
#define execve _execve
#define execvp _execvp
#define sbrk _sbrk
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
+#include <lib.h>
extern char * const **_penviron; /* The default environment. */
size_t full_size;
int err= ENOENT; /* Error return on failure. */
- if (strchr(file, '/') != nil || (path= getenv("PATH")) == nil)
+ if (strchr(file, '/') != NULL || (path= getenv("PATH")) == NULL)
path= "";
/* Compute the maximum length the full name may have, and align. */