Annotation of researchv10no/ipc/mgrs/ns/ns.c, revision 1.1.1.1

1.1       root        1: #include <sys/param.h>
                      2: #include <signal.h>
                      3: #include <sysent.h>
                      4: #include <libc.h>
                      5: #include <fio.h>
                      6: #include <ipc.h>
                      7: #include <string.h>
                      8: #include <errno.h>
                      9: #include <utsname.h>
                     10: #include <pwd.h>
                     11: #include "dbtypes.h"
                     12: 
                     13: /*
                     14:  *  system calls not in sysent.h
                     15:  */
                     16: extern "C" int select(int, fd_set*, fd_set*, int);
                     17: #define WNOHANG        1       /* don't hang in wait */
                     18: 
                     19: /*
                     20:  *  imported
                     21:  */
                     22: extern "C" int detach(char *);
                     23: extern int optind;
                     24: extern char *optarg;
                     25: extern "C" int getopt(int, char *[], char *);
                     26: extern "C" long time(long *);
                     27: extern "C" int uname(utsname *);
                     28: 
                     29: /*
                     30:  *  predeclared
                     31:  */
                     32: int announce(int, char *);
                     33: int doset(int, char *, int *);
                     34: int dovalue(int, char *, char *, int *);
                     35: void dohelp(int);
                     36: void initclient();
                     37: void newclient(int);
                     38: void dropclient(int);
                     39: int clientreq(int);
                     40: Db *getdb(char *, int *);
                     41: void basefiles(char *, char *, char *, char **, char **);
                     42: 
                     43: /*
                     44:  *  global
                     45:  */
                     46: char *av0;
                     47: int debug;
                     48: char *locsysname = 0;
                     49: 
                     50: /*
                     51:  *  return codes from clientreq
                     52:  */
                     53: #define OK 0
                     54: #define DOPARSE 1
                     55: #define DROPCLIENT 2
                     56: 
                     57: /*
                     58:  *  client data
                     59:  */
                     60: fd_set cvec;
                     61: struct client {
                     62:        int fd;
                     63:        char *bp;
                     64:        char *machine;          /* Client's machine from ipcinfo (0 if local) */
                     65:        char *user;             /* Client's login from ipcinfo */
                     66:        int dbhint;             /* Hint for finding the needed user db */
                     67: } client[NOFILE];
                     68: int lastclient = -1;
                     69: 
                     70: main(int ac, char *av[])
                     71: {
                     72:        int i, n;
                     73:        fd_set vec;
                     74:        char errbuf[sizeof(Fbuffer)];
                     75:        int doannounce, doparse;
                     76:        char *mtpt = "ns";
                     77:        int afd = -1;
                     78:        long lastcheck = 0;
                     79:        char *dbloadfile;
                     80:        char *sysdbdir;
                     81:        char *sysdbfile;
                     82:        int  dummyhint;
                     83:        utsname utsn;
                     84:        Db *sysdb;
                     85:        int noparse = 0;
                     86: 
                     87:        av0 = av[0];
                     88:        chdir("/cs");
                     89:        dbloadfile = "/usr/ipc/lib/ns.db";
                     90: 
                     91:        /*
                     92:         *  parse arguments
                     93:         */
                     94:        while((i = getopt(ac, av, "dnm:f:")) != -1)
                     95:                switch(i){
                     96:                case 'd':
                     97:                        debug = 1;
                     98:                        break;
                     99:                case 'm':
                    100:                        mtpt = optarg;
                    101:                        break;
                    102:                case 'f':
                    103:                        dbloadfile = optarg;
                    104:                        break;
                    105:                case 'n':
                    106:                        noparse = 1;
                    107:                        break;
                    108:                }
                    109: 
                    110:        /*
                    111:         * Don't die if pipe breaks
                    112:         */
                    113: 
                    114:        signal(SIGPIPE, SIG_IGN);
                    115: 
                    116:        /*
                    117:         *  let go of the console
                    118:         */
                    119:        if(!debug)
                    120:                detach(mtpt);
                    121: 
                    122:        /*
                    123:         * Find out who we are and make the system name global
                    124:         */
                    125:        if (!uname(&utsn))
                    126:                locsysname = utsn.sysname;
                    127: 
                    128:        Finit(2, errbuf);
                    129:        initclient();
                    130: 
                    131:        /*
                    132:         * Initialize system database and remember root system database
                    133:         * file in sysdb structure
                    134:         */
                    135: 
                    136:        basefiles("/usr/ipc/lib", "ns.db", dbloadfile, &sysdbdir, &sysdbfile);
                    137:        sysdb = newdb((int *) 0, sysdbdir, sysdbfile, locsysname, &dummyhint);
                    138: 
                    139:        /*
                    140:         *  loop forever, announcing and listening for requests.  We
                    141:         *  reannounce whenever a problem occurs with the announcement
                    142:         *  fd.
                    143:         */
                    144:        for(doannounce=doparse=1;;){
                    145:                if(doannounce){
                    146:                        afd = announce(afd, mtpt);
                    147:                        doannounce = 0;
                    148:                }
                    149:                if(doparse || time((long *)0) - lastcheck > 8*60){
                    150:                        if (checkfiles(sysdb)) 
                    151:                                parsefiles(sysdb);
                    152:                        doparse = 0;
                    153:                        lastcheck = time((long *)0);
                    154:                }
                    155:                for(; !doannounce && !doparse;){
                    156:                        /*
                    157:                         *  wait for a request
                    158:                         */
                    159:                        vec = cvec;
                    160:                        FD_SET(afd, vec);
                    161:                        switch(n=select(NOFILE, &vec, 0, 2*60*1000)){
                    162:                        case 0:
                    163:                                /*
                    164:                                 *  check to reparse if the system is
                    165:                                 *  quiescent
                    166:                                 */
                    167:                                if(noparse == 0)
                    168:                                        doparse = 1;
                    169:                                continue;
                    170:                        case -1:
                    171:                                doannounce = 1; /* all fd's bad */
                    172:                                continue;
                    173:                        }
                    174: 
                    175:                        /*
                    176:                         *  new client?  A <0 return means that the 
                    177:                         *  announcement has gone sour.
                    178:                         */
                    179:                        if(FD_ISSET(afd, vec)){
                    180:                                n--;
                    181:                                newclient(afd);
                    182:                        }
                    183: 
                    184:                        /*
                    185:                         *  client request?  A <0 return means the client
                    186:                         *  has gone sour.
                    187:                         */
                    188:                        for(i=0; n>0 && i<NOFILE && client[i].fd>=0; i++){
                    189:                                if(FD_ISSET(client[i].fd, vec)){
                    190:                                        n--;
                    191:                                        switch(clientreq(i)){
                    192:                                        case DROPCLIENT:
                    193:                                                dropclient(i);
                    194:                                                break;
                    195:                                        case DOPARSE:
                    196:                                                doparse = 1;
                    197:                                                break;
                    198:                                        }
                    199:                                }
                    200:                        }
                    201:                }
                    202:        }
                    203: }
                    204: 
                    205: /*
                    206:  *  announce a service
                    207:  */
                    208: announce(int afd, char *mtpt)
                    209: {
                    210:        if(afd>=0)
                    211:                close(afd);
                    212:        sync();
                    213:        for(afd=-1; afd<0; ){
                    214:                afd = ipccreat(mtpt, "");
                    215:                if(afd<0){
                    216:                        logconsole("%s: can't announce (%s)\n",av0,errstr);
                    217:                        sleep(10);
                    218:                }
                    219:        }
                    220:        chmod(mtpt, 0666);
                    221:        logconsole("%s: announced as %s\n", av0, mtpt);
                    222:        return afd;
                    223: }
                    224: 
                    225: /*
                    226:  * Break infile into base directory and file in base directory.  Use
                    227:  * default directory for relative infile.  Use default directory and
                    228:  * default file if there's no infile.
                    229:  */
                    230: void
                    231: basefiles(char *defdir, char *deffile, char *infile, char **basedir, char **file)
                    232: {
                    233:        char    *fileptr;
                    234: 
                    235:        if (fileptr= strrchr(infile,'/')) {
                    236:                *fileptr = 0;
                    237:                *file = strdup(fileptr + 1);
                    238:                if (fileptr == infile)
                    239:                        *basedir = (char *) 0;
                    240:                else if (*infile == '/')
                    241:                        *basedir = strdup(infile);
                    242:                else
                    243:                        *basedir = strdup(path(infile,defdir));
                    244:                *fileptr = '/';
                    245:        } else if (infile && *infile) {
                    246:                *file = strdup(infile);
                    247:                *basedir = strdup(defdir);
                    248:        } else {
                    249:                *file = strdup(deffile);
                    250:                *basedir = strdup(defdir);
                    251:        }
                    252: }
                    253: 
                    254: /*
                    255:  *  set all clients to off
                    256:  */
                    257: void
                    258: initclient()
                    259: {
                    260:        int i;
                    261: 
                    262:        for(i=0; i<NOFILE; i++)
                    263:                client[i].fd = -1;
                    264: }
                    265: 
                    266: void
                    267: ding(int x)
                    268: {
                    269:        signal(SIGALRM, ding);
                    270:        alarm(20);
                    271: }
                    272: 
                    273: /*
                    274:  *  get a request for a new client
                    275:  */
                    276: void
                    277: newclient(int fd)
                    278: {
                    279:        int cfd;
                    280:        int i;
                    281:        ipcinfo *ip;
                    282: 
                    283:        /*
                    284:         *  since we're single stream, don't let listening for
                    285:         *  a call take forever.  The alarm will abort any reads
                    286:         *  in ipclisten and ipcaccept.
                    287:         */
                    288:        signal(SIGALRM, ding);
                    289:        alarm(20);
                    290:        ip = ipclisten(fd);
                    291:        if(ip==0)
                    292:                return;
                    293:        cfd = ipcaccept(ip);
                    294:        alarm(0);
                    295:        if(cfd<0)
                    296:                return;
                    297:        for(i=0; i<NOFILE; i++)
                    298:                if(client[i].fd<0){
                    299:                        client[i].fd = cfd;
                    300:                        FD_SET(cfd, cvec);
                    301:                        if(i>lastclient)
                    302:                                lastclient = i;
                    303:                        if(!client[i].bp)
                    304:                                client[i].bp = malloc(sizeof(Fbuffer));
                    305:                        Finit(cfd, client[i].bp);
                    306:                        client[i].machine = 0;
                    307:                        if (ip->machine && *ip->machine)
                    308:                                client[i].machine = strdup(ip->machine);
                    309:                        client[i].user = strdup(ip->user);
                    310:                        client[i].dbhint = -1;          /* no hint yet */
                    311:                        return;
                    312:                }
                    313:        close(cfd);
                    314: }
                    315: 
                    316: /*
                    317:  *  drop a client
                    318:  */
                    319: void
                    320: dropclient(int c)
                    321: {
                    322:        /*
                    323:         *  close off this client
                    324:         */
                    325:        FD_CLR(client[c].fd, cvec);
                    326:        close(client[c].fd);
                    327:        client[c].fd = -1;
                    328:        if (client[c].machine)
                    329:                free(client[c].machine);
                    330:        if (client[c].user)
                    331:                free(client[c].user);
                    332: 
                    333:        /*
                    334:         *  move last client to this spot, lastclient may equal c
                    335:         */
                    336:        client[c] = client[lastclient];
                    337:        client[lastclient].fd = -1;
                    338:        lastclient--;
                    339: }
                    340: 
                    341: /*
                    342:  *  service a client request
                    343:  */
                    344: int
                    345: clientreq(int c)
                    346: {
                    347:        char buf[512];
                    348:        int n;
                    349:        char *fields[3];
                    350:        int fd = client[c].fd;
                    351: 
                    352:        /*
                    353:         *  read a line and split command and arguments
                    354:         */
                    355:        if((n=read(fd, buf, sizeof(buf)-1))<=0)
                    356:                return DROPCLIENT;
                    357:        buf[n] = '\0';
                    358:        setfields(" \t\n");
                    359:        n = getmfields(buf, fields, 2);
                    360:        if(n<1) {
                    361:                fprint(fd, "ILL null command\n");
                    362:                return OK;
                    363:        }
                    364: 
                    365:        /*
                    366:         *  act on command
                    367:         */
                    368:        if(fstrcmp("set", fields[0])==0){
                    369:                if(n<2)
                    370:                        fprint(fd, "ILL no search key\n");
                    371:                else
                    372:                        return doset(fd, fields[1], &client[c].dbhint);
                    373:        } else if(fstrcmp("value", fields[0])==0) {
                    374:                if(n<2) {
                    375:                        fprint(fd, "ILL no value types, no search key\n");
                    376:                } else {
                    377:                        n = getmfields(fields[1], fields, 2);
                    378:                        if(n<2)
                    379:                                fprint(fd, "ILL no search key\n");
                    380:                        else
                    381:                                dovalue(fd,fields[0],fields[1],
                    382:                                        &client[c].dbhint);
                    383:                }
                    384:        } else if(fstrcmp("help", fields[0])==0) {
                    385:                dohelp(fd);
                    386:        } else if(fstrcmp("quit", fields[0])==0) {
                    387:                return DROPCLIENT;
                    388:        } else if(fstrcmp("reset", fields[0])==0) {
                    389:                Fprint(fd, "OK\n");
                    390:                Fprint(fd, "DONE\n");
                    391:                Fflush(fd);
                    392:                logevent("reset by %s!%s\n",
                    393:                        (client[c].machine? client[c].machine:locsysname),
                    394:                        client[c].user);
                    395:                releasedbs();
                    396:                return DOPARSE;
                    397:        } else
                    398:                fprint(fd, "ILL\n");
                    399:        return OK;
                    400: }
                    401: 
                    402: /*
                    403:  *  Return a `set' of tuples matching allattributes in the request.  The
                    404:  *  request is "set value[,type] value[,type] ..."  The first valid attribute in
                    405:  *  the form: "system!login,db" is interpreted as the db to be searched.
                    406:  *  A request with no db attribute is resolved in the system db.
                    407:  */
                    408: int
                    409: doset(int fd, char *key, int *hint)
                    410: {
                    411:        Set *s = (Set *) 0;
                    412:        int status;
                    413:        Db *d;
                    414: 
                    415:        d = getdb(key,hint);
                    416:        key = key + strspn(key, " \t\n");
                    417: 
                    418:        if (d)
                    419:                s = lookup(key, d->o);
                    420: 
                    421:        if (Fprint(fd, "OK\n") < 0) {
                    422:                if (s) delete s;
                    423:                return DROPCLIENT;
                    424:        }
                    425:        if(s){
                    426:                if(d->origin)
                    427:                        s->sort(d->origin->first);
                    428:                status = s->print(fd);
                    429:                delete s;
                    430:                if (status < 0) 
                    431:                        return DROPCLIENT;
                    432:        }
                    433:        if (Fprint(fd, "DONE\n") < 0)
                    434:                return DROPCLIENT;
                    435:        if (Fflush(fd) < 0)
                    436:                return DROPCLIENT;
                    437:        return 0;
                    438: }
                    439: 
                    440: /*
                    441:  *  Return a single value.  The value is of one of the types listed in
                    442:  *  the first argument of the request.  The value comes from a tuple
                    443:  *  matching all attributes in the request.  The request is
                    444:  *  "value type1|type2|type3|... value[,type] value[,type] ..."
                    445:  *  The first valid attribute in the form: "system!login,db" is 
                    446:  *  interpreted as the db to be searched.  A request with no db 
                    447:  *  attribute is resolved in the system db.
                    448:  */
                    449: int
                    450: dovalue(int fd, char *typelist, char *key, int *hint)
                    451: {
                    452:        int n;
                    453: #define MAXTYPES 10
                    454:        char *types[MAXTYPES+1];
                    455:        Set *s;
                    456:        Db *d;
                    457: 
                    458:        d = getdb(key,hint);
                    459:        setfields("|");
                    460:        n = getmfields(typelist, types, MAXTYPES);
                    461:        if(n<=0) {
                    462:                fprint(fd, "ILL bad types\n");
                    463:                return -1;
                    464:        }
                    465:        types[MAXTYPES] = 0;
                    466: 
                    467:        if (d)
                    468:                s = lookup(key, d->o);
                    469:        Fprint(fd, "OK\n");
                    470:        if(s){
                    471:                if(d->origin)
                    472:                        s->sort(d->origin->first);
                    473:                s->printvalue(fd, types);
                    474:                delete s;
                    475:        }
                    476:        Fprint(fd, "DONE\n");
                    477:        Fflush(fd);
                    478:        return 0;
                    479: }
                    480: 
                    481: /*
                    482:  *  return a usage menu
                    483:  */
                    484: void
                    485: dohelp(int fd)
                    486: {
                    487:        fprint(fd, "OK\n");
                    488:        fprint(fd, "\tset value[,type] value[,type] ...\n");
                    489:        fprint(fd, "\tvalue [type|type|]type value[,type] value[,type] ...\n");
                    490:        fprint(fd, "\thelp\n");
                    491:        fprint(fd, "\tquit\n");
                    492:        fprint(fd, "\treset\n");
                    493:        fprint(fd, "DONE\n");
                    494: }
                    495: 
                    496: /*
                    497:  * get the database to be used in resolving the query qstr.  Qstr is modified
                    498:  * to remove the db identifier.  The db identifier can have any of the following
                    499:  * forms:
                    500:  *        ,db                 :  system database
                    501:  *        system,db           :  system database if system == locsysname
                    502:  *        !user,db            :  database in .nsrc file of login user
                    503:  *        system!user,db      :  same as !user,db if system == locsysname
                    504:  *        (none)              :  system database if no db attribute
                    505:  *
                    506:  * The first valid db attribute in qstr is used as the db identifier.  If no
                    507:  * db attribute is found, the system database is used.  If only invalid attributes
                    508:  * are found, no database is used, i.e. (Db *) 0 is returned.
                    509:  */
                    510: Db *
                    511: getdb(char *qstr, int *hint)
                    512: {
                    513:        char            *commaloc;
                    514:        char            *dbname;
                    515:        char            *uname;
                    516:        char            *cp;
                    517:        struct passwd   *pw;
                    518:        char            failurepending = 0;
                    519:        char            dbnamebuf[MAXDBNAME+1];
                    520:        Db              *d;
                    521: 
                    522:        for (; commaloc = strchr(qstr, ','); qstr = commaloc + 1) {
                    523:                if ((commaloc[1] == 'd') && (commaloc[2] == 'b') &&
                    524:                  ((commaloc[3]=='\n')||(commaloc[3]=='\t')||(commaloc[3]==' '))) {
                    525:                        *commaloc = 0;
                    526:                        for (dbname = commaloc - 1; dbname >= qstr; dbname--) {
                    527:                                if ((*dbname == '\t') || (*dbname == ' ')) {
                    528:                                        dbname++;
                    529:                                        break;
                    530:                                }
                    531:                        }
                    532:                        if (dbname < qstr)
                    533:                                dbname++;
                    534:                        if (dbname == commaloc) {
                    535:                                commaloc[0] = commaloc[1] = commaloc[2] = ' ';
                    536:                                break;  /* System wildcard: ",db" */
                    537:                        }
                    538:                        uname = strchr(dbname,'!');
                    539:                        if (uname != dbname) {
                    540:                                if (uname)
                    541:                                        *uname = 0;
                    542:                                if (fstrcmp(dbname, locsysname)) {
                    543:                                        if (uname) *uname = '!';
                    544:                                        *commaloc = ',';
                    545:                                        failurepending = 1;
                    546:                                        continue;       /* System name differs */
                    547:                                }
                    548:                                if (!uname) {
                    549:                                        for (cp = dbname; cp < commaloc + 3; cp++)
                    550:                                                *cp = ' ';
                    551:                                        break;  /* Sys name matches: "system,db" */
                    552:                                }
                    553:                                *uname = '!';
                    554:                        }
                    555:                        if (pw = getpwnam(uname+1)) {
                    556:                                if (d = finddb(&pw->pw_uid, hint)) {
                    557:                                        if (checkfiles(d))
                    558:                                                parsefiles(d);
                    559:                                } else {
                    560:                                        strncpy(dbnamebuf,locsysname,MAXDBNAME);
                    561:                                        strncat(dbnamebuf,uname,MAXDBNAME);
                    562:                                        d = newdb(&pw->pw_uid, pw->pw_dir, 
                    563:                                                ".nsrc", dbnamebuf, hint);
                    564:                                        parsefiles(d);
                    565:                                }
                    566:                                for (cp = dbname; cp < commaloc + 3; cp++)
                    567:                                        *cp = ' ';
                    568:                                return d;  /* User name matches:             */
                    569:                                           /* "system!user,db" or "!user,db" */
                    570:                        }
                    571:                        *commaloc = ',';
                    572:                        failurepending = 1;
                    573:                        continue;                       /* User name differs */
                    574:                }
                    575:                qstr = commaloc + 1;
                    576:        }
                    577:        if (failurepending) 
                    578:                return (Db *) 0;                        /* No db field matched   */
                    579: 
                    580:        return finddb((int *)0, hint);                  /* System name default */
                    581: }

unix.superglobalmegacorp.com

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