isaexec.c revision 7257d1b4d25bfac0c802847390e98a464fd787ac
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * CDDL HEADER START
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * The contents of this file are subject to the terms of the
908f1e1388f616898b4e515d343c0414f2a6472esd * Common Development and Distribution License (the "License").
908f1e1388f616898b4e515d343c0414f2a6472esd * You may not use this file except in compliance with the License.
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
908f1e1388f616898b4e515d343c0414f2a6472esd * or http://www.opensolaris.org/os/licensing.
908f1e1388f616898b4e515d343c0414f2a6472esd * See the License for the specific language governing permissions
908f1e1388f616898b4e515d343c0414f2a6472esd * and limitations under the License.
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * When distributing Covered Code, include this CDDL HEADER in each
908f1e1388f616898b4e515d343c0414f2a6472esd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
908f1e1388f616898b4e515d343c0414f2a6472esd * If applicable, add the following below this CDDL HEADER, with the
908f1e1388f616898b4e515d343c0414f2a6472esd * fields enclosed by brackets "[]" replaced with your own identifying
908f1e1388f616898b4e515d343c0414f2a6472esd * information: Portions Copyright [yyyy] [name of copyright owner]
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * CDDL HEADER END
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
908f1e1388f616898b4e515d343c0414f2a6472esd * Use is subject to license terms.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd#pragma ident "%Z%%M% %I% %E% SMI"
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd#pragma weak _isaexec = isaexec
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd#include "lint.h"
908f1e1388f616898b4e515d343c0414f2a6472esd#include <sys/types.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <sys/systeminfo.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <unistd.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <string.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <errno.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <limits.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <stdarg.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <stdlib.h>
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * This is a utility routine to allow wrapper programs to simply
908f1e1388f616898b4e515d343c0414f2a6472esd * implement the isalist exec algorithms. See PSARC/1997/220.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esdint
908f1e1388f616898b4e515d343c0414f2a6472esdisaexec(const char *execname, char *const *argv, char *const *envp)
908f1e1388f616898b4e515d343c0414f2a6472esd{
908f1e1388f616898b4e515d343c0414f2a6472esd const char *fname;
908f1e1388f616898b4e515d343c0414f2a6472esd char *isalist;
908f1e1388f616898b4e515d343c0414f2a6472esd char *pathname;
908f1e1388f616898b4e515d343c0414f2a6472esd char *str;
908f1e1388f616898b4e515d343c0414f2a6472esd char *lasts;
908f1e1388f616898b4e515d343c0414f2a6472esd size_t isalen = 255; /* wild guess */
908f1e1388f616898b4e515d343c0414f2a6472esd size_t len;
908f1e1388f616898b4e515d343c0414f2a6472esd int saved_errno;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /*
908f1e1388f616898b4e515d343c0414f2a6472esd * Extract the isalist(5) for userland from the kernel.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd isalist = malloc(isalen);
908f1e1388f616898b4e515d343c0414f2a6472esd do {
908f1e1388f616898b4e515d343c0414f2a6472esd long ret = sysinfo(SI_ISALIST, isalist, isalen);
908f1e1388f616898b4e515d343c0414f2a6472esd if (ret == -1l) {
908f1e1388f616898b4e515d343c0414f2a6472esd free(isalist);
908f1e1388f616898b4e515d343c0414f2a6472esd errno = ENOENT;
908f1e1388f616898b4e515d343c0414f2a6472esd return (-1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd if (ret > isalen) {
908f1e1388f616898b4e515d343c0414f2a6472esd isalen = ret;
908f1e1388f616898b4e515d343c0414f2a6472esd isalist = realloc(isalist, isalen);
908f1e1388f616898b4e515d343c0414f2a6472esd } else
908f1e1388f616898b4e515d343c0414f2a6472esd break;
908f1e1388f616898b4e515d343c0414f2a6472esd } while (isalist != NULL);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd if (isalist == NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd /*
908f1e1388f616898b4e515d343c0414f2a6472esd * Then either a malloc or a realloc failed.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd errno = EAGAIN;
return (-1);
}
/*
* Allocate a full pathname buffer. The sum of the lengths of the
* 'path' and isalist strings is guaranteed to be big enough.
*/
len = strlen(execname) + isalen;
if ((pathname = malloc(len)) == NULL) {
free(isalist);
errno = EAGAIN;
return (-1);
}
/*
* Break the exec name into directory and file name components.
*/
(void) strcpy(pathname, execname);
if ((str = strrchr(pathname, '/')) != NULL) {
*++str = '\0';
fname = execname + (str - pathname);
} else {
fname = execname;
*pathname = '\0';
}
len = strlen(pathname);
/*
* For each name in the isa list, look for an executable file
* with the given file name in the corresponding subdirectory.
* If it's there, exec it. If it's not there, or the exec
* fails, then run the next version ..
*/
str = strtok_r(isalist, " ", &lasts);
saved_errno = ENOENT;
do {
(void) strcpy(pathname + len, str);
(void) strcat(pathname + len, "/");
(void) strcat(pathname + len, fname);
if (access(pathname, X_OK) == 0) {
/*
* File exists and is marked executable. Attempt
* to execute the file from the subdirectory,
* using the user-supplied argv and envp.
*/
(void) execve(pathname, argv, envp);
/*
* If we failed to exec because of a temporary
* resource shortage, it's better to let our
* caller handle it (free memory, sleep for a while,
* or whatever before retrying) rather than drive
* on to run the "less capable" version.
*/
if (errno == EAGAIN) {
saved_errno = errno;
break;
}
}
} while ((str = strtok_r(NULL, " ", &lasts)) != NULL);
free(pathname);
free(isalist);
errno = saved_errno;
return (-1);
}