char *smb_readline(char *prompt, void (*callback)(void), char **(completion_fn)(const char *text, int start, int end)) { char *ret; int fd = fileno(stdin); #if HAVE_LIBREADLINE /* * Current versions of readline on Linux seem to have * problems with EOF on a pipe. */ if (isatty(fd)) { if (completion_fn) rl_attempted_completion_function = completion_fn; if (callback) rl_event_hook = (Function *)callback; ret = readline(prompt); if (ret && *ret) add_history(ret); return ret; } else #endif { fd_set fds; extern FILE *dbf; static pstring line; struct timeval timeout; fprintf(dbf, "%s", prompt); fflush(dbf); while (1) { timeout.tv_sec = 5; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(fd,&fds); if (sys_select_intr(fd+1,&fds,NULL,NULL,&timeout) == 1) { ret = fgets(line, sizeof(line), stdin); return ret; } if (callback) callback(); } } }
static void filter_child(int c, struct in_addr dest_ip) { int s; /* we have a connection from a new client, now connect to the server */ s = open_socket_out(SOCK_STREAM, &dest_ip, 445, LONG_CONNECT_TIMEOUT); if (s == -1) { d_printf("Unable to connect to %s\n", inet_ntoa(dest_ip)); exit(1); } while (c != -1 || s != -1) { fd_set fds; int num; FD_ZERO(&fds); if (s != -1) FD_SET(s, &fds); if (c != -1) FD_SET(c, &fds); num = sys_select_intr(MAX(s+1, c+1),&fds,NULL,NULL,NULL); if (num <= 0) continue; if (c != -1 && FD_ISSET(c, &fds)) { if (!receive_smb(c, packet, BUFFER_SIZE, 0)) { d_printf("client closed connection\n"); exit(0); } filter_request(packet); if (!send_smb(s, packet)) { d_printf("server is dead\n"); exit(1); } } if (s != -1 && FD_ISSET(s, &fds)) { if (!receive_smb(s, packet, BUFFER_SIZE, 0)) { d_printf("server closed connection\n"); exit(0); } filter_reply(packet); if (!send_smb(c, packet)) { d_printf("client is dead\n"); exit(1); } } } d_printf("Connection closed\n"); exit(0); }
static void start_filter(char *desthost) { int s, c; struct in_addr dest_ip; CatchChild(); /* start listening on port 445 locally */ s = open_socket_in(SOCK_STREAM, 445, 0, 0, True); if (s == -1) { d_printf("bind failed\n"); exit(1); } if (listen(s, 5) == -1) { d_printf("listen failed\n"); } if (!resolve_name(desthost, &dest_ip, 0x20)) { d_printf("Unable to resolve host %s\n", desthost); exit(1); } while (1) { fd_set fds; int num; struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); FD_ZERO(&fds); FD_SET(s, &fds); num = sys_select_intr(s+1,&fds,NULL,NULL,NULL); if (num > 0) { c = accept(s, &addr, &in_addrlen); if (c != -1) { if (fork() == 0) { close(s); filter_child(c, dest_ip); exit(0); } else { close(c); } } } } }
static BOOL irix_oplock_msg_waiting(fd_set *fds) { int selrtn; fd_set myfds; struct timeval to; if (oplock_pipe_read == -1) return False; if (fds) { return FD_ISSET(oplock_pipe_read, fds); } /* Do a zero-time select. We just need to find out if there * are any outstanding messages. We use sys_select_intr as * we need to ignore any signals. */ FD_ZERO(&myfds); FD_SET(oplock_pipe_read, &myfds); to = timeval_set(0, 0); selrtn = sys_select_intr(oplock_pipe_read+1,&myfds,NULL,NULL,&to); return (selrtn == 1) ? True : False; }
ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) { fd_set fds; int selrtn; ssize_t readret; size_t nread = 0; struct timeval timeout; /* just checking .... */ if (maxcnt <= 0) return(0); smb_read_error = 0; /* Blocking read */ if (time_out <= 0) { if (mincnt == 0) mincnt = maxcnt; while (nread < mincnt) { readret = sys_read(fd, buf + nread, maxcnt - nread); if (readret == 0) { DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } return((ssize_t)nread); } /* Most difficult - timeout read */ /* If this is ever called on a disk file and mincnt is greater then the filesize then system performance will suffer severely as select always returns true on disk files */ /* Set initial timeout */ timeout.tv_sec = (time_t)(time_out / 1000); timeout.tv_usec = (long)(1000 * (time_out % 1000)); for (nread=0; nread < mincnt; ) { FD_ZERO(&fds); FD_SET(fd,&fds); selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout); /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } /* Did we timeout ? */ if (selrtn == 0) { DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n")); smb_read_error = READ_TIMEOUT; return -1; } readret = sys_read(fd, buf+nread, maxcnt-nread); if (readret == 0) { /* we got EOF on the file descriptor */ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { /* the descriptor is probably dead */ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } /* Return the number we got */ return (ssize_t)nread; }
BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs, int timeout, int *fd_index, int *fd) { int i, resulting_index, res; int *sockets; BOOL good_connect; fd_set r_fds, wr_fds; struct timeval tv; int maxfd; int connect_loop = 10000; /* 10 milliseconds */ timeout *= 1000; /* convert to microseconds */ sockets = SMB_MALLOC_ARRAY(int, num_addrs); if (sockets == NULL) return False; resulting_index = -1; for (i=0; i<num_addrs; i++) sockets[i] = -1; for (i=0; i<num_addrs; i++) { sockets[i] = socket(PF_INET, SOCK_STREAM, 0); if (sockets[i] < 0) goto done; set_blocking(sockets[i], False); } connect_again: good_connect = False; for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; if (connect(sockets[i], (struct sockaddr *)&(addrs[i]), sizeof(*addrs)) == 0) { /* Rather unlikely as we are non-blocking, but it * might actually happen. */ resulting_index = i; goto done; } if (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN) { /* These are the error messages that something is progressing. */ good_connect = True; } else if (errno != 0) { /* There was a direct error */ close(sockets[i]); sockets[i] = -1; } } if (!good_connect) { /* All of the connect's resulted in real error conditions */ goto done; } /* Lets see if any of the connect attempts succeeded */ maxfd = 0; FD_ZERO(&wr_fds); FD_ZERO(&r_fds); for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; FD_SET(sockets[i], &wr_fds); FD_SET(sockets[i], &r_fds); if (sockets[i]>maxfd) maxfd = sockets[i]; } tv.tv_sec = 0; tv.tv_usec = connect_loop; res = sys_select_intr(maxfd+1, &r_fds, &wr_fds, NULL, &tv); if (res < 0) goto done; if (res == 0) goto next_round; for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; /* Stevens, Network Programming says that if there's a * successful connect, the socket is only writable. Upon an * error, it's both readable and writable. */ if (FD_ISSET(sockets[i], &r_fds) && FD_ISSET(sockets[i], &wr_fds)) { /* readable and writable, so it's an error */ close(sockets[i]); sockets[i] = -1; continue; } if (!FD_ISSET(sockets[i], &r_fds) && FD_ISSET(sockets[i], &wr_fds)) { /* Only writable, so it's connected */ resulting_index = i; goto done; } } next_round: timeout -= connect_loop; if (timeout <= 0) goto done; connect_loop *= 1.5; if (connect_loop > timeout) connect_loop = timeout; goto connect_again; done: for (i=0; i<num_addrs; i++) { if (i == resulting_index) continue; if (sockets[i] >= 0) close(sockets[i]); } if (resulting_index >= 0) { *fd_index = resulting_index; *fd = sockets[*fd_index]; set_blocking(*fd, True); } free(sockets); return (resulting_index >= 0); }
ssize_t read_data_until(int fd,char *buffer,size_t N, const struct timeval *endtime) { ssize_t ret; size_t total=0; smb_read_error = 0; while (total < N) { if (endtime != NULL) { fd_set r_fds; struct timeval timeout; int selrtn; if (!timeout_until(&timeout, endtime)) { DEBUG(10,("read_data_until: read timed out\n")); smb_read_error = READ_TIMEOUT; return -1; } FD_ZERO(&r_fds); FD_SET(fd, &r_fds); /* Select but ignore EINTR. */ selrtn = sys_select_intr(fd+1, &r_fds, NULL, NULL, &timeout); if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ DEBUG(0,("read_data_until: select error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } /* Did we timeout ? */ if (selrtn == 0) { DEBUG(10,("read_data_until: select timed out.\n")); smb_read_error = READ_TIMEOUT; return -1; } } ret = sys_read(fd,buffer + total,N - total); if (ret == 0) { DEBUG(10,("read_data_until: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_EOF; return 0; } if (ret == -1) { if (errno == EAGAIN) { /* Non-blocking socket with no data available. Try select again. */ continue; } DEBUG(0,("read_data_until: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_ERROR; return -1; } total += ret; } return (ssize_t)total; }