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