Annotation of 43BSDReno/contrib/isode-beta/others/idist/idistd2.c, revision 1.1.1.1

1.1       root        1: /* idistd2.c -- the non remote operations parts of the protocol */
                      2: 
                      3: /*
                      4:  * $Header: /f/osi/others/idist/RCS/idistd2.c,v 7.0 89/11/23 21:58:33 mrose Rel $
                      5:  *
                      6:  * Parts of the idist server which are not mixed up with remote
                      7:  * operations but depend on the defined types.
                      8:  *
                      9:  * Julian Onions <[email protected]>
                     10:  * Nottingham University Computer Science.
                     11:  *
                     12:  *
                     13:  * $Log:       idistd2.c,v $
                     14:  * Revision 7.0  89/11/23  21:58:33  mrose
                     15:  * Release 6.0
                     16:  * 
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char *rcsid = "$Header: /f/osi/others/idist/RCS/idistd2.c,v 7.0 89/11/23 21:58:33 mrose Rel $";
                     21: #endif
                     22: 
                     23: #include "defs.h"
                     24: #include "Idist-types.h"
                     25: 
                     26: char   *tp, *stp[128];
                     27: 
                     28: extern int catname;
                     29: extern char    target[];
                     30: extern FILE    *cfile;
                     31: extern struct type_Idist_FileSpec *cfiletype;
                     32: extern int oumask;
                     33: extern char    utmpfile[];
                     34: extern char    *tmpname;
                     35: extern struct type_Idist_IA5List *ia5list;
                     36: 
                     37: static char    *cannon ();
                     38: static struct type_Idist_IA5List *str2ia5list ();
                     39: static int compare ();
                     40: extern struct type_Idist_FileSpec *makefs ();
                     41: extern struct type_Idist_QueryResult *query ();
                     42: extern struct type_Idist_FileList *do_listcdir ();
                     43: 
                     44: doexec (cmd)
                     45: char   *cmd;
                     46: {
                     47:        int fd[2], status, pid, i;
                     48:        char    buf[BUFSIZ];
                     49: 
                     50:        if (pipe(fd) < 0)
                     51:                return NOTOK;
                     52: 
                     53:        if ((pid = vfork ()) == 0) {
                     54:                /*
                     55:                 * Return everything the shell commands print.
                     56:                 */
                     57:                (void) close(0);
                     58:                (void) close(1);
                     59:                (void) close(2);
                     60:                (void) open("/dev/null", 0);
                     61:                (void) dup(fd[1]);
                     62:                (void) dup(fd[1]);
                     63:                (void) close(fd[0]);
                     64:                (void) close(fd[1]);
                     65:                execl("/bin/sh", "sh", "-c", cmd, 0);
                     66:                _exit(127);
                     67:        }
                     68:        if (pid == -1)
                     69:                return NOTOK;
                     70: 
                     71:        (void) close(fd[1]);
                     72: 
                     73:        while ((i = read(fd[0], buf, sizeof(buf))) > 0) {
                     74:                addtoia5 (buf, i);
                     75:        }
                     76: 
                     77:        while ((i = wait(&status)) != pid && i != -1)
                     78:                ;
                     79:        if (i == -1)
                     80:                status = -1;
                     81:        (void) close(fd[0]);
                     82: 
                     83:        return OK;
                     84: }
                     85: 
                     86: do_symlink (fs)
                     87: struct type_Idist_FileSpec *fs;
                     88: {
                     89:        char    *new, old[BUFSIZ], *linkname;
                     90:        int     i;
                     91: 
                     92:        new = qb2str (fs -> filename);
                     93:        linkname = cannon (new);
                     94:        free (new);
                     95: 
                     96:        new = qb2str (fs -> linkname);
                     97:        (void) strcpy (old, new);
                     98:        free (new);
                     99: 
                    100:        
                    101:        if (symlink (old, linkname) < 0) {
                    102:                if (errno != ENOENT || chkparent (linkname) < 0 ||
                    103:                    symlink (old, linkname) < 0) {
                    104:                        nadvise (linkname, "Can't symlink %s to", old);
                    105:                        return NOTOK;
                    106:                }
                    107:        }
                    108: 
                    109:        if (bit_on (fs -> fileopts, bit_Idist_Options_compare)) {
                    110:                char    tbuf[BUFSIZ];
                    111: 
                    112:                if ((i = readlink (target, tbuf, BUFSIZ)) >= 0 &&
                    113:                    i == fs -> filesize &&
                    114:                    strncmp (old, tbuf, fs -> filesize) == 0) {
                    115:                        (void) unlink (linkname);
                    116:                        return OK;
                    117:                }
                    118:                if (bit_on (fs -> fileopts, bit_Idist_Options_verify)) {
                    119:                        (void) unlink (linkname);
                    120:                        note ("need to update: %s", target);
                    121:                        return OK;
                    122:                }
                    123:        }
                    124: 
                    125:        if (rename (linkname, target) < 0) {
                    126:                nadvise (target, "can't rename %s to", linkname);
                    127:                (void) unlink (linkname);
                    128:                return NOTOK;
                    129:        }
                    130:        if (bit_on (fs -> fileopts, bit_Idist_Options_compare))
                    131:                note ("updated %s\n", target);
                    132:        return OK;
                    133: }
                    134: 
                    135: static char    *cannon (name)
                    136: char   *name;
                    137: {
                    138:        static char     nname[BUFSIZ];
                    139:        char    *cp;
                    140:        extern  char    *tmpname;
                    141: 
                    142:        if (catname)
                    143:                (void) sprintf (tp, "/%s", name);
                    144:        if((cp = rindex (target, '/')) == NULL)
                    145:                (void) strcpy (nname, tmpname);
                    146:        else if (cp == target)
                    147:                (void) sprintf (nname, "/%s", tmpname);
                    148:        else {
                    149:                *cp = '\0';
                    150:                (void) sprintf (nname, "%s/%s", target, tmpname);
                    151:                *cp = '/';
                    152:        }
                    153:        return nname;
                    154: }
                    155: 
                    156: /*
                    157:  * Check to see if parent directory exists and create one if not.
                    158:  */
                    159: chkparent(name)
                    160:        char *name;
                    161: {
                    162:        register char *cp;
                    163:        struct stat stb;
                    164: 
                    165:        cp = rindex(name, '/');
                    166:        if (cp == NULL || cp == name)
                    167:                return(0);
                    168:        *cp = '\0';
                    169:        if (lstat(name, &stb) < 0) {
                    170:                if (errno == ENOENT && chkparent(name) >= 0 &&
                    171:                    mkdir(name, 0777 & ~oumask) >= 0) {
                    172:                        *cp = '/';
                    173:                        return(0);
                    174:                }
                    175:        } else if (ISDIR(stb.st_mode)) {
                    176:                *cp = '/';
                    177:                return(0);
                    178:        }
                    179:        *cp = '/';
                    180:        return(-1);
                    181: }
                    182: 
                    183: do_rfile (fs)
                    184: struct type_Idist_FileSpec *fs;
                    185: {
                    186:        char    *name, *p;
                    187: 
                    188:        p = qb2str (fs -> filename);
                    189:        name = cannon (p);
                    190:        free (p);
                    191: 
                    192:        if ((cfile = fopen (name, "w")) == NULL) {
                    193:                if (errno != ENOENT || chkparent (name) < 0 ||
                    194:                    (cfile = fopen (name, "w")) == NULL) {
                    195:                        nadvise (name, "Can't create file");
                    196:                        return NOTOK;
                    197:                }
                    198:        }
                    199:        (void) fchmod (fileno (cfile), fs -> filemode);
                    200: 
                    201:        return OK;
                    202: }
                    203: 
                    204: do_hardlink (fs)
                    205: struct type_Idist_FileSpec *fs;
                    206: {
                    207:        char    *new;
                    208:        char    *cp;
                    209:        char    old[BUFSIZ];
                    210:        struct stat stb;
                    211:        int     exists = 0;
                    212: 
                    213:        new = qb2str (fs -> filename);
                    214:        cp = qb2str (fs -> linkname);
                    215:        if (exptilde (old, cp) == NULL) {
                    216:                free (cp);
                    217:                free (new);
                    218:                return NOTOK;
                    219:        }
                    220:        free (cp);
                    221: 
                    222:        if (catname)
                    223:                (void) sprintf (tp, "/%s", new);
                    224:        free (new);
                    225: 
                    226:        if (lstat(target, &stb) == 0) {
                    227:                int mode = stb.st_mode & S_IFMT;
                    228:                if (mode != S_IFREG && mode != S_IFLNK) {
                    229:                        nadvise (NULLCP, "%s: not a regular file",
                    230:                                 host, target);
                    231:                        return NOTOK;
                    232:                }
                    233:                exists = 1;
                    234:        }
                    235:        if (chkparent(target) < 0 ) {
                    236:                nadvise("chkparent", "%s (no parent)", target);
                    237:                return NOTOK;
                    238:        }
                    239:        if (exists && (unlink(target) < 0)) {
                    240:                nadvise ("unlink", "%s", target);
                    241:                return NOTOK;
                    242:        }
                    243:        if (link(old, target) < 0) {
                    244:                nadvise (old,  "can't link %s to", target);
                    245:                return NOTOK;
                    246:        }
                    247:        return OK;
                    248: }
                    249: 
                    250: do_direct (fs)
                    251: struct type_Idist_FileSpec *fs;
                    252: {
                    253:        char    *cp, *name;
                    254:        struct stat stb;
                    255: 
                    256:        cp = name = qb2str (fs -> filename);
                    257: 
                    258:        if (catname >= sizeof(stp)) {
                    259:                nadvise (NULLCP, "Too many directory levels");
                    260:                free (name);
                    261:                return NOTOK;
                    262:        }
                    263: 
                    264:        stp[catname] = tp;
                    265:        if (catname++) {
                    266:                *tp ++ = '/';
                    267:                while (*tp++ = *cp ++)
                    268:                        ;
                    269:                tp --;
                    270:        }
                    271:        
                    272:        if (bit_on (fs -> fileopts, bit_Idist_Options_verify)) {
                    273:                free (name);
                    274:                return OK;
                    275:        }
                    276: 
                    277:        if (lstat (target, &stb) == 0) {
                    278:                if ((stb.st_mode & S_IFMT) == S_IFDIR) {
                    279:                        if ((stb.st_mode & 07777) == fs -> filemode) {
                    280:                                free (name);
                    281:                                return OK;
                    282:                        }
                    283:                        note ("%s remote node %o != local mode %o",
                    284:                              target, stb.st_mode & 07777, fs -> filemode);
                    285:                        free (name);
                    286:                        return OK;
                    287:                }
                    288:                errno = ENOTDIR;
                    289:        }
                    290:        else if (errno == ENOENT && (mkdir (target, fs -> filemode) == 0 ||
                    291:                                     chkparent (target) == 0 &&
                    292:                                     mkdir (target, fs -> filemode) == 0)) {
                    293:                char *owner = qb2str (fs -> fileowner);
                    294:                char *group = qb2str (fs -> filegroup);
                    295: 
                    296:                if (chog (target, owner, group, fs -> filemode) == 0) {
                    297:                        free (owner);
                    298:                        free (group);
                    299:                        free (name);
                    300:                        return OK;
                    301:                }
                    302:                free (owner);
                    303:                free (group);
                    304:        }
                    305:        free (name);
                    306:        nadvise (target, "Can't install directory");
                    307:        tp = stp[--catname];
                    308:        *tp = '\0';
                    309:        return NOTOK;
                    310: }
                    311: 
                    312: /*
                    313:  * Remove a file or directory (recursively) and send back an acknowledge
                    314:  * or an error message.
                    315:  */
                    316: remove(str)
                    317: char   *str;
                    318: {
                    319:        DIR *d;
                    320:        struct direct *dp;
                    321:        struct stat stb;
                    322:        char    buf[BUFSIZ];
                    323:        int     result = OK;
                    324: 
                    325:        if (lstat (str, &stb) < 0) {
                    326:                nadvise (str, "Can't stat file");
                    327:                return NOTOK;
                    328:        }
                    329:        
                    330:        switch (stb.st_mode & S_IFMT) {
                    331:        case S_IFREG:
                    332:        case S_IFLNK:
                    333:                if (unlink(str) < 0) {
                    334:                        nadvise (str, "Can't unlink");
                    335:                        return NOTOK;
                    336:                }
                    337:                note ("removed: %s", str);
                    338:                return OK;
                    339: 
                    340:        case S_IFDIR:
                    341:                break;
                    342: 
                    343:        default:
                    344:                nadvise (NULLCP, "%s: not a plain file", target);
                    345:                return NOTOK;
                    346:        }
                    347: 
                    348:        if ((d = opendir(str)) == NULL) {
                    349:                nadvise (str, "Can't open directory");
                    350:                return NOTOK;
                    351:        }
                    352: 
                    353:        while (dp = readdir(d)) {
                    354:                if (strcmp(dp->d_name, ".") == 0 ||
                    355:                    strcmp(dp->d_name, "..") == 0)
                    356:                        continue;
                    357:                (void) sprintf (buf, "%s/%s", str, dp -> d_name);
                    358:                result = remove(buf) == OK ? result : NOTOK;
                    359:        }
                    360:        closedir(d);
                    361:        if (rmdir(str) < 0) {
                    362:                nadvise (str, "Can't remove directory", str);
                    363:                return NOTOK;
                    364:        }
                    365:        note ("removed: %s", str);
                    366:        return result;
                    367: }
                    368: 
                    369: 
                    370: addtoia5 (str, len)
                    371: char   *str;
                    372: int    len;
                    373: {
                    374:        struct type_Idist_IA5List **ia5p;
                    375: 
                    376:        for (ia5p = &ia5list; *ia5p; ia5p = &(*ia5p) -> next)
                    377:                continue;
                    378: 
                    379:        *ia5p = str2ia5list (str, len);
                    380: }
                    381: 
                    382: struct type_Idist_QueryResult *query (str)
                    383: char   *str;
                    384: {
                    385:        struct type_Idist_QueryResult *qr;
                    386:        struct stat stb;
                    387: 
                    388:        qr = (struct type_Idist_QueryResult *) malloc (sizeof *qr);
                    389:        if (qr == NULL)
                    390:                adios ("memory", "out of");
                    391:        
                    392:        if (catname)
                    393:                (void) sprintf (tp, "/%s", str);
                    394: 
                    395:        if (lstat (target, &stb) < 0) {
                    396:                if (errno == ENOENT) {
                    397:                        qr -> offset = type_Idist_QueryResult_doesntExist;
                    398:                }
                    399:                else {
                    400:                        nadvise ("failed", "lstat");
                    401:                        free (( char *) qr);
                    402:                        qr = NULL;
                    403:                }
                    404:                *tp = '\0';
                    405:                return qr;
                    406:        }
                    407:        qr -> offset = type_Idist_QueryResult_doesExist;
                    408:        switch (stb.st_mode & S_IFMT) {
                    409:            case S_IFREG:
                    410:            case S_IFDIR:
                    411:            case S_IFLNK:
                    412:                qr -> un.doesExist = makefs (stb.st_mode & S_IFMT, 0,
                    413:                                             stb.st_mode & 07777, stb.st_size,
                    414:                                             stb.st_mtime, "", "", str, "");
                    415:                break;
                    416: 
                    417:            default:
                    418:                nadvise (NULLCP, "%s: not a file or directory", str);
                    419:                free ((char *)qr);
                    420:                qr = NULL;
                    421:        }
                    422:        *tp = '\0';
                    423:        return qr;
                    424: }
                    425: 
                    426: static struct type_Idist_IA5List *str2ia5list (s, len)
                    427: char   *s;
                    428: int    len;
                    429: {
                    430:        register struct type_Idist_IA5List *ia5;
                    431: 
                    432:        if ((ia5 = (struct type_Idist_IA5List  *) calloc (1, sizeof *ia5))
                    433:            == NULL)
                    434:                return NULL;
                    435: 
                    436:        if ((ia5 -> IA5String = str2qb (s, len, 1)) == NULL) {
                    437:                free ((char *) ia5);
                    438:                return NULL;
                    439:        }
                    440: 
                    441:        return ia5;
                    442: }
                    443: 
                    444: struct type_Idist_FileList *do_listcdir ()
                    445: {
                    446:        DIR     *d;
                    447:        register struct direct *dp;
                    448:        struct type_Idist_FileList *base, **flp;
                    449:        char    buf[BUFSIZ];
                    450:        struct stat stb;
                    451: 
                    452:        base = NULL;
                    453:        flp = &base;
                    454:        
                    455:        if ((d = opendir (target)) == NULL) {
                    456:                nadvise (target, "Can't open directory");
                    457:                return NULL;
                    458:        }
                    459: 
                    460:        while (dp = readdir (d)) {
                    461:                if (strcmp (dp -> d_name, ".") == 0 ||
                    462:                    strcmp (dp -> d_name, "..") == 0)
                    463:                        continue;
                    464:                (void) sprintf (buf, "%s/%s", target, dp -> d_name);
                    465:                if (lstat (buf, &stb) < 0) {
                    466:                        nadvise (buf, "Can't stat");
                    467:                        continue;
                    468:                }
                    469:                switch (stb.st_mode & S_IFMT) {
                    470:                    case S_IFDIR:
                    471:                    case S_IFLNK:
                    472:                    case S_IFREG:
                    473:                        break;
                    474:                    default:    /* skip sockets, fifos et al... */
                    475:                        continue;
                    476:                }
                    477:                if ((*flp = (struct type_Idist_FileList *)
                    478:                     malloc (sizeof **flp)) == NULL)
                    479:                        adios ("memory", "out of");
                    480: 
                    481:                (*flp) -> FileSpec = makefs (stb.st_mode & S_IFMT, 0,
                    482:                                             stb.st_mode & 07777, stb.st_size,
                    483:                                             stb.st_mtime, "", "",
                    484:                                             dp->d_name, "");
                    485:                (*flp) -> next = NULL;
                    486:                flp = &(*flp) -> next;
                    487:        }
                    488:        closedir (d);
                    489:        return base;
                    490: }
                    491: 
                    492: fixup ()
                    493: {
                    494:        struct timeval tvp[2];
                    495:        char    *new, *p;
                    496:        char    *owner, *group;
                    497:        long    convtime ();
                    498: 
                    499:        p = qb2str (cfiletype -> filename);
                    500:        new = cannon (p);
                    501:        free (p);
                    502:        
                    503:        if (bit_on (cfiletype -> fileopts, bit_Idist_Options_compare)) {
                    504:                if (compare (target, new) == OK) {
                    505:                        (void) unlink (new);
                    506:                        return OK;
                    507:                }
                    508:                if (bit_on (cfiletype -> fileopts, bit_Idist_Options_verify)) {
                    509:                        (void) unlink (new);
                    510:                        note ("need to update: %s", target);
                    511:                        return OK;
                    512:                }
                    513:        }
                    514: 
                    515:        tvp[1].tv_sec =
                    516:                tvp[0].tv_sec =
                    517:                        convtime (cfiletype -> filemtime);
                    518:        tvp[0].tv_usec = tvp[1].tv_usec = 0;
                    519:        if (utimes (new, tvp) < 0)
                    520:                nadvise (new, "utimes failed on");
                    521: 
                    522:        owner = qb2str (cfiletype -> fileowner);
                    523:        group = qb2str (cfiletype -> filegroup);
                    524: 
                    525:        if (chog (new, owner, group, cfiletype -> filemode) < 0) {
                    526:                free (owner);
                    527:                free (group);
                    528:                (void) unlink (new);
                    529:                return NOTOK;
                    530:        }
                    531:        free (owner);
                    532:        free (group);
                    533:        
                    534:        if (rename (new, target) < 0) {
                    535:                nadvise (target, "Can't rename %s to", new);
                    536:                return NOTOK;
                    537:        }
                    538:        if (bit_on (cfiletype -> fileopts, bit_Idist_Options_compare))
                    539:                note ("updated %s", target);
                    540:        free_Idist_FileSpec (cfiletype);
                    541:        cfiletype = NULL;
                    542:        return OK;
                    543: }
                    544: 
                    545: static int     compare (f1, f2)
                    546: char   *f1, *f2;
                    547: {
                    548:        FILE    *fp1, *fp2;
                    549:        char    buf1[BUFSIZ], buf2[BUFSIZ];     /* these two had
                    550:                                                   better be identical */
                    551:        int     n1, n2;
                    552: 
                    553:        if ((fp1 = fopen (f1, "r")) == NULL) {
                    554:                nadvise (f1, "Can't reopen file");
                    555:                return NOTOK;
                    556:        }
                    557:        if ((fp2 = fopen (f2, "r")) == NULL) {
                    558:                nadvise (f2, "Can't reopend file");
                    559:                (void) fclose (fp1);
                    560:                return NOTOK;
                    561:        }
                    562:        for (;;) {
                    563:                n1 = fread (buf1, sizeof buf1[0], sizeof buf1, fp1);
                    564:                n2 = fread (buf2, sizeof buf2[0], sizeof buf2, fp2);
                    565:                if (n1 != n2 || n1 == 0)
                    566:                        break;
                    567:                if (bcmp (buf1, buf2, n1) != 0)
                    568:                        break;
                    569:        }
                    570: 
                    571:        (void) fclose (fp1);
                    572:        (void) fclose (fp2);
                    573:        return n1 == 0 ? OK : NOTOK;
                    574: }
                    575: 
                    576: 
                    577: /*
                    578:  * Change owner, group and mode of file.
                    579:  */
                    580: chog(file, owner, group, mode)
                    581:        char *file, *owner, *group;
                    582:        int mode;
                    583: {
                    584:        register int i;
                    585:        int uid, gid;
                    586:        extern char user[];
                    587:        extern int userid;
                    588: 
                    589:        uid = userid;
                    590:        if (userid == 0) {
                    591:                if (*owner == ':') {
                    592:                        uid = atoi(owner + 1);
                    593:                } else if (pw == NULL || strcmp(owner, pw->pw_name) != 0) {
                    594:                        if ((pw = getpwnam(owner)) == NULL) {
                    595:                                if (mode & 04000) {
                    596:                                        note("%s: unknown login name, clearing setuid",
                    597:                                                host, owner);
                    598:                                        mode &= ~04000;
                    599:                                        uid = 0;
                    600:                                }
                    601:                        } else
                    602:                                uid = pw->pw_uid;
                    603:                } else
                    604:                        uid = pw->pw_uid;
                    605:                if (*group == ':') {
                    606:                        gid = atoi(group + 1);
                    607:                        goto ok;
                    608:                }
                    609:        } else if ((mode & 04000) && strcmp(user, owner) != 0)
                    610:                mode &= ~04000;
                    611:        gid = -1;
                    612:        if (gr == NULL || strcmp(group, gr->gr_name) != 0) {
                    613:                if ((*group == ':' && (getgrgid(gid = atoi(group + 1)) == NULL))
                    614:                   || ((gr = getgrnam(group)) == NULL)) {
                    615:                        if (mode & 02000) {
                    616:                                note("%s: unknown group", group);
                    617:                                mode &= ~02000;
                    618:                        }
                    619:                } else
                    620:                        gid = gr->gr_gid;
                    621:        } else
                    622:                gid = gr->gr_gid;
                    623:        if (userid && gid >= 0) {
                    624:                if (gr) for (i = 0; gr->gr_mem[i] != NULL; i++)
                    625:                        if (!(strcmp(user, gr->gr_mem[i])))
                    626:                                goto ok;
                    627:                mode &= ~02000;
                    628:                gid = -1;
                    629:        }
                    630: ok:
                    631:        if (userid == 0 && chown(file, uid, gid) < 0 )
                    632:                nadvise (file, "chown failed on");
                    633:        if ((mode & 06000) && chmod(file, mode) < 0) {
                    634:                nadvise (file, "chmod to 0%o failed on", mode);
                    635:        }
                    636:        return(0);
                    637: }
                    638: 
                    639: cleanup ()
                    640: {
                    641:        char    *p, *temp;
                    642: 
                    643:        if (cfiletype) {
                    644:                p = qb2str (cfiletype -> filename);
                    645:                temp = cannon (p);
                    646:                (void) unlink (temp);
                    647:        }
                    648: }

unix.superglobalmegacorp.com

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