static void WINAPI cygterm_watch_child_process(void* param) { pcmd_backend_data local = param; char* errormsg = "Child process exit!"; DWORD ret = WaitForSingleObject(local->m_hChildProcess, INFINITE ); from_backend(local->frontend, 0, errormsg, strlen(errormsg)); }
static void c_write1(Telnet telnet, int c) { int backlog; char cc = (char) c; backlog = from_backend(telnet->frontend, 0, &cc, 1); sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG); }
static int serial_gotdata(struct handle *h, void *data, int len) { Serial serial = (Serial)handle_get_privdata(h); if (len <= 0) { const char *error_msg; /* * Currently, len==0 should never happen because we're * ignoring EOFs. However, it seems not totally impossible * that this same back end might be usable to talk to named * pipes or some other non-serial device, in which case EOF * may become meaningful here. */ if (len == 0) error_msg = "End of file reading from serial device"; else error_msg = "Error reading from serial device"; serial_terminate(serial); notify_remote_exit(serial->frontend); logevent(serial->frontend, error_msg); connection_fatal(serial->frontend, "%s", error_msg); return 0; /* placate optimiser */ } else { return from_backend(serial->frontend, 0, data, len); } }
static void c_write(Ldisc ldisc, char *buf, int len) { if( !get_param("PUTTY") && (GetRuTTYFlag()>0) ) { from_backend_local(ldisc->frontend, 0, buf, len); } else { from_backend(ldisc->frontend, 0, buf, len); } }
static DWORD cmd_on_receive_data( pcmd_backend_data local, HANDLE h) { DWORD nBytesRead; char lpszBuffer[256+1]; char *readBuf = NULL; char* sendcmd = NULL; int readlen = 0; char * descmd = NULL; int deslen = 0; DWORD total = 0; DWORD byteleft = 0; if (!ReadFile(h, lpszBuffer, 256, &nBytesRead, NULL) || !nBytesRead) { if (GetLastError() == ERROR_BROKEN_PIPE) return ERROR_BROKEN_PIPE; // pipe done - normal exit path. } // data on! WaitForSingleObject(local->m_hWriteEvent, INFINITE); do { if (nBytesRead) { lpszBuffer[nBytesRead] = '\0'; my_print("[ondata]%x, %d", h, nBytesRead); readBuf = lpszBuffer; readlen = nBytesRead; deslen = readlen*2; descmd = smalloc(deslen); memset(descmd, 0, deslen); cmd_convert_to_cmd_format(readBuf, readlen, descmd, deslen); from_backend(local->frontend, 0, descmd, deslen); sfree(descmd); } if( !PeekNamedPipe(h, lpszBuffer, 256, &nBytesRead, &total, &byteleft) ) { if (GetLastError() == ERROR_BROKEN_PIPE) return ERROR_BROKEN_PIPE; // pipe done - normal exit path. } if( byteleft == 0 ) { SetEvent(local->m_hWriteEvent); break; } if (!ReadFile(h, lpszBuffer, 256, &nBytesRead, NULL) || !nBytesRead) { if (GetLastError() == ERROR_BROKEN_PIPE) return ERROR_BROKEN_PIPE; // pipe done - normal exit path. } }while(1); return ERROR_SUCCESS; }
static void cmd_rollback_until_none(pcmd_backend_data local) { int len = strlen(local->semdcmd); for( len; len >0; len --) { char buf[1]; buf[0] = 127; from_backend(local->frontend, 0, buf, 1); } local->semdcmd[0] = '\0'; }
static int serial_select_result(int fd, int event) { Serial serial; char buf[4096]; int ret; int finished = FALSE; serial = find234(serial_by_fd, &fd, serial_find_by_fd); if (!serial) return 1; /* spurious event; keep going */ if (event == 1) { ret = read(serial->fd, buf, sizeof(buf)); if (ret == 0) { /* * Shouldn't happen on a real serial port, but I'm open * to the idea that there might be two-way devices we * can treat _like_ serial ports which can return EOF. */ finished = TRUE; } else if (ret < 0) { #ifdef EAGAIN if (errno == EAGAIN) return 1; /* spurious */ #endif #ifdef EWOULDBLOCK if (errno == EWOULDBLOCK) return 1; /* spurious */ #endif perror("read serial port"); exit(1); } else if (ret > 0) { serial->inbufsize = from_backend(serial->frontend, 0, buf, ret); serial_uxsel_setup(serial); /* might acquire backlog and freeze */ } } else if (event == 2) { /* * Attempt to send data down the pty. */ serial_try_write(serial); } if (finished) { serial_close(serial); serial->finished = TRUE; notify_remote_exit(serial->frontend); } return !finished; }
static int cygterm_receive(Plug plug, int urgent, char *data, int len) { Local local = (Local)plug; int backlog; cygterm_debug("backend -> display %u", len); // dmemdump(data, len); backlog = from_backend(local->frontend, 0, data, len); // dmemdumpl(data, len); sk_set_frozen(local->s, backlog > CYGTERM_MAX_BACKLOG); cygterm_debug("OK"); return 1; }
void backend_socket_log(void *frontend, int type, SockAddr addr, int port, const char *error_msg, int error_code, Conf *conf, int session_started) { char addrbuf[256], *msg; switch (type) { case 0: sk_getaddr(addr, addrbuf, lenof(addrbuf)); if (sk_addr_needs_port(addr)) { msg = dupprintf("Connecting to %s port %d", addrbuf, port); } else { msg = dupprintf("Connecting to %s", addrbuf); } break; case 1: sk_getaddr(addr, addrbuf, lenof(addrbuf)); msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg); break; case 2: /* Proxy-related log messages have their own identifying * prefix already, put on by our caller. */ { int len, log_to_term; /* Suffix \r\n temporarily, so we can log to the terminal. */ msg = dupprintf("%s\r\n", error_msg); len = (int)strlen(msg); assert(len >= 2); log_to_term = conf_get_int(conf, CONF_proxy_log_to_term); if (log_to_term == AUTO) log_to_term = session_started ? FORCE_OFF : FORCE_ON; if (log_to_term == FORCE_ON) from_backend(frontend, TRUE, msg, len); msg[len-2] = '\0'; /* remove the \r\n again */ } break; default: msg = NULL; /* shouldn't happen, but placate optimiser */ break; } if (msg) { logevent(frontend, msg); sfree(msg); } }
static void c_write(Telnet telnet, char *buf, int len) { int backlog; backlog = from_backend(telnet->frontend, 0, buf, len); sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG); }
static void c_write(Ldisc ldisc, char *buf, int len) { from_backend(ldisc->frontend, 0, buf, len); }
static void c_write(Adb adb, char *buf, int len) { int backlog = from_backend(adb->frontend, 0, buf, len); sk_set_frozen(adb->s, backlog > ADB_MAX_BACKLOG); }
static int cmd_send(void *handle, char *buf, int len) { pcmd_backend_data local = handle; DWORD writed; char *tmp = smalloc(len+1); memset(tmp,0,len+1); if( !handle || !buf || !len ) return 0; if( strstr(buf, "\r\n") == NULL ) { if( len == 1 && buf[0] == 127 ) //backspace { int l = strlen(local->semdcmd); if( l != 0 ) { from_backend(local->frontend, 0, buf, len); l = l-1; } local->semdcmd[l] = '\0'; local->bufsize = 1; } else if( buf[0] == 27 ) { // left || right || up || down char c = buf[2]; if( c == 'A' || c == 'B' ) // up and down { cmd_rollback_until_none(local); if( local->historycount != 0 ) { char* his_buf = (c == 'A') ? cmd_get_previeous_histroy(local) : cmd_get_next_histroy(local); strcpy(local->semdcmd, his_buf); from_backend(local->frontend, 0, local->semdcmd, strlen(local->semdcmd)); } } else { from_backend(local->frontend, 0, buf+1, 2); memcpy(tmp, buf+1, 2); strcat(local->semdcmd, tmp); local->bufsize = 2; } } else { from_backend(local->frontend, 0, buf, len); memcpy(tmp, buf, len); strcat(local->semdcmd, tmp); local->bufsize = len; } } else { char sendcmd[MAX_CMD_BUF]; strcpy(sendcmd, local->semdcmd); cmd_rollback_until_none(local); WriteFile(local->m_hStdInWrite, sendcmd, strlen(sendcmd), &writed, NULL); local->bufsize = writed; WriteFile(local->m_hStdInWrite, "\n", 1, &writed, NULL); local->bufsize += writed; cmd_add_histroy(local, sendcmd); local->current_histroy = NULL; } sfree(tmp); return local->bufsize; }
static void logfopen_callback(void *handle, int mode) { struct LogContext *ctx = (struct LogContext *)handle; char buf[256], *event; struct tm tm; const char *fmode; int shout = FALSE; if (mode == 0) { ctx->state = L_ERROR; /* disable logging */ } else { fmode = (mode == 1 ? "ab" : "wb"); ctx->lgfp = f_open(ctx->currlogfilename, fmode, FALSE); if (ctx->lgfp) { ctx->state = L_OPEN; } else { ctx->state = L_ERROR; shout = TRUE; } } if (ctx->state == L_OPEN) { /* Write header line into log file. */ tm = ltime(); strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s" " =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf); } event = dupprintf(MPEXT_BOM "%s session log (%s mode) to file: %s", ctx->state == L_ERROR ? (mode == 0 ? "Disabled writing" : "Error writing") : (mode == 1 ? "Appending" : "Writing new"), (ctx->logtype == LGTYP_ASCII ? "ASCII" : ctx->logtype == LGTYP_DEBUG ? "raw" : ctx->logtype == LGTYP_PACKETS ? "SSH packets" : ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" : "unknown"), filename_to_str(ctx->currlogfilename)); logevent(ctx->frontend, event); if (shout) { /* * If we failed to open the log file due to filesystem error * (as opposed to user action such as clicking Cancel in the * askappend box), we should log it more prominently. We do * this by sending it to the same place that stderr output * from the main session goes (so, either a console tool's * actual stderr, or a terminal window). * * Of course this is one case in which that policy won't cause * it to turn up embarrassingly in a log file of real server * output, because the whole point is that we haven't managed * to open any such log file :-) */ from_backend(ctx->frontend, 1, event, strlen(event)); from_backend(ctx->frontend, 1, "\r\n", 2); } sfree(event); /* * Having either succeeded or failed in opening the log file, * we should write any queued data out. */ assert(ctx->state != L_OPENING); /* make _sure_ it won't be requeued */ while (bufchain_size(&ctx->queue)) { void *data; int len; bufchain_prefix(&ctx->queue, &data, &len); logwrite(ctx, data, len); bufchain_consume(&ctx->queue, len); } }
static int xyz_Check(Backend *back, void *backhandle, Terminal *term, int outerr) { DWORD exitcode = 0; DWORD bread, avail; char buf[1024]; HANDLE h; if (!term->xyz_transfering) { return 0; } if (outerr) { h = term->xyz_Internals->read_stdout; } else { h = term->xyz_Internals->read_stderr; } bread = 0; PeekNamedPipe(h,buf,1,&bread,&avail,NULL); //check to see if there is any data to read from stdout if (bread != 0) { while (1) { bread = 0; PeekNamedPipe(h,buf,1,&bread,&avail,NULL); if (bread == 0) return 0; if (ReadFile(h,buf,sizeof(buf),&bread,NULL)) { //read the stdout pipe if (bread) { #if 0 char *buffer; int len; buffer = buf; len = bread; if (0) { char *debugbuff; char *bb, *p; int i; debugbuff = _alloca(len*3+128); debugbuff[0] = 0; bb = debugbuff; p = buffer; bb += sprintf(bb, "R: %8d ", time(NULL)); for(i=0; i < len; i++) { bb += sprintf(bb, "%2x ", *p++); } bb += sprintf(bb, "\n"); OutputDebugString(debugbuff); } else { char *debugbuff; debugbuff = _alloca(len+128); memcpy(debugbuff, buffer, len); debugbuff[len] = 0; if (outerr) { strcat(debugbuff, "<<<<<<<\n"); } else { strcat(debugbuff, "*******\n"); } OutputDebugString(debugbuff); } #endif if (outerr) { back->send(backhandle, buf, bread); } else { from_backend(term, 1, buf, bread); } continue; } } // EOF/ERROR xyz_Done(term); return 1; } return 1; } GetExitCodeProcess(term->xyz_Internals->pi.hProcess,&exitcode); if (exitcode != STILL_ACTIVE) { xyz_Done(term); return 1; } return 0; }
static int loop_send(void *handle, char *buf, int len) { struct loop_state *st = handle; return from_backend(st->term, 0, buf, len); }
static void c_write(char *buf, int len) { int backlog = from_backend(0, buf, len); sk_set_frozen(s, backlog > RAW_MAX_BACKLOG); }
int pty_real_select_result(Pty pty, int event, int status) { char buf[4096]; int ret; int finished = FALSE; if (event < 0) { /* * We've been called because our child process did * something. `status' tells us what. */ if ((WIFEXITED(status) || WIFSIGNALED(status))) { /* * The primary child process died. We could keep * the terminal open for remaining subprocesses to * output to, but conventional wisdom seems to feel * that that's the Wrong Thing for an xterm-alike, * so we bail out now (though we don't necessarily * _close_ the window, depending on the state of * Close On Exit). This would be easy enough to * change or make configurable if necessary. */ pty->exit_code = status; pty->child_dead = TRUE; del234(ptys_by_pid, pty); finished = TRUE; } } else { if (event == 1) { ret = read(pty->master_fd, buf, sizeof(buf)); /* * Clean termination condition is that either ret == 0, or ret * < 0 and errno == EIO. Not sure why the latter, but it seems * to happen. Boo. */ if (ret == 0 || (ret < 0 && errno == EIO)) { /* * We assume a clean exit if the pty has closed but the * actual child process hasn't. The only way I can * imagine this happening is if it detaches itself from * the pty and goes daemonic - in which case the * expected usage model would precisely _not_ be for * the pterm window to hang around! */ finished = TRUE; if (!pty->child_dead) pty->exit_code = 0; } else if (ret < 0) { perror("read pty master"); exit(1); } else if (ret > 0) { from_backend(pty->frontend, 0, buf, ret); } } else if (event == 2) { /* * Attempt to send data down the pty. */ pty_try_write(pty); } } if (finished && !pty->finished) { int close_on_exit; uxsel_del(pty->master_fd); pty_close(pty); pty->master_fd = -1; pty->finished = TRUE; /* * This is a slight layering-violation sort of hack: only * if we're not closing on exit (COE is set to Never, or to * Only On Clean and it wasn't a clean exit) do we output a * `terminated' message. */ close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit); if (close_on_exit == FORCE_OFF || (close_on_exit == AUTO && pty->exit_code != 0)) { char message[512]; message[0] = '\0'; if (WIFEXITED(pty->exit_code)) sprintf(message, "\r\n[pterm: process terminated with exit" " code %d]\r\n", WEXITSTATUS(pty->exit_code)); else if (WIFSIGNALED(pty->exit_code)) #ifdef HAVE_NO_STRSIGNAL sprintf(message, "\r\n[pterm: process terminated on signal" " %d]\r\n", WTERMSIG(pty->exit_code)); #else sprintf(message, "\r\n[pterm: process terminated on signal" " %d (%.400s)]\r\n", WTERMSIG(pty->exit_code), strsignal(WTERMSIG(pty->exit_code))); #endif from_backend(pty->frontend, 0, message, strlen(message)); } notify_remote_exit(pty->frontend); } return !finished; }
static void c_write(Raw raw, char *buf, int len) { int backlog = from_backend(raw->frontend, 0, buf, len); sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG); }
int pty_select_result(int fd, int event) { char buf[4096]; int ret; int finished = FALSE; if (fd == pty_master_fd && event == 1) { ret = read(pty_master_fd, buf, sizeof(buf)); /* * Clean termination condition is that either ret == 0, or ret * < 0 and errno == EIO. Not sure why the latter, but it seems * to happen. Boo. */ if (ret == 0 || (ret < 0 && errno == EIO)) { /* * We assume a clean exit if the pty has closed but the * actual child process hasn't. The only way I can * imagine this happening is if it detaches itself from * the pty and goes daemonic - in which case the * expected usage model would precisely _not_ be for * the pterm window to hang around! */ finished = TRUE; if (!pty_child_dead) pty_exit_code = 0; } else if (ret < 0) { perror("read pty master"); exit(1); } else if (ret > 0) { from_backend(pty_frontend, 0, buf, ret); } } else if (fd == pty_signal_pipe[0]) { pid_t pid; int status; char c[1]; read(pty_signal_pipe[0], c, 1); /* ignore its value; it'll be `x' */ do { pid = waitpid(-1, &status, WNOHANG); if (pid == pty_child_pid && (WIFEXITED(status) || WIFSIGNALED(status))) { /* * The primary child process died. We could keep * the terminal open for remaining subprocesses to * output to, but conventional wisdom seems to feel * that that's the Wrong Thing for an xterm-alike, * so we bail out now (though we don't necessarily * _close_ the window, depending on the state of * Close On Exit). This would be easy enough to * change or make configurable if necessary. */ pty_exit_code = status; pty_child_dead = TRUE; finished = TRUE; } } while(pid > 0); } if (finished && !pty_finished) { uxsel_del(pty_master_fd); pty_close(); pty_master_fd = -1; pty_finished = TRUE; /* * This is a slight layering-violation sort of hack: only * if we're not closing on exit (COE is set to Never, or to * Only On Clean and it wasn't a clean exit) do we output a * `terminated' message. */ if (pty_cfg.close_on_exit == FORCE_OFF || (pty_cfg.close_on_exit == AUTO && pty_exit_code != 0)) { char message[512]; if (WIFEXITED(pty_exit_code)) sprintf(message, "\r\n[pterm: process terminated with exit" " code %d]\r\n", WEXITSTATUS(pty_exit_code)); else if (WIFSIGNALED(pty_exit_code)) #ifdef HAVE_NO_STRSIGNAL sprintf(message, "\r\n[pterm: process terminated on signal" " %d]\r\n", WTERMSIG(pty_exit_code)); #else sprintf(message, "\r\n[pterm: process terminated on signal" " %d (%.400s)]\r\n", WTERMSIG(pty_exit_code), strsignal(WTERMSIG(pty_exit_code))); #endif from_backend(pty_frontend, 0, message, strlen(message)); } } return !finished; }
static void c_write(Rlogin rlogin, char *buf, int len) { int backlog = from_backend(rlogin->frontend, 0, buf, len); sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG); }