1 /* $NetBSD: link_mon.c,v 1.1.1.1 2009/12/02 00:27:10 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. 5 * 6 * This copyrighted material is made available to anyone wishing to use, 7 * modify, copy, or redistribute it subject to the terms and conditions 8 * of the GNU Lesser General Public License v.2.1. 9 * 10 * You should have received a copy of the GNU Lesser General Public License 11 * along with this program; if not, write to the Free Software Foundation, 12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13 */ 14 #include <stdlib.h> 15 #include <errno.h> 16 #include <poll.h> 17 18 #include "logging.h" 19 20 struct link_callback { 21 int fd; 22 char *name; 23 void *data; 24 int (*callback)(void *data); 25 26 struct link_callback *next; 27 }; 28 29 static int used_pfds = 0; 30 static int free_pfds = 0; 31 static struct pollfd *pfds = NULL; 32 static struct link_callback *callbacks = NULL; 33 34 int links_register(int fd, char *name, int (*callback)(void *data), void *data) 35 { 36 int i; 37 struct link_callback *lc; 38 39 for (i = 0; i < used_pfds; i++) { 40 if (fd == pfds[i].fd) { 41 LOG_ERROR("links_register: Duplicate file descriptor"); 42 return -EINVAL; 43 } 44 } 45 46 lc = malloc(sizeof(*lc)); 47 if (!lc) 48 return -ENOMEM; 49 50 lc->fd = fd; 51 lc->name = name; 52 lc->data = data; 53 lc->callback = callback; 54 55 if (!free_pfds) { 56 struct pollfd *tmp; 57 tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1)); 58 if (!tmp) { 59 free(lc); 60 return -ENOMEM; 61 } 62 63 pfds = tmp; 64 free_pfds = used_pfds + 1; 65 } 66 67 free_pfds--; 68 pfds[used_pfds].fd = fd; 69 pfds[used_pfds].events = POLLIN; 70 pfds[used_pfds].revents = 0; 71 used_pfds++; 72 73 lc->next = callbacks; 74 callbacks = lc; 75 LOG_DBG("Adding %s/%d", lc->name, lc->fd); 76 LOG_DBG(" used_pfds = %d, free_pfds = %d", 77 used_pfds, free_pfds); 78 79 return 0; 80 } 81 82 int links_unregister(int fd) 83 { 84 int i; 85 struct link_callback *p, *c; 86 87 for (i = 0; i < used_pfds; i++) 88 if (fd == pfds[i].fd) { 89 /* entire struct is copied (overwritten) */ 90 pfds[i] = pfds[used_pfds - 1]; 91 used_pfds--; 92 free_pfds++; 93 } 94 95 for (p = NULL, c = callbacks; c; p = c, c = c->next) 96 if (fd == c->fd) { 97 LOG_DBG("Freeing up %s/%d", c->name, c->fd); 98 LOG_DBG(" used_pfds = %d, free_pfds = %d", 99 used_pfds, free_pfds); 100 if (p) 101 p->next = c->next; 102 else 103 callbacks = c->next; 104 free(c); 105 break; 106 } 107 108 return 0; 109 } 110 111 int links_monitor(void) 112 { 113 int i, r; 114 115 for (i = 0; i < used_pfds; i++) { 116 pfds[i].revents = 0; 117 } 118 119 r = poll(pfds, used_pfds, -1); 120 if (r <= 0) 121 return r; 122 123 r = 0; 124 /* FIXME: handle POLLHUP */ 125 for (i = 0; i < used_pfds; i++) 126 if (pfds[i].revents & POLLIN) { 127 LOG_DBG("Data ready on %d", pfds[i].fd); 128 129 /* FIXME: Add this back return 1;*/ 130 r++; 131 } 132 133 return r; 134 } 135 136 int links_issue_callbacks(void) 137 { 138 int i; 139 struct link_callback *lc; 140 141 for (i = 0; i < used_pfds; i++) 142 if (pfds[i].revents & POLLIN) 143 for (lc = callbacks; lc; lc = lc->next) 144 if (pfds[i].fd == lc->fd) { 145 LOG_DBG("Issuing callback on %s/%d", 146 lc->name, lc->fd); 147 lc->callback(lc->data); 148 break; 149 } 150 return 0; 151 } 152