/** * raw_socket_read - Read data from a socket - Implements Connection::conn_read() */ int raw_socket_read(struct Connection *conn, char *buf, size_t count) { int rc; mutt_sig_allow_interrupt(1); do { rc = read(conn->fd, buf, count); } while (rc < 0 && (errno == EINTR)); if (rc < 0) { mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno)); SigInt = 0; } mutt_sig_allow_interrupt(0); if (SigInt) { mutt_error(_("Connection to %s has been aborted"), conn->account.host); SigInt = 0; rc = -1; } return rc; }
/** * raw_socket_write - Write data to a socket - Implements Connection::conn_write() */ int raw_socket_write(struct Connection *conn, const char *buf, size_t count) { int rc; size_t sent = 0; mutt_sig_allow_interrupt(1); do { do { rc = write(conn->fd, buf + sent, count - sent); } while (rc < 0 && (errno == EINTR)); if (rc < 0) { mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno)); mutt_sig_allow_interrupt(0); return -1; } sent += rc; } while ((sent < count) && (SigInt == 0)); mutt_sig_allow_interrupt(0); return sent; }
/** * mutt_getch - Read a character from the input buffer * @retval obj Event to process * * The priority for reading events is: * 1. UngetKeyEvents buffer * 2. MacroEvents buffer * 3. Keyboard * * This function can return: * - Error `{ -1, OP_NULL }` * - Timeout `{ -2, OP_NULL }` */ struct Event mutt_getch(void) { int ch; struct Event err = { -1, OP_NULL }, ret; struct Event timeout = { -2, OP_NULL }; if (UngetCount) return UngetKeyEvents[--UngetCount]; if (!OptIgnoreMacroEvents && MacroBufferCount) return MacroEvents[--MacroBufferCount]; SigInt = 0; mutt_sig_allow_interrupt(1); #ifdef KEY_RESIZE /* ncurses 4.2 sends this when the screen is resized */ ch = KEY_RESIZE; while (ch == KEY_RESIZE) #endif /* KEY_RESIZE */ #ifdef USE_INOTIFY ch = mutt_monitor_getch(); #else ch = getch(); #endif /* USE_INOTIFY */ mutt_sig_allow_interrupt(0); if (SigInt) { mutt_query_exit(); return err; } /* either timeout, a sigwinch (if timeout is set), or the terminal * has been lost */ if (ch == ERR) { if (!isatty(0)) mutt_exit(1); return timeout; } if ((ch & 0x80) && C_MetaKey) { /* send ALT-x as ESC-x */ ch &= ~0x80; mutt_unget_event(ch, 0); ret.ch = '\033'; ret.op = 0; return ret; } ret.ch = ch; ret.op = 0; return (ch == ctrl('G')) ? err : ret; }
/** * socket_connect - set up to connect to a socket fd * @param fd File descriptor to connect with * @param sa Address info * @retval 0 Success * @retval >0 An errno, e.g. EPERM * @retval -1 Error */ static int socket_connect(int fd, struct sockaddr *sa) { int sa_size; int save_errno; sigset_t set; if (sa->sa_family == AF_INET) sa_size = sizeof(struct sockaddr_in); #ifdef HAVE_GETADDRINFO else if (sa->sa_family == AF_INET6) sa_size = sizeof(struct sockaddr_in6); #endif else { mutt_debug(LL_DEBUG1, "Unknown address family!\n"); return -1; } if (C_ConnectTimeout > 0) alarm(C_ConnectTimeout); mutt_sig_allow_interrupt(1); /* FreeBSD's connect() does not respect SA_RESTART, meaning * a SIGWINCH will cause the connect to fail. */ sigemptyset(&set); sigaddset(&set, SIGWINCH); sigprocmask(SIG_BLOCK, &set, NULL); save_errno = 0; if (connect(fd, sa, sa_size) < 0) { save_errno = errno; mutt_debug(LL_DEBUG2, "Connection failed. errno: %d\n", errno); SigInt = 0; /* reset in case we caught SIGINTR while in connect() */ } if (C_ConnectTimeout > 0) alarm(0); mutt_sig_allow_interrupt(0); sigprocmask(SIG_UNBLOCK, &set, NULL); return save_errno; }