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.
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.
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)); }