Пример #1
0
static BOOL user_ok(const char *user, int snum)
{
	char **valid, **invalid;
	BOOL ret;

	valid = invalid = NULL;
	ret = True;

	if (lp_invalid_users(snum)) {
		str_list_copy(&invalid, lp_invalid_users(snum));
		if (invalid &&
		    str_list_substitute(invalid, "%S", lp_servicename(snum))) {
			if ( invalid &&
			     str_list_sub_basic(invalid,
						current_user_info.smb_name) ) {
				ret = !user_in_list(user,
						    (const char **)invalid);
			}
		}
	}
	if (invalid)
		str_list_free (&invalid);

	if (ret && lp_valid_users(snum)) {
		str_list_copy(&valid, lp_valid_users(snum));
		if ( valid &&
		     str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
			if ( valid &&
			     str_list_sub_basic(valid,
						current_user_info.smb_name) ) {
				ret = user_in_list(user, (const char **)valid);
			}
		}
	}
	if (valid)
		str_list_free (&valid);

	if (ret && lp_onlyuser(snum)) {
		char **user_list = str_list_make (lp_username(snum), NULL);
		if (user_list &&
		    str_list_substitute(user_list, "%S",
					lp_servicename(snum))) {
			ret = user_in_list(user, (const char **)user_list);
		}
		if (user_list) str_list_free (&user_list);
	}

	return(ret);
}
Пример #2
0
int
dcplugin_destroy(DCPlugin * const dcplugin)
{
    Blocking *blocking = dcplugin_get_user_data(dcplugin);

    if (blocking == NULL) {
        return 0;
    }
    str_list_free(blocking->domains);
    blocking->domains = NULL;
    str_list_free(blocking->ips);
    blocking->ips = NULL;
    free(blocking);

    return 0;
}
Пример #3
0
static string
kpse_brace_expand_element P1C(const_string, elt)
{
  unsigned i;
  str_list_type expansions = brace_expand (&elt);
  string ret = (string)xmalloc (1);
  *ret = 0;

  for (i = 0; i != STR_LIST_LENGTH(expansions); i++) {
    /* Do $ and ~ expansion on each element.  */
    string x = kpse_expand (STR_LIST_ELT(expansions,i));
    string save_ret = ret;
    if (!STREQ (x, STR_LIST_ELT(expansions,i))) {
      /* If we did any expansions, do brace expansion again.  Since
         recursive variable definitions are not allowed, this recursion
         must terminate.  (In practice, it's unlikely there will ever be
         more than one level of recursion.)  */
      string save_x = x;
      x = kpse_brace_expand_element (x);
      free (save_x);
    }
    ret = concat3 (ret, x, ENV_SEP_STRING);
    free (save_ret);
    free (x);
  }
  for (i = 0; i != STR_LIST_LENGTH(expansions); ++i) {
      free(STR_LIST_ELT(expansions,i));
  }
  str_list_free(&expansions);
  ret[strlen (ret) - 1] = 0; /* waste the trailing null */
  return ret;
}
Пример #4
0
/* auxiliary recursive function for linked list freeing */
void str_list_free (strlist *value)
{
  if (value == NULL)
    return;
  str_list_free(value->next);
  free(value->str);
  return;
}
Пример #5
0
/* Sadly, quite a lot of the freeing is not safe:
   it seems there are literals used all over. */
