Migration (without history) of the current stable line to subversion.
[portage.git] / src / sandbox-1.1 / sandbox.c
1 /*
2 **    Path sandbox for the gentoo linux portage package system, initially
3 **    based on the ROCK Linux Wrapper for getting a list of created files
4 **
5 **  to integrate with bash, bash should have been built like this
6 **
7 **  ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
8 **
9 **  it's very important that the --enable-static-link option is NOT specified
10 **    
11 **    Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
12 **    Distributed under the terms of the GNU General Public License, v2 or later 
13 **    Author : Geert Bevin <gbevin@uwyn.com>
14 **  $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/sandbox.c,v 1.20.2.1 2004/12/01 22:14:09 carpaski Exp $
15 */
16
17 /* #define _GNU_SOURCE */
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <limits.h>
25 #include <string.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/resource.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include "sandbox.h"
35
36 int preload_adaptable = 1;
37 int cleaned_up = 0;
38 int print_debug = 0;
39 int stop_called = 0;
40
41 /* Read pids file, and load active pids into an array.  Return number of pids in array */
42 int
43 load_active_pids(int fd, int **pids)
44 {
45         char *data = NULL;
46         char *ptr = NULL, *ptr2 = NULL;
47         int my_pid;
48         int num_pids = 0;
49         long len;
50
51         pids[0] = NULL;
52
53         len = file_length(fd);
54
55         /* Allocate and zero datablock to read pids file */
56         data = (char *) malloc((len + 1) * sizeof (char));
57         memset(data, 0, len + 1);
58
59         /* Start at beginning of file */
60         lseek(fd, 0L, SEEK_SET);
61
62         /* read entire file into a buffer */
63         read(fd, data, len);
64
65         ptr = data;
66
67         /* Loop and read all pids */
68         while (1) {
69                 /* Find new line */
70                 ptr2 = strchr(ptr, '\n');
71                 if (ptr2 == NULL)
72                         break;                                                                          /* No more PIDs */
73
74                 /* Clear the \n. And  ptr  should have a null-terminated decimal string */
75                 ptr2[0] = 0;
76
77                 my_pid = atoi(ptr);
78
79                 /* If the PID is still alive, add it to our array */
80                 if ((0 != my_pid) && (0 == kill(my_pid, 0))) {
81                         pids[0] = (int *) realloc(pids[0], (num_pids + 1) * sizeof (int));
82                         pids[0][num_pids] = my_pid;
83                         num_pids++;
84                 }
85
86                 /* Put ptr past the NULL we just wrote */
87                 ptr = ptr2 + 1;
88         }
89
90         if (data)
91                 free(data);
92         data = NULL;
93
94         return num_pids;
95 }
96
97 /* Read ld.so.preload file, and loads dirs into an array.  Return number of entries in array */
98 int
99 load_preload_libs(int fd, char ***preloads)
100 {
101         char *data = NULL;
102         char *ptr = NULL, *ptr2 = NULL;
103         int num_entries = 0;
104         long len;
105
106         preloads[0] = NULL;
107
108         len = file_length(fd);
109
110         /* Allocate and zero datablock to read pids file */
111         data = (char *) malloc((len + 1) * sizeof (char));
112         memset(data, 0, len + 1);
113
114         /* Start at beginning of file */
115         lseek(fd, 0L, SEEK_SET);
116
117         /* read entire file into a buffer */
118         read(fd, data, len);
119
120         ptr = data;
121
122         /* Loop and read all pids */
123         while (1) {
124                 /* Find new line */
125                 ptr2 = strchr(ptr, '\n');
126
127                 /* Clear the \n. And  ptr  should have a null-terminated decimal string
128                  * Don't break from the loop though because the last line may not
129                  * terminated with a \n
130                  */
131                 if (NULL != ptr2)
132                         ptr2[0] = 0;
133
134                 /* If listing does not match our libname, add it to the array */
135                 if ((strlen(ptr)) && (NULL == strstr(ptr, LIB_NAME))) {
136                         preloads[0] =
137                                         (char **) realloc(preloads[0], (num_entries + 1) * sizeof (char **));
138                         preloads[0][num_entries] = strdup(ptr);
139                         num_entries++;
140                 }
141
142                 if (NULL == ptr2)
143                         break;                                                                          /* No more PIDs */
144
145                 /* Put ptr past the NULL we just wrote */
146                 ptr = ptr2 + 1;
147         }
148
149         if (data)
150                 free(data);
151         data = NULL;
152
153         return num_entries;
154 }
155
156 void
157 cleanup()
158 {
159         int i = 0;
160         int success = 1;
161         int pids_file = -1, num_of_pids = 0;
162         int *pids_array = NULL;
163         char pid_string[255];
164         char *sandbox_pids_file;
165 #ifdef USE_LD_SO_PRELOAD
166         int preload_file = -1, num_of_preloads = 0;
167         char preload_entry[255];
168         char **preload_array = NULL;
169 #endif
170
171         /* Generate sandbox pids-file path */
172         sandbox_pids_file = get_sandbox_pids_file();
173
174         /* Remove this sandbox's bash pid from the global pids
175          * file if it has rights to adapt the ld.so.preload file */
176         if ((1 == preload_adaptable) && (0 == cleaned_up)) {
177                 cleaned_up = 1;
178                 success = 1;
179
180                 if (print_debug)
181                         printf("Cleaning up pids file.\n");
182
183                 /* Stat the PIDs file, make sure it exists and is a regular file */
184                 if (file_exist(sandbox_pids_file, 1) <= 0) {
185                         fprintf(stderr, ">>> pids file is not a regular file");
186                         success = 0;
187                         /* We should really not fail if the pidsfile is missing here, but
188                          * rather just exit cleanly, as there is still some cleanup to do */
189                         return;
190                 }
191
192                 pids_file = file_open(sandbox_pids_file, "r+", 1, 0664, "portage");
193                 if (-1 == pids_file) {
194                         success = 0;
195                         /* Nothing more to do here */
196                         return;
197                 }
198
199                 /* Load "still active" pids into an array */
200                 num_of_pids = load_active_pids(pids_file, &pids_array);
201                 //printf("pids: %d\r\n", num_of_pids);
202
203 #ifdef USE_LD_SO_PRELOAD
204                 /* clean the /etc/ld.so.preload file if no other sandbox
205                  * processes are running anymore */
206                 if (1 == num_of_pids) {
207                         success = 1;
208
209                         if (print_debug)
210                                 printf("Cleaning up /etc/ld.so.preload.\n");
211
212                         preload_file = file_open("/etc/ld.so.preload", "r+", 1, 0644);
213                         if (-1 != preload_file) {
214                                 /* Load all the preload libraries into an array */
215                                 num_of_preloads = load_preload_libs(preload_file, &preload_array);
216                                 //printf("num preloads: %d\r\n", num_of_preloads);
217                                 /* Clear file */
218                                 file_truncate(preload_file);
219
220                                 /* store the other preload libraries back into the /etc/ld.so.preload file */
221                                 if (num_of_preloads > 0) {
222                                         for (i = 0; i < num_of_preloads; i++) {
223                                                 sprintf(preload_entry, "%s\n", preload_array[i]);
224                                                 if (write
225                                                                 (preload_file,
226                                                                  preload_entry,
227                                                                  strlen(preload_entry)) != strlen(preload_entry)) {
228                                                         perror(">>> /etc/ld.so.preload file write");
229                                                         success = 0;
230                                                         break;
231                                                 }
232                                         }
233                                 }
234
235                                 /* Free memory used to store preload array */
236                                 for (i = 0; i < num_of_preloads; i++) {
237                                         if (preload_array[i])
238                                                 free(preload_array[i]);
239                                         preload_array[i] = NULL;
240                                 }
241                                 if (preload_array)
242                                         free(preload_array);
243                                 preload_array = NULL;
244
245                                 file_close(preload_file);
246                                 preload_file = -1;
247                         }
248                 }
249 #endif
250
251                 file_truncate(pids_file);
252
253                 /* if pids are still running, write only the running pids back to the file */
254                 if (num_of_pids > 1) {
255                         for (i = 0; i < num_of_pids; i++) {
256                                 if (pids_array[i] != getpid()) {
257                                         sprintf(pid_string, "%d\n", pids_array[i]);
258
259                                         if (write(pids_file, pid_string, strlen(pid_string)) !=
260                                                         strlen(pid_string)) {
261                                                 perror(">>> pids file write");
262                                                 success = 0;
263                                                 break;
264                                         }
265                                 }
266                         }
267
268                         file_close(pids_file);
269                         pids_file = -1;
270                 } else {
271
272                         file_close(pids_file);
273                         pids_file = -1;
274
275                         /* remove the pidsfile, as this was the last sandbox */
276                         unlink(sandbox_pids_file);
277                 }
278
279                 if (pids_array != NULL)
280                         free(pids_array);
281                 pids_array = NULL;
282         }
283
284         free(sandbox_pids_file);
285         if (0 == success)
286                 return;
287 }
288
289 void
290 stop(int signum)
291 {
292         if (stop_called == 0) {
293                 stop_called = 1;
294                 printf("Caught signal %d in pid %d\r\n", signum, getpid());
295         cleanup();
296         } else {
297                 fprintf(stderr, "Pid %d alreadly caught signal and is still cleaning up\n", getpid());
298         }
299 }
300
301 void
302 setenv_sandbox_write(char *home_dir, char *portage_tmp_dir, char *var_tmp_dir,
303                                                                                  char *tmp_dir)
304 {
305         char buf[1024];
306         
307         /* bzero out entire buffer then append trailing 0 */
308         memset(buf, 0, sizeof(buf));
309
310         if (!getenv(ENV_SANDBOX_WRITE)) {
311                 /* these could go into make.globals later on */
312                 snprintf(buf, sizeof(buf),
313                         "%s:%s/.gconfd/lock:%s/.bash_history:",         \
314                         "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:"       \
315                         "/dev/vc/:/dev/tty:/tmp/:"                      \
316                         "/dev/shm/ngpt:/var/log/scrollkeeper.log:"      \
317                         "/usr/tmp/conftest:/usr/lib/conftest:"          \
318                         "/usr/lib32/conftest:/usr/lib64/conftest:"      \
319                         "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf",
320                         home_dir, home_dir);
321
322                 if (NULL == portage_tmp_dir) {
323                         strncat(buf, tmp_dir, sizeof(buf));
324                         strncat(buf, ":", sizeof(buf));
325                         strncat(buf, var_tmp_dir, sizeof(buf));
326                         strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
327                 } else {
328                         strncat(buf, portage_tmp_dir, sizeof(buf));
329                         strncat(buf, ":", sizeof(buf));
330                         strncat(buf, tmp_dir, sizeof(buf));
331                         strncat(buf, ":", sizeof(buf));
332                         strncat(buf, var_tmp_dir, sizeof(buf));
333                         strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
334                 }
335                 buf[sizeof(buf) - 1] = '\0';
336                 setenv(ENV_SANDBOX_WRITE, buf, 1);
337         }
338 }
339
340 void
341 setenv_sandbox_predict(char *home_dir)
342 {
343         char buf[1024];
344
345         memset(buf, 0, sizeof(buf));
346
347         if (!getenv(ENV_SANDBOX_PREDICT)) {
348                 /* these should go into make.globals later on */
349                 snprintf(buf, sizeof(buf), "%s/.:"      \
350                                 "/usr/lib/python2.0/:"  \
351                                 "/usr/lib/python2.1/:"  \
352                                 "/usr/lib/python2.2/:"  \
353                                 "/usr/lib/python2.3/:"  \
354                                 "/usr/lib/python2.4/:"  \
355                                 "/usr/lib/python2.5/:"  \
356                                 "/usr/lib/python3.0/:",
357                         home_dir);
358
359                 buf[sizeof(buf) - 1] = '\0';
360                 setenv(ENV_SANDBOX_PREDICT, buf, 1);
361         }
362 }
363
364 int
365 print_sandbox_log(char *sandbox_log)
366 {
367         int sandbox_log_file = -1;
368         char *beep_count_env = NULL;
369         int i, color, beep_count = 0;
370         long len = 0;
371         char *buffer = NULL;
372
373         sandbox_log_file = file_open(sandbox_log, "r", 1, 0664, "portage");
374         if (-1 == sandbox_log_file)
375                 return 0;
376
377         len = file_length(sandbox_log_file);
378         buffer = (char *) malloc((len + 1) * sizeof (char));
379         memset(buffer, 0, len + 1);
380         read(sandbox_log_file, buffer, len);
381         file_close(sandbox_log_file);
382
383         color = ( (getenv("NOCOLOR") != NULL) ? 0 : 1);
384
385         if (color) printf("\e[31;01m");
386         printf("--------------------------- ACCESS VIOLATION SUMMARY ---------------------------");
387         if (color) printf("\033[0m");
388         if (color) printf("\e[31;01m");
389         printf("\nLOG FILE = \"%s\"", sandbox_log);
390         if (color) printf("\033[0m");
391         printf("\n\n");
392         printf("%s", buffer);
393         if (buffer)
394                 free(buffer);
395         buffer = NULL;
396         printf
397                         ("\e[31;01m--------------------------------------------------------------------------------\033[0m\n");
398
399         beep_count_env = getenv(ENV_SANDBOX_BEEP);
400         if (beep_count_env)
401                 beep_count = atoi(beep_count_env);
402         else
403                 beep_count = DEFAULT_BEEP_COUNT;
404
405         for (i = 0; i < beep_count; i++) {
406                 fputc('\a', stderr);
407                 if (i < beep_count - 1)
408                         sleep(1);
409         }
410         return 1;
411 }
412
413 int
414 spawn_shell(char *argv_bash[])
415 {
416 #ifdef USE_SYSTEM_SHELL
417         int i = 0;
418         char *sh = NULL;
419         int first = 1;
420         int ret;
421         long len = 0;
422
423         while (1) {
424                 if (NULL == argv_bash[i])
425                         break;
426                 if (NULL != sh)
427                         len = strlen(sh);
428                 sh = (char *) realloc(sh, len + strlen(argv_bash[i]) + 5);
429                 if (first) {
430                         sh[0] = 0;
431                         first = 0;
432                 }
433                 strcat(sh, "\"");
434                 strcat(sh, argv_bash[i]);
435                 strcat(sh, "\" ");
436
437                 //printf("%s\n", argv_bash[i]);
438                 i++;
439         }
440         printf("%s\n", sh);
441         ret = system(sh);
442         if (sh)
443                 free(sh);
444         sh = NULL;
445
446         if (-1 == ret)
447                 return 0;
448         return 1;
449
450 #else
451 # ifndef NO_FORK
452         int pid;
453         int status = 0;
454         int ret = 0;
455
456         pid = fork();
457
458         /* Child's process */
459         if (0 == pid) {
460 # endif
461                 execv(argv_bash[0], argv_bash);
462 # ifndef NO_FORK
463                 return 0;
464         } else if (pid < 0) {
465                 return 0;
466         }
467         ret = waitpid(pid, &status, 0);
468         if ((-1 == ret) || (status > 0))
469                 return 0;
470 # endif
471         return 1;
472 #endif
473 }
474
475 int
476 main(int argc, char **argv)
477 {
478         int i = 0, success = 1;
479 #ifdef USE_LD_SO_PRELOAD
480         int preload_file = -1;
481 #endif
482         int sandbox_log_presence = 0;
483         int sandbox_log_file = -1;
484         int pids_file = -1;
485         long len;
486
487         int *pids_array = NULL;
488         int num_of_pids = 0;
489
490         // char run_arg[255];
491         char portage_tmp_dir[PATH_MAX];
492         char var_tmp_dir[PATH_MAX];
493         char tmp_dir[PATH_MAX];
494         char sandbox_log[255];
495         char sandbox_debug_log[255];
496         char sandbox_dir[255];
497         char sandbox_lib[255];
498         char *sandbox_pids_file;
499         char sandbox_rc[255];
500         char pid_string[255];
501         char **argv_bash = NULL;
502
503         char *run_str = "-c";
504         char *home_dir = NULL;
505         char *tmp_string = NULL;
506 #ifdef USE_LD_SO_PRELOAD
507         char **preload_array = NULL;
508         int num_of_preloads = 0;
509 #endif
510
511         /* Only print info if called with no arguments .... */
512         if (argc < 2)
513                 print_debug = 1;
514
515         if (print_debug)
516                 printf
517                                 ("========================== Gentoo linux path sandbox ===========================\n");
518
519         /* check if a sandbox is already running */
520         if (NULL != getenv(ENV_SANDBOX_ON)) {
521                 fprintf(stderr,
522                                                 "Not launching a new sandbox instance\nAnother one is already running in this process hierarchy.\n");
523                 exit(1);
524         } else {
525
526                 /* determine the location of all the sandbox support files */
527                 if (print_debug)
528                         printf("Detection of the support files.\n");
529
530                 /* Generate base sandbox path */
531                 tmp_string = get_sandbox_path(argv[0]);
532                 strncpy(sandbox_dir, tmp_string, 254);
533                 if (tmp_string)
534                         free(tmp_string);
535                 tmp_string = NULL;
536                 strcat(sandbox_dir, "/");
537
538                 /* Generate sandbox lib path */
539                 tmp_string = get_sandbox_lib(sandbox_dir);
540                 strncpy(sandbox_lib, tmp_string, 254);
541                 if (tmp_string)
542                         free(tmp_string);
543                 tmp_string = NULL;
544
545                 /* Generate sandbox pids-file path */
546                 sandbox_pids_file = get_sandbox_pids_file();
547
548                 /* Generate sandbox bashrc path */
549                 tmp_string = get_sandbox_rc(sandbox_dir);
550                 strncpy(sandbox_rc, tmp_string, 254);
551                 if (tmp_string)
552                         free(tmp_string);
553                 tmp_string = NULL;
554
555                 /* verify the existance of required files */
556                 if (print_debug)
557                         printf("Verification of the required files.\n");
558
559 #ifndef SB_HAVE_64BIT_ARCH
560                 if (file_exist(sandbox_lib, 0) <= 0) {
561                         fprintf(stderr, "Could not open the sandbox library at '%s'.\n",
562                                                         sandbox_lib);
563                         return -1;
564                 } 
565 #endif
566                 if (file_exist(sandbox_rc, 0) <= 0) {
567                         fprintf(stderr, "Could not open the sandbox rc file at '%s'.\n",
568                                                         sandbox_rc);
569                         return -1;
570                 }
571 #ifdef USE_LD_SO_PRELOAD
572                 /* ensure that the /etc/ld.so.preload file contains an entry for the sandbox lib */
573                 if (print_debug)
574                         printf("Setting up the ld.so.preload file.\n");
575
576                 /* check if the /etc/ld.so.preload is a regular file */
577                 if (file_exist("/etc/ld.so.preload", 1) < 0) {
578                         fprintf(stderr, ">>> /etc/ld.so.preload file is not a regular file\n");
579                         exit(1);
580                 }
581
582                 if (getuid() == 0) {
583                         /* Our r+ also will create the file if it doesn't exist */
584                         preload_file = file_open("/etc/ld.so.preload", "r+", 1, 0644);
585                         if (-1 == preload_file) {
586                                 preload_adaptable = 0;
587 /*      exit(1);*/
588                         }
589                 } else {
590                         /* Avoid permissions warnings if we're not root */
591                         preload_adaptable = 0;
592                 }
593
594                 /* Only update /etc/ld.so.preload if we can write to it ... */
595                 if (1 == preload_adaptable) {
596                         /* Load entries of preload table */
597                         num_of_preloads = load_preload_libs(preload_file, &preload_array);
598
599                         /* Zero out our ld.so.preload file */
600                         file_truncate(preload_file);
601
602                         /* Write contents of preload file */
603                         for (i = 0; i < num_of_preloads + 1; i++) {
604                                 /* First entry should be our sandbox library */
605                                 if (0 == i) {
606                                         if (write
607                                                         (preload_file, sandbox_lib,
608                                                          strlen(sandbox_lib)) != strlen(sandbox_lib)) {
609                                                 perror(">>> /etc/ld.so.preload file write");
610                                                 success = 0;
611                                                 break;
612                                         }
613                                 } else {
614                                         /* Output all other preload entries */
615                                         if (write
616                                                         (preload_file, preload_array[i - 1],
617                                                          strlen(preload_array[i - 1])) != strlen(preload_array[i - 1])) {
618                                                 perror(">>> /etc/ld.so.preload file write");
619                                                 success = 0;
620                                                 break;
621                                         }
622                                 }
623                                 /* Don't forget the return character after each line! */
624                                 if (1 != write(preload_file, "\n", 1)) {
625                                         perror(">>> /etc/ld.so.preload file write");
626                                         success = 0;
627                                         break;
628                                 }
629                         }
630
631                         for (i = 0; i < num_of_preloads; i++) {
632                                 if (preload_array[i])
633                                         free(preload_array[i]);
634                                 preload_array[i] = NULL;
635                         }
636                         if (preload_array)
637                                 free(preload_array);
638                         num_of_preloads = 0;
639                         preload_array = NULL;
640                 }
641
642                 /* That's all we needed to do with the preload file */
643                 if (0 < preload_file)
644                         file_close(preload_file);
645                 preload_file = -1;
646 #endif
647
648                 /* set up the required environment variables */
649                 if (print_debug)
650                         printf("Setting up the required environment variables.\n");
651
652                 /* Generate sandbox log full path */
653                 tmp_string = get_sandbox_log();
654                 strncpy(sandbox_log, tmp_string, 254);
655                 if (tmp_string)
656                         free(tmp_string);
657                 tmp_string = NULL;
658
659                 setenv(ENV_SANDBOX_LOG, sandbox_log, 1);
660
661                 snprintf(sandbox_debug_log, sizeof(sandbox_debug_log), "%s%s%s",
662                                                  DEBUG_LOG_FILE_PREFIX, pid_string, LOG_FILE_EXT);
663                 setenv(ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log, 1);
664
665                 home_dir = getenv("HOME");
666                 if (!home_dir) {
667                         home_dir = "/tmp";
668                         setenv("HOME", home_dir, 1);
669                 }
670
671                 /* drobbins: we need to expand these paths using realpath() so that PORTAGE_TMPDIR
672                  * can contain symlinks (example, /var is a symlink, /var/tmp is a symlink.)  Without
673                  * this, access is denied to /var/tmp, hurtin' ebuilds.
674                  */
675
676                 {       char *e;
677                         e = getenv("PORTAGE_TMPDIR");
678                         if ( e && ( strlen(e) < sizeof(portage_tmp_dir)-1 ) && (strlen(e) > 1) )
679                                 realpath(e, portage_tmp_dir);
680
681                 }
682                 realpath("/var/tmp", var_tmp_dir);
683                 realpath("/tmp", tmp_dir);
684
685                 setenv(ENV_SANDBOX_DIR, sandbox_dir, 1);
686                 setenv(ENV_SANDBOX_LIB, sandbox_lib, 1);
687                 setenv("LD_PRELOAD", sandbox_lib, 1);
688
689                 if (!getenv(ENV_SANDBOX_DENY))
690                         setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
691
692                 if (!getenv(ENV_SANDBOX_READ))
693                         setenv(ENV_SANDBOX_READ, "/", 1);
694
695                 /* Set up Sandbox Write path */
696                 setenv_sandbox_write(home_dir, portage_tmp_dir, var_tmp_dir, tmp_dir);
697                 setenv_sandbox_predict(home_dir);
698
699                 setenv(ENV_SANDBOX_ON, "1", 0);
700
701                 /* if the portage temp dir was present, cd into it */
702                 if (NULL != portage_tmp_dir)
703                         chdir(portage_tmp_dir);
704
705                 argv_bash = (char **) malloc(6 * sizeof (char *));
706                 argv_bash[0] = strdup("/bin/bash");
707                 argv_bash[1] = strdup("-rcfile");
708                 argv_bash[2] = strdup(sandbox_rc);
709
710                 if (argc < 2)
711                         argv_bash[3] = NULL;
712                 else
713                         argv_bash[3] = strdup(run_str); /* "-c" */
714
715                 argv_bash[4] = NULL;                            /* strdup(run_arg); */
716                 argv_bash[5] = NULL;
717
718                 if (argc >= 2) {
719                         for (i = 1; i < argc; i++) {
720                                 if (NULL == argv_bash[4])
721                                         len = 0;
722                                 else
723                                         len = strlen(argv_bash[4]);
724
725                                 argv_bash[4] =
726                                                 (char *) realloc(argv_bash[4],
727                                                                                                                  (len + strlen(argv[i]) + 2) * sizeof (char));
728
729                                 if (0 == len)
730                                         argv_bash[4][0] = 0;
731                                 if (1 != i)
732                                         strcat(argv_bash[4], " ");
733
734                                 strcat(argv_bash[4], argv[i]);
735                         }
736                 }
737
738                 /* set up the required signal handlers */
739                 signal(SIGHUP, &stop);
740                 signal(SIGINT, &stop);
741                 signal(SIGQUIT, &stop);
742                 signal(SIGTERM, &stop);
743
744                 /* this one should NEVER be set in ebuilds, as it is the one
745                  * private thing libsandbox.so use to test if the sandbox
746                  * should be active for this pid, or not.
747                  *
748                  * azarah (3 Aug 2002)
749                  */
750
751                 setenv("SANDBOX_ACTIVE", "armedandready", 1);
752
753                 /* Load our PID into PIDs file */
754                 success = 1;
755                 if (file_exist(sandbox_pids_file, 1) < 0) {
756                         success = 0;
757                         fprintf(stderr, ">>> %s is not a regular file\n", sandbox_pids_file);
758                 } else {
759                         pids_file = file_open(sandbox_pids_file, "r+", 1, 0664, "portage");
760                         if (-1 == pids_file)
761                                 success = 0;
762                 }
763                 if (1 == success) {
764                         /* Grab still active pids */
765                         num_of_pids = load_active_pids(pids_file, &pids_array);
766
767                         /* Zero out file */
768                         file_truncate(pids_file);
769
770                         /* Output active pids, and append our pid */
771                         for (i = 0; i < num_of_pids + 1; i++) {
772                                 /* Time for our entry */
773                                 if (i == num_of_pids)
774                                         sprintf(pid_string, "%d\n", getpid());
775                                 else
776                                         sprintf(pid_string, "%d\n", pids_array[i]);
777
778                                 if (write(pids_file, pid_string, strlen(pid_string)) !=
779                                                 strlen(pid_string)) {
780                                         perror(">>> pids file write");
781                                         success = 0;
782                                         break;
783                                 }
784                         }
785                         /* Clean pids_array */
786                         if (pids_array)
787                                 free(pids_array);
788                         pids_array = NULL;
789                         num_of_pids = 0;
790
791                         /* We're done with the pids file */
792                         file_close(pids_file);
793                 }
794
795                 /* Something went wrong, bail out */
796                 if (0 == success) {
797                         perror(">>> pids file write");
798                         exit(1);
799                 }
800
801                 /* STARTING PROTECTED ENVIRONMENT */
802                 if (print_debug) {
803                         printf("The protected environment has been started.\n");
804                         printf
805                                         ("--------------------------------------------------------------------------------\n");
806                 }
807
808                 if (print_debug)
809                         printf("Shell being started in forked process.\n");
810
811                 /* Start Bash */
812                 if (!spawn_shell(argv_bash)) {
813                         if (print_debug)
814                                 fprintf(stderr, ">>> shell process failed to spawn\n");
815                         success = 0;
816                 }
817
818                 /* Free bash stuff */
819                 for (i = 0; i < 6; i++) {
820                         if (argv_bash[i])
821                                 free(argv_bash[i]);
822                         argv_bash[i] = NULL;
823                 }
824                 if (argv_bash)
825                         free(argv_bash);
826                 argv_bash = NULL;
827
828                 if (print_debug)
829                         printf("Cleaning up sandbox process\n");
830
831                 cleanup();
832
833                 if (print_debug) {
834                         printf
835                                         ("========================== Gentoo linux path sandbox ===========================\n");
836                         printf("The protected environment has been shut down.\n");
837                 }
838
839                 if (file_exist(sandbox_log, 0)) {
840                         sandbox_log_presence = 1;
841                         success = 1;
842                         if (!print_sandbox_log(sandbox_log))
843                                 success = 0;
844
845 #if 0
846                         if (!success)
847                                 exit(1);
848 #endif
849
850                         sandbox_log_file = -1;
851                 } else if (print_debug) {
852                         printf
853                                         ("--------------------------------------------------------------------------------\n");
854                 }
855
856                 if ((sandbox_log_presence) || (!success))
857                         return 1;
858                 else
859                         return 0;
860         }
861 }
862
863 // vim:expandtab noai:cindent ai