ImperialViolet

Misspent Youth (08 Aug 2003)

[Amazon link] Frankly, I expected better from Hamilton and probably should have paid heed to the reviewers on Amazon. Hamilton writes some really good books; never hard core sci-fi, but good old fashioned page-turners.

But the plot of this book reads like a low-budget porno script and the characters are uninteresting and unbelievable. I read to the end, but mainly because I had nothing else to do.

Autofs

DoC's primary web server (the server which you are getting this page from) has been failing a lot recently with autofs problems. At one point it died 3 times in as many hours so we switched to a different box and sat it on 146.169.1.10. That was ok for while until it died in the same place. I hope to get the opps output and have a look.

But autofs (the userland part) is a little dodgy. It can get upset pretty easily with NFS mounts as can amd (the alternative, written by CSG at Imperial) is only a little better. Both are pretty huge programs for doing a simple task. I think I'll write a replacement over the weekend.

UNIX tricks

Little to most people know of UNIX domain sockets. They may only work on the localhost, but when local communication is all you need they offer a number of funky features.

Firstly, you can find out who is connected to you:

struct client *
client_init (int socket)
{
        struct  ucred creds;
        socklen_t creds_len = sizeof (creds);
        struct  passwd  *pwent;

        if (getsockopt (socket, SOL_SOCKET, SO_PEERCRED, &creds, &creds_len) == -1)
                return NULL;
        if (creds_len != sizeof (struct ucred))
                return NULL;
        pwent = getpwuid (creds.uid);
        if (!pwent) {
                syslog_write (slog, LOG_WARNING, "Lookup in passwd for UID %d failed", creds.uid);
                return NULL;
        }

Secondly, you can pass file descriptors down them:

// Transmits @new_sock over @dest_sock using SCM_RIGHTS
int
send_fd (int dest_sock, int new_sock) {
        struct msghdr   msg = {0};
        struct cmsghdr  *cmsg;
        char            buf[CMSG_SPACE (sizeof (new_sock))];
        int             *fdptr;

        msg.msg_control = buf;
        msg.msg_controllen = sizeof (buf);
        cmsg = CMSG_FIRSTHDR(&msg); 
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        fdptr = (int *)CMSG_DATA(cmsg);
        *fdptr = new_sock;
        // Sum of the length of all control messages in the buffer: 
        msg.msg_controllen = cmsg->cmsg_len;
        if (sendmsg (dest_sock, &msg, 0) == -1) {
                fprintf (stderr, "Failed to write to child: %s\n", 
                                strerror (errno));
                return 10;
        }

        return 0;
}
// Reads a file descriptor from stdin using SCM_RIGHTS
int
get_fd ()
{               
        char buf[CMSG_SPACE(sizeof (int))];
        struct msghdr msg;
        struct cmsghdr *cmsg;
        
        msg.msg_control = buf;
        msg.msg_controllen = sizeof (buf);
        msg.msg_name = NULL;
        msg.msg_iov = NULL;
        msg.msg_iovlen = 0;
        if (recvmsg (0, &msg, 0) != 0)
                return -1;
        cmsg = CMSG_FIRSTHDR (&msg);
        if (cmsg->cmsg_type != SCM_RIGHTS) {
                syslog_write (slog, LOG_ERR, "CMSG type was not SCM_RIGHTS");
                return -1;
        }
        return *((int *) CMSG_DATA (cmsg));
}