/*****************************************************************************\ * Copyright (c) 2002-2004 Pelle Johansson. * * All rights reserved. * * * * This file is part of the moftpd package. Use and distribution of * * this software is governed by the terms in the file LICENCE, which * * should have come with this package. * \*****************************************************************************/ /* $moftpd: events_select.c 1251 2005-03-06 22:24:29Z morth $ */ #include "system.h" #include "events.h" static fd_set readSet, writeSet; static int maxFd = 0; extern int urgData; void events_einit (void) { FD_ZERO(&readSet); FD_ZERO(&writeSet); maxFd = 0; } int events_earf (int fd, void *data) { if (fd >= FD_SETSIZE) { // We're restricted by FD_SETSIZE in select(). errno = EINVAL; return -1; } if (!FD_ISSET (fd, &readSet)) { /* Update maxFd if appropriate. */ if(fd >= maxFd) maxFd = fd + 1; FD_SET(fd, &readSet); } return 0; } int events_eawf (int fd, void *data) { if (fd >= FD_SETSIZE) { // We're restricted by FD_SETSIZE in select(). errno = EINVAL; return -1; } if (!FD_ISSET (fd, &writeSet)) { /* Update maxFd if appropriate. */ if(fd >= maxFd) maxFd = fd + 1; FD_SET(fd, &writeSet); } return 0; } void events_errf (int fd) { if(fd < 0 || fd >= FD_SETSIZE) return; if (FD_ISSET (fd, &readSet)) { FD_CLR(fd, &readSet); /* We might be able to lower maxFd. Check! */ if(fd == maxFd - 1) { int fdIter, newMax = -1; for(fdIter = maxFd - 2; fdIter >= 0; fdIter--) { if(FD_ISSET(fdIter, &readSet) || FD_ISSET(fdIter, &writeSet)) { newMax = fdIter; break; } } maxFd = newMax + 1; } } } void events_erwf (int fd) { if(fd < 0 || fd >= FD_SETSIZE) return; if (FD_ISSET (fd, &writeSet)) { FD_CLR(fd, &writeSet); /* We might be able to lower maxFd. Check! */ if(fd == maxFd - 1) { int fdIter, newMax = -1; for(fdIter = maxFd - 2; fdIter >= 0; fdIter--) { if(FD_ISSET(fdIter, &readSet) || FD_ISSET(fdIter, &writeSet)) { newMax = fdIter; break; } } maxFd = newMax + 1; } } } int run_events (void) { fd_set rSet, wSet, eSet; int fdIter; struct timeval tv; rSet = readSet; wSet = writeSet; eSet = readSet; tv.tv_sec = 10; tv.tv_usec = 0; if(select(maxFd, &rSet, &wSet, &eSet, &tv) < 0) { if(errno == EINTR) return 0; syslog (LOG_ERR, "select: %m"); return -1; } urgData = 0; for(fdIter = 0; fdIter < maxFd; fdIter++) { /* * Cheack readSet and writeSet as well as they might have been removed * by an earlier handler. */ if(FD_ISSET(fdIter, &eSet) && FD_ISSET(fdIter, &readSet)) { /* * "Exceptional state" means urgent data available on sockets. * Hopefully that's the only thing that activates it, not completely * sure. */ if (events_run_handler (fdIter, 0, 1)) break; } if(FD_ISSET(fdIter, &rSet) && FD_ISSET(fdIter, &readSet)) { if (events_run_handler (fdIter, 0, 0)) break; } if(FD_ISSET(fdIter, &wSet) && FD_ISSET(fdIter, &writeSet)) { if (events_run_handler (fdIter, 1, 0)) break; } } return 0; }