4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
27 * interfaces to exec a command and run it till all loadobjects have
28 * been loaded (rtld sync point).
36 #include <sys/types.h>
39 #include "prb_proc_int.h"
46 #define PRELOAD "LD_PRELOAD"
47 #define LIBPROBE "libtnfprobe.so.1"
53 static prb_status_t
sync_child(int pid
, volatile shmem_msg_t
*smp
,
54 prb_proc_ctl_t
**proc_pp
);
57 * prb_child_create() - this routine instantiates and rendevous with the
58 * target child process. This routine returns an opaque handle for the
62 prb_child_create(const char *cmdname
, char * const *cmdargs
,
63 const char *loption
, const char *libtnfprobe_path
,
64 char * const *envp
, prb_proc_ctl_t
**ret_val
)
68 char executable_name
[PATH_MAX
+ 2];
69 extern char **environ
;
70 char * const * env_to_use
;
71 size_t loptlen
, probepathlen
;
72 volatile shmem_msg_t
*smp
;
74 /* initialize shmem communication buffer to cause child to wait */
75 prbstat
= prb_shmem_init(&smp
);
79 /* fork to create the child process */
81 if (childpid
== (pid_t
)-1) {
82 DBG(perror("prb_child_create: fork failed"));
83 return (prb_status_map(errno
));
89 /* ---- CHILD PROCESS ---- */
91 DBG_TNF_PROBE_1(prb_child_create_1
, "libtnfctl",
92 "sunw%verbosity 1; sunw%debug 'child process created'",
93 tnf_long
, pid
, getpid());
100 /* append libtnfprobe.so to the LD_PRELOAD environment */
101 loptlen
= (loption
) ? strlen(loption
) : 0;
102 /* probepathlen has a "/" added in ("+ 1") */
103 probepathlen
= (libtnfprobe_path
) ?
104 (strlen(libtnfprobe_path
) + 1) : 0;
105 oldenv
= getenv(PRELOAD
);
107 newenv
= (char *)malloc(strlen(PRELOAD
) +
119 (void) strcpy(newenv
, PRELOAD
);
120 (void) strcat(newenv
, "=");
121 (void) strcat(newenv
, oldenv
);
122 (void) strcat(newenv
, " ");
124 (void) strcat(newenv
, libtnfprobe_path
);
125 (void) strcat(newenv
, "/");
127 (void) strcat(newenv
, LIBPROBE
);
129 (void) strcat(newenv
, " ");
130 (void) strcat(newenv
, loption
);
133 newenv
= (char *)malloc(strlen(PRELOAD
) +
142 (void) strcpy(newenv
, PRELOAD
);
143 (void) strcat(newenv
, "=");
145 (void) strcat(newenv
, libtnfprobe_path
);
146 (void) strcat(newenv
, "/");
148 (void) strcat(newenv
, LIBPROBE
);
150 (void) strcat(newenv
, " ");
151 (void) strcat(newenv
, loption
);
154 (void) putenv((char *)newenv
);
155 env_to_use
= environ
;
157 * We don't check the return value of putenv because the
158 * desired libraries might already be in the target, even
159 * if our effort to change the environment fails. We
160 * should continue either way ...
163 /* wait until the parent releases us */
164 (void) prb_shmem_wait(smp
);
166 DBG_TNF_PROBE_1(prb_child_create_2
, "libtnfctl",
168 "sunw%debug 'child process about to exec'",
169 tnf_string
, cmdname
, cmdname
);
172 * make the child it's own process group.
173 * This is so that signals delivered to parent are not
174 * also delivered to child.
177 prbstat
= find_executable(cmdname
, executable_name
);
179 DBG((void) fprintf(stderr
, "prb_child_create: %s\n",
180 prb_status_str(prbstat
)));
181 /* parent waits for exit */
184 if (execve(executable_name
, cmdargs
, env_to_use
) == -1) {
185 DBG(perror("prb_child_create: exec failed"));
192 /* ---- PARENT PROCESS ---- */
193 /* child is waiting for us */
195 prbstat
= sync_child(childpid
, smp
, ret_val
);
200 return (PRB_STATUS_OK
);
205 * interface that registers the address of the debug structure
206 * in the target process. This is where the linker maintains all
207 * the information about the loadobjects
210 prb_dbgaddr(prb_proc_ctl_t
*proc_p
, uintptr_t dbgaddr
)
212 proc_p
->dbgaddr
= dbgaddr
;
216 * continue the child until the run time linker has loaded in all
217 * the loadobjects (rtld sync point)
220 sync_child(int childpid
, volatile shmem_msg_t
*smp
, prb_proc_ctl_t
**proc_pp
)
222 prb_proc_ctl_t
*proc_p
, *oldproc_p
;
223 prb_status_t prbstat
= PRB_STATUS_OK
;
224 prb_status_t tempstat
;
225 prb_proc_state_t pstate
;
227 prbstat
= prb_proc_open(childpid
, proc_pp
);
233 prbstat
= prb_proc_stop(proc_p
);
238 * default is to kill-on-last-close. In case we cannot sync with
239 * target, we don't want the target to continue.
241 prbstat
= prb_proc_setrlc(proc_p
, B_FALSE
);
245 prbstat
= prb_proc_setklc(proc_p
, B_TRUE
);
249 /* REMIND: do we have to wait on SYS_exec also ? */
250 prbstat
= prb_proc_exit(proc_p
, SYS_execve
, PRB_SYS_ADD
);
254 prbstat
= prb_proc_entry(proc_p
, SYS_exit
, PRB_SYS_ADD
);
258 prbstat
= prb_shmem_clear(smp
);
262 prbstat
= prb_proc_cont(proc_p
);
266 prbstat
= prb_proc_wait(proc_p
, B_FALSE
, NULL
);
272 * If we had exec'ed a setuid/setgid program PIOCWSTOP
273 * will return EAGAIN. Reopen the 'fd' and try again.
274 * Read the last section of /proc man page - we reopen first
275 * and then close the old fd.
278 tempstat
= prb_proc_reopen(childpid
, proc_pp
);
281 /* here EACCES means exec'ed a setuid/setgid program */
282 (void) prb_proc_close(oldproc_p
);
286 (void) prb_proc_close(oldproc_p
);
292 prbstat
= prb_shmem_free(smp
);
296 prbstat
= prb_proc_state(proc_p
, &pstate
);
300 if (pstate
.ps_issysexit
&& (pstate
.ps_syscallnum
== SYS_execve
)) {
301 /* expected condition */
302 prbstat
= PRB_STATUS_OK
;
304 prbstat
= prb_status_map(ENOENT
);
308 /* clear old interest mask */
309 prbstat
= prb_proc_exit(proc_p
, 0, PRB_SYS_NONE
);
313 prbstat
= prb_proc_entry(proc_p
, 0, PRB_SYS_NONE
);
317 /* Successful return */
318 return (PRB_STATUS_OK
);
321 (void) prb_proc_close(proc_p
);