| |
1 /* |
| |
2 ** openpkg.c -- OpenPKG Frontend |
| |
3 ** Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/> |
| |
4 ** |
| |
5 ** This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
| |
6 ** All rights reserved. Licenses which grant limited permission to use, |
| |
7 ** copy, modify and distribute this software are available from the |
| |
8 ** OpenPKG GmbH. |
| |
9 ** |
| |
10 ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
| |
11 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| |
12 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| |
13 ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
| |
14 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| |
15 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| |
16 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| |
17 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| |
18 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| |
19 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| |
20 ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| |
21 ** SUCH DAMAGE. |
| |
22 */ |
| |
23 |
| |
24 /* program information */ |
| |
25 #define LICENSE \ |
| |
26 "Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>\n" \ |
| |
27 "\n" \ |
| |
28 "This software is property of the OpenPKG GmbH, DE MUC HRB 160208.\n" \ |
| |
29 "All rights reserved. Licenses which grant limited permission to use,\n" \ |
| |
30 "copy, modify and distribute this software are available from the\n" \ |
| |
31 "OpenPKG GmbH.\n" \ |
| |
32 "\n" \ |
| |
33 "THIS SOFTWARE IS PROVIDED \"AS IS\" AND ANY EXPRESSED OR IMPLIED\n" \ |
| |
34 "WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" \ |
| |
35 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n" \ |
| |
36 "IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR\n" \ |
| |
37 "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" \ |
| |
38 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" \ |
| |
39 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n" \ |
| |
40 "USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n" \ |
| |
41 "ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n" \ |
| |
42 "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\n" \ |
| |
43 "OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n" \ |
| |
44 "SUCH DAMAGE.\n" |
| |
45 |
| |
46 /* system includes */ |
| |
47 #include <stdio.h> |
| |
48 #include <stdlib.h> |
| |
49 #include <stdarg.h> |
| |
50 #include <string.h> |
| |
51 #include <sys/types.h> |
| |
52 #include <sys/param.h> |
| |
53 #include <sys/stat.h> |
| |
54 #include <pwd.h> |
| |
55 #include <grp.h> |
| |
56 #include <unistd.h> |
| |
57 #include <errno.h> |
| |
58 |
| |
59 /* sanity check compilation */ |
| |
60 #ifndef OPENPKG_PREFIX |
| |
61 #error OpenPKG instance prefix not defined |
| |
62 #endif |
| |
63 #ifndef OPENPKG_SUSR |
| |
64 #error OpenPKG super user not defined |
| |
65 #endif |
| |
66 #ifndef OPENPKG_MUSR |
| |
67 #error OpenPKG management user not defined |
| |
68 #endif |
| |
69 |
| |
70 /* platform specifics */ |
| |
71 #if defined(OPENPKG_PLATFORM_FREEBSD) || \ |
| |
72 defined(OPENPKG_PLATFORM_NETBSD) || \ |
| |
73 defined(OPENPKG_PLATFORM_OPENBSD) || \ |
| |
74 defined(OPENPKG_PLATFORM_SUNOS) || \ |
| |
75 defined(OPENPKG_PLATFORM_LINUX) || \ |
| |
76 defined(OPENPKG_PLATFORM_DARWIN) || \ |
| |
77 defined(OPENPKG_PLATFORM_AIX) || \ |
| |
78 defined(OPENPKG_PLATFORM_IRIX) || \ |
| |
79 defined(OPENPKG_PLATFORM_HPUX) |
| |
80 #define HAVE_INITGROUPS |
| |
81 #endif |
| |
82 |
| |
83 /* global debug enable flag */ |
| |
84 static int debug_enable = 0; |
| |
85 |
| |
86 /* helper function: emulate (still less portable) setenv(3) via (more portable) putenv(3) */ |
| |
87 static int my_setenv(const char *name, const char *value, int overwrite) |
| |
88 { |
| |
89 char *pair; |
| |
90 |
| |
91 if (overwrite == 0 && getenv(name) != NULL) |
| |
92 return 0; |
| |
93 if ((pair = malloc(strlen(name) + 1 + strlen(value) + 1)) == NULL) |
| |
94 return -1; |
| |
95 strcpy(pair, name); |
| |
96 strcat(pair, "="); |
| |
97 strcat(pair, value); |
| |
98 putenv(pair); |
| |
99 return 0; |
| |
100 } |
| |
101 |
| |
102 /* helper function for printing a warning message */ |
| |
103 static void warn(const char *fmt, ...) |
| |
104 { |
| |
105 va_list ap; |
| |
106 |
| |
107 va_start(ap, fmt); |
| |
108 fprintf(stderr, "openpkg:WARNING: "); |
| |
109 vfprintf(stderr, fmt, ap); |
| |
110 fprintf(stderr, "\n"); |
| |
111 va_end(ap); |
| |
112 return; |
| |
113 } |
| |
114 |
| |
115 /* helper function for printing a debug message */ |
| |
116 static void debug(const char *fmt, ...) |
| |
117 { |
| |
118 va_list ap; |
| |
119 |
| |
120 va_start(ap, fmt); |
| |
121 if (debug_enable) { |
| |
122 fprintf(stderr, "openpkg:DEBUG: "); |
| |
123 vfprintf(stderr, fmt, ap); |
| |
124 fprintf(stderr, "\n"); |
| |
125 } |
| |
126 va_end(ap); |
| |
127 return; |
| |
128 } |
| |
129 |
| |
130 /* helper function for printing a fatal message and exit */ |
| |
131 static void fatal(const char *fmt, ...) |
| |
132 { |
| |
133 va_list ap; |
| |
134 |
| |
135 va_start(ap, fmt); |
| |
136 fprintf(stderr, "openpkg:ERROR: "); |
| |
137 vfprintf(stderr, fmt, ap); |
| |
138 fprintf(stderr, "\n"); |
| |
139 va_end(ap); |
| |
140 exit(1); |
| |
141 return; |
| |
142 } |
| |
143 |
| |
144 /* adjust process privileges */ |
| |
145 static void adjust_privileges(uid_t uid, gid_t gid, int login) |
| |
146 { |
| |
147 struct passwd *pw; |
| |
148 char cwd[MAXPATHLEN]; |
| |
149 |
| |
150 /* optionally emulate a more complete login */ |
| |
151 if (login) { |
| |
152 /* determine information about user id */ |
| |
153 if ((pw = getpwuid(uid)) == NULL) |
| |
154 fatal("unable to resolve user id \"%d\": %s", uid, strerror(errno)); |
| |
155 |
| |
156 /* reset some essential environment variables */ |
| |
157 my_setenv("LOGNAME", pw->pw_name, 1); |
| |
158 my_setenv("USER", pw->pw_name, 1); |
| |
159 my_setenv("SHELL", pw->pw_shell, 1); |
| |
160 my_setenv("HOME", pw->pw_dir, 1); |
| |
161 |
| |
162 #ifdef HAVE_INITGROUPS |
| |
163 /* initialize complete group access list */ |
| |
164 if (initgroups(pw->pw_name, pw->pw_gid) == -1) |
| |
165 fatal("failed to initialize access group list via initgroups(3): %s", strerror(errno)); |
| |
166 #endif |
| |
167 } |
| |
168 |
| |
169 /* switch to group id (first) */ |
| |
170 if (setgid(gid) == -1) |
| |
171 fatal("failed to set group id via setgid(2): %s", strerror(errno)); |
| |
172 |
| |
173 /* switch to user id (second) */ |
| |
174 if (setuid(uid) == -1) |
| |
175 fatal("failed to set user id via setuid(2): %s", strerror(errno)); |
| |
176 |
| |
177 /* in case the current working directory is NO LONGER accessible, |
| |
178 try to switch to the home directory of the target identity to |
| |
179 prevent failures in subsequently called programs (e.g. GNU bash) */ |
| |
180 if (login) { |
| |
181 if (getcwd(cwd, sizeof(cwd)) == NULL) { |
| |
182 warn("current working directory is no longer accessible -- switching to \"%s\"", pw->pw_dir); |
| |
183 if (chdir(pw->pw_dir) == -1) |
| |
184 fatal("unable to chdir(2) to \"%s\": %s", pw->pw_dir, strerror(errno)); |
| |
185 } |
| |
186 } |
| |
187 |
| |
188 return; |
| |
189 } |
| |
190 |
| |
191 /* check whether caller is an explictly configured management user */ |
| |
192 static int check_whether_is_manager(uid_t my_uid, gid_t my_gid, uid_t m_uid, gid_t m_gid) |
| |
193 { |
| |
194 char buf[1024]; |
| |
195 char *username; |
| |
196 char *groupname; |
| |
197 char *filename; |
| |
198 struct stat sb; |
| |
199 char *cp; |
| |
200 FILE *fp; |
| |
201 struct passwd *pw; |
| |
202 struct group *gr; |
| |
203 int i; |
| |
204 int ok_uid; |
| |
205 int ok_gid; |
| |
206 int is_manager; |
| |
207 |
| |
208 is_manager = 0; |
| |
209 |
| |
210 /* path to the managers configuration file */ |
| |
211 filename = OPENPKG_PREFIX "/etc/openpkg/managers"; |
| |
212 |
| |
213 /* check permissions of file */ |
| |
214 if (stat(filename, &sb) == -1) { |
| |
215 warn("unable to determine information about configuration" |
| |
216 " file \"%s\": %s -- ignoring file", filename, strerror(errno)); |
| |
217 return 0; |
| |
218 } |
| |
219 if (sb.st_uid != m_uid) { |
| |
220 warn("invalid owner user id %d (expected %d) on configuration" |
| |
221 " file \"%s\" -- ignoring file", sb.st_uid, m_uid, filename); |
| |
222 return 0; |
| |
223 } |
| |
224 if (sb.st_gid != m_gid) { |
| |
225 warn("invalid owner group id %d (expected %d) on configuration" |
| |
226 " file \"%s\" -- ignoring file", sb.st_gid, m_gid, filename); |
| |
227 return 0; |
| |
228 } |
| |
229 if (sb.st_mode != (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH)) { |
| |
230 warn("invalid permissions on configuration" |
| |
231 " file \"%s\" -- ignoring file", filename); |
| |
232 return 0; |
| |
233 } |
| |
234 |
| |
235 /* parse configuration file */ |
| |
236 if ((fp = fopen(filename, "r")) == NULL) { |
| |
237 warn("unable to open configuration file \"%s\": %s -- ignoring file", filename, strerror(errno)); |
| |
238 return 0; |
| |
239 } |
| |
240 while ((cp = fgets(buf, sizeof(buf), fp)) != NULL) { |
| |
241 /* parse entry as "<username>[:<groupname>]" where both |
| |
242 <username> and <groupname> can be set and default to "*" |
| |
243 to indicate an arbitrary user or group */ |
| |
244 if ((i = strlen(buf)) == 0) { |
| |
245 warn("unexpected empty buffer during parsing of configuration file \"%\"", filename); |
| |
246 break; |
| |
247 } |
| |
248 if (i >= sizeof(buf)) { |
| |
249 warn("unexpected buffer overflow during parsing of configuration file \"%\"", filename); |
| |
250 break; |
| |
251 } |
| |
252 if (buf[i-1] != '\r' && buf[i-1] != '\n') { |
| |
253 warn("unexpected non-newline-terminated line found during parsing of configuration file \"%\"", filename); |
| |
254 break; |
| |
255 } |
| |
256 username = buf + strspn(buf, " \t"); |
| |
257 cp = username + strcspn(username, " \t#\r\n"); |
| |
258 *cp = '\0'; |
| |
259 if (username[0] == '#' || username[0] == '\r' || username[0] == '\n' || username[0] == '\0') |
| |
260 continue; |
| |
261 groupname = "*"; |
| |
262 if ((cp = strchr(username, ':')) != NULL) { |
| |
263 *cp++ = '\0'; |
| |
264 groupname = cp; |
| |
265 } |
| |
266 debug("parsing result: username=\"%s\" groupname=\"%s\"", username, groupname); |
| |
267 |
| |
268 /* check whether UID is ok */ |
| |
269 ok_uid = 0; |
| |
270 if (strcmp(username, "*") == 0) |
| |
271 ok_uid = 1; |
| |
272 else { |
| |
273 if ((pw = getpwnam(username)) == NULL) { |
| |
274 warn("invalid username \"%s\" in \"%s\"", username, filename); |
| |
275 continue; |
| |
276 } |
| |
277 if (pw->pw_uid == my_uid) |
| |
278 ok_uid = 1; |
| |
279 } |
| |
280 |
| |
281 /* check whether GID is ok */ |
| |
282 ok_gid = 0; |
| |
283 if (strcmp(groupname, "*") == 0) |
| |
284 ok_gid = 1; |
| |
285 else { |
| |
286 if ((gr = getgrnam(groupname)) == NULL) { |
| |
287 warn("invalid groupname \"%s\" in \"%s\"", groupname, filename); |
| |
288 continue; |
| |
289 } |
| |
290 if (gr->gr_gid == my_gid) |
| |
291 ok_gid = 1; |
| |
292 } |
| |
293 |
| |
294 /* if both UID and GID are ok, user is manager */ |
| |
295 debug("matching: username ok = %s, groupname ok = %s", ok_uid ? "yes" : "no", ok_gid ? "yes" : "no"); |
| |
296 if (ok_uid && ok_gid) { |
| |
297 is_manager = 1; |
| |
298 break; |
| |
299 } |
| |
300 } |
| |
301 fclose(fp); |
| |
302 return is_manager; |
| |
303 } |
| |
304 |
| |
305 /* check whether command requires super-user privileges */ |
| |
306 static int check_whether_require_superuser(int argc, char *argv[]) |
| |
307 { |
| |
308 int require_superuser; |
| |
309 int i, j; |
| |
310 |
| |
311 require_superuser = 0; |
| |
312 if (argc > 1 && strcmp(argv[1], "rpm") == 0) { |
| |
313 for (i = 2; i < argc; i++) { |
| |
314 if (strcmp(argv[i], "--") == 0) |
| |
315 break; |
| |
316 else if ( strcmp(argv[i], "--erase") == 0 |
| |
317 || strcmp(argv[i], "--freshen") == 0 |
| |
318 || strcmp(argv[i], "--install") == 0 |
| |
319 || strcmp(argv[i], "--upgrade") == 0 |
| |
320 || strcmp(argv[i], "--import") == 0 |
| |
321 || strcmp(argv[i], "--initdb") == 0 |
| |
322 || strcmp(argv[i], "--rebuilddb") == 0 |
| |
323 || strcmp(argv[i], "--db-build") == 0 |
| |
324 || strcmp(argv[i], "--db-rebuild") == 0 |
| |
325 || strcmp(argv[i], "--db-cleanup") == 0 |
| |
326 || strcmp(argv[i], "--db-fixate") == 0 |
| |
327 || strcmp(argv[i], "--setperms") == 0 |
| |
328 || strcmp(argv[i], "--setugids") == 0) { |
| |
329 require_superuser = 1; |
| |
330 break; |
| |
331 } |
| |
332 else if ( argv[i][0] == '-' |
| |
333 && argv[i][1] != '-' |
| |
334 && argv[i][1] != 'b' |
| |
335 && argv[i][1] != 't' |
| |
336 ) { |
| |
337 for (j = 1; argv[i][j] != '\0'; j++) { |
| |
338 if ( ( argv[i][j] == 'q' |
| |
339 || argv[i][j] == 'K') |
| |
340 && argv[i][j+1] != '\0') { |
| |
341 j++; |
| |
342 continue; |
| |
343 } |
| |
344 else if ( argv[i][j] == 'i' |
| |
345 || argv[i][j] == 'U' |
| |
346 || argv[i][j] == 'F' |
| |
347 || argv[i][j] == 'V' |
| |
348 || argv[i][j] == 'e') { |
| |
349 require_superuser = 1; |
| |
350 break; |
| |
351 } |
| |
352 } |
| |
353 if (require_superuser) |
| |
354 break; |
| |
355 } |
| |
356 } |
| |
357 } |
| |
358 else if (argc > 1 && strcmp(argv[1], "rc") == 0) { |
| |
359 require_superuser = 1; |
| |
360 for (i = 2; i < argc; i++) { |
| |
361 if (strcmp(argv[i], "--") == 0) |
| |
362 break; |
| |
363 else if ( strcmp(argv[i], "-p") == 0 |
| |
364 || strcmp(argv[i], "--print") == 0 |
| |
365 || strcmp(argv[i], "-e") == 0 |
| |
366 || strcmp(argv[i], "--eval") == 0 |
| |
367 || strcmp(argv[i], "-q") == 0 |
| |
368 || strcmp(argv[i], "--query") == 0 |
| |
369 || strcmp(argv[i], "-c") == 0 |
| |
370 || strcmp(argv[i], "--config") == 0) { |
| |
371 require_superuser = 0; |
| |
372 break; |
| |
373 } |
| |
374 } |
| |
375 } |
| |
376 return require_superuser; |
| |
377 } |
| |
378 |
| |
379 /* main program */ |
| |
380 int main(int argc, char **argv, char **envp) |
| |
381 { |
| |
382 int keep_original_privileges; |
| |
383 int is_manager; |
| |
384 int require_superuser; |
| |
385 uid_t my_uid, my_euid; |
| |
386 gid_t my_gid, my_egid; |
| |
387 uid_t m_uid; |
| |
388 gid_t m_gid; |
| |
389 uid_t s_uid; |
| |
390 gid_t s_gid; |
| |
391 struct passwd *pw; |
| |
392 struct group *gr; |
| |
393 int dry_run; |
| |
394 int license; |
| |
395 |
| |
396 /* parse command line options */ |
| |
397 license = 0; |
| |
398 dry_run = 0; |
| |
399 keep_original_privileges = 0; |
| |
400 if (argc <= 0) |
| |
401 abort(); |
| |
402 argv++; argc--; |
| |
403 while (argc > 0) { |
| |
404 if (argv[0][0] != '-') |
| |
405 break; |
| |
406 else if (strcmp(argv[0], "--") == 0) { |
| |
407 argv++; argc--; |
| |
408 break; |
| |
409 } |
| |
410 else if (strcmp(argv[0], "--license") == 0) { |
| |
411 license = 1; |
| |
412 argv++; argc--; |
| |
413 continue; |
| |
414 } |
| |
415 else if (strcmp(argv[0], "--debug") == 0) { |
| |
416 debug_enable = 1; |
| |
417 argv++; argc--; |
| |
418 continue; |
| |
419 } |
| |
420 else if (strcmp(argv[0], "--dry-run") == 0) { |
| |
421 dry_run = 1; |
| |
422 argv++; argc--; |
| |
423 continue; |
| |
424 } |
| |
425 else if (strcmp(argv[0], "--keep-privileges") == 0) { |
| |
426 keep_original_privileges = 1; |
| |
427 argv++; argc--; |
| |
428 continue; |
| |
429 } |
| |
430 break; |
| |
431 } |
| |
432 argv--; argc++; |
| |
433 |
| |
434 /* display stand-alone license information */ |
| |
435 if (license) { |
| |
436 fprintf(stdout, "%s", LICENSE); |
| |
437 exit(0); |
| |
438 } |
| |
439 |
| |
440 /* determine our current real and effective user/group ids */ |
| |
441 my_uid = getuid(); |
| |
442 my_gid = getgid(); |
| |
443 my_euid = geteuid(); |
| |
444 my_egid = getegid(); |
| |
445 if ((pw = getpwuid(my_uid)) == NULL) |
| |
446 fatal("unable to resolve current user id %d: %s", my_uid, strerror(errno)); |
| |
447 if ((gr = getgrgid(my_gid)) == NULL) |
| |
448 fatal("unable to resolve current group id %d: %s", my_gid, strerror(errno)); |
| |
449 debug("current-user: usr=%s uid=%d euid=%d grp=%s gid=%d egid=%d", |
| |
450 pw->pw_name, my_uid, my_euid, gr->gr_name, my_gid, my_egid); |
| |
451 |
| |
452 /* determine super user/group id */ |
| |
453 if ((pw = getpwnam(OPENPKG_SUSR)) == NULL) |
| |
454 fatal("unable to resolve OpenPKG superuser username \"%s\": %s", OPENPKG_SUSR, strerror(errno)); |
| |
455 s_uid = pw->pw_uid; |
| |
456 s_gid = pw->pw_gid; |
| |
457 debug("super-user: s_usr=%s s_uid=%d s_gid=%d", OPENPKG_SUSR, s_uid, s_gid); |
| |
458 |
| |
459 /* determine management user/group id */ |
| |
460 if ((pw = getpwnam(OPENPKG_MUSR)) == NULL) |
| |
461 fatal("unable to resolve OpenPKG management username \"%s\": %s", OPENPKG_MUSR, strerror(errno)); |
| |
462 m_uid = pw->pw_uid; |
| |
463 m_gid = pw->pw_gid; |
| |
464 debug("management-user: m_grp=%s m_uid=%d m_gid=%d", OPENPKG_MUSR, m_uid, m_gid); |
| |
465 |
| |
466 /* determine whether caller is explicitly configured as a management user */ |
| |
467 is_manager = 0; |
| |
468 if (!keep_original_privileges) |
| |
469 is_manager = check_whether_is_manager(my_uid, my_gid, m_uid, m_gid); |
| |
470 debug("current user is manager: %s", is_manager ? "yes" : "no"); |
| |
471 |
| |
472 /* determine whether command requires super-user privileges */ |
| |
473 require_superuser = check_whether_require_superuser(argc, argv); |
| |
474 debug("current command requires super user privileges: %s", require_superuser ? "yes" : "no"); |
| |
475 |
| |
476 /* adjust privileges according to determined information */ |
| |
477 if (!keep_original_privileges && require_superuser && is_manager && my_euid == 0) { |
| |
478 /* increase privileges to super user */ |
| |
479 debug("increase privileges to super user"); |
| |
480 adjust_privileges(s_uid, s_gid, 1); |
| |
481 } |
| |
482 else if (!keep_original_privileges && !require_superuser && is_manager && my_euid == 0) { |
| |
483 /* decrease privileges to management user */ |
| |
484 debug("decrease privileges to management user"); |
| |
485 adjust_privileges(m_uid, m_gid, 1); |
| |
486 } |
| |
487 else /* keep_original_privileges || !is_manager */ { |
| |
488 /* drop effective privileges for current user*/ |
| |
489 debug("drop effective privileges for current user"); |
| |
490 adjust_privileges(my_uid, my_gid, 0); |
| |
491 } |
| |
492 |
| |
493 /* pass-through control to real Execution Frontend (shell script) */ |
| |
494 argv[0] = OPENPKG_PREFIX "/lib/openpkg/openpkg"; |
| |
495 debug("execute \"%s\"", argv[0]); |
| |
496 if (!dry_run) { |
| |
497 if (execve(argv[0], argv, envp) == -1) |
| |
498 fatal("failed to execute \"%s\": %s", argv[0], strerror(errno)); |
| |
499 /* NOT REACHED */ |
| |
500 fatal("INTERNAL ERROR"); |
| |
501 } |
| |
502 return 0; |
| |
503 } |
| |
504 |