Annotation of researchv10no/ipc/mgrs/svcmgr/service.c, revision 1.1

1.1     ! root        1: #include "mgr.h"
        !             2: #include <sys/param.h>
        !             3: #include <errno.h>
        !             4: #include <ctype.h>
        !             5: #include <signal.h>
        !             6: #include <sys/filio.h>
        !             7: #include <libc.h>
        !             8: #include <pwd.h>
        !             9: 
        !            10: extern int debug;
        !            11: 
        !            12: static fd_set  listenset;      /* set of fd's on which we are listening */
        !            13: static Service *svchead;       /* head of services */
        !            14: static Service *nsvchead;      /* new head of services */
        !            15: static int     toannounce;     /* true if there's anything to announce */
        !            16: 
        !            17: /*
        !            18:  *  Parse a service definition line.  The line is of the form:
        !            19:  *  `service action+action+action+... source'
        !            20:  */
        !            21: Service *
        !            22: newservice(cp)
        !            23:        char *cp;
        !            24: {
        !            25: #      define MAXACTS 32
        !            26:        char *arg;
        !            27:        char *acts[MAXACTS];
        !            28:        Service *sp=(Service *)malloc(sizeof(Service));
        !            29:        int i, n, plus;
        !            30:        Action *lap;
        !            31: 
        !            32:        if(sp==NULL) {
        !            33:                logevent("out of memory parsing service\n");
        !            34:                return NULL;
        !            35:        }
        !            36:        sp->ap = NULL;
        !            37:        sp->listen = -1;
        !            38:        sp->name = NULL;
        !            39:        sp->next = (Service *)NULL;
        !            40:        sp->accept = 0;
        !            41:        sp->lasttime = 1;
        !            42:        sp->from = NULL;
        !            43:        sp->same = NULL;
        !            44: 
        !            45:        /* find service name */
        !            46:        for(; isspace(*cp); cp++)
        !            47:                ;
        !            48:        for(arg=cp; *arg && !isspace(*arg); arg++)
        !            49:                ;
        !            50:        if(isspace(*arg))
        !            51:                *arg++ = '\0';
        !            52:        sp->name = strdup(cp);
        !            53: 
        !            54:        /* 
        !            55:         *  separate actions.  actions are separated by '+'s and
        !            56:         *  whitespace.  actions may have arguments in ()'s.
        !            57:         */
        !            58:        for(; isspace(*arg); arg++)
        !            59:                ;
        !            60:        for(plus=1, n=0; *arg && n<MAXACTS && plus; n++) {
        !            61:                /*  find next action */
        !            62:                acts[n] = arg;
        !            63:                for(plus = 0;;arg++)
        !            64:                        if(*arg=='(') {
        !            65:                                for(;;arg++)
        !            66:                                        if(*arg=='\\' && *(arg+1)==')')
        !            67:                                                arg++;
        !            68:                                        else if(*arg==')')
        !            69:                                                break;
        !            70:                        } else if(*arg=='+') {
        !            71:                                plus = 1;
        !            72:                                *arg++ = '\0';
        !            73:                                break;
        !            74:                        } else if(isspace(*arg)) {
        !            75:                                *arg++ = '\0';
        !            76:                                break;
        !            77:                        } else if(*arg=='\0')
        !            78:                                break;
        !            79: 
        !            80:                /* dump whitespace */
        !            81:                for(;; arg++)
        !            82:                        if(*arg=='+')
        !            83:                                plus = 1;
        !            84:                        else if(!isspace(*arg))
        !            85:                                break;
        !            86:        }
        !            87:        if (n <= 0) {
        !            88:                logevent("service with no action `%s'\n", cp);
        !            89:                freeservice(sp);
        !            90:                return NULL;
        !            91:        }
        !            92: 
        !            93:        /* parse actions */
        !            94:        for(lap=NULL, i=0; i<n; i++) {
        !            95:                if (lap==NULL)
        !            96:                        sp->ap = lap = newaction(acts[i]);
        !            97:                else
        !            98:                        lap = lap->next = newaction(acts[i]);
        !            99:                if (lap==NULL) {
        !           100:                        freeservice(sp);
        !           101:                        return NULL;
        !           102:                }
        !           103:                lap->next = NULL;
        !           104:                sp->accept |= lap->accept;
        !           105:        }
        !           106: 
        !           107:        /* look for source specifier */
        !           108:        if(*arg){
        !           109:                acts[0] = arg;
        !           110:                while(*arg && !isspace(*arg))
        !           111:                        arg++;
        !           112:                *arg = 0;
        !           113:                if((sp->from=newre(acts[0]))==NULL){
        !           114:                        logevent("illegal reg exp in service `%s %s'\n", sp->name,
        !           115:                                acts[0]);
        !           116:                        freeservice(sp);
        !           117:                        return NULL;
        !           118:                }
        !           119:        }
        !           120: 
        !           121:        if(sp->from)
        !           122:                logevent("newservice(%s for %s)\n", sp->name, acts[0]);
        !           123:        else
        !           124:                logevent("newservice(%s)\n", sp->name);
        !           125:        return sp;
        !           126: }
        !           127: 
        !           128: freeservice(sp)
        !           129:        Service *sp;
        !           130: {
        !           131:        if(sp==NULL)
        !           132:                return;
        !           133:        if(sp->listen>=0) {
        !           134:                logevent("denouncing %s\n", sp->name);
        !           135:                close(sp->listen);
        !           136:                FD_CLR(sp->listen, listenset);
        !           137:        }
        !           138:        if(sp->name!=NULL)
        !           139:                free(sp->name);
        !           140:        for(; sp->ap!=NULL; sp->ap=sp->ap->next)
        !           141:                freeaction(sp->ap);
        !           142:        if(sp->from)
        !           143:                freere(sp->from);
        !           144:        if(sp->same)
        !           145:                freeservice(sp->same);
        !           146:        free((char *)sp);
        !           147: }
        !           148: 
        !           149: /*
        !           150:  *  Add a service to the ones for which we are listening
        !           151:  */
        !           152: addservice(sp)
        !           153:        Service *sp;
        !           154: {
        !           155:        Service *p;
        !           156: 
        !           157:        /* look through new list for a previous version */
        !           158:        for(p=nsvchead; p; p=p->next)
        !           159:                if (strcmp(sp->name, p->name)==0){
        !           160:                        /* string after previous versions */
        !           161:                        for(; p->same; p=p->same)
        !           162:                                ;
        !           163:                        p->same = sp;
        !           164:                        return 0;
        !           165:                }
        !           166: 
        !           167:        /* look for an announced version of the service */
        !           168:        for(p=svchead; p; p=p->next)
        !           169:                if (strcmp(sp->name, p->name)==0)
        !           170:                        break;
        !           171: 
        !           172:        /* inherit fd from old service */
        !           173:        if (p) {
        !           174:                sp->listen = p->listen;
        !           175:                p->listen = -1;
        !           176:        } else
        !           177:                toannounce=1;
        !           178: 
        !           179:        /* add the new service */
        !           180:        sp->next = nsvchead;
        !           181:        nsvchead = sp;
        !           182:        return 0;
        !           183: }
        !           184: 
        !           185: /*
        !           186:  *  Start the listening process on any services not already listening.
        !           187:  */
        !           188: startsvcs()
        !           189: {
        !           190:        Service *p, *np;
        !           191: 
        !           192:        /* denounce old services */
        !           193:        for(p=svchead; p; p=np) {
        !           194:                np = p->next;
        !           195:                freeservice(p);
        !           196:        }
        !           197: 
        !           198:        /* install new services */
        !           199:        svchead = nsvchead;
        !           200:        nsvchead = (Service *)NULL;
        !           201: 
        !           202:        announcesvcs();
        !           203: }
        !           204: 
        !           205: /*
        !           206:  *  Announce any services not already listening
        !           207:  */
        !           208: announcesvcs()
        !           209: {
        !           210:        Service *p;
        !           211: 
        !           212: 
        !           213:        /* announce new services */
        !           214:        toannounce=0;
        !           215:        for(p=svchead; p; p=p->next) {
        !           216:                if (p->listen>=0)
        !           217:                        continue;
        !           218:                logevent("announcing %s\n", p->name);
        !           219:                p->listen = ipccreat(p->name, "light");
        !           220:                if (p->listen<0) {
        !           221:                        logevent("failed\n");
        !           222:                        toannounce=1;
        !           223:                        continue;
        !           224:                }
        !           225:                chmod(p->name, 0666);
        !           226:                FD_SET(p->listen, listenset);
        !           227:        }
        !           228: }
        !           229: 
        !           230: /*
        !           231:  *  Reset all services
        !           232:  */
        !           233: resetsvcs()
        !           234: {
        !           235:        Service *p, *np;
        !           236: 
        !           237:        /* shut down all listeners */
        !           238:        logevent("resetsrvcs()\n");
        !           239:        for(p=svchead; p; p=np) {
        !           240:                logevent("retracting %s\n", p->name);
        !           241:                np = p->next;
        !           242:                freeservice(p);
        !           243:        }
        !           244:        svchead = (Service *)NULL;
        !           245:        readfiles();
        !           246: }
        !           247: 
        !           248: /*
        !           249:  *  An alarm during a listen 
        !           250:  */
        !           251: int
        !           252: dingaling()
        !           253: {
        !           254:        signal(SIGALRM, dingaling);
        !           255:        logevent("timout in listen\n");
        !           256:        alarm(5);
        !           257: }
        !           258: 
        !           259: /*
        !           260:  *  A Zombie exists
        !           261:  */
        !           262: int
        !           263: sigchild()
        !           264: {
        !           265: }
        !           266: 
        !           267: /*
        !           268:  *  Get a request and vector to the appropriate service
        !           269:  */
        !           270: Request *
        !           271: listen()
        !           272: {
        !           273:        fd_set readset;
        !           274:        Service *sp;
        !           275:        static Request rp;
        !           276:        ipcinfo *ip;
        !           277:        int n;
        !           278:        int (*sigalrm)();
        !           279:        long lastcheck = 0;
        !           280:        static char line[ARB];
        !           281:        struct passwd *pwsearch();
        !           282: 
        !           283:        for(;;) {
        !           284:                /*
        !           285:                 *  clean up utmp and make entries to wtmp
        !           286:                 */
        !           287:                checkkids();
        !           288: 
        !           289:                /*
        !           290:                 *  wait for 
        !           291:                 *      - a child to die
        !           292:                 *      - a call in
        !           293:                 *      - 30 seconds to elapse
        !           294:                 */
        !           295:                signal(SIGCHLD, sigchild);
        !           296:                readset = listenset;
        !           297:                n = select(NOFILE, &readset, (fd_set *)NULL, 30*1000);
        !           298:                signal(SIGCHLD, SIG_IGN);
        !           299: 
        !           300:                /*
        !           301:                 *  every 2 minutes see if the configuration has
        !           302:                 *  changed.  this is fairly costly so don't do it too
        !           303:                 *  often.
        !           304:                 */
        !           305:                if(time((long *)0) - lastcheck > 2*60){
        !           306:                        pwsearch((char *)0, 0, line); /* prime the pump */
        !           307:                        if(checkfiles())
        !           308:                                readfiles();
        !           309:                        lastcheck = time((long *)0);
        !           310:                }
        !           311:                if(toannounce)
        !           312:                        announcesvcs();
        !           313:                if(n<=0)
        !           314:                        continue;
        !           315: 
        !           316:                /*
        !           317:                 *  a call has arrived
        !           318:                 */
        !           319:                if(debug)
        !           320:                        logtime("request\n");
        !           321:                for(sp=svchead; sp; sp=sp->next) {
        !           322:                        if (sp->listen<0)
        !           323:                                continue;
        !           324:                        if (FD_ISSET(sp->listen, readset))
        !           325:                                break;
        !           326:                }
        !           327:                if (!sp) {
        !           328:                        logevent("listen on bad fd\n");
        !           329:                        resetsvcs();
        !           330:                        continue;
        !           331:                }
        !           332:                sigalrm=signal(SIGALRM, dingaling);
        !           333:                alarm(5);
        !           334:                if ((ip = ipclisten(sp->listen)) == NULL) {
        !           335:                        logevent("%s: bad listen: %s %d\n", sp->name,
        !           336:                                errstr, errno);
        !           337:                        close(sp->listen);
        !           338:                        FD_CLR(sp->listen, listenset);
        !           339:                        sp->listen = -1;
        !           340:                        toannounce=1;
        !           341:                        signal(SIGALRM, SIG_IGN);       /* close race */
        !           342:                        alarm(0);
        !           343:                        signal(SIGALRM, sigalrm);
        !           344:                        continue;
        !           345:                }
        !           346:                if(sp->ap->func == 0){
        !           347:                        close(ipcaccept(ip));
        !           348:                        logstatus("in", ip);
        !           349:                        readfiles();
        !           350:                        continue;
        !           351:                }
        !           352:                signal(SIGALRM, SIG_IGN);       /* close race */
        !           353:                alarm(0);
        !           354:                signal(SIGALRM, sigalrm);
        !           355:                if (ip->machine==NULL || ip->user==NULL) {
        !           356:                        ipcreject(ip, EACCES, "no machine or user name");
        !           357:                        logstatus("in", ip);
        !           358:                        continue;
        !           359:                }
        !           360:                for(; sp; sp = sp->same){
        !           361:                        if(!sp->from)
        !           362:                                break;
        !           363:                        if(execre(sp->from, ip->machine, (regsubexp *)0, 0))
        !           364:                                break;
        !           365:                }
        !           366:                if(sp==0){
        !           367:                        ipcreject(ip, EACCES, "no such service");
        !           368:                        logstatus("in", ip);
        !           369:                        continue;
        !           370:                }
        !           371:                if(!(sp->accept) && ipcaccept(ip)<0) {
        !           372:                        logstatus("in", ip);
        !           373:                        continue;
        !           374:                }
        !           375: #ifdef PEX
        !           376:                ioctl(ip->cfd, FIOANPX, 0);
        !           377: #endif PEX
        !           378:                return(newrequest(ip, sp));
        !           379:        }
        !           380: }
        !           381: 
        !           382: /*
        !           383:  *  Close all service fds
        !           384:  */
        !           385: closesvcs()
        !           386: {
        !           387:        Service *p;
        !           388: 
        !           389:        toannounce=1;
        !           390:        for(p=svchead; p; p=p->next)
        !           391:                close(p->listen);
        !           392: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.