OLD | NEW |
1 // Copyright (c) 2014 The Native Client Authors. All rights reserved. | 1 // Copyright (c) 2014 The Native Client Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Emulates spawning/waiting process by asking JavaScript to do so. | 5 // Emulates spawning/waiting process by asking JavaScript to do so. |
6 | 6 |
7 // Include quoted spawn.h first so we can build in the presence of an installed | 7 // Include quoted spawn.h first so we can build in the presence of an installed |
8 // copy of nacl-spawn. | 8 // copy of nacl-spawn. |
9 #define IN_NACL_SPAWN_CC | 9 #define IN_NACL_SPAWN_CC |
10 #include "spawn.h" | 10 #include "spawn.h" |
11 | 11 |
12 #include "nacl_main.h" | 12 #include "nacl_main.h" |
13 | 13 |
14 #include <netinet/in.h> | 14 #include <netinet/in.h> |
15 #include <assert.h> | 15 #include <assert.h> |
16 #include <errno.h> | 16 #include <errno.h> |
17 #include <fcntl.h> | 17 #include <fcntl.h> |
18 #include <libgen.h> | 18 #include <libgen.h> |
19 #include <limits.h> | 19 #include <limits.h> |
| 20 #include <locale.h> |
20 #include <irt.h> | 21 #include <irt.h> |
21 #include <irt_dev.h> | 22 #include <irt_dev.h> |
22 #include <netinet/in.h> | 23 #include <netinet/in.h> |
23 #include <setjmp.h> | 24 #include <setjmp.h> |
24 #include <stdint.h> | 25 #include <stdint.h> |
25 #include <stdio.h> | 26 #include <stdio.h> |
26 #include <stdlib.h> | 27 #include <stdlib.h> |
27 #include <string.h> | 28 #include <string.h> |
| 29 #include <sys/mount.h> |
28 #include <sys/socket.h> | 30 #include <sys/socket.h> |
29 #include <sys/stat.h> | 31 #include <sys/stat.h> |
30 #include <sys/types.h> | 32 #include <sys/types.h> |
31 #include <sys/wait.h> | 33 #include <sys/wait.h> |
32 #include <unistd.h> | 34 #include <unistd.h> |
33 | 35 |
34 #include <string> | 36 #include <string> |
35 #include <vector> | 37 #include <vector> |
36 | 38 |
37 #include "ppapi/cpp/instance.h" | 39 #include "ppapi/cpp/instance.h" |
38 #include "ppapi/cpp/var.h" | 40 #include "ppapi/cpp/var.h" |
39 #include "ppapi/cpp/var_array.h" | 41 #include "ppapi/cpp/var_array.h" |
40 #include "ppapi/cpp/var_dictionary.h" | 42 #include "ppapi/cpp/var_dictionary.h" |
41 #include "ppapi_simple/ps_instance.h" | 43 #include "ppapi_simple/ps_instance.h" |
42 | 44 |
43 #include "library_dependencies.h" | 45 #include "library_dependencies.h" |
44 #include "path_util.h" | 46 #include "path_util.h" |
45 | 47 |
46 | 48 |
47 extern char** environ; | 49 extern char** environ; |
48 extern int nacl_spawn_pid; | 50 |
49 extern int nacl_spawn_ppid; | 51 int nacl_spawn_pid; |
| 52 int nacl_spawn_ppid; |
50 | 53 |
51 struct NaClSpawnReply { | 54 struct NaClSpawnReply { |
52 pthread_mutex_t mu; | 55 pthread_mutex_t mu; |
53 pthread_cond_t cond; | 56 pthread_cond_t cond; |
54 | 57 |
55 pp::VarDictionary result; | 58 pp::VarDictionary result; |
56 }; | 59 }; |
57 | 60 |
| 61 |
| 62 // Get an environment variable as an int, or return -1 if the value cannot |
| 63 // be converted to an int. |
| 64 static int getenv_as_int(const char *env) { |
| 65 const char* env_str = getenv(env); |
| 66 if (!env_str) { |
| 67 return -1; |
| 68 } |
| 69 errno = 0; |
| 70 int env_int = strtol(env_str, NULL, 0); |
| 71 if (errno) { |
| 72 return -1; |
| 73 } |
| 74 return env_int; |
| 75 } |
| 76 |
| 77 static int mkdir_checked(const char* dir) { |
| 78 int rtn = mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO); |
| 79 if (rtn != 0) { |
| 80 fprintf(stderr, "mkdir '%s' failed: %s\n", dir, strerror(errno)); |
| 81 } |
| 82 return rtn; |
| 83 } |
| 84 |
| 85 static int do_mount(const char *source, const char *target, |
| 86 const char *filesystemtype, unsigned long mountflags, |
| 87 const void *data) { |
| 88 NACL_LOG("mount[%s] '%s' at '%s'\n", filesystemtype, source, target); |
| 89 return mount(source, target, filesystemtype, mountflags, data); |
| 90 } |
| 91 |
| 92 extern void nacl_setup_env() { |
| 93 umount("/"); |
| 94 do_mount("", "/", "memfs", 0, NULL); |
| 95 |
| 96 // Setup common environment variables, but don't override those |
| 97 // set already by ppapi_simple. |
| 98 setenv("HOME", "/home/user", 0); |
| 99 setenv("PATH", "/bin", 0); |
| 100 setenv("USER", "user", 0); |
| 101 setenv("LOGNAME", "user", 0); |
| 102 |
| 103 const char* home = getenv("HOME"); |
| 104 mkdir_checked("/home"); |
| 105 mkdir_checked(home); |
| 106 mkdir_checked("/tmp"); |
| 107 mkdir_checked("/bin"); |
| 108 mkdir_checked("/etc"); |
| 109 mkdir_checked("/mnt"); |
| 110 mkdir_checked("/mnt/http"); |
| 111 mkdir_checked("/mnt/html5"); |
| 112 |
| 113 const char* data_url = getenv("NACL_DATA_URL"); |
| 114 if (!data_url) |
| 115 data_url = "./"; |
| 116 NACL_LOG("NACL_DATA_URL=%s\n", data_url); |
| 117 |
| 118 const char* mount_flags = getenv("NACL_DATA_MOUNT_FLAGS"); |
| 119 if (!mount_flags) |
| 120 mount_flags = ""; |
| 121 NACL_LOG("NACL_DATA_MOUNT_FLAGS=%s\n", mount_flags); |
| 122 |
| 123 if (do_mount(data_url, "/mnt/http", "httpfs", 0, mount_flags) != 0) { |
| 124 perror("mounting http filesystem at /mnt/http failed"); |
| 125 } |
| 126 |
| 127 if (do_mount("/", "/mnt/html5", "html5fs", 0, "type=PERSISTENT") != 0) { |
| 128 perror("Mounting HTML5 filesystem in /mnt/html5 failed"); |
| 129 } else { |
| 130 mkdir("/mnt/html5/home", 0777); |
| 131 struct stat st; |
| 132 if (stat("/mnt/html5/home", &st) < 0 || !S_ISDIR(st.st_mode)) { |
| 133 perror("Unable to create home directory in persistent storage"); |
| 134 } else { |
| 135 if (do_mount("/home", home, "html5fs", 0, "type=PERSISTENT") != 0) { |
| 136 fprintf(stderr, "Mounting HTML5 filesystem in %s failed.\n", home); |
| 137 } |
| 138 } |
| 139 } |
| 140 |
| 141 if (do_mount("/", "/tmp", "html5fs", 0, "type=TEMPORARY") != 0) { |
| 142 perror("Mounting HTML5 filesystem in /tmp failed"); |
| 143 } |
| 144 |
| 145 /* naclprocess.js sends the current working directory using this |
| 146 * environment variable. */ |
| 147 const char* pwd = getenv("PWD"); |
| 148 if (pwd != NULL) { |
| 149 if (chdir(pwd)) { |
| 150 fprintf(stderr, "chdir() to %s failed: %s\n", pwd, strerror(errno)); |
| 151 } |
| 152 } |
| 153 |
| 154 // Tell the NaCl architecture to /etc/bashrc of mingn. |
| 155 #if defined(__x86_64__) |
| 156 static const char kNaClArch[] = "x86_64"; |
| 157 #elif defined(__i686__) |
| 158 static const char kNaClArch[] = "i686"; |
| 159 #elif defined(__arm__) |
| 160 static const char kNaClArch[] = "arm"; |
| 161 #elif defined(__pnacl__) |
| 162 static const char kNaClArch[] = "pnacl"; |
| 163 #else |
| 164 # error "Unknown architecture" |
| 165 #endif |
| 166 // Set NACL_ARCH with a guess if not set (0 == set if not already). |
| 167 setenv("NACL_ARCH", kNaClArch, 0); |
| 168 // Set NACL_BOOT_ARCH if not inherited from a parent (0 == set if not already |
| 169 // set). This will let us prefer PNaCl if we started with PNaCl (for tests |
| 170 // mainly). |
| 171 setenv("NACL_BOOT_ARCH", kNaClArch, 0); |
| 172 |
| 173 setlocale(LC_CTYPE, ""); |
| 174 |
| 175 nacl_spawn_pid = getenv_as_int("NACL_PID"); |
| 176 nacl_spawn_ppid = getenv_as_int("NACL_PPID"); |
| 177 } |
| 178 |
58 static std::string GetCwd() { | 179 static std::string GetCwd() { |
59 char cwd[PATH_MAX] = "."; | 180 char cwd[PATH_MAX] = "."; |
60 if (!getcwd(cwd, PATH_MAX)) { | 181 if (!getcwd(cwd, PATH_MAX)) { |
61 NACL_LOG("getcwd failed: %s\n", strerror(errno)); | 182 NACL_LOG("getcwd failed: %s\n", strerror(errno)); |
62 assert(0); | 183 assert(0); |
63 } | 184 } |
64 return cwd; | 185 return cwd; |
65 } | 186 } |
66 | 187 |
67 static std::string GetAbsPath(const std::string& path) { | 188 static std::string GetAbsPath(const std::string& path) { |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 return spawnve_impl(P_OVERLAY, path, argv, envp); | 977 return spawnve_impl(P_OVERLAY, path, argv, envp); |
857 } | 978 } |
858 | 979 |
859 int execlpe(const char *path, const char *arg, ...) { /* char* const envp[] */ | 980 int execlpe(const char *path, const char *arg, ...) { /* char* const envp[] */ |
860 VARG_TO_ARGV_ENVP; | 981 VARG_TO_ARGV_ENVP; |
861 // TODO(bradnelson): Limit path resolution to 'p' variants. | 982 // TODO(bradnelson): Limit path resolution to 'p' variants. |
862 return spawnve_impl(P_OVERLAY, path, argv, envp); | 983 return spawnve_impl(P_OVERLAY, path, argv, envp); |
863 } | 984 } |
864 | 985 |
865 }; // extern "C" | 986 }; // extern "C" |
OLD | NEW |