/* ============ Path search helper
*
* The variable path (passed by reference) should be set to the start
- * of the path before the first call; path_advance will update
- * this value as it proceeds. Successive calls to path_advance will return
+ * of the path before the first call; padvance will update
+ * this value as it proceeds. Successive calls to padvance will return
* the possible path expansions in sequence. If an option (indicated by
* a percent sign) appears in the path entry then the global variable
* pathopt will be set to point to it; otherwise pathopt will be set to
* NULL.
*/
-static const char *pathopt; /* set by path_advance */
+static const char *pathopt; /* set by padvance */
-static char *
-path_advance(const char **path, const char *name)
+static int
+padvance(const char **path, const char *name)
{
const char *p;
char *q;
size_t len;
if (*path == NULL)
- return NULL;
+ return -1;
start = *path;
for (p = start; *p && *p != ':' && *p != '%'; p++)
continue;
*path = p + 1;
else
*path = NULL;
- return stalloc(len);
+ return len;
}
char c;
struct stat statb;
int flags;
+ int len;
flags = cdopt();
dest = *argptr;
if (!*dest)
dest = ".";
path = bltinlookup("CDPATH");
- while (path) {
- c = *path;
- p = path_advance(&path, dest);
+ while (p = path, (len = padvance(&path, dest)) >= 0) {
+ c = *p;
+ p = stalloc(len);
+
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
if (c && c != ':')
flags |= CD_PRINT;
} else {
try_PATH:
e = ENOENT;
- while ((cmdname = path_advance(&path, prog)) != NULL) {
+ while (padvance(&path, argv[0]) >= 0) {
+ cmdname = stackblock();
if (--idx < 0 && pathopt == NULL) {
tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
}
- stunalloc(cmdname);
}
}
idx = cmdp->param.index;
path = pathval();
do {
- name = path_advance(&path, cmdp->cmdname);
- stunalloc(name);
+ padvance(&path, cmdp->cmdname);
} while (--idx >= 0);
+ name = stackblock();
out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
}
p = command;
} else {
do {
- p = path_advance(&path, command);
- stunalloc(p);
+ padvance(&path, command);
} while (--j >= 0);
+ p = stackblock();
}
if (describe_command_verbose) {
out1fmt(" is %s", p);
mpath = mpathset() ? mpathval() : mailval();
new_hash = 0;
for (;;) {
- p = path_advance(&mpath, nullstr);
- if (p == NULL)
+ int len;
+
+ len = padvance(&mpath, nullstr);
+ if (!len)
+ break;
+ p = stackblock();
break;
if (*p == '\0')
continue;
* search for the file, which is necessary to find sub-commands.
*/
static char *
-find_dot_file(char *name)
+find_dot_file(char *basename)
{
char *fullname;
const char *path = pathval();
struct stat statb;
+ int len;
/* don't try this for absolute or relative paths */
- if (strchr(name, '/'))
- return name;
+ if (strchr(basename, '/'))
+ return basename;
- while ((fullname = path_advance(&path, name)) != NULL) {
+ while ((len = padvance(&path, basename)) >= 0) {
+ fullname = stackblock();
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
- /*
- * Don't bother freeing here, since it will
- * be freed by the caller.
- */
- return fullname;
+ /* This will be freed by the caller. */
+ return stalloc(len);
}
- if (fullname != name)
- stunalloc(fullname);
}
/* not found in PATH */
#if ENABLE_ASH_BASH_SOURCE_CURDIR
- return name;
+ return basename;
#else
- ash_msg_and_raise_error("%s: not found", name);
+ ash_msg_and_raise_error("%s: not found", basename);
/* NOTREACHED */
#endif
}
int e;
int updatetbl;
struct builtincmd *bcmd;
+ int len;
/* If name contains a slash, don't use PATH or hash table */
if (strchr(name, '/') != NULL) {
e = ENOENT;
idx = -1;
loop:
- while ((fullname = path_advance(&path, name)) != NULL) {
- stunalloc(fullname);
- /* NB: code below will still use fullname
- * despite it being "unallocated" */
+ while ((len = padvance(&path, name)) >= 0) {
+ fullname = stackblock();
idx++;
if (pathopt) {
if (prefix(pathopt, "builtin")) {
if (!S_ISREG(statb.st_mode))
continue;
if (pathopt) { /* this is a %func directory */
- stalloc(strlen(fullname) + 1);
+ stalloc(len);
/* NB: stalloc will return space pointed by fullname
* (because we don't have any intervening allocations
* between stunalloc above and this stalloc) */