Annotation of src/usr.bin/aucat/listen.c, Revision 1.1
1.1 ! ratchov 1: /* $OpenBSD$ */
! 2: /*
! 3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17: #include <sys/types.h>
! 18: #include <sys/socket.h>
! 19: #include <sys/un.h>
! 20:
! 21: #include <err.h>
! 22: #include <errno.h>
! 23: #include <fcntl.h>
! 24: #include <poll.h>
! 25: #include <stdio.h>
! 26: #include <stdlib.h>
! 27: #include <string.h>
! 28: #include <unistd.h>
! 29:
! 30: #include "conf.h"
! 31: #include "sock.h"
! 32: #include "listen.h"
! 33:
! 34: struct fileops listen_ops = {
! 35: "listen",
! 36: sizeof(struct listen),
! 37: listen_close,
! 38: NULL, /* read */
! 39: NULL, /* write */
! 40: NULL, /* start */
! 41: NULL, /* stop */
! 42: listen_nfds,
! 43: listen_pollfd,
! 44: listen_revents
! 45: };
! 46:
! 47: struct listen *
! 48: listen_new(struct fileops *ops, char *path)
! 49: {
! 50: int sock;
! 51: struct sockaddr_un sockname;
! 52: struct listen *f;
! 53:
! 54: sock = socket(AF_UNIX, SOCK_STREAM, 0);
! 55: if (sock < 0) {
! 56: perror("socket");
! 57: exit(1);
! 58: }
! 59: if (unlink(path) < 0 && errno != ENOENT) {
! 60: perror("unlink");
! 61: exit(1);
! 62: }
! 63: sockname.sun_family = AF_UNIX;
! 64: strlcpy(sockname.sun_path, path, sizeof(sockname.sun_path));
! 65: if (bind(sock, (struct sockaddr *)&sockname,
! 66: sizeof(struct sockaddr_un)) < 0) {
! 67: perror("bind");
! 68: exit(1);
! 69: }
! 70: if (listen(sock, 1) < 0) {
! 71: perror("listen");
! 72: exit(1);
! 73: }
! 74: f = (struct listen *)file_new(ops, path, 1);
! 75: f->path = strdup(path);
! 76: if (f->path == NULL) {
! 77: perror("strdup");
! 78: exit(1);
! 79: }
! 80: f->fd = sock;
! 81: return f;
! 82: }
! 83:
! 84: int
! 85: listen_nfds(struct file *f) {
! 86: return 1;
! 87: }
! 88:
! 89: int
! 90: listen_pollfd(struct file *file, struct pollfd *pfd, int events)
! 91: {
! 92: struct listen *f = (struct listen *)file;
! 93:
! 94: pfd->fd = f->fd;
! 95: pfd->events = POLLIN;
! 96: return 1;
! 97: }
! 98:
! 99: int
! 100: listen_revents(struct file *file, struct pollfd *pfd)
! 101: {
! 102: struct listen *f = (struct listen *)file;
! 103: struct sockaddr caddr;
! 104: socklen_t caddrlen;
! 105: int sock;
! 106:
! 107: if (pfd->revents & POLLIN) {
! 108: DPRINTF("listen_revents: accepting connection\n");
! 109: caddrlen = sizeof(caddrlen);
! 110: sock = accept(f->fd, &caddr, &caddrlen);
! 111: if (sock < 0) {
! 112: perror("accept");
! 113: return 0;
! 114: }
! 115: if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
! 116: perror("fcntl(sock, O_NONBLOCK)");
! 117: close(sock);
! 118: return 0;
! 119: }
! 120: (void)sock_new(&sock_ops, sock, "socket");
! 121: }
! 122: return 0;
! 123: }
! 124:
! 125: void
! 126: listen_close(struct file *file)
! 127: {
! 128: struct listen *f = (struct listen *)file;
! 129:
! 130: (void)unlink(f->path);
! 131: free(f->path);
! 132: (void)close(f->fd);
! 133: }