Long udp_connect(char *addr, Int port, Int *socket_return) { SOCKET fd; Int result, flags; struct in_addr inaddr; struct sockaddr_in saddr; /* Convert address to struct in_addr. */ inaddr.s_addr = inet_addr(addr); if (inaddr.s_addr == -1) return address_id; /* Get a socket for the connection. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == SOCKET_ERROR) return socket_id; /* Set the socket non-blocking. */ #ifdef __Win32__ result = 1; ioctlsocket(fd, FIONBIO, &result); #else flags = fcntl(fd, F_GETFL); #ifdef FNDELAY flags |= FNDELAY; #else #ifdef O_NDELAY flags |= O_NDELAY; #endif #endif fcntl(fd, F_SETFL, flags); #endif /* Make the connection. */ memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons((unsigned short) port); saddr.sin_addr = inaddr; do { result = connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)); } while (result == SOCKET_ERROR && GETERR() == ERR_INTR); *socket_return = fd; if (result != SOCKET_ERROR || GETERR() == ERR_INPROGRESS || GETERR() == ERR_AGAIN) return NOT_AN_IDENT; else return translate_connect_error(GETERR()); }
Int close_file(filec_t * file) { file->f.closed = 1; if (fclose(file->fp) == EOF) return GETERR(); return 0; }
cList *open_file(cStr * name, cStr * smode, Obj * obj) { char mode[4]; Int rw = 0; char *s = NULL; filec_t *fnew = file_new(); struct stat sbuf; /* parse the mode first, if the string pointer is NULL, set it readable */ if (smode != NULL) { s = smode->s; if (*s == '+') { rw = 1; fnew->f.readable = fnew->f.writable = 1; s++; } if (*s == '>') { s++; if (*s == '>') { s++; mode[0] = 'a'; } else { mode[0] = 'w'; } fnew->f.writable = 1; } else { if (*s == '<') s++; mode[0] = 'r'; fnew->f.readable = 1; } /* here is where we branch from perl, '-' is used to specify it as a 'binary' file (i.e. use buffers not cold strings) */ if (*s == '-') { s++; fnew->f.binary = 1; } } else { mode[0] = 'r'; fnew->f.readable = 1; } /* most systems ignore this, some need it */ mode[1] = 'b'; if (rw) { mode[2] = '+'; mode[3] = '\0'; } else { mode[2] = '\0'; } fnew->path = build_path(name->s, NULL, DISALLOW_DIR); if (fnew->path == NULL) return NULL; /* redundant, as build_path could have done this, but we have a special case which we need to handle differently */ if (stat(fnew->path->s, &sbuf) == F_SUCCESS) { /* Patch #6 -- Bruce Mitchener */ if (S_ISDIR(sbuf.st_mode)) { cthrow(directory_id, "\"%s\" is a directory.", fnew->path->s); file_discard(fnew, NULL); return NULL; } } fnew->fp = fopen(fnew->path->s, mode); if (fnew->fp == NULL) { if (GETERR() == ERR_NOMEM) panic("open_file(): %s", strerror(GETERR())); cthrow(file_id, "%s (%s)", strerror(GETERR()), name->s); file_discard(fnew, NULL); return NULL; } file_add(fnew); obj->file = fnew; fnew->objnum = obj->objnum; return statbuf_to_list(&sbuf); }
/* Wait for I/O events. sec is the number of seconds we can wait before * returning, or -1 if we can wait forever. Returns nonzero if an I/O event * happened. */ Int io_event_wait(Int sec, Conn *connections, server_t *servers, pending_t *pendings) { struct timeval tv, *tvp; Conn *conn; server_t *serv; pending_t *pend; fd_set read_fds, write_fds, except_fds; Int flags, nfds, count, result, error; int dummy = sizeof(int); /* Set time structure according to sec. */ if (sec == -1) { tvp = NULL; /* this is a rather odd thing to happen for me */ write_err("select: forever wait"); } else { tv.tv_sec = (long) sec; tv.tv_usec = 0; tvp = &tv; } /* Begin with blank file descriptor masks and an nfds of 0. */ FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_ZERO(&except_fds); nfds = 0; /* Listen for new data on connections, and also check for ability to write * to them if we have data to write. */ for (conn = connections; conn; conn = conn->next) { if (!conn->flags.dead) { FD_SET(conn->fd, &except_fds); FD_SET(conn->fd, &read_fds); } if (conn->write_buf->len) FD_SET(conn->fd, &write_fds); if (conn->fd >= nfds) nfds = conn->fd + 1; } /* Listen for connections on the server sockets. */ for (serv = servers; serv; serv = serv->next) { FD_SET(serv->server_socket, &read_fds); if (serv->server_socket >= nfds) nfds = serv->server_socket + 1; } /* Check pending connections for ability to write. */ for (pend = pendings; pend; pend = pend->next) { if (pend->error != NOT_AN_IDENT) { /* The connect has already failed; just set the finished bit. */ pend->finished = 1; } else { FD_SET(pend->fd, &write_fds); if (pend->fd >= nfds) nfds = pend->fd + 1; } } #ifdef __Win32__ /* Winsock 2.0 will return EINVAL (invalid argument) if there are no sockets checked in any of the FDSETs. At least one server must be listening before the call is made. Winsock 1.1 behaves differently. */ if (servers || connections || pendings) { #endif /* Call select(). */ count = select(nfds, &read_fds, &write_fds, &except_fds, tvp); #ifdef __Win32__ } else { count = 0; } #endif /* Lose horribly if select() fails on anything but an interrupted system * call. On ERR_INTR, we'll return 0. */ if (count == SOCKET_ERROR) { if (GETERR() != ERR_INTR) panic("select() failed"); /* Stop and return zero if no I/O events occurred. */ return 0; } /* Check if any connections are readable or writable. */ for (conn = connections; conn; conn = conn->next) { if (FD_ISSET(conn->fd, &except_fds)) { conn->flags.dead = 1; fprintf(stderr, "An exception occurred during select()\n"); } if (FD_ISSET(conn->fd, &read_fds)) conn->flags.readable = 1; if (FD_ISSET(conn->fd, &write_fds)) conn->flags.writable = 1; } /* Check if any server sockets have new connections. */ for (serv = servers; serv; serv = serv->next) { if (FD_ISSET(serv->server_socket, &read_fds)) { serv->client_socket = accept(serv->server_socket, (struct sockaddr *) &sockin, &addr_size); if (serv->client_socket == SOCKET_ERROR) continue; #ifdef __Win32__ result = 1; ioctlsocket(serv->client_socket, FIONBIO, &result); #else flags = fcntl(serv->client_socket, F_GETFL); flags |= O_NONBLOCK; fcntl(serv->client_socket, F_SETFL, flags); #endif /* Get address and local port of client. */ strcpy(serv->client_addr, inet_ntoa(sockin.sin_addr)); serv->client_port = ntohs(sockin.sin_port); /* Set the CLOEXEC flag on socket so that it will be closed for a * execute() operation. */ #ifdef FD_CLOEXEC flags = fcntl(serv->client_socket, F_GETFD); flags |= FD_CLOEXEC; fcntl(serv->client_socket, F_SETFD, flags); #endif } } /* Check if any pending connections have succeeded or failed. */ for (pend = pendings; pend; pend = pend->next) { if (FD_ISSET(pend->fd, &write_fds)) { result = getpeername(pend->fd, (struct sockaddr *) &sockin, &addr_size); if (result == SOCKET_ERROR) { getsockopt(pend->fd, SOL_SOCKET, SO_ERROR, (char *) &error, &dummy); pend->error = translate_connect_error(error); } else { pend->error = NOT_AN_IDENT; } pend->finished = 1; } } /* Return nonzero, indicating that at least one I/O event occurred. */ return 1; }