PageRenderTime 66ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/pathscale/libf/pxf/pxfexecve.c

https://github.com/somian/Path64
C | 423 lines | 184 code | 37 blank | 202 comment | 41 complexity | 1223ccc2b85c1ed0932c411f8e503edf MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /*
  2. Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved.
  3. Path64 is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation version 2.1
  6. Path64 is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  8. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  9. License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with Path64; see the file COPYING. If not, write to the Free
  12. Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  13. 02110-1301, USA.
  14. Special thanks goes to SGI for their continued support to open source
  15. */
  16. #pragma ident "@(#) libf/pxf/pxfexecve.c 92.1 06/29/99 11:36:06"
  17. #include <errno.h>
  18. #include <liberrno.h>
  19. #include <fortran.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. extern char *_fc_acopy(_fcd f);
  24. /*
  25. * PXFEXECVE -- execute a new process image file using new environment
  26. * variables
  27. * (section 3.1.2 of Posix 1003.9-1992)
  28. *
  29. * Synopsis:
  30. * SUBROUTINE PXFEXECVE (PATH,LENPATH,ARGV,LENARGV,IARGC,
  31. * + ENV,LENENV,IENVC,IERROR)
  32. * INTEGER LENPATH,IARGC,LENARGV(0:IARGC-1),LENENV,IENVC,IERROR
  33. * CHARACTER*(*) PATH,ARGV(0:IARGC-1),ENV(IENVC)
  34. *
  35. * Function description:
  36. * The routine PXFEXECVE uses the execve(2) system call to replace the
  37. * current process image with a new process image. The environment
  38. * variables are not inherited from the calling process image.
  39. * The environment variables for the new process image are specified by
  40. * the ENV argument.
  41. *
  42. * Description of arguments:
  43. * PATH is an input character variable or array element containing
  44. * the pathname of the new process image file.
  45. *
  46. * LENPATH is an input integer variable for the length of PATH. If
  47. * LENPATH is zero, trailing blanks are removed.
  48. *
  49. * ARGV is an input array of character strings. ARGV contains the
  50. * arguments to be passed to the new process image.
  51. *
  52. * LENARGV is an input array of intergers. Each element in LENARGV
  53. * contains the length of the corresponding character
  54. * string in ARGV. If an element in LENARGV is zero, the
  55. * corresponding element in ARGV will have all trailing
  56. * blanks stripped.
  57. *
  58. * IARGC is an input integer variable. IARGC contains the number of
  59. * arguments to pass to the new process image.
  60. *
  61. * ENV is an input array of character strings. ENV contains the
  62. * environment variables for the new process image.
  63. *
  64. * LENENV is an input array of integers. Each element in LENENV
  65. * contains the length of the corresponding character
  66. * string in ENV. IF an element in LENENV is zero, the
  67. * corresponding element in ENV will have all trailing
  68. * blanks stripped.
  69. *
  70. * IENVC is an input integer variable. IENVC contains the number of
  71. * environment variables for the new process image.
  72. *
  73. * IERROR is an output integer variable that will contain
  74. * the status:
  75. *
  76. * zero - PXFEXECVE was unsuccessful.
  77. *
  78. * nonzero - PXFEXECVE was not successful.
  79. *
  80. * PXFEXECVE may return any of the following error
  81. * values:
  82. *
  83. * EACCES If the new process file is not a regular file,
  84. * the new process image file mode denies execution
  85. * permission, or search permission is denied for
  86. * a directory listed in the new process image
  87. * file's path prefix.
  88. *
  89. * ENOENT If one or more components of the new process
  90. * image file's path name do not exist.
  91. *
  92. * ENOEXEC If the new process image file has the
  93. * appropriate access permission but an invalid
  94. * magic number in its header.
  95. *
  96. * ENOMEM If the memory needed to create structures used
  97. * by PXFEXECVE could not be allocated.
  98. *
  99. * EINVAL If LENPATH < 0 or LENPATH > LEN(PATH), any
  100. * element of LENARGV, or any element of LENENV is
  101. * less than zero or greater than the length of the
  102. * corresponding element in ARGV.
  103. *
  104. * UNICOS 9 only errors:
  105. *
  106. * E2BIG If the number of bytes in ARGV is greater than
  107. * the system-imposed limit of ARG_MAX found in
  108. * <limits.h>.
  109. *
  110. * EDMOFF If the process image file is offline, and
  111. * the data migration facility is not configured
  112. * in the system.
  113. *
  114. * EFAULT If the new process image file is not as long as
  115. * indicated by the size values in it header.
  116. *
  117. * ENOMEM If the new process requires more memory than is
  118. * allowed by the system-imposed maximum MAXMEM.
  119. *
  120. * EOFFLIN If the process image file is offline, and
  121. * automatic file retrieval is disabled.
  122. *
  123. * EOFLNDD If the file is offline, and the data management
  124. * daemon is not currently executing.
  125. *
  126. * EOFLNNR If the file is offline, and it is currently
  127. * unretrievable.
  128. *
  129. * IRIX 6.2 only errors:
  130. *
  131. * E2BIG If the number of bytes in the new process's argument
  132. * list is greater than the system-imposed limit
  133. * {ARG_MAX} [see sysconf(2), intro(2), and limits.h].
  134. * The argument list limit is the sum of the size of
  135. * the argument list plus the size of the environment's
  136. * exported shell variables.
  137. *
  138. * E2BIG If the number of bytes in the first line of an
  139. * interpreter file is greater than 256 bytes.
  140. *
  141. * EAGAIN If there is not enough memory.
  142. *
  143. * ELIBACC If the required shared library does not have
  144. * execute permission.
  145. *
  146. * ELIBEXEC If PATH points to a shared library.
  147. *
  148. * ELIBMAX If the required number of shared libraries
  149. * exceeds the system imposed maximum {SHLIB_MAX)
  150. * [see intro(2)].
  151. *
  152. * ELOOP If too many symbolic links were encountered in
  153. * translating PATH.
  154. *
  155. * ENAMETOOLONG If the length of PATH exceeds PATH_MAX found
  156. * in <limits.h>, or the length of a path
  157. * component exceeds NAME_MAX found in <limits.h>
  158. * while POSIX_NO_TRUNC is in effect.
  159. *
  160. * ENOEXEC If the executable process image file has badly
  161. * formed header information or the requested
  162. * virtual addresses are not available.
  163. *
  164. * ENOMEM If the new process image requires more virtual
  165. * space than is allowed either by the
  166. * system-imposed maximum or the process imposed
  167. * maximum PROCSIZE_MAX [see getrlimit(2) and
  168. * intro(2)].
  169. *
  170. * EPERM If a non-superuser tries to execute a setuid
  171. * file which belongs to some other user and the
  172. * file system in which then file resides has
  173. * been mounted with the nosuid option [see
  174. * fstab(4)], or if a non-superuser attempts to
  175. * execute a setuid or setgid shell script with
  176. * a uid or gid which is different than the user's
  177. * effective uid/gid, and the configured value for
  178. * nosuidshells is non-zero (the default) [see
  179. * intro(2) and lboot(1M)].
  180. *
  181. */
  182. #ifdef _UNICOS
  183. void
  184. PXFEXECVE(
  185. #else
  186. void
  187. _PXFEXECVE(
  188. #endif
  189. _fcd PATH,
  190. _f_int *LENPATH,
  191. _fcd ARGV, /* packed array of fortran strings */
  192. _f_int *LENARGV,
  193. _f_int *IARGC,
  194. _fcd ENV, /* packed array of fortran strings */
  195. _f_int *LENENV,
  196. _f_int *IENVC,
  197. _f_int *IERROR
  198. )
  199. {
  200. char **arg, /* vector of argument strings for execve */
  201. **env, /* vector of environment strings for execve */
  202. *cpath, /* file path for executable */
  203. *cstring_ARGV, /* the C-style string for the ARGV fortran character
  204. descriptor */
  205. *cstring_ENV; /* the C-style string for the ENV fortran character
  206. descriptor */
  207. int clenpath, /* equal to *LENPATH, the user defined length of PATH */
  208. i,j, /* loop counters */
  209. position, /* current position in the string cstring_ARGV */
  210. ciargc, /* equal to *IARGC, the number of arguments for execve */
  211. cienvc, /* equal to *IENVC, the number of environement variables
  212. for execve */
  213. cstring_lenargv, /* the length of the FCD ARGV. Note: This is the length of
  214. an individual FCD in the array ARGV. */
  215. cstring_lenenv, /* the length of the FCD ENV. Note: This is the length of
  216. an individual FCD in the array ENV. */
  217. len; /* length of string to copy from cstring_ARGV or
  218. cstring_ENV to a string in the arg vector of strings
  219. or env vector of strings, respectively. */
  220. clenpath = *LENPATH;
  221. cstring_lenargv = _fcdlen(ARGV);
  222. ciargc = *IARGC;
  223. cstring_lenenv = _fcdlen(ENV);
  224. cienvc = *IENVC;
  225. /* check for valid path length passed in by user */
  226. if (clenpath < 0 || clenpath > _fcdlen(PATH)) {
  227. *IERROR = EINVAL;
  228. return;
  229. } else {
  230. if (clenpath == 0) {
  231. /*
  232. * If length is zero, user wants trailing blanks stripped.
  233. * Otherwise, malloc memory and copy the string adding a
  234. * NULL terminator.
  235. */
  236. cpath = _fc_acopy(PATH);
  237. } else {
  238. cpath = (char *)malloc(clenpath + 1);
  239. if (cpath != NULL) {
  240. memcpy(cpath, _fcdtocp(PATH), clenpath);
  241. cpath[clenpath] = '\0';
  242. } else {
  243. *IERROR = ENOMEM;
  244. return;
  245. }
  246. }
  247. }
  248. /* check the LENARGV array for proper values before copying ARGV strings */
  249. i = 0;
  250. while (i < ciargc) {
  251. len = LENARGV[i];
  252. if (len < 0 || len > cstring_lenargv) {
  253. *IERROR = EINVAL;
  254. free(cpath);
  255. return;
  256. }
  257. i++;
  258. }
  259. /* check the LENENV array for proper values before copying ENV strings */
  260. i = 0;
  261. while (i < cienvc) {
  262. len = LENENV[i];
  263. if (len < 0 || len > cstring_lenenv) {
  264. *IERROR = EINVAL;
  265. free(cpath);
  266. return;
  267. }
  268. i++;
  269. }
  270. /* attempt to copy all argument strings from ARGV */
  271. arg = (char **)calloc(ciargc + 1,sizeof(char *));
  272. if (arg == NULL) {
  273. *IERROR = ENOMEM;
  274. free(cpath);
  275. return;
  276. }
  277. cstring_ARGV = _fcdtocp(ARGV);
  278. /* malloc the memory for all the strings copy each Fortran string
  279. * into a C-style string */
  280. for (i = 0, position = 0; i < ciargc; position += cstring_lenargv, i++) {
  281. len = LENARGV[i];
  282. /* strip off trailing blanks */
  283. if (len == 0) {
  284. len = cstring_lenargv - 1;
  285. while ((len > 0) &&
  286. cstring_ARGV[(i * cstring_lenargv) + len] == ' ') {
  287. len--;
  288. }
  289. len++;
  290. }
  291. if ((arg[i] = (char *)malloc((len+1)*sizeof(char))) == NULL) {
  292. for (; i >= 0; i--) {
  293. free(arg[i]);
  294. }
  295. free(arg);
  296. free(cpath);
  297. *IERROR = ENOMEM;
  298. return;
  299. }
  300. strncpy(arg[i], &cstring_ARGV[position], len);
  301. arg[i][len] = '\0';
  302. }
  303. /* attempt to copy all environment strings from ENV */
  304. env = (char **)calloc(cienvc + 1,sizeof(char *));
  305. if (env == NULL) {
  306. *IERROR = ENOMEM;
  307. for (; i >= 0; i--) {
  308. free(arg[i]);
  309. }
  310. free(arg);
  311. free(env);
  312. free(cpath);
  313. return;
  314. }
  315. cstring_ENV = _fcdtocp(ARGV);
  316. /* malloc the memory for all the strings copy each Fortran string
  317. * into a C-style string */
  318. for (j = 0, position = 0; j < cienvc; position += cstring_lenenv, j++) {
  319. len = LENENV[j];
  320. /* strip off trailing blanks */
  321. if (len == 0) {
  322. len = cstring_lenenv - 1;
  323. while ((len > 0) &&
  324. cstring_ENV[(j * cstring_lenenv) + len] == ' ') {
  325. len--;
  326. }
  327. len++;
  328. }
  329. if ((env[j] = (char *)malloc((len+1)*sizeof(char))) == NULL) {
  330. for (; i >= 0; i--) {
  331. free(arg[i]);
  332. }
  333. free(arg);
  334. for (; j >= 0; j--) {
  335. free(env[j]);
  336. }
  337. free(env);
  338. free(cpath);
  339. *IERROR = ENOMEM;
  340. return;
  341. }
  342. strncpy(env[j], &cstring_ENV[position], len);
  343. env[j][len] = '\0';
  344. }
  345. if (execve(cpath, arg, env) == -1) {
  346. for (i--; i >= 0; i--) {
  347. free(arg[i]);
  348. }
  349. free(arg);
  350. for (; j >= 0; j--) {
  351. free(env[j]);
  352. }
  353. free(env);
  354. free(cpath);
  355. *IERROR = errno;
  356. return;
  357. }
  358. *IERROR = 0;
  359. }
  360. #ifndef _UNICOS
  361. void
  362. pxfexecve_(
  363. char *PATH,
  364. _f_int *LENPATH,
  365. char *ARGV,
  366. _f_int *LENARGV,
  367. _f_int *IARGC,
  368. char *ENV,
  369. _f_int *LENENV,
  370. _f_int *IENVC,
  371. _f_int *IERROR,
  372. _f_int pathlen,
  373. _f_int argvlen,
  374. _f_int envlen
  375. )
  376. {
  377. _PXFEXECVE( _cptofcd(PATH,pathlen), LENPATH, _cptofcd(ARGV,argvlen),
  378. LENARGV, IARGC, _cptofcd(ENV,envlen), LENENV, IENVC, IERROR);
  379. }
  380. #endif