Annotation of researchv10no/ipc/mgrs/svcmgr/service.c, revision 1.1.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.