Ejemplo n.º 1
0
/* 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;
}