void
kpathsea_finish (kpathsea kpse)
{
#if KPATHSEA_CAN_FREE
    int i;
    kpse_format_info_type f;
#endif /* KPATHSEA_CAN_FREE */
    if (kpse==NULL)
        return;
#if KPATHSEA_CAN_FREE
    /* free internal stuff */
    hash_free (kpse->cnf_hash);
    hash_free (kpse->db);
    hash_free (kpse->alias_db);
    str_list_free(&kpse->db_dir_list);
    hash_free (kpse->link_table);
    cache_free (kpse->the_cache, kpse->cache_length);
    hash_free (kpse->map);
    string_free (kpse->map_path);
    string_free (kpse->elt);
    /*string_free (kpse->path);*/
    if (kpse->log_file != (FILE *)NULL)
        fclose(kpse->log_file);
    string_free (kpse->invocation_name);
    string_free (kpse->invocation_short_name);
    string_free (kpse->program_name);
    string_free (kpse->fallback_font);
    string_free (kpse->fallback_resolutions_string);
    if(kpse->fallback_resolutions != NULL)
        free(kpse->fallback_resolutions);
    for (i = 0; i != kpse_last_format; ++i) {
        f = kpse->format_info[i];
        /*string_free ((string)f.path);*/
        string_free ((string)f.override_path);
        string_free ((string)f.client_path);
        /*string_free ((string)f.cnf_path);*/
    }

    if (kpse->missfont != (FILE *)NULL)
        fclose(kpse->missfont);

    for (i = 0; i < (int)kpse->expansion_len; i++) {
        string_free (kpse->expansions[i].var);
    }
    free (kpse->expansions);
    if (kpse->saved_env!=NULL) {
        for (i = 0; i != kpse->saved_count; ++i)
            string_free (kpse->saved_env[i]);
        free (kpse->saved_env);
    }
#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
    if (kpse->suffixlist != NULL) {
        char **p;
        for p = kpse->suffixlist; *p; p++)
            free (*p);
        free (kpse->suffixlist);
    }
