Example #1
0
File: net.c Project: whilke/ColdC
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());
}
Example #2
0
File: file.c Project: nrhtr/genesis
Int close_file(filec_t * file)
{
    file->f.closed = 1;
    if (fclose(file->fp) == EOF)
        return GETERR();
    return 0;
}
Example #3
0
File: file.c Project: nrhtr/genesis
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);
}
Example #4
0
File: net.c Project: whilke/ColdC
/* 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;
}