/* Main server module common for all transports * This module will do the initial transport setups. * Then it receives the command from client in CDC format * and transmits the response back to the client. * In the case of socket, it receives the command from the client * and sends the response directly to the client via TCP socket. * * In the case of serial & wifi , it receives the command from the driver * and sends the response to the driver. */ int remote_server_exec(int argc, char **argv, void *wl) { int err; int transport_descriptor; char *async_cmd_flag = NULL; int skip; int download_flag = 0; #if defined(LINUX) || defined(vxworks) || defined(OLYMPIC_RWL) char old_intf_name[IFNAMSIZ]; #endif #ifdef WIN32 char shell_fname[MAX_SHELL_FILE_LENGTH]; DWORD dwlen; #endif #ifdef RWL_DONGLE int uart_enable = 1; /* To set dongle flag when dongle server starts */ if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable, sizeof(int))) < 0) { DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err); } #endif if (rwl_iovar_check (wl) < 0) { DPRINT_ERR(ERR, "wl_server: RWL_WIFI/RWL_DONGLE not defined "); DPRINT_ERR(ERR, "Or In-Dongle mode enabled\n"); exit(0); } /* Initialise for all the transports - socket, serial, and wifi * In Socket transport, main socket handler will be returned. */ if ((transport_descriptor = rwl_transport_setup(argc, argv)) < 0) return BCME_ERROR; #ifdef RWL_WIFI remote_wifi_ser_init_cmds(wl); #endif /* Create a directory /tmp/RWL for the shell response files */ if (rwl_create_dir() < 0) return BCME_ERROR; #ifdef RWLASD /* DUT initialization function */ wfa_dut_init(&trafficBuf, &respBuf, &parmsVal, &xcCmdBuf, &toutvalp); #endif #if defined(LINUX) || defined(vxworks) /* Copy old interface name to restore it */ store_old_interface(wl, old_intf_name); #endif /* defined(LINUX) || defined(vxworks) */ while (1) { uchar *buf_ptr = NULL; #ifdef VISTA_SERVER int index; char *vista_buf[MAX_VISTA_ARGC]; #endif #ifdef RWL_SERIAL g_rwl_hndle = transport_descriptor; #else g_rwl_hndle = -1; #endif #ifdef RWL_DONGLE if (set_ctrlc) { uart_enable = 0; if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable, sizeof(int))) < 0) { DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err); } set_ctrlc = 0; exit(0); } #endif /* RWL_DONGLE */ /* Receive the CDC header */ if ((remote_rx_header(wl, transport_descriptor)) == BCME_ERROR) { DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n"); continue; } DPRINT_INFO(OUTPUT, "REC : cmd %d\t msg len %d msg flag %d\t msg status %d\n", g_rem_ptr->msg.cmd, g_rem_ptr->msg.len, g_rem_ptr->msg.flags, g_rem_ptr->msg.status); #ifdef RWL_WIFI /* send the response to remote if it is findserver cmd, this is specific to wifi */ if (g_rem_ptr->msg.flags & REMOTE_FINDSERVER_IOCTL) { remote_wifi_response(wl); continue; } #endif /* RWL_WIFI */ /* * Allocate buffer only if there is a response message expected. * Some commands such as up/down do not output anything. */ if (g_rem_ptr->msg.len) { if ((buf_ptr = malloc(g_rem_ptr->msg.len)) == NULL) { DPRINT_ERR(ERR, "malloc of %d bytes failed\n", g_rem_ptr->msg.len); continue; } } /* Receive the data */ if ((err = remote_rx_data(buf_ptr)) == BCME_ERROR) { if (buf_ptr) free(buf_ptr); continue; } /* Process RWL negotiate commands */ if (g_rem_ptr->msg.flags & REMOTE_NEGOTIATE_CMD) { if (g_rem_ptr->msg.cmd == NEGOTIATE_GET_OS) { if (g_rem_ptr->msg.len >= sizeof(int)) { #if defined(LINUX) *(int*)buf_ptr = LINUX_OS; #elif defined(VISTA_SERVER) *(int*)buf_ptr = WINVISTA_OS; #elif defined(WIN32) *(int*)buf_ptr = WIN32_OS; #elif defined(MACOSX) *(int*)buf_ptr = MAC_OSX; #else *(int*)buf_ptr = UNKNOWN_OS; #endif g_rem_ptr->msg.len = sizeof(int); DPRINT_INFO(OUTPUT, "RESP : os type %d\n", *(int*)buf_ptr); if (remote_tx_response(wl, buf_ptr, 0) < 0) DPRINT_ERR(ERR, "\nReturn results failed\n"); } } #ifdef RWL_SOCKET close_sock_handle(g_rwl_hndle); #endif /* RWL_SOCKET */ if (buf_ptr) free(buf_ptr); continue; } /* Process command */ if (g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) { /* Get the response length first and get the response buffer in case of * synchronous shell commands and the buf_ptr will have the response file * name. In case of asynchronous shell commands, buf_ptr * will be get updated by the remote_shell_execute function. */ need_speedy_response = 1; #ifndef WIN32 if (buf_ptr) { async_cmd_flag = strstr((char*)buf_ptr, "%"); } if ((err = remote_shell_execute((char*)buf_ptr, wl)) > 0) { if (async_cmd_flag) g_rem_ptr->msg.len = err; } /* Sync shell command: No need to send response from here */ else { #ifdef RWL_SOCKET /* Transmitted to client. Then close the handle & * get the new handle for next transmission & reception. */ close_sock_handle(g_rwl_hndle); #endif /* RWL_SOCKET */ continue; } #else if ((err = remote_shell_execute((char*)buf_ptr, wl)) != SUCCESS) { DPRINT_ERR(ERR, "Error in executing shell command\n"); if (buf_ptr) free(buf_ptr); #ifdef RWL_SOCKET /* Transmitted to client. Then close the handle & * get the new handle for next transmission & reception. */ close_sock_handle(g_rwl_hndle); #endif /* RWL_SOCKET */ continue; } /* Get the response from the temporary file */ if ((err = remote_shell_get_resp(shell_fname, wl)) != SUCCESS) { DPRINT_ERR(ERR, "Error in executing shell command\n"); } if (buf_ptr) free(buf_ptr); #ifdef RWL_SOCKET /* Transmitted to client. Then close the handle & * get the new handle for next transmission & reception. */ close_sock_handle(g_rwl_hndle); #endif /* RWL_SOCKET */ continue; #endif /* WIN32 */ } /* REMOTE_SHELL_CMD */ #ifdef RWLASD if (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) { if ((err = remote_asd_exec(buf_ptr, (int *)&g_rem_ptr->msg.len)) < 0) { DPRINT_ERR(ERR, "Error in executing asd command\n"); } } /* REMOTE_ASD_CMD */ #endif /* * added to take care of OID base problem for cross OS RWL cleint server * In case of LX Server and WIN32 client OID base need to be removed * In case of WIN32 server and LX client OID base need to be added */ if (!(g_rem_ptr->msg.flags & REMOTE_ASD_CMD)) { #if defined(LINUX) || defined(vxworks) if (g_rem_ptr->msg.cmd > MAX_IOVAR) g_rem_ptr->msg.cmd -= WL_OID_BASE; #endif #if defined(WIN32) if (g_rem_ptr->msg.cmd < MAX_IOVAR) g_rem_ptr->msg.cmd += WL_OID_BASE; #endif } #ifdef VISTA_SERVER if (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD) { vista_buf[0] = strtok(buf_ptr, " \t\n"); for (index = 1; (vista_buf[index] = strtok(NULL, " \t\n")) != NULL; index++); if ((err = remote_vista_exec(wl, vista_buf)) < 0) { DPRINT_ERR(ERR, "Error in executing vista command\n"); } memcpy(buf_ptr, vista_buf[0], strlen(vista_buf[0])); g_rem_ptr->msg.len = strlen(vista_buf[0]); } /* REMOTE_VISTA_CMD */ #endif /* VISTA_SERVER */ #ifndef OLYMPIC_RWL #if defined(LINUX) || defined(vxworks) #ifndef RWL_DONGLE if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL || g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) { if (strlen(g_rem_ptr->intf_name) != 0) { #if defined(LINUX) struct ifreq ifr; /* validate the interface */ memset(&ifr, 0, sizeof(ifr)); if (g_rem_ptr->intf_name) strncpy(ifr.ifr_name, g_rem_ptr->intf_name, IFNAMSIZ); if (wl_check((void *)&ifr)) { DPRINT_ERR(ERR, "%s: wl driver adapter not found\n", g_rem_ptr->intf_name); /* Signal end of command output */ g_rem_ptr->msg.len = 0; remote_tx_response(wl, NULL, BCME_NODEVICE); if (buf_ptr) free(buf_ptr); #ifdef RWL_SOCKET close_sock_handle(g_rwl_hndle); #endif continue; } #endif /* LINUX */ #if defined(vxworks) if (wl_check((void *)g_rem_ptr->intf_name)) { DPRINT_ERR(ERR, "%s: wl driver adapter not found\n", g_rem_ptr->intf_name); /* Signal end of command output */ g_rem_ptr->msg.len = 0; remote_tx_response(wl, NULL, BCME_NODEVICE); if (buf_ptr) free(buf_ptr); #ifdef RWL_SOCKET close_sock_handle(g_rwl_hndle); #endif continue; } #endif /* vxworks */ if (set_interface(wl, g_rem_ptr->intf_name) == BCME_OK) DPRINT_DBG(OUTPUT, "\n %s Interface will be used \n", (char *)wl); } } #endif /* ifndef RWL_DONGLE */ #endif /* defined(LINUX) || defined(vxworks) */ #endif /* ifndef OLYMPIC_RWL */ if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL || g_rem_ptr->msg.flags & RDHD_SET_IOCTL) { #ifdef WIN32 #if defined (RWL_DONGLE) || defined (RWL_WIFI) /* For commands with msg length as zero initialize the buffer to null */ if (g_rem_ptr->msg.len == 0) buf_ptr = NULL; #endif #else if (g_rem_ptr->msg.len == 0) buf_ptr = NULL; #endif /* WIN32 */ #if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) || defined(MACOSX) || defined(TARGET_wiced) #ifdef OLYMPIC_RWL set_interface(wl, old_intf_name); #endif #if defined( TARGET_wiced ) set_interface(wl, g_rem_ptr->intf_name); #endif if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) { if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr && !strncmp((const char *)buf_ptr, "init", g_rem_ptr->msg.len)) { DPRINT_INFO(OUTPUT, "REC : init command\n"); err = 0; } else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr && !strncmp((const char *)buf_ptr, "download", g_rem_ptr->msg.len)) { DPRINT_INFO(OUTPUT, "REC : download command\n"); download_flag = download_flag? 0: 1; if (download_flag) { DPRINT_INFO(OUTPUT, "download started\n"); start_download( ); } else { DPRINT_INFO(OUTPUT, "download completed\n"); finish_download( ); } err = 0; } else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr && !strncmp((const char *)buf_ptr, "membytes", g_rem_ptr->msg.len)) { DPRINT_INFO(OUTPUT, "REC : membytes command\n"); skip = strlen("membytes "); uint32_t address = *((uint32_t*)(buf_ptr + skip)); skip += sizeof(uint32_t); uint32_t len = *((uint32_t*)(buf_ptr + skip)); skip += sizeof(uint32_t); if ( len != g_rem_ptr->msg.len - skip ) { DPRINT_ERR(ERR, "Length does not match\n"); } membytes_write( address, buf_ptr + skip, g_rem_ptr->msg.len - skip ); err = 0; } else { err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len, TRUE); DPRINT_INFO(OUTPUT, "SEND : cmd %d\t msg len %d\n", g_rem_ptr->msg.cmd, g_rem_ptr->msg.len); DPRINT_INFO(OUTPUT, "error code: %d\n", err); } } #if defined(LINUX) if (err == IOCTL_ERROR) { DPRINT_ERR(ERR, "Error in executing wl_ioctl\n"); DPRINT_ERR(ERR, "Setting Default Interface1 \n"); set_interface(wl, old_intf_name); } if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) { err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len, TRUE); } #endif /* LINUX */ #elif vxworks if ((err = wl_ioctl_vx(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len)) != 0) { DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n"); } if (err == IOCTL_ERROR) { DPRINT_ERR(ERR, "Error in executing wl_ioctl\n"); DPRINT_ERR(ERR, "Setting Default Interface \n"); set_interface(wl, old_intf_name); } #elif WIN32 dwlen = g_rem_ptr->msg.len; if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) { g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd - WL_OID_BASE + OID_DHD_IOCTLS; } err = (int)ir_setinformation(wl, g_rem_ptr->msg.cmd, buf_ptr, &dwlen); #endif /* LINUX TARGETOS_symbian MACOSX */ g_rem_ptr->msg.flags = REMOTE_SET_IOCTL; } /* RDHD/REMOTE_SET_IOCTL */ if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL || g_rem_ptr->msg.flags & RDHD_GET_IOCTL) { #if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) || defined(MACOSX) || defined(TARGET_wiced) if (g_rem_ptr->msg.cmd == WLC_GET_VAR && buf_ptr && strncmp((const char *)buf_ptr, "exit", g_rem_ptr->msg.len) == 0) { /* exit command from remote client terminates server */ free(buf_ptr); break; } #if defined( TARGET_wiced ) set_interface(wl, g_rem_ptr->intf_name); #endif if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL) err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len, FALSE); #if defined (LINUX) if (err == IOCTL_ERROR) { DPRINT_ERR(ERR, "REMOTE_GET_IOCTL::Error in executing wl_ioctl\n"); DPRINT_ERR(ERR, "Setting Default Interface \n"); set_interface(wl, old_intf_name); } if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL) err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len, FALSE); #endif /* LINUX */ #elif vxworks if ((err = wl_ioctl_vx(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr, g_rem_ptr->msg.len)) != 0) { DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n"); } if (err == IOCTL_ERROR) { DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n"); DPRINT_ERR(ERR, "Setting Default Interface \n"); set_interface(wl, old_intf_name); } #elif WIN32 if (g_rem_ptr->msg.cmd == (WL_OID_BASE + WLC_GET_VAR) && strncmp(buf_ptr, "exit", g_rem_ptr->msg.len) == 0) { /* exit command from remote client terminates server */ if (buf_ptr) { free(buf_ptr); } break; } dwlen = g_rem_ptr->msg.len; if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL) { g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd - WL_OID_BASE + OID_DHD_IOCTLS; } err = (int)ir_queryinformation(wl, g_rem_ptr->msg.cmd, buf_ptr, &dwlen); #endif /* defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) || defined(TARGET_wiced) */ g_rem_ptr->msg.flags = REMOTE_GET_IOCTL; } /* REMOTE_GET_IOCTL */ DPRINT_INFO(OUTPUT, "RESP : cmd %d\t msg len %d\n", g_rem_ptr->msg.cmd, g_rem_ptr->msg.len); #if defined(LINUX) || defined(vxworks) /* setting back default interface */ set_interface(wl, old_intf_name); #endif /* defined(LINUX) || defined(vxworks) */ /* Transmit the response results */ if (remote_tx_response(wl, buf_ptr, err) < 0) { DPRINT_ERR(ERR, "\nReturn results failed\n"); } #ifdef RWL_SOCKET if (g_rem_ptr->msg.flags != REMOTE_SHELL_CMD) /* Transmitted to client. Then close the handle & get the new handle * for next transmission & reception. In case of shell commands this * should be closed in respective shellproc files. */ close_sock_handle(g_rwl_hndle); #endif /* RWL_SOCKET */ if (buf_ptr) { free(buf_ptr); } } /* end of while */ #if defined (RWL_SOCKET) /* Close the main handle for socket */ close_sock_handle(transport_descriptor); #elif defined(RWL_SERIAL) /* Close the main handle for serial pipe */ rwl_close_pipe(remote_type, (void*)&transport_descriptor); #endif #ifdef RWLASD wfa_dut_deinit(); #endif return err; }
/* Handle synchronous shell commands here */ static int remote_shell_sync_exec(char *cmd_buf_ptr, void *wl) { char *kill_cmd_token; char sync_file_name[] = TEMPLATE; int fd, msg_len; char cmd[(strlen(cmd_buf_ptr) + 1)]; int pid, status, pid_final; char buf[SHELL_RESP_SIZE], cmd_find_lastpid[PID_SEARCH_CMD_SIZE]; int nbytes = 0; int child_status; static int sent_once = 0; struct utsname name; FILE *fpt; /* Default Size of Return Value of the shell command is 2bytes */ kill_cmd_token = strstr(cmd_buf_ptr, "kill"); /* Synchronous Kill command processing is handled separately */ if (kill_cmd_token != NULL) { msg_len = remote_kill_cmd_exec(cmd_buf_ptr); remote_tx_response(wl, cmd_buf_ptr, msg_len); return 0; } /* Process synchronous command other than kill command */ if ((fd = mkstemp(sync_file_name)) < 0) { perror("mkstemp failed"); DPRINT_ERR(ERR, "\n errno:%d\n", errno); sprintf(cmd_buf_ptr, "%s\n", "mkstemp failed"); return BCME_ERROR; } close(fd); strcpy(cmd, cmd_buf_ptr); /* Synchronous timeout command processing is handled separately */ if (strstr(cmd_buf_ptr, "--timeout") != NULL) { if ((msg_len = shell_timeout_cmd (cmd, sync_file_name) > 0)) { /* Signal end of command output */ g_rem_ptr->msg.len = 0; g_rem_ptr->msg.cmd = g_return_stat; remote_tx_response(wl, NULL, 0); return msg_len; } else { /* Parse out --timeout <val> since command is successful * point buffer to the shell command */ strcpy(cmd, cmd_buf_ptr); strtok_r(cmd, " ", &cmd_buf_ptr); strcpy(cmd, cmd_buf_ptr); strtok_r(cmd, " ", &cmd_buf_ptr); } } /* Schedule an ALARM in case of timeout value of SHELL_TIMEOUT seconds */ /* Defalut time out only in case of Non socket transport */ alarm(g_shellsync_timeout); /* registering the relevant signals to handle end of child process, * the ctrl+c event on the server side and the kill command on the * server process */ signal(SIGCHLD, rwl_chld_handler); signal(SIGINT, handle_ctrlc); signal(SIGTERM, handle_ctrlc); /* Set g_sig_chld before forking */ g_sig_chld = 1; if (strcmp("reboot", cmd_buf_ptr) == 0) { /* reboot command */ memset(buf, 0, sizeof(buf)); strncpy(buf, REBOOT_MSG, sizeof(REBOOT_MSG)); remote_tx_response(wl, buf, 0); /* Signal end of command output */ g_rem_ptr->msg.len = 0; g_rem_ptr->msg.cmd = 0; remote_tx_response(wl, NULL, 0); sleep(1); /* Clean up the temp file */ remove(sync_file_name); } if ((pid = fork()) == 0) { close(STDOUT_FILENO); fd = open(sync_file_name, O_WRONLY|O_SYNC); /* Redirect stdin to dev/null. This handles un usual commands like * sh cat from the client side */ close(STDIN_FILENO); open("/dev/null", O_RDONLY); close(STDERR_FILENO); fcntl(fd, F_DUPFD, STDERR_FILENO); if ((status = execl(SH_PATH, "sh", "-c", cmd_buf_ptr, NULL)) == -1) { perror("Exec error"); } } /* end of fork */ g_shellsync_pid = pid; /* The g_return_stat is being set for short commands */ waitpid(g_shellsync_pid, &child_status, WNOHANG); if (WIFEXITED(child_status)) g_return_stat = WEXITSTATUS(child_status); else g_return_stat = 1; /* Read file in the interim from a temp file and send back the results */ fd = open(sync_file_name, O_RDONLY|O_SYNC); while (1) { /* read file in the interim and send back the results */ nbytes = read(fd, buf, SHELL_RESP_SIZE); g_rem_ptr->msg.len = nbytes; if (nbytes > 0) { remote_tx_response(wl, buf, 0); #ifdef RWL_SERIAL /* usleep introduced for flooding of data over serial port */ usleep(1); #endif } if (get_ctrlc_header(wl) >= 0) { if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) { uname(&name); /* Checking for mips architecture * The mips machine responds differently to * execl command. so the pid is incremented * to kill the right command. */ if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0) pid++; if (strncmp(name.machine, "armv5tel", sizeof(name.machine)) == 0) { snprintf(cmd_find_lastpid, sizeof(cmd_find_lastpid), "ps | awk \'PRINT $1\' | tail -n 1"); if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) { sprintf(buf, "%s\n", "Can't return PID"); return BCME_ERROR; } fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid), fpt); pid_final = atoi(cmd_find_lastpid); while (pid <= pid_final) { kill(pid, SIGKILL); pid++; } pclose(fpt); } else { kill(pid, SIGKILL); } break; } } if (get_ctrlc_header(wl) >= 0) { if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) { uname(&name); /* Checking for mips architecture * The mips machine responds differently to * execl command. so the pid is incremented * to kill the right command. */ if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0) { pid++; kill(pid, SIGKILL); } /* Checking for arm architecture * The multiple commands would not work * for ctrl+C. So we kill the processes * spawned after the parent. This method has * its own limitations but the busybox in pxa * doesnot have many options to implement it better */ else { if (strncmp(name.machine, "armv5tel", sizeof(name.machine)) == 0) { /* The command below is used to get the * PIDs and they are killed */ snprintf(cmd_find_lastpid, sizeof(cmd_find_lastpid), "ps | awk \'PRINT $1\' | tail -n 1"); if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) { sprintf(buf, "%s\n", "Can't return PID"); return BCME_ERROR; } fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid), fpt); pid_final = atoi(cmd_find_lastpid); while (pid <= pid_final) { kill(pid, SIGKILL); pid++; } pclose(fpt); } /* In the case of x86, on receiving ctrl+C * the child PIDs are obtained by searching * the parent PID to obtain the PIDs of the * and kill them */ else { while (pid != 0) { /* The commad below is used to get the * child PIDs by using their parent PID */ snprintf(cmd_find_lastpid, sizeof(cmd_find_lastpid), "ps al | awk \"{ if (\\$4 == %d)" " {print \\$3}}\"| head -n 1", g_shellsync_pid); if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) { sprintf(buf, "%s\n", "Can't return PID"); return BCME_ERROR; } fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid), fpt); pid = atoi(cmd_find_lastpid); if (pid == 0) kill(g_shellsync_pid, SIGKILL); else kill(pid, SIGKILL); pclose(fpt); } } } break; } } if (set_ctrlc == 1) { g_rem_ptr->msg.len = 0; g_rem_ptr->msg.cmd = g_return_stat; remote_tx_response(wl, NULL, g_return_stat); unlink(sync_file_name); kill(0, SIGKILL); } /* It is possible that the child would have exited * However we did not get a chance to read the file * In this case go once again and check the file */ if (!sent_once && !g_sig_chld) { sent_once = 1; continue; } if (!(g_sig_chld || nbytes)) break; } wait(NULL); close(fd); /* Signal end of command output */ g_rem_ptr->msg.len = 0; g_rem_ptr->msg.cmd = g_return_stat; remote_tx_response(wl, NULL, g_return_stat); /* Cancel the time out alarm if any */ alarm(0); sent_once = 0; /* Clean up the temp file */ unlink(sync_file_name); g_shellsync_timeout = DEFAULT_SHELL_TIMEOUT; signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); return BCME_OK; }