/** * \brief Updates this state. */ void Hero::GrabbingState::update() { if (is_suspended()) { return; } // the hero is grabbing an obstacle: check the direction pressed int wanted_direction8 = get_commands().get_wanted_direction8(); int sprite_direction8 = get_sprites().get_animation_direction8(); // release the obstacle Hero& hero = get_hero(); if (!get_commands().is_command_pressed(GameCommands::ACTION)) { hero.set_state(new FreeState(hero)); } // push the obstacle else if (wanted_direction8 == sprite_direction8) { hero.set_state(new PushingState(hero)); } // pull the obstacle else if (wanted_direction8 == (sprite_direction8 + 4) % 8) { hero.set_state(new PullingState(hero)); } }
void main(void) { sif= (unsigned char SIF_ADDRESS_SPACE *)0xffff; printf("Testing simulator interface at %s[0x%x]\n", SIF_ADDRESS_SPACE_NAME, SIF_ADDRESS); printf("%s", detect()?"Interface found.":"Interface not found"); if (detect()) { int i; i= get_ifversion(); get_sim_version(); printf(" Version %d (of simulator %s)\n", i, sim_version); get_commands(); printf("Interface knows about %d commands:\n", nuof_commands); for (i= 0; i < nuof_commands; i++) printf("%c", commands[i]); printf("\n"); print_cmd_infos(); sif_print("Message from simulated program: Hello World!\n"); fout_demo("Write this message\n" "to simif output file.\n" "\n" "Done.\n"); fin_demo(); } else printf("\n"); //* (char __idata *) 0 = * (char __xdata *) 0x7654; *sif= SIFCM_STOP; }
static int open_mailto_url( const WCHAR *url ) { #ifdef __APPLE__ static const WCHAR defaultmailers[] = { '/','u','s','r','/','b','i','n','/','o','p','e','n',0,0 }; #else static const WCHAR defaultmailers[] = {'x','d','g','-','e','m','a','i','l',0, 'm','o','z','i','l','l','a','-','t','h','u','n','d','e','r','b','i','r','d',0, 't','h','u','n','d','e','r','b','i','r','d',0, 'e','v','o','l','u','t','i','o','n',0,0 }; #endif static const WCHAR mailersW[] = {'M','a','i','l','e','r','s',0}; WCHAR mailers[256]; HKEY key; LONG r; /* @@ Wine registry key: HKCU\Software\Wine\WineBrowser */ if (!(r = RegOpenKeyW( HKEY_CURRENT_USER, browser_key, &key ))) { r = get_commands( key, mailersW, mailers, sizeof(mailers) ); RegCloseKey( key ); } if (r != ERROR_SUCCESS) memcpy( mailers, defaultmailers, sizeof(defaultmailers) ); return launch_app( mailers, url ); }
/** * \brief Updates this state. */ void Hero::BoomerangState::update() { HeroState::update(); Hero& hero = get_hero(); if (hero.is_animation_finished()) { if (direction_pressed8 == -1) { // the player can press the diagonal arrows before or after the boomerang key direction_pressed8 = get_commands().get_wanted_direction8(); } int boomerang_direction8; if (direction_pressed8 == -1 || direction_pressed8 % 2 == 0) { boomerang_direction8 = get_sprites().get_animation_direction() * 2; } else { boomerang_direction8 = direction_pressed8; } double angle = Geometry::degrees_to_radians(boomerang_direction8 * 45); get_entities().add_entity(std::make_shared<Boomerang>( std::static_pointer_cast<Hero>(get_hero().shared_from_this()), max_distance, speed, angle, sprite_name )); hero.set_state(new FreeState(hero)); } }
void player_connection::handle_read( const boost::system::error_code error, const size_t len ) { if ( error && error != boost::asio::error::eof ) { //LOG_HIGH( SS, "player connection (" << _player_id << ") received an error that was not eof " ); // ASSUME disconnected by mud return; } if( error == boost::asio::error::eof ) { LOG_LOW( SS, "player connection (" << _player_id << ") received eof ") ; _server->lost_link( _player_id ); return; } // I think the handler won't get called until it reads *some* data, unless there is an error. // So if we get this far len shouldn't be 0 assert( len > 0 ); if ( len > 0 ) { // LOG_LOW( SS, "read " << len ); } for( int i = 0 ; i < len ; ++i) { _buf += _raw[i]; } get_commands(); start_read(); }
/** * \brief Updates this state. */ void Hero::SwordSwingingState::update() { State::update(); // check the animation if (get_sprites().is_animation_finished()) { sword_finished = true; if (hero.get_movement() == NULL) { // if the player is still pressing the sword key, start loading the sword if (get_commands().is_command_pressed(GameCommands::ATTACK) && !attacked) { hero.set_state(new SwordLoadingState(hero)); } else { hero.set_state(new FreeState(hero)); } } else { // the sword animation is finished, but the movement continues hero.get_sprites().set_animation_stopped_normal(); } } // check the movement if any if (hero.get_movement() != NULL && hero.get_movement()->is_finished()) { hero.clear_movement(); if (sword_finished) { hero.set_state(new FreeState(hero)); } } }
/** * \brief Updates this state. */ void Hero::SwordLoadingState::update() { PlayerMovementState::update(); if (is_suspended() || !is_current_state()) { return; } uint32_t now = System::now(); // detect when the sword is loaded (i.e. ready for a spin attack) if (!sword_loaded && now >= sword_loaded_date) { play_load_sound(); sword_loaded = true; } if (!get_commands().is_command_pressed(GameCommand::ATTACK)) { // the player has just released the sword key // stop loading the sword, go to the normal state or make a spin attack Hero& hero = get_entity(); if (!sword_loaded) { // the sword was not loaded yet: go to the normal state hero.set_state(new FreeState(hero)); } else { // the sword is loaded: release a spin attack hero.set_state(new SpinAttackState(hero)); } } }
int main(int argc, char **argv) { SpiceCoreInterface *core; Command *commands; int num_commands; int i; Test *test; spice_test_config_parse_args(argc, argv); sized = 0; for (i = 1 ; i < argc; ++i) { if (strcmp(argv[i], "sized") == 0) { sized = 1; } /* render last frame */ if (strcmp(argv[i], "render") == 0) { render_last_frame = 1; } } srand(time(NULL)); // todo: add args list of test numbers with explenations core = basic_event_loop_init(); test = test_new(core); spice_server_set_streaming_video(test->server, SPICE_STREAM_VIDEO_ALL); test_add_display_interface(test); get_commands(&commands, &num_commands); test_set_command_list(test, commands, num_commands); basic_event_loop_mainloop(); free(commands); return 0; }
/** * \brief Updates this state. */ void Hero::PullingState::update() { State::update(); Hero& hero = get_hero(); if (!is_moving_grabbed_entity()) { int wanted_direction8 = get_commands().get_wanted_direction8(); int opposite_direction8 = (get_sprites().get_animation_direction8() + 4) % 8; // stop pulling if the action key is released or if there is no more obstacle if (!get_commands().is_command_pressed(GameCommand::ACTION) || !hero.is_facing_obstacle()) { hero.set_state(new FreeState(hero)); } // stop pulling the obstacle if the player changes his direction else if (wanted_direction8 != opposite_direction8) { hero.set_state(new GrabbingState(hero)); } // see if the obstacle is an entity that the hero can pull else { Detector* facing_entity = hero.get_facing_entity(); if (facing_entity != nullptr) { if (facing_entity->get_type() == EntityType::BLOCK) { // TODO use dynamic binding hero.try_snap_to_facing_entity(); } if (facing_entity->start_movement_by_hero()) { std::string path = " "; path[0] = path[1] = '0' + opposite_direction8; pulling_movement = std::make_shared<PathMovement>( path, 40, false, false, false ); hero.set_movement(pulling_movement); pulled_entity = facing_entity; pulled_entity->notify_moving_by(hero); } } } } }
/** * \brief Updates this state. */ void Hero::SwordTappingState::update() { State::update(); Hero& hero = get_hero(); if (hero.get_movement() == NULL) { // the hero is not being pushed after hitting an enemy const Rectangle& facing_point = hero.get_facing_point(); if (!get_commands().is_command_pressed(GameCommands::ATTACK) || get_commands().get_wanted_direction8() != get_sprites().get_animation_direction8() || !get_map().test_collision_with_obstacles(hero.get_layer(), facing_point.get_x(), facing_point.get_y(), hero)) { // the sword key has been released, the player has moved or the obstacle is gone if (get_sprites().get_current_frame() >= 5) { // when the animation is ok, stop tapping the wall, go back to loading the sword hero.set_state(new SwordLoadingState(hero)); } } else { // play the sound every 100 ms uint32_t now = System::now(); if (get_sprites().get_current_frame() == 3 && now >= next_sound_date) { Detector* facing_entity = hero.get_facing_entity(); std::string sound_id; if (facing_entity != NULL) { sound_id = facing_entity->get_sword_tapping_sound(); } else { sound_id = "sword_tapping"; } Sound::play(sound_id); next_sound_date = now + 100; } } } else if (hero.get_movement()->is_finished()) { // the hero was pushed by an enemy hero.set_state(new FreeState(hero)); } }
/** * \brief Starts this state. * \param previous_state the previous state */ void Hero::BoomerangState::start(const HeroState* previous_state) { HeroState::start(previous_state); if (get_map().get_entities().is_boomerang_present()) { Hero& hero = get_hero(); hero.set_state(new FreeState(hero)); } else { get_sprites().set_animation_boomerang(tunic_preparing_animation); this->direction_pressed8 = get_commands().get_wanted_direction8(); } }
int main(int argc,char *argv[]) { short error; /* general purpose error variable */ int pid; gProcessNumber = atoi(argv[1]); gPid = getpid(); printf("Worker Process %03d is now running. Pid=%d Logfile=%s.\n", gProcessNumber,gPid,argv[3]); // get name of input command file which will be remapped to STDIN // all parms and commands are input through stdin file strcpy(gCommandFile,argv[2]); /* open a log file */ LogInit(argv[3],5); /* print header */ LogMsg(LINEAFTER,"ODBC/SQL/TM Query/Transaction Generator (NOMAD)\n" "Compiled: %s %s\n\n", __DATE__,__TIME__); /* read in command file contents and see what we're supposed to do */ if(get_commands()!=SUCCESS) exit(EXIT_FAILURE); LogMsg(LINEAFTER,"MasterSeed = %d\n",gMasterSeed); /* initialize some globals, find and open required files */ if(initialize()!=0) exit(EXIT_FAILURE); post_status(STARTED); /* get needed info about each of the tables this process will use */ if(get_table_info(gpTableDesc,(short)gTableCount)!=0) exit(EXIT_FAILURE); /* now start the main execution loop */ error=execute_command_list(0,gpList[0]->duration); /*>>> handle error somehow */ /*>>> may not be a need to handle errors if it already posts... */ /*>>>...error messages to the logfile */ post_status(FINISHED); /* perform any clean up */ /*>>> there currently isn't anything to do for clean-up, but later... */ /*>>> ...versions will support this option */ exit(EXIT_SUCCESS); } /* end of main() */
int help(int argc, const char** argv) { shell_func func; //Check if they are trying to find help for a particular command if (argc > 1) { func = get_help(argv[1]); if (func == NULL) { putstr("Sorry no help exists for the command '"); putstr(argv[1]); putstr("'\n"); } else { func(argc, (const char **)argv); } } else { //List all possible commands putstr("Available commands:"); putoptions(get_commands("")); putch('\n'); } return 0; }
/** * @brief Updates this state. */ void Hero::ConveyorBeltState::update() { State::update(); if (suspended) { return; } if (snapping && hero.get_movement()->is_finished()) { // the hero is now exactly placed on the conveyor belt: start the conveyor belt's movement snapping = false; std::string path = " "; path[0] = path[1] = '0' + conveyor_belt.get_direction(); hero.clear_movement(); hero.set_movement(new PathMovement(path, 64, false, false, false)); } else { // see if the conveyor belt's movement is finished if (hero.get_movement()->is_finished() || !hero.on_conveyor_belt) { hero.set_state(new FreeState(hero)); } else { // update the sprites direction int keys_direction8 = get_commands().get_wanted_direction8(); int movement_direction8 = conveyor_belt.get_direction(); int animation_direction = get_sprites().get_animation_direction(keys_direction8, movement_direction8); if (animation_direction != get_sprites().get_animation_direction() && animation_direction != -1) { get_sprites().set_animation_direction(animation_direction); } } hero.on_conveyor_belt = false; } }
/* @details -# scan the incoming message for the command and requested path -# start the return message with a "{" -# if both a command and request is present -# if the command is "GET" -# if the path is "/" call get_top_page -# else if the path starts with "/vars" call get_vars -# else if the path starts with "/commands" call get_commands -# else create an error message reply -# else if the command is "POST" do something at some point. -# else create an error message reply -# else create an error message reply -# close the return message with a "}" -# create the http header for the reply message -# call tc_write to send the reply message */ void Trick::JSONVariableServerThread::parse_request() { // Need to protect against buffer overflow char command[32] ; char path[512] ; std::stringstream ss ; std::stringstream body ; int ret ; ret = sscanf(incoming_msg, "%s %s", command , path) ; body << "{" << std::endl ; if ( ret == 2 ) { //std::cout << "command = " << command << std::endl ; //std::cout << "path = " << path << std::endl ; if ( ! strcmp(command, "GET") ) { if ( ! strcmp(path, "/") ) { // send the top page ret = get_top_page(body) ; } else if ( ! strncmp(path, "/vars", 5)) { // get list of variables or value ret = get_vars(body, &path[5]) ; } else if ( ! strncmp(path, "/commands", 9)) { // get list of commands ret = get_commands(body, &path[9]) ; } else { ret = 404 ; body << " \"name\" : \"" << path << "\" ," << std::endl ; body << " \"message\" : \"Not Found\"" << std::endl ; } } else if ( ! strcmp( command, "POST") ) { //TODO: Allow setting variable values with POST. ret = 405 ; body << " \"verb\" : \"" << command << "\" ," << std::endl ; body << " \"message\" : \"Method not allowed\"" << std::endl ; } else { ret = 405 ; body << " \"verb\" : \"" << command << "\" ," << std::endl ; body << " \"message\" : \"Method not allowed\"" << std::endl ; } } else { ret = 400 ; body << " \"message\" : \"Bad Request\"" << std::endl ; } body << "}" << std::endl ; ss << "HTTP/1.1 " << ret ; switch (ret) { case 200: ss << " OK" ; break ; case 400: ss << " Bad Request" ; break ; case 404: ss << " Not Found" ; break ; case 405: ss << " Method Not Allowed" ; break ; default: ss << " Unknown" ; break ; } ss << std::endl ; ss << "Content-Type: application/json" << std::endl ; ss << "Content-Length: " << body.str().size() << std::endl << std::endl ; ss << body.str() ; //std::cout << ss.str() ; tc_write(&connection, (char *)ss.str().c_str() , ss.str().size()) ; }
int main(int argc, char **argv, char **envp) { tnfctl_errcode_t err = TNFCTL_ERR_NONE; int sys_err; tnfctl_trace_attrs_t trace_attrs; tnfctl_event_t event = TNFCTL_EVENT_EINTR; pid_t prex_pid; /* internationalization stuff */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); g_argv = argv; prex_pid = getpid(); #if defined(DEBUG) fprintf(stderr, "### prex_pid = %d ###\n", prex_pid); #endif prex_dmodel = get_data_model(prex_pid); #if defined(DEBUG) fprintf(stderr, "### prex_dmodel = %d ###\n", prex_dmodel); #endif scanargs(argc, argv); if (g_kernelmode) { /* prexing the kernel */ err = tnfctl_kernel_open(&g_hndl); if (err) { err_fatal(gettext( "%s: trouble attaching to the kernel: %s\n"), argv[0], tnfctl_strerror(err)); } } else { /* prexing a user process */ if (g_targetpid != 0) { /* check data model */ check_pid_model(argv, envp); /* attach case */ err = tnfctl_pid_open(g_targetpid, &g_hndl); if (err == TNFCTL_ERR_NOLIBTNFPROBE) { err_fatal(gettext( "%s: missing symbols, is " "libtnfprobe.so loaded in target?\n"), argv[0], tnfctl_strerror(err)); } else if (err) { err_fatal(gettext( "%s: trouble attaching to target " "process: %s\n"), argv[0], tnfctl_strerror(err)); } } else { /* check elf class model */ check_exec_model(argv, envp); /* exec case */ err = tnfctl_exec_open(g_cmdname, g_cmdargs, NULL, g_preload, NULL, &g_hndl); if (err == TNFCTL_ERR_NONE) err = tnfctl_trace_attrs_get(g_hndl, &trace_attrs); if (err) { err_fatal(gettext( "%s: trouble creating target process: " "%s\n"), argv[0], tnfctl_strerror(err)); } g_targetpid = trace_attrs.targ_pid; } sys_err = set_signal(); if (sys_err) err_fatal(gettext( "%s: trouble setting up signal handler: %s\n"), argv[0], strerror(err)); } /* initialize the source stack for the parser */ source_init(); if (!g_kernelmode) { /* set the tracefile name and size */ err = set_tracefile(g_hndl); if (err) { (void) fprintf(stderr, gettext( "%s: trouble initializing tracefile: %s\n"), argv[0], tnfctl_strerror(err)); goto Cleanup; } err = check_trace_error(g_hndl); if (err) { (void) fprintf(stderr, gettext( "%s: cannot read tracing status : %s\n"), argv[0], tnfctl_strerror(err)); goto Cleanup; } } /* accept commands from stdin the first time through */ g_getcmds = B_TRUE; /* set up default aliases */ set_default_cmd(); /* set up creator/destructor function to call for new probes */ err = set_probe_discovery_callback(g_hndl); if (err) { (void) fprintf(stderr, gettext( "%s: error in probe discovery : %s\n"), argv[0], tnfctl_strerror(err)); goto Cleanup; } if (g_kernelmode) { prbk_warn_pfilter_empty(); } while (err == TNFCTL_ERR_NONE) { if (g_kernelmode || g_getcmds) { g_getcmds = B_FALSE; get_commands(); } if (!g_kernelmode && (g_getcmds == B_FALSE)) { err = tnfctl_continue(g_hndl, &event, NULL); if (err) { (void) fprintf(stderr, gettext( "%s: cannot continue target : %s\n"), argv[0], tnfctl_strerror(err)); goto Cleanup; } } err = check_trace_error(g_hndl); if (err) { (void) fprintf(stderr, gettext( "%s: cannot read tracing status : %s\n"), argv[0], tnfctl_strerror(err)); goto Cleanup; } if (!g_kernelmode) { if (event == TNFCTL_EVENT_EXEC) { (void) printf(gettext( "Target process exec'd\n")); quit(B_FALSE, B_TRUE); /* quit resume */ } else if (event == TNFCTL_EVENT_EXIT) { /* target exited */ (void) fprintf(stderr, gettext( "%s: target process exited\n"), g_argv[0]); goto Cleanup; } else if (event == TNFCTL_EVENT_TARGGONE) { /* target terminated */ (void) fprintf(stderr, gettext("%s: target process disappeared (without calling exit)\n"), g_argv[0]); goto Cleanup; } } } Cleanup: err = tnfctl_close(g_hndl, TNFCTL_TARG_DEFAULT); if (err) (void) fprintf(stderr, gettext( "%s: error on closing : %s\n"), argv[0], tnfctl_strerror(err)); exit(0); return (0); }
int main(int argc, char *argv[]) { command_t *cmd; mem_region_t *mr; target_context_t *tc; #if !defined(WIN32) cmd = get_commands(argc, argv); if(cmd == NULL) return -1; #endif /* open raw ethernet socket if desired, then drop root */ #if !defined(WIN32) if (opt_ethernet) eth_raw_socket(); #endif drop_root(); /* miscellaneous initialization */ init_crc32(); /* open a connection to the target */ if (!(tc = target_open(opt_port, opt_ethernet ? opt_netif : NULL))){ panic("couldn't open connection to target"); return -1; } while (cmd) { command_t *tmp; if (opt_verbose) print_command(cmd); switch (cmd->type) { #ifdef AJ_FIRMUPDATE_SUPPORT case CMD_FIRMUPDATE: mr = slurp_file_or_die(cmd->input_path); if(require_flags(tc, REQ_MEM_MAP) == -1){ return -1; } firmupdate(tc, mr); break; #endif case CMD_DOWNLOAD: if (cmd->region && cmd->info.download.have_address){ panic("can't specify both region and address"); return -1; } mr = slurp_file_or_die(cmd->input_path); if(require_flags(tc, REQ_MEM_MAP) == -1){ return -1; } if (cmd->region) download_to_region(tc, mr, cmd->region); else if (cmd->info.download.have_address) download_to_addr(tc, mr, cmd->addr); else{ warn("download: must specify address or region\n"); return -1; } break; case CMD_ERASE: if (cmd->region && cmd->info.download.have_address){ panic("can't specify both region and address"); return -1; } if(require_flags(tc, REQ_MEM_MAP) == -1){ return -1; } if (cmd->region) erase_region(tc, cmd->region); else if (cmd->info.download.have_address) erase_addr(tc, cmd->addr); else{ warn("erase: must specify address or region\n"); return -1; } break; case CMD_MAP: if(require_flags(tc, REQ_MEM_MAP) == -1){ return -1; } region_print(tc->memmap); return 0; case CMD_TERMINAL: if(restore_interactive(tc) == -1){ return -1; } #if !defined(WIN32) serial_terminal(); #endif return 0; case CMD_MD5SUM: if (cmd->region && cmd->info.download.have_address){ panic("md5sum: can't specify both region and address"); return -1; } if (cmd->size == 0) { warn("md5sum: must specify size\n"); return -1; } if (cmd->region){ if(require_flags(tc, REQ_MEM_MAP) == -1){ return -1; } md5sum_region(tc, cmd->region, cmd->size); } else if (cmd->info.download.have_address) { md5sum_addr(tc, cmd->addr, cmd->size); } else{ warn("md5sum: must specify address or region\n"); return -1; } break; default: warn("unsupported command\n"); return -1; } tmp = cmd; cmd = cmd->next; /* * We don't free paths in the command because we don't * know whether or not they're dynamically allocated. * Thus we leak a little memory. It's not like this * is a long-running program... */ free(tmp); } restore_interactive(tc); return 0; }
/** * \brief Returns whether the hero is still pressing the key that made him * start running. * \return true if the hero is still pressing the running key */ bool Hero::RunningState::is_pressing_running_key() const { return get_commands().is_command_pressed(command); }
int main(void) { // Helpful Flags bool IS_NOT_ALONE, IS_ALONE, IS_INTERNAL, IS_EXTERNAL, IS_CD, IS_EXIT; bool IS_PARENT, IS_CHILD, IS_REDIRECTED, IS_FIRST, IS_LAST, IS_MIDDLE; // Pipe Holders int *pipe_left; int *pipe_right; // Holders for dup'd STDIN, OUT in case of redirected internal commands int ORIGINAL_STDIN, ORIGINAL_STDOUT; // Holder for command string from STDIO. char *str; // This gets the current username char *login; login = getlogin(); // This is the current working directory // This will be updated on cd commands run internally char cwd[MAXPATH]; getcwd(cwd, MAXPATH); // pointer to pid holder for children and waiting pid_t child_pid; // for execution & internal/external checking char *command_name; size_t command_length; // parsed command holder + pointer for counting number of commands command *comms = NULL; command *command_walker; char prompt[80]; // for loop iteration variable int i; // This will never be freed until we exit (and then by default). pipe_left = malloc(2*sizeof(int)); pipe_right = malloc(2*sizeof(int)); if ((pipe_left == NULL) || (pipe_right == NULL)) { fprintf(stderr, "%s: Could not allocate holder for potential pipes. Exiting.\n", SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } /** * Curiosity Shell Control Flow * The structure of the program is broken up as follows: * Pipe Creation * Fork Handler * Pipe Cleanup * Redirection (Including for Parent Internal Commands) * Command Run (Child, Parent), Parent Wait (if appropriate) * Reset Temporary Parent Redirection for Internal Commands * Get Next User Input */ while(1){ // Free the previous command free_commands(comms); // Display prompt. sprintf(prompt, "%s:%s> ", login, cwd); str = readline(prompt); if (str == NULL) { exit(EXIT_SUCCESS); } // Save the history. if (str && *str) add_history (str); // Prepare to tokenize command_length = strlen((const char *) str); if (command_length == 0) { comms = NULL; continue; } // Tokenize & parse into discrete commands comms = get_commands(str); if (str != NULL) free(str); // If no commands, create another prompt in the next iteration if (comms == NULL) { continue; } // count number of commands, command_length command_length = 0; command_walker = comms; while (command_walker->argv != NULL) { command_length += 1; command_walker += 1; } // Set IS_ALONE, IS_NOT_ALONE Flags IS_ALONE = false; IS_NOT_ALONE = false; if (command_length == 1) IS_ALONE = true; if (command_length > 1) IS_NOT_ALONE = true; /* Handle Latest Set of Commands */ for (i = 0; i < command_length; i++) { /* Set Flags for THIS command IS_FIRST, IS_MIDDLE, IS_LAST, IS_INTERNAL, IS_EXTERNAL, IS_CD, IS_EXIT */ command_name = comms[i].argv[0]; IS_FIRST = false; IS_MIDDLE = false; IS_LAST = false; if (i == 0) { IS_FIRST = true; } if (i == (command_length-1)) { IS_LAST = true; } if ((!IS_FIRST) && (!IS_LAST)) { IS_MIDDLE = true; } IS_INTERNAL = false; IS_EXTERNAL = true; IS_CD = false; IS_EXIT = false; if (strcmp((const char *)command_name, (const char *) "cd") == 0) { IS_CD = true; } if (strcmp((const char *)command_name, (const char *) "exit") == 0) { IS_EXIT = true; } if (IS_CD || IS_EXIT) { IS_INTERNAL = true; } if (IS_INTERNAL) { IS_EXTERNAL = false; } /* Pipe & Fork Handler (fork_yourself), Set IS_PARENT, IS_CHILD in fork_yourself, and use its return value to determine error */ if (IS_FIRST && IS_ALONE) { // No piping // Fork and set IS_PARENT, IS_CHILD if (!fork_yourself(IS_INTERNAL, IS_ALONE, &IS_PARENT, &IS_CHILD, &child_pid)) { break; } // No pipe handling } else if (IS_FIRST && IS_NOT_ALONE) { // pipe to pipe_right, check for pipe errors & return to prompt // if errors found. if (!pipe_creation_handler(&pipe_left, &pipe_right, 1)) { fprintf(stderr, "%s: Right-pipe creation error for command %s.\n", SHELL_ERROR_IDENTIFIER, command_name); break; } // Fork and set IS_PARENT, IS_CHILD if (!fork_yourself(IS_INTERNAL, IS_ALONE, &IS_PARENT, &IS_CHILD, &child_pid)) { break; } // parent closes pipe_right_write // errors reported by close are inconsequential if (IS_PARENT) { close(pipe_right[1]); } // child closes pipe_right_read // child duplicates pipe_right_write to stdout, then closes it. // errors reported by close are inconsequential if (IS_CHILD) { close(pipe_right[0]); if (dup2(pipe_right[1], STDOUT_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } close(pipe_right[1]); } } else if (IS_LAST && IS_NOT_ALONE) { // swap pipe_left/pipe_right // no piping pipe_creation_handler(&pipe_left, &pipe_right, 0); // Fork and set IS_PARENT, IS_CHILD if (!fork_yourself(IS_INTERNAL, IS_ALONE, &IS_PARENT, &IS_CHILD, &child_pid)) { break; } // parent closees pipe_left_read // errors reported by close are inconsequential if (IS_PARENT) { close(pipe_left[0]); } // child duplicates pipe_left_read to its stdin, then closes it // errors reported by close are inconsequential if (IS_CHILD) { if (dup2(pipe_left[0], STDIN_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } close(pipe_left[0]); } } else if (IS_MIDDLE && IS_NOT_ALONE) { // swap pipe_left/pipe_right pipe_creation_handler(&pipe_left, &pipe_right, 0); // pipe to pipe_right, check for pipe errors & return to prompt if // errors found. if (!pipe_creation_handler(&pipe_left, &pipe_right, 1)) { fprintf(stderr, "%s: Right-pipe creation error for command %s.\n", SHELL_ERROR_IDENTIFIER, command_name); break; } // Fork and set IS_PARENT, IS_CHILD if (!fork_yourself(IS_INTERNAL, IS_ALONE, &IS_PARENT, &IS_CHILD, &child_pid)) { break; } // parent closes pipe_left_read and pipe_right_write // errors reported by close are inconsequential if (IS_PARENT) { close(pipe_left[0]); close(pipe_right[1]); } // child closes pipe_right_read, duplicates pipe_left_read to stdin, // pipe_right_write to stdout, then closes both. // errors reported by close are inconsequential if (IS_CHILD) { close(pipe_right[0]); if (dup2(pipe_left[0], STDIN_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } if (dup2(pipe_right[1], STDOUT_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } close(pipe_left[0]); close(pipe_right[1]); } } else { // Unknown case. fprintf(stderr, "%s: Unexpected pipe handling case for command %s.\n", SHELL_ERROR_IDENTIFIER, command_name); break; } /* Redirection Handler Set IS_REDIRECTED flag Save STDIN/STDOUT/STDERR for later restoration This implementation possibly racks up "erroneous file handlers" unless dup() removes those on error. */ IS_REDIRECTED = false; if (IS_PARENT && IS_INTERNAL) { if (comms[i].ifile != NULL) { IS_REDIRECTED = true; ORIGINAL_STDIN = dup(STDIN_FILENO); if (ORIGINAL_STDIN == -1) { perror(SHELL_ERROR_IDENTIFIER); break; } } if (comms[i].ofile != NULL) { IS_REDIRECTED = true; ORIGINAL_STDOUT = dup(STDOUT_FILENO); if (ORIGINAL_STDOUT == -1) { perror(SHELL_ERROR_IDENTIFIER); break; } } // Not necessary as we do not handle STDERR redirection // ORIGINAL_STDERR = dup(STDERR_FILENO); // if (ORIGINAL_STDERR == -1) { // perror(SHELL_ERROR_IDENTIFIER); // break; // } if (!redirection(comms[i].ifile, comms[i].ofile, comms[i].append)) { break; } } else if (IS_CHILD) { IS_REDIRECTED = true; if (!redirection(comms[i].ifile, comms[i].ofile, comms[i].append)) { break; } } /* Run/Wait Handler */ if(IS_CHILD && IS_INTERNAL){ if(!run_internal(IS_CD, IS_EXIT, cwd, comms[i].argv, comms[i].argc)){ exit(EXIT_FAILURE); } else{ exit(EXIT_SUCCESS); } } if(IS_CHILD && IS_EXTERNAL){ execute(comms[i].argv); } if(IS_PARENT && IS_INTERNAL && IS_ALONE){ run_internal(IS_CD, IS_EXIT, cwd, comms[i].argv, comms[i].argc); } if(IS_PARENT && IS_INTERNAL && IS_NOT_ALONE){ if(!(waiting(child_pid))){ break; } } if(IS_PARENT && IS_EXTERNAL){ if(!(waiting(child_pid))){ break; } } /* Parent STDIO Reset In case of Single Internal Command with Redirection */ /* On failure, MUST EXIT as user can no longer target STDIN or see our STDOUT, possibly. */ if (IS_PARENT && IS_INTERNAL && IS_ALONE && IS_REDIRECTED) { if (comms[i].ifile != NULL) { if (dup2(ORIGINAL_STDIN, STDIN_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } close(ORIGINAL_STDIN); } if (comms[i].ofile != NULL) { if (dup2(ORIGINAL_STDOUT, STDOUT_FILENO) == -1) { perror(SHELL_ERROR_IDENTIFIER); exit(EXIT_FAILURE); } close(ORIGINAL_STDOUT); } // Do not need to handle STDERR, we do not support it's redirection } } } exit(EXIT_SUCCESS); }