int chroot( const char *pathname ) { int result; rtems_filesystem_location_info_t loc; /* an automatic call to new private env the first time */ if (rtems_current_user_env == &rtems_global_user_env) { rtems_libio_set_private_env(); /* try to set a new private env*/ if (rtems_current_user_env == &rtems_global_user_env) /* not ok */ rtems_set_errno_and_return_minus_one( ENOTSUP ); }; result = chdir(pathname); if (result) { rtems_set_errno_and_return_minus_one( errno ); }; /* clone the new root location */ if (rtems_filesystem_evaluate_path(".", 0, &loc, 0)) { /* our cwd has changed, though - but there is no easy way of return :-( */ rtems_set_errno_and_return_minus_one( errno ); } rtems_filesystem_freenode(&rtems_filesystem_root); rtems_filesystem_root = loc; return 0; }
int main( int argc, char **argv ) #endif { int status; /* * This test is the C equivalent of this sequence. #mkdir /one #mkdir /one/one #touch /one/one.test #touch /one/two/two.test #chroot /one #if !fileexists(/one/one.test) echo "SUCCESSFUL" #if fileexists(/two/two.test) echo "SUCCESSFUL" #rtems_set_private_env() ! reset at the global environment #if fileexists(/one/one.test) echo "SUCESSFUL" #if !fileexists(/two/two.test) echo "SUCCESSFUL" */ printf( "\n\n*** CHROOT01 TEST ***\n" ); status = mkdir( "/one", 0777); rtems_test_assert( status == 0 ); status = mkdir( "/one/one", 0777); rtems_test_assert( status == 0 ); status = mkdir( "/one/two", 0777); rtems_test_assert( status == 0 ); touch( "/one/one.test" ); touch( "/one/two/two.test" ); status = chroot( "/one" ); rtems_test_assert( status == 0 ); status = fileexists( "/one/one.test" ); printf( "%s on /one/one.test\n", (!status) ? "SUCCESS" : "FAILURE" ); status = fileexists( "/two/two.test" ); printf( "%s on /two/two.test\n", (status) ? "SUCCESS" : "FAILURE" ); puts( "Reset the private environment" ); rtems_libio_set_private_env(); status = fileexists( "/one/one.test" ); printf( "%s on /one/one.test\n", ( status) ? "SUCCESS" : "FAILURE" ); status = fileexists( "/two/two.test" ); printf( "%s on /two/two.test\n", (!status) ? "SUCCESS" : "FAILURE" ); printf( "*** END OF CHROOT01 TEST ***\n" ); rtems_test_exit(0); }
/*PAGE * * session * * This task handles single session. It is waked up when the FTP daemon gets a * service request from a remote machine. Here, we watch for commands that * will come through the control connection. These commands are then parsed * and executed until the connection is closed, either unintentionally or * intentionally with the "QUIT" command. * * Input parameters: * arg - pointer to corresponding SessionInfo. * * Output parameters: * NONE */ static void session(rtems_task_argument arg) { FTPD_SessionInfo_t *const info = (FTPD_SessionInfo_t *)arg; int chroot_made = 0; rtems_libio_set_private_env(); /* chroot() can fail here because the directory may not exist yet. */ chroot_made = chroot(ftpd_root) == 0; while(1) { rtems_event_set set; rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &set); chroot_made = chroot_made || chroot(ftpd_root) == 0; chdir("/"); errno = 0; send_reply(info, 220, FTPD_SERVER_MESSAGE); while (1) { char buf[FTPD_BUFSIZE]; char *cmd, *opts, *args; if (fgets(buf, FTPD_BUFSIZE, info->ctrl_fp) == NULL) { syslog(LOG_INFO, "ftpd: Connection aborted."); break; } split_command(buf, &cmd, &opts, &args); if (!strcmp("QUIT", cmd)) { send_reply(info, 221, "Goodbye."); break; } else { exec_command(info, cmd, args); } } /* Close connection and put ourselves back into the task pool. */ close_data_socket(info); close_stream(info); task_pool_release(info); } }
rtems_task task_routine( rtems_task_argument not_used ) { rtems_status_code sc; puts( "task_routine - setting up a private environment" ); sc = rtems_libio_set_private_env(); directive_failed( sc, "set private env" ); sleep( 1 ); rtems_task_delete( RTEMS_SELF ); }
bool rtems_shell_main_loop( rtems_shell_env_t *shell_env_arg ) { rtems_shell_env_t *shell_env; rtems_shell_cmd_t *shell_cmd; rtems_status_code sc; struct termios term; struct termios previous_term; char *prompt = NULL; int cmd; int cmd_count = 1; /* assume a script and so only 1 command line */ char *cmds[RTEMS_SHELL_CMD_COUNT]; char *cmd_argv; int argc; char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS]; bool result = true; bool input_file = false; int line = 0; FILE *stdinToClose = NULL; FILE *stdoutToClose = NULL; rtems_shell_initialize_command_set(); shell_env = rtems_current_shell_env = rtems_shell_init_env( shell_env_arg ); /* * @todo chrisj * Remove the use of task variables. Change to have a single * allocation per shell and then set into a notepad register * in the TCB. Provide a function to return the pointer. * Task variables are a virus to embedded systems software. */ sc = rtems_task_variable_add( RTEMS_SELF, (void*)&rtems_current_shell_env, rtems_shell_env_free ); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_task_variable_add(current_shell_env):"); return false; } setuid(0); setgid(0); rtems_current_user_env->euid = rtems_current_user_env->egid = 0; fileno(stdout); /* fprintf( stderr, "-%s-%s-\n", shell_env->input, shell_env->output ); */ if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) { if (strcmp(shell_env->output, "stderr") == 0) { stdout = stderr; } else if (strcmp(shell_env->output, "/dev/null") == 0) { fclose (stdout); } else { FILE *output = fopen(shell_env_arg->output, shell_env_arg->output_append ? "a" : "w"); if (!output) { fprintf(stderr, "shell: open output %s failed: %s\n", shell_env_arg->output, strerror(errno)); return false; } stdout = output; stdoutToClose = output; } } if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) { FILE *input = fopen(shell_env_arg->input, "r"); if (!input) { fprintf(stderr, "shell: open input %s failed: %s\n", shell_env_arg->input, strerror(errno)); return false; } stdin = input; stdinToClose = input; shell_env->forever = false; input_file =true; } else { /* make a raw terminal,Linux Manuals */ if (tcgetattr(fileno(stdin), &previous_term) >= 0) { term = previous_term; term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); term.c_oflag &= ~OPOST; term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); term.c_cflag |= CLOCAL | CREAD; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) { fprintf(stderr, "shell:cannot set terminal attributes(%s)\n",shell_env->devname); } } cmd_count = RTEMS_SHELL_CMD_COUNT; prompt = malloc(RTEMS_SHELL_PROMPT_SIZE); if (!prompt) fprintf(stderr, "shell:cannot allocate prompt memory\n"); } setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/ rtems_shell_initialize_command_set(); /* * Allocate the command line buffers. */ cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE); if (!cmd_argv) { fprintf(stderr, "no memory for command line buffers\n" ); } cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE); if (!cmds[0]) { fprintf(stderr, "no memory for command line buffers\n" ); } if (cmd_argv && cmds[0]) { memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); for (cmd = 1; cmd < cmd_count; cmd++) { cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE; } do { /* Set again root user and root filesystem, side effect of set_priv..*/ sc = rtems_libio_set_private_env(); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_libio_set_private_env():"); result = false; break; } /* * By using result here, we can fall to the bottom of the * loop when the connection is dropped during login and * keep on trucking. */ if (shell_env->login_check != NULL) { result = rtems_shell_login(stdin,stdout); } else { result = true; } if (result) { const char *c; memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); if (!input_file) { rtems_shell_cat_file(stdout,"/etc/motd"); fprintf(stdout, "\n" "RTEMS SHELL (Ver.1.0-FRC):%s. " \ __DATE__". 'help' to list commands.\n", shell_env->devname); } if (input_file) chdir(shell_env->cwd); else chdir("/"); /* XXX: chdir to getpwent homedir */ shell_env->exit_shell = false; for (;;) { int cmd; /* Prompt section */ if (prompt) { rtems_shell_get_prompt(shell_env, prompt, RTEMS_SHELL_PROMPT_SIZE); } /* getcmd section */ cmd = rtems_shell_line_editor(cmds, cmd_count, RTEMS_SHELL_CMD_SIZE, prompt, stdin, stdout); if (cmd == -1) continue; /* empty line */ if (cmd == -2) break; /*EOF*/ line++; if (shell_env->echo) fprintf(stdout, "%d: %s\n", line, cmds[cmd]); /* evaluate cmd section */ c = cmds[cmd]; while (*c) { if (!isblank((unsigned char)*c)) break; c++; } if (*c == '\0') /* empty line */ continue; if (*c == '#') { /* comment character */ cmds[cmd][0] = 0; continue; } if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) { fprintf(stdout, "Shell exiting\n" ); break; } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */ fprintf(stdout, "System shutting down at user request\n" ); exit(0); } /* exec cmd section */ /* TODO: * To avoid user crash catch the signals. * Open a new stdio files with posibility of redirection * * Run in a new shell task background. (unix &) * Resuming. A little bash. */ memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE); if (!rtems_shell_make_args(cmd_argv, &argc, argv, RTEMS_SHELL_MAXIMUM_ARGUMENTS)) { shell_cmd = rtems_shell_lookup_cmd(argv[0]); if ( argv[0] == NULL ) { shell_env->errorlevel = -1; } else if ( shell_cmd == NULL ) { shell_env->errorlevel = rtems_shell_script_file(argc, argv); } else { shell_env->errorlevel = shell_cmd->command(argc, argv); } } /* end exec cmd section */ if (shell_env->exit_shell) break; } fflush( stdout ); fflush( stderr ); } } while (result && shell_env->forever); } if (cmds[0]) free (cmds[0]); if (cmd_argv) free (cmd_argv); if (prompt) free (prompt); if (stdinToClose) { fclose( stdinToClose ); } else { if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) { fprintf( stderr, "shell: cannot reset terminal attributes (%s)\n", shell_env->devname ); } } if ( stdoutToClose ) fclose( stdoutToClose ); return result; }
rtems_task Init( rtems_task_argument argument ) { rtems_status_code sc; void *opaque; rtems_id current_task_id; rtems_id task_id; rtems_name another_task_name; Heap_Information_block Info; puts( "\n\n*** TEST USER ENVIRONMENT ROUTINE - 01 ***" ); puts( "Init - allocating most of heap -- OK" ); opaque = rtems_heap_greedy_allocate( 0 ); puts( "Init - attempt to reset env - expect RTEMS_NO_MEMORY" ); sc = rtems_libio_set_private_env(); rtems_test_assert( sc == RTEMS_NO_MEMORY ); puts( "Init - freeing the allocated memory" ); rtems_heap_greedy_free( opaque ); puts( "Init - allocating most of workspace memory" ); opaque = rtems_workspace_greedy_allocate( 0 ); puts( "Init - attempt to reset env - expect RTEMS_TOO_MANY" ); sc = rtems_libio_set_private_env(); rtems_test_assert( sc == RTEMS_TOO_MANY ); puts( "Init - freeing the workspace memory" ); rtems_workspace_greedy_free( opaque ); puts( "Init - creating a task name and a task -- OK" ); another_task_name = rtems_build_name( 'T','S','K','D' ); sc = rtems_task_create( another_task_name, 1, RTEMS_MINIMUM_STACK_SIZE * 2, RTEMS_INTERRUPT_LEVEL(31), RTEMS_DEFAULT_ATTRIBUTES, &task_id ); puts( "Init - starting the task_routine, to set its private environment" ); sc = rtems_task_start( task_id, task_routine, 0); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); puts( "Init - attempt to share the env with another task -- Expect error" ); sc = rtems_libio_share_private_env( task_id ); rtems_test_assert( sc == RTEMS_UNSATISFIED ); sleep( 1 ); puts( "Init - attempt to share the env with another task -- OK" ); sc = rtems_libio_share_private_env( task_id ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( rtems_current_user_env->task_id == task_id ); puts( "Init - Get current task id" ); current_task_id = rtems_task_self(); puts( "Init - Attempt to reset current task's environment" ); sc = rtems_libio_set_private_env(); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( rtems_current_user_env->task_id == current_task_id ); puts( "Init - attempt to share the env with another task -- OK" ); sc = rtems_libio_share_private_env( task_id ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( rtems_current_user_env->task_id == task_id ); puts( "Init - attempt to share with self -- OK" ); sc = rtems_libio_share_private_env( task_id ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); puts( "*** END OF TEST USER ENVIRONMENT ROUTINE - 01 ***" ); rtems_test_exit(0); }
/* utility wrapper */ static void spawned_shell(void *targ) { rtems_status_code sc; FILE *nstd[3]={0}; FILE *ostd[3]={ stdin, stdout, stderr }; int i=0; struct shell_args *arg = targ; bool login_failed = false; bool start = true; sc=rtems_libio_set_private_env(); /* newlib hack/workaround. Before we change stdin/out/err we must make * sure the internal data are initialized (fileno(stdout) has this sideeffect). * This should probably be done from RTEMS' libc support layer... * (T.S., newlibc-1.13; 2005/10) */ fileno(stdout); if (RTEMS_SUCCESSFUL != sc) { rtems_error(sc,"rtems_libio_set_private_env"); goto cleanup; } /* redirect stdio */ for (i=0; i<3; i++) { if ( !(nstd[i]=fopen(arg->devname,"r+")) ) { perror("unable to open stdio"); goto cleanup; } } stdin = nstd[0]; stdout = nstd[1]; stderr = nstd[2]; #if 0 printk("STDOUT is now %x (%x) (FD %i/%i)\n", stdout,nstd[1],fileno(stdout),fileno(nstd[1])); printf("hello\n"); write(fileno(stdout),"hellofd\n",8); #endif /* call their routine */ if (rtems_telnetd_config.login_check != NULL) { start = rtems_shell_login_prompt( stdin, stderr, arg->devname, rtems_telnetd_config.login_check ); login_failed = !start; } if (start) { rtems_telnetd_config.command( arg->devname, arg->arg); } stdin = ostd[0]; stdout = ostd[1]; stderr = ostd[2]; if (login_failed) { syslog( LOG_AUTHPRIV | LOG_WARNING, "telnetd: to many wrong passwords entered from %s", arg->peername ); } cleanup: release_a_Connection(arg->devname, arg->peername, nstd, i); free(arg); }
rtems_task Init( rtems_task_argument ignored ) { GetLine *gl = 0; char *symf = 0, *sysscr=0, *user_script=0, *bufp; int argc = 0; int result = 0; int no_net = 0; char *dfltSrv = 0; char *pathspec = 0; #ifdef NFS_SUPPORT MntDescRec bootmnt = { "/boot", 0, 0 }; MntDescRec homemnt = { "/home", 0, 0 }; #endif char *argv[7]={ "Cexp", /* program name */ 0, 0, 0, 0 }; rtems_libio_set_private_env(); #ifdef HAVE_PCIBIOS #if RTEMS_VERSION_ATLEAST(4,6,99) pci_initialize(); #else pcib_init(); #endif #endif #ifdef STACK_CHECKER_ON { extern void Stack_check_Initialize(); Stack_check_Initialize(); } #endif #ifdef HAVE_LIBBSPEXT bspExtInit(); #endif /* make /tmp directory */ mkTmpDir(); printf("Welcome to RTEMS GeSys\n"); printf("This system $Name: GeSys_2_4 $ was built on %s\n",system_build_date); printf("$Id: init.c,v 1.43 2008/03/22 20:36:13 guest Exp $\n"); #ifdef EARLY_CMDLINE_GET { char *cmdlinetmp; EARLY_CMDLINE_GET(&cmdlinetmp); #ifdef HAVE_LIBNETBOOT /* Let libnetboot process the command line string; all * special name=value pairs recognized by libnetboot will * be removed... */ nvramFixupBsdnetConfig(1, cmdlinetmp); #endif cmdlinePairExtract(cmdlinetmp, putenv, 1); } #endif #if defined(USE_TECLA) /* * Install our special line discipline which implements * TIOCGWINSZ */ printf("Installing TIOCGWINSZ line discipline: %s.\n", ansiTiocGwinszInstall(7) ? "failed" : "ok"); #endif /* * Make sure the time-of-day clock is at least initialized. * The dummy routine just sets the date to 1/1/2000 */ dummy_clock_init(); cexpInit(cexpExcHandlerInstall); printf("To skip initialization, press a key now..."); fflush(stdout); if ( getchar_timeout(fileno(stdin),10) > 0 ) { printf("OK; skipping to shell"); no_net = 1; argc = 1; } printf("\n"); #ifndef CDROM_IMAGE #ifndef SKIP_NETINI #define SKIP_NETINI getenv("SKIP_NETINI") #endif /* check if we have a real ifconfig (first is loopback) */ if ( !no_net && (! (SKIP_NETINI) || !BUILTIN_SYMTAB) && rtems_bsdnet_config.ifconfig ) { gesys_network_start(); } else { fprintf(stderr,"Skipping network initialization - you can do it manually\n"); fprintf(stderr,"by invoking 'gesys_network_start()' (needs BOOTP/DHCP server)\n"); argc = 1; no_net = 1; } #endif #ifndef CDROM_IMAGE if ( BOOTPFN ) { char *slash,*dot; pathspec = malloc(strlen(BOOTPFN) + (BUILTIN_SYMTAB ? strlen(SYSSCRIPT) : strlen(SYMEXT)) + 1); strcpy(pathspec, BOOTPFN); slash = strrchr(pathspec,'/'); if ( BUILTIN_SYMTAB ) { if ( slash ) strcpy(slash+1,SYSSCRIPT); else strcpy(pathspec,SYSSCRIPT); } else { dot = strrchr(pathspec,'.'); if (slash>dot) dot=0; /* substitute suffix */ if (dot) { strcpy(dot,SYMEXT); } else { strcat(pathspec,SYMEXT); } } } { char *tarvar; void *addr; int len; if ( (tarvar=getenv("TARFS")) && 2 == sscanf(tarvar,"%p:%i",&addr,&len) && len > 0 ) { mkdir("/tar",0777); rtems_tarfs_load("/tar",addr,len); } } #else { extern void *gesys_tarfs_image_start; extern unsigned long gesys_tarfs_image_size; printf("Loading TARFS... %s\n", rtems_tarfs_load("/tmp", gesys_tarfs_image_start, gesys_tarfs_image_size) ? "FAILED" : "OK"); pathspec=strdup(BUILTIN_SYMTAB ? "/tmp/"SYSSCRIPT : "/tmp/rtems.sym"); } #endif dflt_fname = "rtems.sym"; #ifdef TFTP_SUPPORT path_prefix = strdup("/TFTP/BOOTP_HOST/"); #elif defined(NFS_SUPPORT) path_prefix = strdup(":/remote/rtems:"); #elif defined(RSH_SUPPORT) path_prefix = strdup("~rtems/"); #endif getDfltSrv(&dfltSrv); #ifdef PSIM { extern int loadTarImg(int verbose, int lun); if ( !pathspec ) { loadTarImg(1, 0); pathspec = strdup("/bin/"SYSSCRIPT); } else { fprintf(stderr,"PSIM: root tarfs not loaded (pathspec was '%s')\n",pathspec); } } #endif if ( no_net && ( !pathspec || LOCAL_PATH != pathType(pathspec) ) ) goto shell_entry; /* omit prompting for the symbol file */ if ( pathspec ) goto firstTimeEntry; /* no pathspec but a builtin symtab -> * skip reading symtab / system script */ if ( BUILTIN_SYMTAB ) goto bare_entry; do { chdir("/"); #ifdef NFS_SUPPORT if ( releaseMount( &bootmnt ) ) { fprintf(stderr,"Unable to unmount /boot NFS - don't know what to do, sorry\n"); break; } #endif freeps(&symf); freeps(&user_script); if (!gl) { assert( gl = new_GetLine(LINE_LENGTH, 10*LINE_LENGTH) ); /* silence warnings about missing .teclarc */ gl_configure_getline(gl,0,0,0); } do { printf("Symbol file can be loaded by:\n"); #ifdef NFS_SUPPORT printf(" NFS: [<uid>.<gid>@][<host>]:<export_path>:<symfile_path>\n"); #endif #ifdef TFTP_SUPPORT printf(" TFTP: [/TFTP/<host_ip>]<symfile_path>\n"); #endif #ifdef RSH_SUPPORT printf(" RSH: [<host>:]~<user>/<symfile_path>\n"); #endif #ifdef USE_TECLA bufp = gl_get_line(gl, "Enter Symbol File Name: ", pathspec, ( pathspec && *pathspec ) ? strlen(pathspec) : 0 ); #else bufp = my_getline(gl, "Enter Symbol File Name: ", LINE_LENGTH); #endif } while (!bufp || !*bufp); pathspec = realloc(pathspec, strlen(bufp) + 1); strcpy(pathspec, bufp); bufp = pathspec + strlen(bufp) - 1; while ( bufp >= pathspec && ('\n' == *bufp || '\r' == *bufp) ) *bufp-- = 0; firstTimeEntry: { int fd = -1, ed = -1; char *slash; getDfltSrv( &dfltSrv ); #ifdef TFTP_SUPPORT chdir("/TFTP/BOOTP_HOST/"); #endif switch ( pathType(pathspec) ) { case LOCAL_PATH: fd = open(pathspec,O_RDONLY); if ( fd >= 0 ) symf = strdup(pathspec); break; #ifdef TFTP_SUPPORT case TFTP_PATH: fd = isTftpPath( &dfltSrv, pathspec, &ed, &symf ); break; #endif #ifdef NFS_SUPPORT case NFS_PATH: fd = isNfsPath( &dfltSrv, pathspec, &ed, &symf, &bootmnt ); break; #endif #ifdef RSH_SUPPORT case RSH_PATH: fd = rshCopy( &dfltSrv, pathspec, &symf ); break; #endif default: fprintf(stderr,"Unrecognized pathspec; maybe remote FS support is not compiled in ?\n"); break; } if ( 0==result && dfltSrv ) { /* allow the default server to be overridden by the pathspec * during the first pass (original pathspec from boot) */ theSrv = strdup(dfltSrv); } if ( (fd < 0) && !BUILTIN_SYMTAB ) { fprintf(stderr,"Unable to open symbol file (%s)\n", -11 == fd ? "not a valid pathspec" : strerror(errno)); continue; } if ( fd >= 0 ) close(fd); if ( ed >= 0 ) close(ed); freeps( &sysscr ); sysscr = strdup(SYSSCRIPT); #if defined(RSH_SUPPORT) && !defined(CDROM_IMAGE) if ( !ISONTMP(symf) ) { #endif if ( (slash = strrchr(symf,'/')) ) { int ch=*(slash+1); *(slash+1)=0; printf("Change Dir to '%s'",symf); if ( chdir(symf) ) printf(" FAILED: %s",strerror(errno)); fputc('\n',stdout); *(slash+1)=ch; } #if defined(RSH_SUPPORT) && !defined(CDROM_IMAGE) } else { char *scrspec = malloc( strlen(pathspec) + strlen(SYSSCRIPT) + 1); strcpy(scrspec, pathspec); if ( (slash = strrchr(scrspec, '/')) ) strcpy( slash+1, SYSSCRIPT ); else strcpy( scrspec, SYSSCRIPT ); getDfltSrv( &dfltSrv ); freeps( &sysscr ); if ( (fd = rshCopy( &dfltSrv, scrspec, &sysscr )) >= 0 ) { close( fd ); } else { freeps( &sysscr ); } freeps(&scrspec); } #endif bare_entry: printf("Trying symfile '%s', system script '%s'\n", BUILTIN_SYMTAB ? "BUILTIN" : symf, sysscr ? sysscr :"(NONE)"); argc = 1; #ifdef DEFAULT_CPU_ARCH_FOR_CEXP if ( DEFAULT_CPU_ARCH_FOR_CEXP && *DEFAULT_CPU_ARCH_FOR_CEXP ) { argv[argc++] = "-a"; argv[argc++] = DEFAULT_CPU_ARCH_FOR_CEXP; } #endif if ( !BUILTIN_SYMTAB ) { argv[argc++] = "-s"; argv[argc++] = symf; } if ( sysscr ) { argv[argc++] = sysscr; } shell_entry: result = argc > 1 ? cexp_main(argc, argv) : 0; if ( ISONTMP( symf ) ) unlink( symf ); if ( sysscr && ISONTMP( sysscr ) ) unlink( sysscr ); freeps(&symf); freeps(&sysscr); if (!result || CEXP_MAIN_NO_SCRIPT==result) { int rc; if (gl) { del_GetLine(gl); gl = 0; } freeps(&pathspec); /* try a user script */ if ((user_script=getenv("INIT"))) { printf("Trying user script '%s':\n",user_script); pathspec = strdup(user_script); user_script = 0; getDfltSrv(&dfltSrv); switch ( pathType( pathspec ) ) { #ifdef NFS_SUPPORT case NFS_PATH: if ( 0 == (rc = isNfsPath( &dfltSrv, pathspec, 0, &user_script, &homemnt ) ) ) { /* valid NFS path; try to mount; */ if ( !bootmnt.uidhost || strcmp( homemnt.uidhost, bootmnt.uidhost ) || !bootmnt.rpath || strcmp( homemnt.rpath , bootmnt.rpath ) ) rc = nfsMount(homemnt.uidhost, homemnt.rpath, homemnt.mntpt); } break; #endif case RSH_PATH: fprintf(stderr,"RSH download of user scripts is not supported\n"); rc = -1; break; #ifdef TFTP_SUPPORT case TFTP_PATH: rc = isTftpPath( &dfltSrv, pathspec, 0, &user_script ); break; #endif case LOCAL_PATH: /* they might refer to a path on the local FS (already mounted NFS) */ user_script = pathspec; pathspec = 0; rc = 0; break; default: fprintf(stderr,"Invalid path specifier; support for remote FS not compiled in?\n"); rc = -1; break; } freeps(&pathspec); argc = 2; if ( rc ) { fprintf(stderr,"Unable to determine filesystem for user script\n"); freeps(&user_script); argc = 1; } else { if ((slash = strrchr(user_script,'/'))) { /* chdir to where the user script resides */ int ch=*(++slash); *(slash)=0; printf("Change Dir to '%s'\n",user_script); chdir(user_script); *(slash)=ch; argv[1]=slash; } else { argv[1]=user_script; } } argc=2; } else { argc=1; } do { result=cexp_main(argc,argv); argc=1; freeps(&user_script); } while (!result || CEXP_MAIN_NO_SCRIPT==result); chdir("/"); #ifdef NFS_SUPPORT releaseMount( &homemnt ); #endif } } switch (result) { case CEXP_MAIN_NO_SYMS : fprintf(stderr,"CEXP_MAIN_NO_SYMS\n"); result = 0; break; case CEXP_MAIN_INVAL_ARG: fprintf(stderr,"CEXP_MAIN_INVAL_ARG\n"); break; case CEXP_MAIN_NO_SCRIPT: fprintf(stderr,"CEXP_MAIN_NO_SCRIPT\n"); break; case CEXP_MAIN_KILLED : fprintf(stderr,"CEXP_MAIN_KILLED\n"); break; case CEXP_MAIN_NO_MEM : fprintf(stderr,"CEXP_MAIN_NO_MEM\n"); break; default: if (result) fprintf(stderr,"unknown error\n"); } } while ( !result ); /* retry asking for a sym-filename */ if (gl) { del_GetLine(gl); gl = 0; } fprintf(stderr,"Unable to execute CEXP - suspending initialization...\n"); rtems_task_suspend(RTEMS_SELF); exit( 1 ); }
int chroot( const char *path ) { int rv = 0; rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_filesystem_eval_path_context_t ctx; int eval_flags = RTEMS_FS_PERMS_EXEC | RTEMS_FS_FOLLOW_LINK; rtems_filesystem_location_info_t loc; rtems_filesystem_global_location_t *new_current_loc; /* * We use the global environment for path evaluation. This makes it possible * to escape from a chroot environment referencing an unmounted file system. */ rtems_filesystem_eval_path_start_with_root_and_current( &ctx, path, eval_flags, &rtems_global_user_env.root_directory, &rtems_global_user_env.current_directory ); rtems_filesystem_eval_path_extract_currentloc( &ctx, &loc ); new_current_loc = rtems_filesystem_location_transform_to_global( &loc ); if ( !rtems_filesystem_global_location_is_null( new_current_loc ) ) { rtems_filesystem_global_location_t *new_root_loc = rtems_filesystem_global_location_obtain( &new_current_loc ); rtems_filesystem_node_types_t type = (*new_root_loc->location.mt_entry->ops->node_type_h)( &new_root_loc->location ); if ( type == RTEMS_FILESYSTEM_DIRECTORY ) { sc = rtems_libio_set_private_env(); if (sc == RTEMS_SUCCESSFUL) { rtems_filesystem_global_location_assign( &rtems_filesystem_root, new_root_loc ); rtems_filesystem_global_location_assign( &rtems_filesystem_current, new_current_loc ); } else { if (sc != RTEMS_UNSATISFIED) { errno = ENOMEM; } rv = -1; } } else { rtems_filesystem_location_error( &new_root_loc->location, ENOTDIR ); rv = -1; } if ( rv != 0 ) { rtems_filesystem_global_location_release( new_root_loc ); } } else { rv = -1; } rtems_filesystem_eval_path_cleanup( &ctx ); if ( rv != 0 ) { rtems_filesystem_global_location_release( new_current_loc ); } return rv; }