Пример #6
0
static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser)
{
	char **list;
	const char *service = lp_servicename(conn->service);
	BOOL read_only_ret = lp_readonly(conn->service);

	if (!service)
		return read_only_ret;

	str_list_copy(&list, lp_readlist(conn->service));
	if (list) {
		if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
			DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n"));
		}
		if (!str_list_substitute(list, "%S", service)) {
			DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n"));
		}
		if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) {
			read_only_ret = True;
		}
		str_list_free(&list);
	}

	str_list_copy(&list, lp_writelist(conn->service));
	if (list) {
		if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
			DEBUG(0, ("is_share_read_only_for_user: ERROR: write list substitution failed\n"));
		}
		if (!str_list_substitute(list, "%S", service)) {
			DEBUG(0, ("is_share_read_only_for_user: ERROR: write list service substitution failed\n"));
		}
		if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) {
			read_only_ret = False;
		}
		str_list_free(&list);
	}

	DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user %s\n",
		service, read_only_ret ? "read-only" : "read-write", vuser->user.unix_name ));

	return read_only_ret;
}
Пример #7
0
/****************************************************************************
parse the debug levels from smb.conf. Example debug level string:
  3 tdb:5 printdrivers:7
Note: the 1st param has no "name:" preceeding it.
****************************************************************************/
BOOL debug_parse_levels(const char *params_str)
{
    char **params;

    /* Just in case */
    debug_init();

    if (AllowDebugChange == False)
        return True;

    params = str_list_make(params_str, NULL);

    if (debug_parse_params(params))
    {
        debug_dump_status(5);
        str_list_free(&params);
        return True;
    } else {
        str_list_free(&params);
        return False;
    }
}
Пример #8
0
void web_set_lang(const char *lang_string)
{
	char **lang_list, **count;
	struct pri_list *pl;
	int lang_num, i;

	/* build the lang list */
	lang_list = str_list_make(lang_string, ", \t\r\n");
	if (!lang_list) return;
	
	/* sort the list by priority */
	lang_num = 0;
	count = lang_list;
	while (*count && **count) {
		count++;
		lang_num++;
	}
	pl = SMB_MALLOC_ARRAY(struct pri_list, lang_num);
	if (!pl) {
		return;
	}

	for (i = 0; i < lang_num; i++) {
		char *pri_code;
		if ((pri_code=strstr(lang_list[i], ";q="))) {
			*pri_code = '\0';
			pri_code += 3;
			sscanf(pri_code, "%f", &(pl[i].pri));
		} else {
			pl[i].pri = 1;
		}
		pl[i].string = SMB_STRDUP(lang_list[i]);
	}
	str_list_free(&lang_list);

	qsort(pl, lang_num, sizeof(struct pri_list), &qsort_cmp_list);

	/* it's not an error to not initialise - we just fall back to 
	   the default */

	for (i = 0; i < lang_num; i++) {
		if (lang_tdb_init(pl[i].string)) break;
	}

	for (i = 0; i < lang_num; i++) {
		SAFE_FREE(pl[i].string);
	}
	SAFE_FREE(pl);

	return;
}
Пример #9
0
static int spawn_shell(char *argv_bash[], char **env, int debug)
{
	int status = 0;
	int ret = 0;

	child_pid = fork();

	/* Child's process */
	if (0 == child_pid) {
		int ret = execve(argv_bash[0], argv_bash, env);
		sb_pwarn("failed to exec child");
		_exit(ret);
	} else if (child_pid < 0) {
		if (debug)
			sb_pwarn("process failed to spawn!");
		return 1;
	}

	/* fork() creates a copy of this, so no need to use more memory than
	 * absolutely needed. */
	str_list_free(argv_bash);
	str_list_free(env);

	ret = waitpid(child_pid, &status, 0);
	if (-1 == ret) {
		sb_pwarn("failed to waitpid for child");
		return 1;
	} else if (status != 0) {
		if (WIFSIGNALED(status)) {
			psignal(WTERMSIG(status), "Sandboxed process killed by signal");
			return 128 + WTERMSIG(status);
		} else if (debug)
			sb_warn("process returned with failed exit status %d!", WEXITSTATUS(status));
		return WEXITSTATUS(status) ? : 1;
	}

	return 0;
}
Пример #10
0
static str_list_type brace_expand P1C(const_string *, text)
{
    str_list_type result, partial, recurse;
    const_string p;
    result = str_list_init();
    partial = str_list_init();
    for (p = *text; *p && *p != '}'; ++p) {
        /* FIXME: Should be IS_ENV_SEP(*p) */
        if (*p == ENV_SEP || *p == ',') {
            expand_append(&partial, *text, p);
            str_list_concat(&result, partial);
            str_list_free(&partial);
            *text = p+1;
            partial = str_list_init();
        } else if (*p == '{') {
            expand_append(&partial, *text, p);
            ++p;
            recurse = brace_expand(&p);
            str_list_concat_elements(&partial, recurse);
            str_list_free(&recurse);
            /* Check for missing closing brace. */
            if (*p != '}') {
                WARNING1 ("%s: Unmatched {", *text);
            }
            *text = p+1;
        } else if (*p == '$') {
            /* Skip ${VAR} */
            if (*(p+1) == '{')
                for (p+=2; *p!='}';++p);
        }
    }
    expand_append(&partial, *text, p);
    str_list_concat(&result, partial);
    str_list_free(&partial);
    *text = p;
    return result;
}
int
dcplugin_destroy(DCPlugin * const dcplugin)
{
    Context *context = dcplugin_get_user_data(dcplugin);

    if (context == NULL) {
        return 0;
    }
    str_list_free(context->blacklist);
    context->blacklist = NULL;
    GeoIP_delete(context->geoip);
    context->geoip = NULL;
    free(context);

    return 0;
}
Пример #12
0
static int
parse_str_list(StrList ** const str_list_p, const char * const file)
{
    char     line[512U];
    char    *host;
    FILE    *fp;
    char    *ptr;
    StrList *str_list_item;
    StrList *str_list_last = NULL;
    int      ret = -1;

    assert(str_list_p != NULL);
    *str_list_p = NULL;
    if ((fp = fopen(file, "r")) == NULL) {
        return -1;
    }
    while (fgets(line, (int) sizeof line, fp) != NULL) {
        while ((ptr = strchr(line, '\n')) != NULL ||
               (ptr = strchr(line, '\r')) != NULL) {
            *ptr = 0;
        }
        if ((host = host_only(line)) == NULL || *host == 0) {
            continue;
        }
        if ((str_list_item = calloc(1U, sizeof *str_list_item)) == NULL ||
            (str_list_item->str = strdup(host)) == NULL) {
            break;
        }
        str_list_item->next = NULL;
        *(*str_list_p == NULL ? str_list_p : &str_list_last->next) = str_list_item;
        str_list_last = str_list_item;
    }
    if (!feof(fp)) {
        str_list_free(*str_list_p);
        *str_list_p = NULL;
    } else {
        ret = 0;
    }
    fclose(fp);

    return ret;
}
static StrList *
parse_str_list(const char * const file)
{
    char     line[300U];
    FILE    *fp;
    char    *ptr;
    StrList *str_list = NULL;
    StrList *str_list_item;
    StrList *str_list_last = NULL;

    if ((fp = fopen(file, "r")) == NULL) {
        return NULL;
    }
    while (fgets(line, (int) sizeof line, fp) != NULL) {
        while ((ptr = strchr(line, '\n')) != NULL ||
               (ptr = strchr(line, '\r')) != NULL) {
            *ptr = 0;
        }
        if (*line == 0 || *line == '#') {
            continue;
        }
        if ((str_list_item = calloc(1U, sizeof *str_list_item)) == NULL ||
            (str_list_item->str = strdup(line)) == NULL) {
            break;
        }
        str_list_item->next = NULL;
        *(str_list == NULL ? &str_list : &str_list_last->next) = str_list_item;
        str_list_last = str_list_item;
    }
    if (!feof(fp)) {
        str_list_free(str_list);
        str_list = NULL;
    }
    fclose(fp);

    return str_list;
}
Пример #14
0
// if val1 = val2 then its a unique value; otherwise it's a range
int acpp_asm_add_symbol_value(int val1, int val2, char *error_msg) {

  int range = abs(val2-val1);
  int increment_sign = (val1 < val2) ? 1 : -1;
  int symbol_number;

  /* if it's a ranged symbol, the number of symbol names added must equal the value range */
  if (range) {

    symbol_number = 0;
    strlist *t_sl = symbol_name_list;

    /* counts the number of symbols added */
    while (t_sl != NULL) {
      symbol_number++;
      t_sl = t_sl->next;
    }

    if (range+1 != symbol_number) {
      sprintf(error_msg, "Different ranges specified in symbol mapping");
      return 0;
    }
  }

  /* assign each symbol to its value and adds to the map_symbol_list list */
  strlist *t_sl = symbol_name_list;
  ac_asm_symbol *t_symbol = NULL;

  int i=0;
  while (t_sl != NULL) {

    /* creates the symbol */
    t_symbol = (ac_asm_symbol *) malloc(sizeof(ac_asm_symbol));

    t_symbol->symbol = strdup(t_sl->str);
    t_symbol->value = val1;
    t_symbol->map_marker = strdup(mapping_list_tail->marker);

    if (range) t_symbol->value += (i*increment_sign);
    t_symbol->next = NULL;

    /* insert it in the symbol_list */
    if (!symbol_list) {
      symbol_list = t_symbol; 
    }
    else {
      ac_asm_symbol *t = symbol_list;
      if (strcmp(t_symbol->symbol, t->symbol) < 0)
      {
        t_symbol->next = symbol_list;
        symbol_list = t_symbol;
      } else
      {
	while ((t->next != NULL) && (strcmp(t_symbol->symbol, t->next->symbol) >= 0)) {
          t = t->next;
        }
        t_symbol->next = t->next;
        t->next = t_symbol;
      }
    }

    i++;
    t_sl = t_sl->next;
  }
  
  /* freeing symbol_name_list memory */
  str_list_free(symbol_name_list);  

  /* done with the name list */
  symbol_name_list = NULL;
  symbol_name_list_tail = NULL;

  return 1;
}
Пример #15
0
static int
transfer_dir_internal(struct vsf_session* p_sess, int is_control,
                      struct vsf_sysutil_dir* p_dir,
                      const struct mystr* p_base_dir_str,
                      const struct mystr* p_option_str,
                      const struct mystr* p_filter_str,
                      int is_verbose)
{
  struct mystr_list dir_list = INIT_STRLIST;
  struct mystr_list subdir_list = INIT_STRLIST;
  struct mystr dir_prefix_str = INIT_MYSTR;
  struct mystr_list* p_subdir_list = 0;
  struct str_locate_result loc_result = str_locate_char(p_option_str, 'R');
  int failed = 0;
  enum EVSFRWTarget target = kVSFRWData;
  if (is_control)
  {
    target = kVSFRWControl;
  }
  if (loc_result.found && tunable_ls_recurse_enable)
  {
    p_subdir_list = &subdir_list;
  }
  vsf_ls_populate_dir_list(&dir_list, p_subdir_list, p_dir, p_base_dir_str,
                           p_option_str, p_filter_str, is_verbose);
  if (p_subdir_list)
  {
    int retval;
    str_copy(&dir_prefix_str, p_base_dir_str);
    str_append_text(&dir_prefix_str, ":\r\n");
    retval = ftp_write_str(p_sess, &dir_prefix_str, target);
    if (retval != 0)
    {
      failed = 1;
    }
  }
  if (!failed)
  {
    failed = write_dir_list(p_sess, &dir_list, target);
  }
  /* Recurse into the subdirectories if required... */
  if (!failed)
  {
    struct mystr sub_str = INIT_MYSTR;
    unsigned int num_subdirs = str_list_get_length(&subdir_list);
    unsigned int subdir_index;
    for (subdir_index = 0; subdir_index < num_subdirs; subdir_index++)
    {
      int retval;
      struct vsf_sysutil_dir* p_subdir;
      const struct mystr* p_subdir_str = 
        str_list_get_pstr(&subdir_list, subdir_index);
      if (str_equal_text(p_subdir_str, ".") ||
          str_equal_text(p_subdir_str, ".."))
      {
        continue;
      }
      str_copy(&sub_str, p_base_dir_str);
      str_append_char(&sub_str, '/');
      str_append_str(&sub_str, p_subdir_str);
      p_subdir = str_opendir(&sub_str);
      if (p_subdir == 0)
      {
        /* Unreadable, gone missing, etc. - no matter */
        continue;
      }
      str_alloc_text(&dir_prefix_str, "\r\n");
      retval = ftp_write_str(p_sess, &dir_prefix_str, target);
      if (retval != 0)
      {
        failed = 1;
        vsf_sysutil_closedir(p_subdir);
        break;
      }
      retval = transfer_dir_internal(p_sess, is_control, p_subdir, &sub_str,
                                     p_option_str, p_filter_str, is_verbose);
      vsf_sysutil_closedir(p_subdir);
      if (retval != 0)
      {
        failed = 1;
        break;
      }
    }
    str_free(&sub_str);
  }
  str_list_free(&dir_list);
  str_list_free(&subdir_list);
  str_free(&dir_prefix_str);
  if (!failed)
  {
    return 0;
  }
  else
  {
    return -1;
  }
}
Пример #16
0
NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) 
{
	char **auth_method_list = NULL; 
	NTSTATUS nt_status;

	if (lp_auth_methods() && !str_list_copy(&auth_method_list, lp_auth_methods())) {
		return NT_STATUS_NO_MEMORY;
	}

	if (auth_method_list == NULL) {
		switch (lp_security()) 
		{
		case SEC_DOMAIN:
			DEBUG(5,("Making default auth method list for security=domain\n"));
			auth_method_list = str_list_make("guest sam winbind:ntdomain", NULL);
			break;
		case SEC_SERVER:
			DEBUG(5,("Making default auth method list for security=server\n"));
			auth_method_list = str_list_make("guest sam smbserver", NULL);
			break;
		case SEC_USER:
			if (lp_encrypted_passwords()) {	
				if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) {
					DEBUG(5,("Making default auth method list for DC, security=user, encrypt passwords = yes\n"));
					auth_method_list = str_list_make("guest sam winbind:trustdomain", NULL);
				} else {
					DEBUG(5,("Making default auth method list for standalone security=user, encrypt passwords = yes\n"));
					auth_method_list = str_list_make("guest sam", NULL);
				}
			} else {
				DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
				auth_method_list = str_list_make("guest unix", NULL);
			}
			break;
		case SEC_SHARE:
			if (lp_encrypted_passwords()) {
				DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
				auth_method_list = str_list_make("guest sam", NULL);
			} else {
				DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
				auth_method_list = str_list_make("guest unix", NULL);
			}
			break;
		case SEC_ADS:
			DEBUG(5,("Making default auth method list for security=ADS\n"));
			auth_method_list = str_list_make("guest sam winbind:ntdomain", NULL);
			break;
		default:
			DEBUG(5,("Unknown auth method!\n"));
			return NT_STATUS_UNSUCCESSFUL;
		}
	} else {
		DEBUG(5,("Using specified auth order\n"));
	}
	
	if (!NT_STATUS_IS_OK(nt_status = make_auth_context_text_list(auth_context, auth_method_list))) {
		str_list_free(&auth_method_list);
		return nt_status;
	}
	
	str_list_free(&auth_method_list);
	return nt_status;
}
Пример #17
0
static str_list_type
path_search P4C(const_string, path,  string, name,
                boolean, must_exist,  boolean, all)
{
  string elt;
  str_list_type ret_list;
  boolean done = false;
  ret_list = str_list_init (); /* some compilers lack struct initialization */

  for (elt = kpse_path_element (path); !done && elt;
       elt = kpse_path_element (NULL)) {
    str_list_type *found;
    boolean allow_disk_search = true;

    if (*elt == '!' && *(elt + 1) == '!') {
      /* Those magic leading chars in a path element means don't search the
         disk for this elt.  And move past the magic to get to the name.  */
      allow_disk_search = false;
      elt += 2;
    }

    /* See elt-dirs.c for side effects of this function */
    kpse_normalize_path(elt);
    
    /* Try ls-R, unless we're searching for texmf.cnf.  Our caller
       (search), also tests first_search, and does the resetting.  */
    found = first_search ? NULL : kpse_db_search (name, elt, all);

    /* Search the filesystem if (1) the path spec allows it, and either
         (2a) we are searching for texmf.cnf ; or
         (2b) no db exists; or 
         (2c) no db's are relevant to this elt; or
         (3) MUST_EXIST && NAME was not in the db.
       In (2*), `found' will be NULL.
       In (3),  `found' will be an empty list. */
    if (allow_disk_search && (!found || (must_exist && !STR_LIST (*found)))) {
      str_llist_type *dirs = kpse_element_dirs (elt);
      if (dirs && *dirs) {
        if (!found)
          found = XTALLOC1 (str_list_type);
        *found = dir_list_search (dirs, name, all);
      }
    }
    
    /* Did we find anything anywhere?  */
    if (found && STR_LIST (*found))
      if (all)
        str_list_concat (&ret_list, *found);
      else {
        str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
        done = true;
      }

    /* Free the list space, if any (but not the elements).  */
    if (found) {
      str_list_free (found);
      free (found);
    }
  }

  /* Free the expanded name we were passed.  It can't be in the return
     list, since the path directories got unconditionally prepended.  */
  free (name);
  
  return ret_list;
}      
Пример #18
0
int main(int argc, char **argv)
{
	struct sigaction act_new;

	int sandbox_log_presence = 0;

	struct sandbox_info_t sandbox_info;

	char **sandbox_environ;
	char **argv_bash = NULL;

	char *run_str = "-c";

	/* Only print info if called with no arguments .... */
	if (argc < 2)
		print_debug = 1;
	else {
		/* handle a few common options */
		if (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-V")) {
			puts(
				"Gentoo path sandbox\n"
				" version: " PACKAGE_VERSION "\n"
				" C lib:   " LIBC_VERSION " (" LIBC_PATH ")\n"
				" build:   " __DATE__ " " __TIME__ "\n"
				" contact: " PACKAGE_BUGREPORT " via http://bugs.gentoo.org/\n"
				" rtld:    "
#ifdef BROKEN_RTLD_NEXT
					"next is broken ;(\n"
#else
					"next is OK! :D\n"
#endif
#ifndef SB_SCHIZO
# define SB_SCHIZO "no"
#endif
				" schizo:  " SB_SCHIZO "\n"
				"\nconfigured with these options:\n"
				SANDBOX_CONFIGURE_OPTS
			);
			return 0;
		} else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
			puts(
				"Usage: sandbox [program [program args...]]\n"
				"\n"
				"Sandbox will start up a sandbox session and execute the specified program.\n"
				"If no program is specified, an interactive shell is automatically launched.\n"
				"You can use this to quickly test out sandbox behavior.\n"
				"\n"
				"Upon startup, initial settings are taken from these files / directories:\n"
				"\t" SANDBOX_CONF_FILE "\n"
				"\t" SANDBOX_CONFD_DIR "\n"
				"\n"
				"Contact: " PACKAGE_BUGREPORT " via http://bugs.gentoo.org/"
			);
			return 0;
		}
	}

	dputs(sandbox_banner);

	/* check if a sandbox is already running */
	if (!is_env_on(ENV_SANDBOX_TESTING))
		if (NULL != getenv(ENV_SANDBOX_ACTIVE))
			sb_err("not launching a new sandbox as one is already running in this process hierarchy");

	/* determine the location of all the sandbox support files */
	dputs("Detection of the support files.");

	if (-1 == setup_sandbox(&sandbox_info, print_debug))
		sb_err("failed to setup sandbox");

	/* verify the existance of required files */
	dputs("Verification of the required files.");

	if (!rc_file_exists(sandbox_info.sandbox_rc))
		sb_perr("could not open the sandbox rc file: %s", sandbox_info.sandbox_rc);

	/* set up the required environment variables */
	dputs("Setting up the required environment variables.");

	/* If not in portage, cd into it work directory */
	if ('\0' != sandbox_info.work_dir[0])
		if (chdir(sandbox_info.work_dir))
			sb_perr("chdir(%s) failed", sandbox_info.work_dir);

	/* Setup the child environment stuff.
	 * XXX:  We free this in spawn_shell(). */
	sandbox_environ = setup_environ(&sandbox_info, print_debug);
	if (NULL == sandbox_environ)
		goto oom_error;

	/* Setup bash argv */
	str_list_add_item_copy(argv_bash, "/bin/bash", oom_error);
	str_list_add_item_copy(argv_bash, "-rcfile", oom_error);
	str_list_add_item_copy(argv_bash, sandbox_info.sandbox_rc, oom_error);
	if (argc >= 2) {
		int i;

		str_list_add_item_copy(argv_bash, run_str, oom_error);
		str_list_add_item_copy(argv_bash, argv[1], oom_error);
		for (i = 2; i < argc; i++) {
			char *tmp_ptr;

			tmp_ptr = xrealloc(argv_bash[4],
					   (strlen(argv_bash[4]) +
					    strlen(argv[i]) + 2) *
					   sizeof(char));
			argv_bash[4] = tmp_ptr;

			snprintf(argv_bash[4] + strlen(argv_bash[4]),
				 strlen(argv[i]) + 2, " %s",
				 argv[i]);
		}
	}

	/* set up the required signal handlers ... but allow SIGHUP to be
	 * ignored in case people are running `nohup ...` #217898
	 */
	if (signal(SIGHUP, &stop) == SIG_IGN)
		signal(SIGHUP, SIG_IGN);
