00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2.1 of the GNU Lesser General Public License 00007 as published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 #pragma ident "@(#) libf/pxf/pxfexecve.c 92.1 06/29/99 11:36:06" 00038 00039 #include <errno.h> 00040 #include <liberrno.h> 00041 #include <fortran.h> 00042 #include <string.h> 00043 #include <malloc.h> 00044 #include <unistd.h> 00045 00046 extern char *_fc_acopy(_fcd f); 00047 00048 /* 00049 * PXFEXECVE -- execute a new process image file using new environment 00050 * variables 00051 * (section 3.1.2 of Posix 1003.9-1992) 00052 * 00053 * Synopsis: 00054 * SUBROUTINE PXFEXECVE (PATH,LENPATH,ARGV,LENARGV,IARGC, 00055 * + ENV,LENENV,IENVC,IERROR) 00056 * INTEGER LENPATH,IARGC,LENARGV(0:IARGC-1),LENENV,IENVC,IERROR 00057 * CHARACTER*(*) PATH,ARGV(0:IARGC-1),ENV(IENVC) 00058 * 00059 * Function description: 00060 * The routine PXFEXECVE uses the execve(2) system call to replace the 00061 * current process image with a new process image. The environment 00062 * variables are not inherited from the calling process image. 00063 * The environment variables for the new process image are specified by 00064 * the ENV argument. 00065 * 00066 * Description of arguments: 00067 * PATH is an input character variable or array element containing 00068 * the pathname of the new process image file. 00069 * 00070 * LENPATH is an input integer variable for the length of PATH. If 00071 * LENPATH is zero, trailing blanks are removed. 00072 * 00073 * ARGV is an input array of character strings. ARGV contains the 00074 * arguments to be passed to the new process image. 00075 * 00076 * LENARGV is an input array of intergers. Each element in LENARGV 00077 * contains the length of the corresponding character 00078 * string in ARGV. If an element in LENARGV is zero, the 00079 * corresponding element in ARGV will have all trailing 00080 * blanks stripped. 00081 * 00082 * IARGC is an input integer variable. IARGC contains the number of 00083 * arguments to pass to the new process image. 00084 * 00085 * ENV is an input array of character strings. ENV contains the 00086 * environment variables for the new process image. 00087 * 00088 * LENENV is an input array of integers. Each element in LENENV 00089 * contains the length of the corresponding character 00090 * string in ENV. IF an element in LENENV is zero, the 00091 * corresponding element in ENV will have all trailing 00092 * blanks stripped. 00093 * 00094 * IENVC is an input integer variable. IENVC contains the number of 00095 * environment variables for the new process image. 00096 * 00097 * IERROR is an output integer variable that will contain 00098 * the status: 00099 * 00100 * zero - PXFEXECVE was unsuccessful. 00101 * 00102 * nonzero - PXFEXECVE was not successful. 00103 * 00104 * PXFEXECVE may return any of the following error 00105 * values: 00106 * 00107 * EACCES If the new process file is not a regular file, 00108 * the new process image file mode denies execution 00109 * permission, or search permission is denied for 00110 * a directory listed in the new process image 00111 * file's path prefix. 00112 * 00113 * ENOENT If one or more components of the new process 00114 * image file's path name do not exist. 00115 * 00116 * ENOEXEC If the new process image file has the 00117 * appropriate access permission but an invalid 00118 * magic number in its header. 00119 * 00120 * ENOMEM If the memory needed to create structures used 00121 * by PXFEXECVE could not be allocated. 00122 * 00123 * EINVAL If LENPATH < 0 or LENPATH > LEN(PATH), any 00124 * element of LENARGV, or any element of LENENV is 00125 * less than zero or greater than the length of the 00126 * corresponding element in ARGV. 00127 * 00128 * UNICOS 9 only errors: 00129 * 00130 * E2BIG If the number of bytes in ARGV is greater than 00131 * the system-imposed limit of ARG_MAX found in 00132 * <limits.h>. 00133 * 00134 * EDMOFF If the process image file is offline, and 00135 * the data migration facility is not configured 00136 * in the system. 00137 * 00138 * EFAULT If the new process image file is not as long as 00139 * indicated by the size values in it header. 00140 * 00141 * ENOMEM If the new process requires more memory than is 00142 * allowed by the system-imposed maximum MAXMEM. 00143 * 00144 * EOFFLIN If the process image file is offline, and 00145 * automatic file retrieval is disabled. 00146 * 00147 * EOFLNDD If the file is offline, and the data management 00148 * daemon is not currently executing. 00149 * 00150 * EOFLNNR If the file is offline, and it is currently 00151 * unretrievable. 00152 * 00153 * IRIX 6.2 only errors: 00154 * 00155 * E2BIG If the number of bytes in the new process's argument 00156 * list is greater than the system-imposed limit 00157 * {ARG_MAX} [see sysconf(2), intro(2), and limits.h]. 00158 * The argument list limit is the sum of the size of 00159 * the argument list plus the size of the environment's 00160 * exported shell variables. 00161 * 00162 * E2BIG If the number of bytes in the first line of an 00163 * interpreter file is greater than 256 bytes. 00164 * 00165 * EAGAIN If there is not enough memory. 00166 * 00167 * ELIBACC If the required shared library does not have 00168 * execute permission. 00169 * 00170 * ELIBEXEC If PATH points to a shared library. 00171 * 00172 * ELIBMAX If the required number of shared libraries 00173 * exceeds the system imposed maximum {SHLIB_MAX) 00174 * [see intro(2)]. 00175 * 00176 * ELOOP If too many symbolic links were encountered in 00177 * translating PATH. 00178 * 00179 * ENAMETOOLONG If the length of PATH exceeds PATH_MAX found 00180 * in <limits.h>, or the length of a path 00181 * component exceeds NAME_MAX found in <limits.h> 00182 * while POSIX_NO_TRUNC is in effect. 00183 * 00184 * ENOEXEC If the executable process image file has badly 00185 * formed header information or the requested 00186 * virtual addresses are not available. 00187 * 00188 * ENOMEM If the new process image requires more virtual 00189 * space than is allowed either by the 00190 * system-imposed maximum or the process imposed 00191 * maximum PROCSIZE_MAX [see getrlimit(2) and 00192 * intro(2)]. 00193 * 00194 * EPERM If a non-superuser tries to execute a setuid 00195 * file which belongs to some other user and the 00196 * file system in which then file resides has 00197 * been mounted with the nosuid option [see 00198 * fstab(4)], or if a non-superuser attempts to 00199 * execute a setuid or setgid shell script with 00200 * a uid or gid which is different than the user's 00201 * effective uid/gid, and the configured value for 00202 * nosuidshells is non-zero (the default) [see 00203 * intro(2) and lboot(1M)]. 00204 * 00205 */ 00206 00207 #ifdef _UNICOS 00208 void 00209 PXFEXECVE( 00210 #else 00211 void 00212 _PXFEXECVE( 00213 #endif 00214 _fcd PATH, 00215 _f_int *LENPATH, 00216 _fcd ARGV, /* packed array of fortran strings */ 00217 _f_int *LENARGV, 00218 _f_int *IARGC, 00219 _fcd ENV, /* packed array of fortran strings */ 00220 _f_int *LENENV, 00221 _f_int *IENVC, 00222 _f_int *IERROR 00223 ) 00224 { 00225 char **arg, /* vector of argument strings for execve */ 00226 **env, /* vector of environment strings for execve */ 00227 *cpath, /* file path for executable */ 00228 *cstring_ARGV, /* the C-style string for the ARGV fortran character 00229 descriptor */ 00230 *cstring_ENV; /* the C-style string for the ENV fortran character 00231 descriptor */ 00232 int clenpath, /* equal to *LENPATH, the user defined length of PATH */ 00233 i,j, /* loop counters */ 00234 position, /* current position in the string cstring_ARGV */ 00235 ciargc, /* equal to *IARGC, the number of arguments for execve */ 00236 cienvc, /* equal to *IENVC, the number of environement variables 00237 for execve */ 00238 cstring_lenargv, /* the length of the FCD ARGV. Note: This is the length of 00239 an individual FCD in the array ARGV. */ 00240 cstring_lenenv, /* the length of the FCD ENV. Note: This is the length of 00241 an individual FCD in the array ENV. */ 00242 len; /* length of string to copy from cstring_ARGV or 00243 cstring_ENV to a string in the arg vector of strings 00244 or env vector of strings, respectively. */ 00245 00246 clenpath = *LENPATH; 00247 cstring_lenargv = _fcdlen(ARGV); 00248 ciargc = *IARGC; 00249 cstring_lenenv = _fcdlen(ENV); 00250 cienvc = *IENVC; 00251 00252 00253 /* check for valid path length passed in by user */ 00254 if (clenpath < 0 || clenpath > _fcdlen(PATH)) { 00255 *IERROR = EINVAL; 00256 return; 00257 } else { 00258 if (clenpath == 0) { 00259 /* 00260 * If length is zero, user wants trailing blanks stripped. 00261 * Otherwise, malloc memory and copy the string adding a 00262 * NULL terminator. 00263 */ 00264 cpath = _fc_acopy(PATH); 00265 00266 } else { 00267 00268 cpath = (char *)malloc(clenpath + 1); 00269 if (cpath != NULL) { 00270 memcpy(cpath, _fcdtocp(PATH), clenpath); 00271 cpath[clenpath] = '\0'; 00272 } else { 00273 *IERROR = ENOMEM; 00274 return; 00275 } 00276 00277 } 00278 } 00279 00280 00281 00282 /* check the LENARGV array for proper values before copying ARGV strings */ 00283 i = 0; 00284 while (i < ciargc) { 00285 len = LENARGV[i]; 00286 if (len < 0 || len > cstring_lenargv) { 00287 *IERROR = EINVAL; 00288 free(cpath); 00289 return; 00290 } 00291 i++; 00292 } 00293 00294 /* check the LENENV array for proper values before copying ENV strings */ 00295 i = 0; 00296 while (i < cienvc) { 00297 len = LENENV[i]; 00298 if (len < 0 || len > cstring_lenenv) { 00299 *IERROR = EINVAL; 00300 free(cpath); 00301 return; 00302 } 00303 i++; 00304 } 00305 00306 00307 /* attempt to copy all argument strings from ARGV */ 00308 00309 arg = (char **)calloc(ciargc + 1,sizeof(char *)); 00310 if (arg == NULL) { 00311 *IERROR = ENOMEM; 00312 free(cpath); 00313 return; 00314 } 00315 00316 cstring_ARGV = _fcdtocp(ARGV); 00317 00318 /* malloc the memory for all the strings copy each Fortran string 00319 * into a C-style string */ 00320 for (i = 0, position = 0; i < ciargc; position += cstring_lenargv, i++) { 00321 len = LENARGV[i]; 00322 /* strip off trailing blanks */ 00323 if (len == 0) { 00324 len = cstring_lenargv - 1; 00325 while ((len > 0) && 00326 cstring_ARGV[(i * cstring_lenargv) + len] == ' ') { 00327 len--; 00328 } 00329 len++; 00330 } 00331 if ((arg[i] = (char *)malloc((len+1)*sizeof(char))) == NULL) { 00332 for (; i >= 0; i--) { 00333 free(arg[i]); 00334 } 00335 free(arg); 00336 free(cpath); 00337 *IERROR = ENOMEM; 00338 return; 00339 } 00340 00341 strncpy(arg[i], &cstring_ARGV[position], len); 00342 arg[i][len] = '\0'; 00343 } 00344 00345 00346 /* attempt to copy all environment strings from ENV */ 00347 00348 env = (char **)calloc(cienvc + 1,sizeof(char *)); 00349 if (env == NULL) { 00350 *IERROR = ENOMEM; 00351 for (; i >= 0; i--) { 00352 free(arg[i]); 00353 } 00354 free(arg); 00355 free(env); 00356 free(cpath); 00357 return; 00358 } 00359 00360 cstring_ENV = _fcdtocp(ARGV); 00361 00362 /* malloc the memory for all the strings copy each Fortran string 00363 * into a C-style string */ 00364 for (j = 0, position = 0; j < cienvc; position += cstring_lenenv, j++) { 00365 len = LENENV[j]; 00366 /* strip off trailing blanks */ 00367 if (len == 0) { 00368 len = cstring_lenenv - 1; 00369 while ((len > 0) && 00370 cstring_ENV[(j * cstring_lenenv) + len] == ' ') { 00371 len--; 00372 } 00373 len++; 00374 } 00375 if ((env[j] = (char *)malloc((len+1)*sizeof(char))) == NULL) { 00376 for (; i >= 0; i--) { 00377 free(arg[i]); 00378 } 00379 free(arg); 00380 for (; j >= 0; j--) { 00381 free(env[j]); 00382 } 00383 free(env); 00384 free(cpath); 00385 *IERROR = ENOMEM; 00386 return; 00387 } 00388 00389 strncpy(env[j], &cstring_ENV[position], len); 00390 env[j][len] = '\0'; 00391 } 00392 00393 00394 if (execve(cpath, arg, env) == -1) { 00395 for (i--; i >= 0; i--) { 00396 free(arg[i]); 00397 } 00398 free(arg); 00399 for (; j >= 0; j--) { 00400 free(env[j]); 00401 } 00402 free(env); 00403 free(cpath); 00404 *IERROR = errno; 00405 return; 00406 } 00407 00408 *IERROR = 0; 00409 } 00410 00411 #ifndef _UNICOS 00412 void 00413 pxfexecve_( 00414 char *PATH, 00415 _f_int *LENPATH, 00416 char *ARGV, 00417 _f_int *LENARGV, 00418 _f_int *IARGC, 00419 char *ENV, 00420 _f_int *LENENV, 00421 _f_int *IENVC, 00422 _f_int *IERROR, 00423 _f_int pathlen, 00424 _f_int argvlen, 00425 _f_int envlen 00426 ) 00427 { 00428 _PXFEXECVE( _cptofcd(PATH,pathlen), LENPATH, _cptofcd(ARGV,argvlen), 00429 LENARGV, IARGC, _cptofcd(ENV,envlen), LENENV, IENVC, IERROR); 00430 } 00431 #endif 00432 00433 00434 00435 00436
1.5.6