void ControlReaderThread::setupRequest(void *data) { struct usb_functionfs_event *e = (struct usb_functionfs_event *)data; /* USB Still Image Capture Device Definition, Section 5 */ /* www.usb.org/developers/devclass_docs/usb_still_img10.pdf */ //qDebug() << "bRequestType:" << e->u.setup.bRequestType; //qDebug() << "bRequest:" << e->u.setup.bRequest; //qDebug() << "wValue:" << e->u.setup.wValue; //qDebug() << "wIndex:" << e->u.setup.wIndex; //qDebug() << "wLength:" << e->u.setup.wLength; switch(e->u.setup.bRequest) { case PTP_REQ_GET_DEVICE_STATUS: if(e->u.setup.bRequestType == 0xa1) sendStatus(m_status); else stall((e->u.setup.bRequestType & USB_DIR_IN)>0); break; case PTP_REQ_CANCEL: emit cancelTransaction(); break; case PTP_REQ_DEVICE_RESET: emit deviceReset(); break; //case PTP_REQ_GET_EXTENDED_EVENT_DATA: default: stall((e->u.setup.bRequestType & USB_DIR_IN)>0); break; } }
void led_red_blink(int ms) { led_red_on(); stall(ms); led_red_off(); stall(ms); }
void led_yellow_blink(int ms) { led_yellow_on(); stall(ms); led_yellow_off(); stall(ms); }
/* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ static void setctty(const char *name) { int fd; revoke(name); if ((fd = open(name, O_RDWR)) == -1) { stall("can't open %s: %m", name); _exit(1); } if (login_tty(fd) == -1) { stall("can't get %s for controlling terminal: %m", name); _exit(1); } }
/* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ static void open_console(void) { int fd; /* * Try to open /dev/console. Open the device with O_NONBLOCK to * prevent potential blocking on a carrier. */ revoke(_PATH_CONSOLE); if ((fd = open(_PATH_CONSOLE, O_RDWR | O_NONBLOCK)) != -1) { (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); if (login_tty(fd) == 0) return; close(fd); } /* No luck. Log output to file if possible. */ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { stall("cannot open null device."); _exit(1); } if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO); close(fd); } fd = open(_PATH_INITLOG, O_WRONLY | O_APPEND | O_CREAT, 0644); if (fd == -1) dup2(STDIN_FILENO, STDOUT_FILENO); else if (fd != STDOUT_FILENO) { dup2(fd, STDOUT_FILENO); close(fd); } dup2(STDOUT_FILENO, STDERR_FILENO); }
void parse_descriptor(void) { switch((SWAPENDIAN(pSetupPacket->wValue) & HI_BYTE) >> 8) { case DESCR_TYPE_DEVICE: descrbuffer = (uint8*)&(DeviceDescriptor); cbuff_tail = 0; if(SWAPENDIAN(pSetupPacket->wLength) < DeviceDescriptor.bLength) cbuff_head =SWAPENDIAN(pSetupPacket->wLength); else cbuff_head = DeviceDescriptor.bLength; send_config(); break; case DESCR_TYPE_CONFIGURATION: descrbuffer = (uint8*)&(ConfigurationDescriptor); cbuff_tail = 0; if(SWAPENDIAN(pSetupPacket->wLength) < sizeof(FULL_CONFIG)) cbuff_head = SWAPENDIAN(pSetupPacket->wLength); else cbuff_head = sizeof(FULL_CONFIG); send_config(); break; case DESCR_TYPE_STRING: switch(SWAPENDIAN(pSetupPacket->wValue) & LO_BYTE) { case STDENDPREQ_LANG: descrbuffer = (uint8*)&(LangDescriptor); cbuff_tail = 0; if(SWAPENDIAN(pSetupPacket->wLength) < sizeof(LANG_DESCR)) cbuff_head = SWAPENDIAN(pSetupPacket->wLength); else cbuff_head = LangDescriptor.bLength; send_config(); break; case STDENDPREQ_PRODUCT: descrbuffer = (uint8*)&(DevStringDescriptor); cbuff_tail = 0; if(SWAPENDIAN(pSetupPacket->wLength) < sizeof(DEVSTRING_DESCR)) cbuff_head = SWAPENDIAN(pSetupPacket->wLength); else cbuff_head = DevStringDescriptor.bLength; send_config(); break; case STDENDPREQ_MANUF: descrbuffer = (uint8*)&(ManufStringDescriptor); cbuff_tail = 0; if(SWAPENDIAN(pSetupPacket->wLength) < sizeof(MANUFSTRING_DESCR)) cbuff_head = SWAPENDIAN(pSetupPacket->wLength); else cbuff_head = ManufStringDescriptor.bLength; send_config(); break; default: stall(); break; } } }
static uint32_t v_add(uint32_t in_x, uint32_t in_y) { x = in_x; y = in_y; run = 0; cycle(); run = 1; do { cycle(); } while (stall()); return z(); }
void parse_device_setup(void) { switch(pSetupPacket->bReq) { case STDDEVREQ_SET_ADDR: address = (uint8)SWAPENDIAN(pSetupPacket->wValue); raw_send(ADD_UDATAEND0,0); break; case STDDEVREQ_GET_DESCR: parse_descriptor(); break; case STDDEVREQ_GET_CONFIG: raw_send(ADD_UDATAEND0,0); break; case STDDEVREQ_SET_CONFIG: raw_send(ADD_UDATAEND0,0); switch(SWAPENDIAN(pSetupPacket->wValue)) { case 1: /* we support only one config */ R_UCR1 = TX1E; R_UCR2 = RX2E; sbuff_tail = sbuff_head = rbuff_tail = rbuff_head = 0; cbuff_tail = cbuff_head = 0; dev_configured = TRUE; rx_toggle = 0; break; case 0: /* if config is 0, we return to address state */ R_UCR1 = 0x00; R_UCR2 = 0x00; dev_configured = FALSE; break; default: stall(); break; } break; case STDDEVREQ_CLEAR_FEATURE: case STDDEVREQ_SET_FEATURE: case STDDEVREQ_SET_DESCR: default: stall(); break; } }
void parse_std_setup(void) { switch(pSetupPacket->bmReqType & REQ_MASK_RECIPIENT) { case REQ_RECIP_DEVICE: parse_device_setup(); break; case REQ_RECIP_INTERFACE: case REQ_RECIP_ENDPOINT: case REQ_RECIP_OTHER: default: stall(); break; } }
void dataout_endp2(void) { R_UCR2 &= ~RX2E; R_UIR2 = RXD2FR; /* if toggle matches, get data*/ if(rx_toggle == (R_USR1 & R2SEQ)) receive_data(); else stall(); /* prepare next data toggle*/ rx_toggle ^= R2SEQ; R_UCR2 = RX2E; }
void parse_setup_packet(void) { pSetupPacket=(SETUP_REQ*)ADD_UDATAEND0; switch(pSetupPacket->bmReqType & REQ_MASK_TYPE) { case REQ_TYPE_STANDARD: parse_std_setup(); break; case REQ_TYPE_CLASS: case REQ_TYPE_VENDOR: case REQ_TYPE_RESERVERD: default: stall(); break; } }
/* * Run a shell script. * Returns 0 on success, otherwise the next transition to enter: * - single_user if fork/execv/waitpid failed, or if the script * terminated with a signal or exit code != 0. * - death_single if a SIGTERM was delivered to init(8). */ static state_func_t run_script(const char *script) { pid_t pid, wpid; int status; char *argv[4]; const char *shell; struct sigaction sa; shell = get_shell(); if ((pid = fork()) == 0) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, (struct sigaction *)0); sigaction(SIGHUP, &sa, (struct sigaction *)0); open_console(); char _sh[] = "sh"; char _autoboot[] = "autoboot"; argv[0] = _sh; argv[1] = __DECONST(char *, script); argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0; argv[3] = 0; sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0); #ifdef LOGIN_CAP setprocresources(RESOURCE_RC); #endif execv(shell, argv); stall("can't exec %s for %s: %m", shell, script); _exit(1); /* force single user mode */ }
/*! \details This function handles the standard requests on endpoint 0. * This should be the default action for endpoint 0. The default * action is set using usb_dev_init() with the following code * \code * usb_set_ep_action(USB_DEV_PORT, 0, usb_dev_std_setup); * \endcode * * */ int usb_dev_std_setup(void * context, const void * data /*! Callback data */){ uint32_t event = (uint32_t)data; if ( event == USB_SETUP_EVENT ){ usb_dev_std_setup_stage(); usb_dev_std_ep0_data.cnt = usb_setup_pkt.wLength; if ( usb_setup_pkt.bmRequestType.bitmap_t.type == USB_DEV_REQUEST_STANDARD){ switch (usb_setup_pkt.bRequest) { case USB_DEV_REQUEST_GET_STATUS: if (!usb_dev_std_req_get_status()) { stall(); return 1; } usb_dev_std_datain_stage(); break; case USB_DEV_REQUEST_CLEAR_FEATURE: if (!usb_dev_std_reg_set_clrfeature(0)) { stall(); return 1; } usb_dev_std_statusin_stage(); usb_feature_event(); break; case USB_DEV_REQUEST_SET_FEATURE: if (!usb_dev_std_reg_set_clrfeature(1)) { stall(); return 1; } usb_dev_std_statusin_stage(); usb_feature_event(); break; case USB_DEV_REQUEST_SET_ADDRESS: if (!usb_dev_std_req_setaddr()) { stall(); return 1; } usb_dev_std_statusin_stage(); break; case USB_DEV_REQUEST_GET_DESCRIPTOR: if (!usb_dev_std_req_getdesc()) { stall(); return 1; } usb_dev_std_datain_stage(); break; case USB_DEV_REQUEST_SET_DESCRIPTOR: hwpl_usb_stallep(USB_DEV_PORT, (void*)0x00); usb_dev_std_ep0_data.cnt = 0; break; case USB_DEV_REQUEST_GET_CONFIGURATION: if (!usb_dev_std_req_getcfg()) { stall(); return 1; } usb_dev_std_datain_stage(); break; case USB_DEV_REQUEST_SET_CONFIGURATION: if (!usb_dev_std_req_setcfg()) { stall(); return 1; } usb_dev_std_statusin_stage(); usb_configure_event(); break; case USB_DEV_REQUEST_GET_INTERFACE: if (!usb_dev_std_req_getinterface()) { stall(); return 1; } usb_dev_std_datain_stage(); break; case USB_DEV_REQUEST_SET_INTERFACE: if (!usb_dev_std_req_setinterface()) { stall(); return 1; } usb_interface_event(); usb_dev_std_statusin_stage(); break; default: stall(); return 1; } } else if ( usb_setup_pkt.bmRequestType.bitmap_t.type == USB_DEV_REQUEST_CLASS ){ switch (usb_setup_pkt.bmRequestType.bitmap_t.recipient) { case USB_DEV_REQUEST_TO_DEVICE: stall(); return 1; case USB_DEV_REQUEST_TO_INTERFACE: if ( usb_dev_adc_if_req(event) ) return 1; if ( usb_dev_msc_if_req(event) ) return 1; if ( usb_dev_cdc_if_req(event) ) return 1; if ( usb_dev_hid_if_req(event) ) return 1; break; } stall(); return 1; } } else if ( event == USB_OUT_EVENT ){ if (usb_setup_pkt.bmRequestType.bitmap_t.dir == USB_DEV_REQUEST_HOST_TO_DEVICE) { if (usb_dev_std_ep0_data.cnt) { usb_dev_std_dataout_stage(); if (usb_dev_std_ep0_data.cnt == 0){ switch (usb_setup_pkt.bmRequestType.bitmap_t.type) { case USB_DEV_REQUEST_STANDARD: stall(); return 1; case USB_DEV_REQUEST_CLASS: if (1){ switch (usb_setup_pkt.bmRequestType.bitmap_t.recipient) { case USB_DEV_REQUEST_TO_DEVICE: stall(); return 1; case USB_DEV_REQUEST_TO_INTERFACE: if ( usb_dev_adc_if_req(event) ) return 1; if ( usb_dev_msc_if_req(event) ) return 1; if ( usb_dev_cdc_if_req(event) ) return 1; if ( usb_dev_hid_if_req(event) ) return 1; case USB_DEV_REQUEST_TO_ENDPOINT: default: stall(); return 1; } break; default: stall(); return 1; } break; } } } } else { usb_dev_std_statusout_stage(); } } else if ( event == USB_IN_EVENT){ if (usb_setup_pkt.bmRequestType.bitmap_t.dir == USB_DEV_REQUEST_DEVICE_TO_HOST) { usb_dev_std_datain_stage(); } else { if (usb_dev_std_addr & USB_ENDPOINT_IN) { usb_dev_std_addr &= 0x7F; hwpl_usb_setaddr(USB_DEV_PORT, (void*)((int)usb_dev_std_addr)); } } } else if ( event == USB_OUT_EVENT_STALL){ hwpl_usb_unstallep(USB_DEV_PORT, (void*)0x00); } else if ( event == USB_IN_EVENT_STALL ){ hwpl_usb_unstallep(USB_DEV_PORT, (void*)(USB_ENDPOINT_IN|0x00)); } return 1; }
//==================================================================== //==================================================================== void L2_cache::process_client_request (Coh_msg* request, bool first) { DBG_L2_CACHE_ID(cout, "process_client_request(), addr= " << hex << request->addr << dec << endl); /** This code may be modified in the future to enable parallel events while transient (read while waiting for previous read-unblock). For the time being, just assume no parallel events for a single address */ if (mshr->has_match(request->addr)) { DBG_L2_CACHE_ID(cout, " PREV_PEND_STALL, addr= " << hex << request->addr << dec << endl); assert(first); stall (request, C_PREV_PEND_STALL); stats_PREV_PEND_STALLs++; return; } // IMPORTANT: it's important to also check the stall buffer for requests for the same line. if(first) { if(stall_buffer_has_match(request->addr)) { stall (request, C_PREV_PEND_STALL); stats_PREV_PEND_STALLs++; return; } } /** Assumption; all requests require an MSHR, even those that have enough permissions to hit (because of potential for transient while waiting for unblock messages)*/ hash_entry* mshr_entry = mshr->reserve_block_for(request->addr); if (mshr_entry == 0) { DBG_L2_CACHE_ID(cout, " MSHR_STALL, addr= " << hex << request->addr << dec << endl); assert(first); stall (request, C_MSHR_STALL); stats_MSHR_STALLs++; return; } mshr_map[mshr_entry->get_idx()] = 0; hash_entry* hash_table_entry = 0; /** Miss logic. */ if (!my_table->has_match (request->addr)) { DBG_L2_CACHE(cout, " L2_cache: request is miss.\n"); //first check if request is an invalidation request; a missed invalidation request should //be ignored. if(managers[0]->is_invalidation_request(request)) { DBG_L2_CACHE(cout, " L2_cache: a missed invalidation request; ignore it.\n"); mshr_entry->invalidate(); delete request; return; } /** Check if an invalid block exists already or the LRU block can begin eviction. */ hash_table_entry = my_table->reserve_block_for (request->addr); if (hash_table_entry != 0) { mshr_map[mshr_entry->get_idx()] = hash_table_entry; L2_algorithm (mshr_entry, request); } else { //no hash entry available, eviction required. hash_entry* victim = my_table->get_replacement_entry(request->addr); ManagerInterface* victim_manager = managers[victim->get_idx()]; if (victim_manager->req_pending() == false && mcp_stalled_req[victim_manager->getManagerID()] == 0) { //The 2nd part of the if statement is necessary because a manager could be in I state and waiting for //data from memory. DBG_L2_CACHE(cout, " L2_cache start replacement, victim line addr= " <<hex<< victim->get_line_addr() <<dec<< "\n"); assert(mshr->has_match(victim->get_line_addr()) == false); //victim shouldn't have an mshr entry. start_eviction(victim_manager, request); } else { //the client for the victim is in transient, so it must have a stalled request in the //stall buffer; we cannot overwrite with this to-be-stalled request. The easiest solution is //for the request to give up the MSHR, and wait for wakeup when the victim's request is //finished and it releases its mshr. DBG_L2_CACHE(cout, " LRU BUSY_STALL waiting for " <<hex<< my_table->get_replacement_entry(request->addr)->get_line_addr() <<dec<< "\n"); assert(first); mshr_entry->invalidate(); stall (request, C_LRU_BUSY_STALL); stats_LRU_BUSY_STALLs++; return; } }//eviction } /** Hit and Partial-hit logic (block exists, but coherence miss). */ else { DBG_L2_CACHE(cout, " L2_cache :: process_client_request(), request hits in hash table.\n"); hash_table_entry = my_table->get_entry(request->addr); /** entry for this address exists, now we need to consider what state it's in */ if(managers[hash_table_entry->get_idx()]->req_pending() == true) { //One possibility is the entry is being evicted. //Treat TRANS_STALL the same way as LRU_BUSY_STALL. That is, we free the mshr and //wait for wakeup when the victim finishes. //##### NOTE #####: here we must give up the MSHR entry; otherwise, when response for the //eviction comes back, it will get this MSHR entry because it's a hit on the victim. //The request waiting for the eviction will not be processed. DBG_L2_CACHE(cout, " L2_cache: TRANS_STALL\n"); assert(first); mshr_entry->invalidate(); stall (request, C_TRANS_STALL); stats_TRANS_STALLs++; return; } mshr_map[mshr_entry->get_idx()] = hash_table_entry; /** We need to bring the MSHR up to speed w.r.t. state so the req can be processed. */ /** So we copy the block over */ update_hash_entry(mshr_entry, hash_table_entry); L2_algorithm (mshr_entry, request); } }
eError DHT::readData() { uint8_t i = 0, j = 0, b = 0, data_valid = 0; uint32_t bit_value[DHT_DATA_BIT_COUNT] = {0}; eError err = ERROR_NONE; //time_t currentTime = time(NULL); DigitalInOut DHT_io(_pin); // IO must be in hi state to start if (ERROR_NONE != stall(DHT_io, 0, 250)) { return BUS_BUSY; } // start the transfer DHT_io.output(); DHT_io = 0; // only 500uS for DHT22 but 18ms for DHT11 (_DHTtype == 22) ? wait_ms(18) : wait(1); DHT_io = 1; wait_us(30); DHT_io.input(); // wait till the sensor grabs the bus if (ERROR_NONE != stall(DHT_io, 1, 40)) { return ERROR_NOT_PRESENT; } // sensor should signal low 80us and then hi 80us if (ERROR_NONE != stall(DHT_io, 0, 100)) { return ERROR_SYNC_TIMEOUT; } if (ERROR_NONE != stall(DHT_io, 1, 100)) { return ERROR_NO_PATIENCE; } // capture the data for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) { if (ERROR_NONE != stall(DHT_io, 0, 75)) { return ERROR_DATA_TIMEOUT; } // logic 0 is 28us max, 1 is 70us wait_us(40); bit_value[i * 8 + j] = DHT_io; if (ERROR_NONE != stall(DHT_io, 1, 50)) { return ERROR_DATA_TIMEOUT; } } } // store the data for (i = 0; i < 5; i++) { b = 0; for (j = 0; j < 8; j++) { if (bit_value[i * 8 + j] == 1) { b |= (1 << (7 - j)); } } DHT_data[i] = b; } // uncomment to see the checksum error if it exists //printf(" 0x%02x + 0x%02x + 0x%02x + 0x%02x = 0x%02x \n", DHT_data[0], DHT_data[1], DHT_data[2], DHT_data[3], DHT_data[4]); data_valid = DHT_data[0] + DHT_data[1] + DHT_data[2] + DHT_data[3]; if (DHT_data[4] == data_valid) { //_lastReadTime = currentTime; _lastTemperature = CalcTemperature(); _lastHumidity = CalcHumidity(); } else { err = ERROR_CHECKSUM; } return err; }
void USBDeviceClass::ISRHandler() { if (_pack_message == true) { return; } // End-Of-Reset if (usbd.isEndOfResetInterrupt()) { // Configure EP 0 initEP(0, USB_ENDPOINT_TYPE_CONTROL); // Enable Setup-Received interrupt usbd.epBank0EnableSetupReceived(0); _usbConfiguration = 0; usbd.ackEndOfResetInterrupt(); } // Start-Of-Frame if (usbd.isStartOfFrameInterrupt()) { usbd.ackStartOfFrameInterrupt(); } // Endpoint 0 Received Setup interrupt if (usbd.epBank0IsSetupReceived(0)) { usbd.epBank0AckSetupReceived(0); USBSetup *setup = reinterpret_cast<USBSetup *>(udd_ep_out_cache_buffer[0]); /* Clear the Bank 0 ready flag on Control OUT */ // The RAM Buffer is empty: we can receive data usbd.epBank0ResetReady(0); bool ok; if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) { // Standard Requests ok = handleStandardSetup(*setup); } else { // Class Interface Requests ok = handleClassInterfaceSetup(*setup); } if (ok) { usbd.epBank1SetReady(0); } else { stall(0); } if (usbd.epBank1IsStalled(0)) { usbd.epBank1AckStalled(0); // Remove stall request usbd.epBank1DisableStalled(0); } } // end Received Setup handler uint8_t i=0; uint8_t ept_int = usbd.epInterruptSummary() & 0xFE; // Remove endpoint number 0 (setup) while (ept_int != 0) { // Check if endpoint has a pending interrupt if ((ept_int & (1 << i)) != 0) { // Endpoint Transfer Complete (0/1) Interrupt if (usbd.epBank0IsTransferComplete(i) || usbd.epBank1IsTransferComplete(i)) { handleEndpoint(i); } ept_int &= ~(1 << i); } i++; if (i > USB_EPT_NUM) break; // fire exit } }
/* * Bring the system up single user. */ state_func_t single_user(void) { pid_t pid, wpid; int status; sigset_t mask; const char *shell; char *argv[2]; #ifdef SECURE struct ttyent *typ; struct passwd *pp; static const char banner[] = "Enter root password, or ^D to go multi-user\n"; char *clear, *password; #endif #ifdef DEBUGSHELL char altshell[128]; #endif if (Reboot) { /* Instead of going single user, let's reboot the machine */ sync(); alarm(2); pause(); reboot(howto); _exit(0); } shell = get_shell(); if ((pid = fork()) == 0) { /* * Start the single user session. */ setctty(_PATH_CONSOLE); #ifdef TESTBED #define TERMCMD "/bootcmd" if (access(TERMCMD, F_OK) == 0) { FILE *fp; char cmd[256], *bp; char *myargv[3]; /* * Very simple; the file contains the path of a * command to run. No arguments supported, sorry. */ if ((fp = fopen(TERMCMD, "r")) == NULL) { /* Lets avoid loops! */ unlink(TERMCMD); goto skip; } if (fgets(cmd, sizeof(cmd), fp) == NULL) { fclose(fp); /* Lets avoid loops! */ unlink(TERMCMD); goto skip; } fclose(fp); /* Lets avoid loops! */ unlink(TERMCMD); if ((bp = rindex(cmd, '\n'))) *bp = '\0'; if (access(cmd, X_OK) != 0) { emergency("%s does not exist!", cmd); goto skip; } /* See comment below */ sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); char name[] = "-sh"; myargv[0] = name; myargv[1] = cmd; myargv[2] = 0; execv(_PATH_BSHELL, myargv); stall("can't exec %s for %s: %m", _PATH_BSHELL, cmd); } /* * If something goes wrong, we want to sit in single user mode * so that we might catch the error. Not sure, might have to * do something fancier, like perhaps add a state transition * for this */ skip: #endif #ifdef SECURE /* * Check the root password. * We don't care if the console is 'on' by default; * it's the only tty that can be 'off' and 'secure'. */ typ = getttynam("console"); pp = getpwnam("root"); if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp && *pp->pw_passwd) { write_stderr(banner); for (;;) { clear = getpass("Password:"******"single-user login failed\n"); } } endttyent(); endpwent(); #endif /* SECURE */ #ifdef DEBUGSHELL { char *cp = altshell; int num; #define SHREQUEST "Enter full pathname of shell or RETURN for " write_stderr(SHREQUEST); write_stderr(shell); write_stderr(": "); while ((num = read(STDIN_FILENO, cp, 1)) != -1 && num != 0 && *cp != '\n' && cp < &altshell[127]) cp++; *cp = '\0'; if (altshell[0] != '\0') shell = altshell; } #endif /* DEBUGSHELL */ /* * Unblock signals. * We catch all the interesting ones, * and those are reset to SIG_DFL on exec. */ sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); /* * Fire off a shell. * If the default one doesn't work, try the Bourne shell. */ char name[] = "-sh"; argv[0] = name; argv[1] = 0; execv(shell, argv); emergency("can't exec %s for single user: %m", shell); execv(_PATH_BSHELL, argv); emergency("can't exec %s for single user: %m", _PATH_BSHELL); sleep(STALL_TIMEOUT); _exit(1); } if (pid == -1) { /* * We are seriously hosed. Do our best. */ emergency("can't fork single-user shell, trying again"); while (waitpid(-1, (int *) 0, WNOHANG) > 0) continue; return (state_func_t) single_user; } requested_transition = 0; do { if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) collect_child(wpid); if (wpid == -1) { if (errno == EINTR) continue; warning("wait for single-user shell failed: %m; restarting"); return (state_func_t) single_user; } if (wpid == pid && WIFSTOPPED(status)) { warning("init: shell stopped, restarting\n"); kill(pid, SIGCONT); wpid = -1; } } while (wpid != pid && !requested_transition); if (requested_transition) return (state_func_t) requested_transition; if (!WIFEXITED(status)) { if (WTERMSIG(status) == SIGKILL) { /* * reboot(8) killed shell? */ warning("single user shell terminated."); sleep(STALL_TIMEOUT); _exit(0); } else { warning("single user shell terminated, restarting"); return (state_func_t) single_user; } } runcom_mode = FASTBOOT; return (state_func_t) runcom; }