958 Chapter 46
static void /* Executed in child process: serve a single client */
wserveRequest(const struct requestMsg *req)
{
int fd;
ssize_t numRead;
struct responseMsg resp;
fd = open(req->pathname, O_RDONLY);
if (fd == -1) { /* Open failed: send error text */
e resp.mtype = RESP_MT_FAILURE;
snprintf(resp.data, sizeof(resp.data), "%s", "Couldn't open");
msgsnd(req->clientId, &resp, strlen(resp.data) + 1, 0);
exit(EXIT_FAILURE); /* and terminate */
}
/* Transmit file contents in messages with type RESP_MT_DATA. We don't
diagnose read() and msgsnd() errors since we can't notify client. */
r resp.mtype = RESP_MT_DATA;
while ((numRead = read(fd, resp.data, RESP_MSG_SIZE)) > 0)
if (msgsnd(req->clientId, &resp, numRead, 0) == -1)
break;
/* Send a message of type RESP_MT_END to signify end-of-file */
t resp.mtype = RESP_MT_END;
msgsnd(req->clientId, &resp, 0, 0); /* Zero-length mtext */
}
int
main(int argc, char *argv[])
{
struct requestMsg req;
pid_t pid;
ssize_t msgLen;
int serverId;
struct sigaction sa;
/* Create server message queue */
serverId = msgget(SERVER_KEY, IPC_CREAT | IPC_EXCL |
S_IRUSR | S_IWUSR | S_IWGRP);
if (serverId == -1)
errExit("msgget");
/* Establish SIGCHLD handler to reap terminated children */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = grimReaper;
y if (sigaction(SIGCHLD, &sa, NULL) == -1)
errExit("sigaction");