/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#define __EXTENSIONS__
#include <string.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <zone.h>
#include "libproc.h"
#include "Pcontrol.h"
/*
* Pexecname.c - Way too much code to attempt to derive the full pathname of
* the executable file from a process handle, be it dead or alive.
*/
/*
* Once we've computed a cwd and a relative path, we use try_exec() to
* form an absolute path, call resolvepath() on it, and then let the
* caller's function do the final confirmation.
*/
static int
{
int i;
if (path[0] != '/')
else
buf[i] = '\0';
}
return (0); /* resolvepath failed */
}
/*
* The Pfindexec function contains the logic for the executable name dance.
* The caller provides a possible executable name or likely directory (the
* aout parameter), and a function which is responsible for doing any
* final confirmation on the executable pathname once a possible full
* pathname has been chosen.
*/
char *
{
char *p = path, *q;
if (P->execname)
return (P->execname); /* Already found */
errno = 0; /* Set to zero so we can tell if stat() failed */
/*
* First try: use the provided default value, if it is not a directory.
* If the aout parameter turns out to be a directory, this is
* interpreted as the directory to use as an alternate cwd for
* our subsequent attempts to locate the executable.
*/
goto found;
else
aout = ".";
aout = ".";
/*
* At this point 'aout' is either "." or an alternate cwd. We use
* realpath(3c) to turn this into a full pathname free of ".", "..",
* and symlinks. If this fails for some reason, fall back to "."
*/
/*
* Second try: read the string pointed to by the AT_SUN_EXECNAME
* auxv element, saved when the program was exec'd. If the full
* pathname try_exec() forms fails, try again using just the
* basename appended to our cwd. If that also fails, and the process
* is in a zone, try again with the zone path instead of our cwd.
*/
goto found;
goto found;
if (getzoneid() == GLOBAL_ZONEID &&
sizeof (zpath)) != -1) {
/*
* try_exec() only combines its cwd and path arguments
* if path is relative; but in our case even an absolute
* path inside a zone is a relative path from the global
* zone perspective. So we turn a non-global zone's
* absolute path into a relative path here before
* calling try_exec().
*/
goto found;
}
}
/*
* Third try: try using the first whitespace-separated token
* saved in the psinfo_t's pr_psargs (the initial value of argv[0]).
*/
*p = '\0';
goto found;
goto found;
}
/*
* Fourth try: read the string pointed to by argv[0] out of the
* stack in the process's address space.
*/
goto found;
goto found;
}
/*
* Fifth try: read the process's $PATH environment variable and
* search each directory named there for the name matching pr_fname.
*/
/*
* If the name from pr_psargs contains pr_fname as its
* leading string, then accept the name from pr_psargs
* because more bytes are saved there. Otherwise use
* pr_fname because this gives us new information.
*/
*p = '\0';
/*
* Now iterate over the $PATH elements, trying to form
* an executable pathname with each one.
*/
if (*p != '/')
continue; /* Ignore anything relative */
goto found;
}
}
return (NULL);
return (P->execname);
}
/*
* Callback function for Pfindexec(). We return a match if we can stat the
* suggested pathname and confirm its device and inode number match our
*/
static int
{
}
/*
* Return the full pathname for the executable file. If the process handle is
* a core file, we've already tried our best to get the executable name.
* Otherwise, we make an attempt using Pfindexec().
*/
char *
{
return (buf);
}
int ret;
/*
* Try to get the path information first.
*/
return (buf);
}
/*
* Stat the executable file so we can compare Pfindexec's
* suggestions to the actual device and inode number.
*/
return (NULL);
/*
* Attempt to figure out the current working directory of the
* target process. This only works if the target process has
* not changed its current directory since it was exec'd.
*/
}
return (NULL);
}