#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO
* - should check for close() errors, theoretically
*/
int make_server_socket(const struct sockaddr_un *sa, int backlog) {
int server_socket;
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("socket");
exit(1);
}
/* The standard seems to be to unlink whatever file might be there
* before binding. This seems dangerous and bad to me, but it's what
* I see everywhere and allows me to use the same accept program as
* with tcplisten, so I'll let it be for now. */
/* unlink() naturally fails if the file didn't exist. For other
* cases, let bind produce the error */
unlink(sa->sun_path);
if (bind(server_socket, (struct sockaddr *) sa, sizeof(*sa)) != 0) {
perror("bind");
exit(1);
}
if (listen(server_socket, backlog) != 0) {
perror("listen");
exit(1);
}
return server_socket;
}
int main(int argc, char *const argv[]) {
int server_socket;
struct sockaddr_un sa;
char *const *new_argv;
int option;
int listen_backlog = 20;
const char *socket_path;
while ((option = getopt(argc, argv, "b:")) != -1) {
switch (option) {
case 'b':
listen_backlog = atoi(optarg);
break;
}
}
if (optind + 1 >= argc) {
fprintf(stderr,
"Usage: %s [-b listen_backlog] socket_path command...\n", argv[0]);
exit(1);
}
sa.sun_family = AF_UNIX;
socket_path = argv[optind];
if (strlen(socket_path) >= sizeof(sa.sun_path)) {
fprintf(stderr, "Socket name too long: %s\n", socket_path);
exit(100);
}
strcpy(sa.sun_path, socket_path);
server_socket = make_server_socket(&sa, listen_backlog);
if (dup2(server_socket, STDIN_FILENO) == -1) {
perror("dup2");
exit(1);
}
close(server_socket);
new_argv = argv + optind + 1;
execvp(*new_argv, new_argv);
perror("execvp");
exit(1);
}
syntax highlighted by Code2HTML, v. 0.9.1