// // ac_fdio.c - file descriptor io functions // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // // // Thanks to Gary Frerking for writing the Serial Programming HOWTO at // http://www.tldp.org/HOWTO/Serial-Programming-HOWTO // Much of this is based on his descriptions and examples. // //#@DOC@ file descriptor io functions //########################################################################### //############################### INCLUDES ################################## //########################################################################### #include "ac_fdio.h" #include <stdio.h> #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <string.h> //########################################################################### //############################### TYPEDEFS ################################## //########################################################################### //=========================================================================== // AcFdInfo - info about 1 file descriptor //=========================================================================== typedef struct AcFdInfoRec { int fd; AcFdFunc func; void *data; struct AcFdInfoRec *next; struct AcFdInfoRec *prev; } AcFdInfo; //=========================================================================== // AcFdGroup - Group of file descriptors //=========================================================================== struct AcFdGroupRec { int fdmax; fd_set fds; AcFdInfo head; struct timeval *timeout; }; //########################################################################### //############################### GLOBALS ################################### //########################################################################### //########################################################################### //############################### CODE ###################################### //########################################################################### //=========================================================================== // AcFdGroupCreate() //=========================================================================== AcFdGroup *AcFdGroupCreate(void) { AcFdGroup *grp = calloc(1,sizeof(AcFdGroup)); if (!grp) return 0; FD_ZERO(&grp->fds); grp->fdmax = -1; grp->head.next = &grp->head; grp->head.prev = &grp->head; return grp; } //=========================================================================== // AcFdGroupDestroy() //=========================================================================== void AcFdGroupDestroy(AcFdGroup *grp) { // // remove all file descriptors // AcFdGroupRemove(grp,-1,0,0); AcFdGroupClearTimeout(grp); free(grp); } //=========================================================================== // AcFdGroupAdd() - add fd to group //=========================================================================== int AcFdGroupAdd(AcFdGroup *grp, int fd, AcFdFunc func, void *data) { AcFdInfo *i = calloc(1,sizeof(AcFdInfo)); if (!i) return -1; i->fd = fd; i->func = func; i->data = data; i->next = grp->head.prev; i->prev = &grp->head; i->next->prev = i; i->prev->next = i; return 0; } //=========================================================================== // AcFdGroupRemove() - remove fd from group //=========================================================================== int AcFdGroupRemove(AcFdGroup *grp, int fd, AcFdFunc func, void *data) { AcFdInfo *i = grp->head.next; for(; i != &grp->head; i=i->next) { AcFdInfo *prev, *next; if (fd >= 0 && i->fd != fd) continue; if (func && i->func != func) continue; if (data && i->data != data) continue; prev = i->prev; next = i->next; next->prev = prev; prev->next = next; free(i); i = prev; } return 0; } //=========================================================================== // AcFdGroupCalcSet() - calc fds & fdmax //=========================================================================== static void AcFdGroupCalcSet(AcFdGroup *grp) { AcFdInfo *i = grp->head.next; FD_ZERO(&grp->fds); grp->fdmax = -1; for(; i != &grp->head; i=i->next) { FD_SET(i->fd, &grp->fds); grp->fdmax = (i->fd+1 > grp->fdmax) ? i->fd+1 : grp->fdmax; } } //=========================================================================== // AcFdGroupSetTimeout() - set te timeout period for select calls //=========================================================================== void AcFdGroupSetTimeout(AcFdGroup *grp, long sec, long usec) { grp->timeout = malloc(sizeof(struct timeval)); grp->timeout->tv_sec = sec; grp->timeout->tv_usec = usec; } //=========================================================================== // AcFdGroupClearTimeout() - turn off the timeout (wait forever - default) //=========================================================================== void AcFdGroupClearTimeout(AcFdGroup *grp) { if (grp->timeout) { free(grp->timeout); grp->timeout = 0; } } //=========================================================================== // AcFdGroupDoWait() - wait for input & call handlers //=========================================================================== // If a fd becomes readable, one of the handler functions is called and its // return value is returned. // If a timeout occurs -2 is returned. // If an error occurs -1 is returned. // static int AcFdGroupDoWait(AcFdGroup *grp, struct timeval *tmo) { AcFdInfo *i; int cnt; // // are there any fd to wait on? // AcFdGroupCalcSet(grp); if (grp->fdmax <= 0) { if (tmo) { grp->fdmax = 0; } else { return -1; } } // // wait until one of the fd has data to read // cnt = select(grp->fdmax, &grp->fds, 0, 0, tmo); if (cnt <= 0) { return (cnt==0)? -2 : -1; } // // call associated function // i = &grp->head; while(1) { i = i->next; if (i == &grp->head) return 0; if (FD_ISSET(i->fd, &grp->fds)) { if (i->func) { return i->func(i->fd, i->data); } else { return -1; } } } } //=========================================================================== // AcFdGroupWaitTimeout() - wait for & process input with timeout //=========================================================================== // // returns -2 on timeout // int AcFdGroupWaitTimeout(AcFdGroup *grp, unsigned long usecTimeout) { struct timeval timeout; if (usecTimeout > 1000000) { timeout.tv_sec = usecTimeout/1000000; timeout.tv_usec = usecTimeout % 1000000; } else { timeout.tv_sec = 0; timeout.tv_usec = usecTimeout; } return AcFdGroupDoWait(grp, &timeout); } //=========================================================================== // AcFdGroupWait() - wait for & process input //=========================================================================== int AcFdGroupWait(AcFdGroup *grp) { struct timeval timeout, *tmo = 0; if (grp->timeout) { memcpy(&timeout, grp->timeout, sizeof(timeout)); tmo = &timeout; } return AcFdGroupDoWait(grp, tmo); } //=========================================================================== // AcFdGroupLoop() - loop waiting for & processing input //=========================================================================== int AcFdGroupLoop(AcFdGroup *grp) { for(;;) { int result = AcFdGroupWait(grp); if (result) return result; } } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:24:47 PDT 2007