#define wsignal(sig, act) \
	do { \
		sighandler_t _old = signal(sig, act); \
		if (_old == SIG_ERR) \
			sb_pwarn("unable to bind signal %s", #sig); \
		else if (_old != SIG_DFL && _old != SIG_IGN) \
			sb_warn("signal %s already had a handler ...", #sig); \
	} while (0)
	wsignal(SIGINT, &stop);
	wsignal(SIGQUIT, &stop);
	wsignal(SIGTERM, &stop);
	act_new.sa_sigaction = usr1_handler;
	sigemptyset (&act_new.sa_mask);
	act_new.sa_flags = SA_SIGINFO | SA_RESTART;
	sigaction (SIGUSR1, &act_new, NULL);

	/* STARTING PROTECTED ENVIRONMENT */
	dputs("The protected environment has been started.");
	dputs(sandbox_footer);
	dputs("Process being started in forked instance.");

	/* Start Bash */
	int shell_exit = spawn_shell(argv_bash, sandbox_environ, print_debug);

	/* As spawn_shell() free both argv_bash and sandbox_environ, make sure
	 * we do not run into issues in future if we need a OOM error below
	 * this ... */
	argv_bash = NULL;
	sandbox_environ = NULL;

	dputs("Cleaning up sandbox process");
	dputs(sandbox_banner);
	dputs("The protected environment has been shut down.");

	if (rc_file_exists(sandbox_info.sandbox_log)) {
		sandbox_log_presence = 1;
		print_sandbox_log(sandbox_info.sandbox_log);
	} else
		dputs(sandbox_footer);

	if (!is_env_on(ENV_SANDBOX_TESTING))
		if (sandbox_log_presence && shell_exit == 0)
			shell_exit = 1;
	return shell_exit;

oom_error:
	if (NULL != argv_bash)
		str_list_free(argv_bash);

	sb_perr("out of memory (environ)");
}