#include #include #include #include #include #include #include /* 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); }