Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
android /platform /bionic /refs/heads/main /. /libc /bionic /exec.cpp
blob: 56544d039057963e8b541ed3aa36d5b3380ae23f [file] [log] [blame]
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]1/*-
2 * Copyright (c) 1991, 1993
3 *The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include<sys/types.h>
31#include<sys/uio.h>
32
33#include<errno.h>
34#include<limits.h>
35#include<paths.h>
36#include<stdarg.h>
37#include<stdio.h>
38#include<stdlib.h>
39#include<string.h>
40#include<unistd.h>
41
Elliott Hughes4d215aa2017-10-18 15:54:56 -0700[diff] [blame]42#include"private/FdPath.h"
Evgenii Stepanov3031a7e2022-05-12 15:50:47 -0700[diff] [blame]43#include"private/__bionic_get_shell_path.h"
Elliott Hughes4d215aa2017-10-18 15:54:56 -0700[diff] [blame]44
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]45extern"C"char** environ;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]46
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]47enum{ExecL,ExecLE,ExecLP};
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]48
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]49template<int variant>
50staticint __execl(constchar* name,constchar* argv0, va_list ap){
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]51// Count the arguments.
52 va_list count_ap;
53 va_copy(count_ap, ap);
54size_t n=1;
55while(va_arg(count_ap,char*)!=nullptr){
56++n;
57}
58 va_end(count_ap);
59
60// Construct the new argv.
61char* argv[n+1];
62 argv[0]=const_cast<char*>(argv0);
63 n=1;
64while((argv[n]= va_arg(ap,char*))!=nullptr){
65++n;
66}
67
68// Collect the argp too.
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]69char** argp=(variant==ExecLE)? va_arg(ap,char**): environ;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]70
71 va_end(ap);
72
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]73return(variant==ExecLP)? execvp(name, argv): execve(name, argv, argp);
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]74}
75
76int execl(constchar* name,constchar* arg,...){
77 va_list ap;
78 va_start(ap, arg);
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]79int result= __execl<ExecL>(name, arg, ap);
Mikhail Lappo13ec1cf2017-03-25 19:02:55 +0100[diff] [blame]80 va_end(ap);
81return result;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]82}
83
84int execle(constchar* name,constchar* arg,...){
85 va_list ap;
86 va_start(ap, arg);
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]87int result= __execl<ExecLE>(name, arg, ap);
Mikhail Lappo13ec1cf2017-03-25 19:02:55 +0100[diff] [blame]88 va_end(ap);
89return result;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]90}
91
92int execlp(constchar* name,constchar* arg,...){
93 va_list ap;
94 va_start(ap, arg);
Elliott Hughesa1b1bfd2020-06-04 08:04:06 -0700[diff] [blame]95int result= __execl<ExecLP>(name, arg, ap);
Mikhail Lappo13ec1cf2017-03-25 19:02:55 +0100[diff] [blame]96 va_end(ap);
97return result;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]98}
99
100int execv(constchar* name,char*const* argv){
101return execve(name, argv, environ);
102}
103
104int execvp(constchar* name,char*const* argv){
105return execvpe(name, argv, environ);
106}
107
Elliott Hughes3c115902016-08-24 19:27:04 -0700[diff] [blame]108staticint __exec_as_script(constchar* buf,char*const* argv,char*const* envp){
109size_t arg_count=1;
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]110while(argv[arg_count]!=nullptr)++arg_count;
111
Elliott Hughes3c115902016-08-24 19:27:04 -0700[diff] [blame]112constchar* script_argv[arg_count+2];
113 script_argv[0]="sh";
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]114 script_argv[1]= buf;
Elliott Hughes3c115902016-08-24 19:27:04 -0700[diff] [blame]115 memcpy(script_argv+2, argv+1, arg_count*sizeof(char*));
Elliott Hughes886370c2019-03-21 21:11:41 -0700[diff] [blame]116return execve(__bionic_get_shell_path(),const_cast<char**>(script_argv), envp);
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]117}
118
119int execvpe(constchar* name,char*const* argv,char*const* envp){
120// Do not allow null name.
121if(name==nullptr||*name=='\0'){
122 errno= ENOENT;
123return-1;
124}
125
126// If it's an absolute or relative path name, it's easy.
Elliott Hughes3c115902016-08-24 19:27:04 -0700[diff] [blame]127if(strchr(name,'/')&& execve(name, argv, envp)==-1){
Elliott Hughes63615062016-08-25 17:40:27 -0700[diff] [blame]128if(errno== ENOEXEC)return __exec_as_script(name, argv, envp);
129return-1;
Elliott Hughes3c115902016-08-24 19:27:04 -0700[diff] [blame]130}
Elliott Hughes1b40aaf2016-08-18 10:11:36 -0700[diff] [blame]131
132// Get the path we're searching.
133constchar* path= getenv("PATH");
134if(path==nullptr) path= _PATH_DEFPATH;
135
136// Make a writable copy.
137size_t len= strlen(path)+1;
138char writable_path[len];
139 memcpy(writable_path, path, len);
140
141bool saw_EACCES=false;
142
143// Try each element of $PATH in turn...
144char* strsep_buf= writable_path;
145constchar* dir;
146while((dir= strsep(&strsep_buf,":"))){
147// It's a shell path: double, leading and trailing colons
148// mean the current directory.
149if(*dir=='\0') dir=const_cast<char*>(".");
150
151size_t dir_len= strlen(dir);
152size_t name_len= strlen(name);
153
154char buf[dir_len+1+ name_len+1];
155 mempcpy(mempcpy(mempcpy(buf, dir, dir_len),"/",1), name, name_len+1);
156
157 execve(buf, argv, envp);
158switch(errno){
159case EISDIR:
160case ELOOP:
161case ENAMETOOLONG:
162case ENOENT:
163case ENOTDIR:
164break;
165case ENOEXEC:
166return __exec_as_script(buf, argv, envp);
167case EACCES:
168 saw_EACCES=true;
169break;
170default:
171return-1;
172}
173}
174if(saw_EACCES) errno= EACCES;
175return-1;
176}
Elliott Hughes4d215aa2017-10-18 15:54:56 -0700[diff] [blame]177
178int fexecve(int fd,char*const* argv,char*const* envp){
179// execveat with AT_EMPTY_PATH (>= 3.19) seems to offer no advantages.
180 execve(FdPath(fd).c_str(), argv, envp);
181if(errno== ENOENT) errno= EBADF;
182return-1;
183}

[8]ページ先頭

©2009-2025 Movatter.jp