Annotation of 42BSD/ingres/source/dbu/copy.c, revision 1.1

1.1     ! root        1: # include      <stdio.h>
        !             2: # include      <func.h>
        !             3: # include      <pv.h>
        !             4: # include      <ingres.h>
        !             5: # include      <aux.h>
        !             6: # include      <access.h>
        !             7: # include      <symbol.h>
        !             8: # include      <lock.h>
        !             9: # include      <signal.h>
        !            10: # include      <sccs.h>
        !            11: 
        !            12: SCCSID(@(#)copy.c      7.6     9/26/83)
        !            13: 
        !            14: /*
        !            15: **  COPY -- Performs an ingres COPY.
        !            16: **
        !            17: **     Trace Flags:
        !            18: **             30
        !            19: */
        !            20: 
        !            21: 
        !            22: # define       MAXMAP          3 * MAXDOM
        !            23: # define       DUMMY           'd'
        !            24: # define       ESCAPE          '\\'
        !            25: 
        !            26: extern short   tTdbu[100];
        !            27: extern int     copy();
        !            28: extern int     null_fn();
        !            29: 
        !            30: struct fn_def CopyFn =
        !            31: {
        !            32:        "COPY",
        !            33:        copy,
        !            34:        null_fn,
        !            35:        null_fn,
        !            36:        NULL,
        !            37:        0,
        !            38:        tTdbu,
        !            39:        100,
        !            40:        'Z',
        !            41:        0
        !            42: };
        !            43: 
        !            44: 
        !            45: 
        !            46: 
        !            47: struct map
        !            48: {
        !            49:        char    name[MAXNAME+1];        /* attribute name */
        !            50:        char    ftype;          /* attfrmt of file domain */
        !            51:        char    rtype;          /* attfrmt of relation domain */
        !            52:        int     flen;           /* attfrml of file domain */
        !            53:        int     rlen;           /* attfrml of relation domain */
        !            54:        int     roffset;        /* attoff of relation domain */
        !            55:        int     used;           /* tag for duplicate checking */
        !            56:        char    *fdelim;        /* pointer to list of file param delims */
        !            57:        char    *paramname;     /* pointer to original parameter name */
        !            58:                                /* used for supplying domain name in case of error */
        !            59: };
        !            60: struct map     Map[MAXMAP];            /* one entry for each user
        !            61:                                   specified domain in copy statement. */
        !            62: 
        !            63: int    Mapcount;               /* number of Map entries   */
        !            64: 
        !            65: 
        !            66: DESC   Des;            /* descriptor for copied relation     */
        !            67: 
        !            68: extern struct out_arg  Out_arg;        /* user defined formats for numeric output */
        !            69: 
        !            70: FILE   *File_iop;              /* i/o file pointer */
        !            71: char   *Filename;              /* pointer to file name */
        !            72: 
        !            73: int    Into;                   /* into is one if this is a copy into file */
        !            74: 
        !            75: char   Inbuf[BUFSIZ];          /* input holder */
        !            76: char   Outbuf[BUFSIZ];         /* output holder */
        !            77: 
        !            78: long   Tupcount;               /* number of tuples processed */
        !            79: char   *Relname;               /* name of relation */
        !            80: long   Duptuple;               /* number of duplicate tuples */
        !            81: long   Baddoms;                /* number of domains with control chars */
        !            82: long   Truncount;              /* number of truncations on a c0 field */
        !            83: int    Piped[2];               /* pipe descriptor for copy communication */
        !            84: char   *Cpdomains[] =          /* dummy domain names for copy "into" */
        !            85: {
        !            86:        "nl",           "\n",
        !            87:        "tab",          "\t",
        !            88:        "sp",           " ",
        !            89:        "nul",          "\0",
        !            90:        "null",         "\0",
        !            91:        "comma",        ",",
        !            92:        "colon",        ":",
        !            93:        "dash",         "-",
        !            94:        "lparen",       "(",
        !            95:        "rparen",       ")",
        !            96:        0
        !            97: };
        !            98: 
        !            99: char   Delimitor[] =   ",\n\t";        /* default delims for c0 & d0 */
        !           100: 
        !           101: 
        !           102: 
        !           103: copy(pc,pv)
        !           104: int    pc;
        !           105: PARM   pv[];
        !           106: {
        !           107:        extern char     *Usercode;
        !           108:        extern int      Noupdt;
        !           109:        register int    i, pid;
        !           110:        register char   *cp;
        !           111:        int             stat;
        !           112:        int             copydone();
        !           113:        int             op;
        !           114: 
        !           115: #      ifdef xZTR1
        !           116:        if (tTf(30,1))
        !           117:        {
        !           118:                printf("entered copy\n");
        !           119:                prvect(pc, pv);
        !           120:        }
        !           121: #      endif
        !           122:        Duptuple = 0;
        !           123:        Truncount = 0;
        !           124:        Tupcount = 0;
        !           125:        Baddoms = 0;
        !           126:        Relname = pv[0].pv_val.pv_str;
        !           127:        Into = (pv[pc-2].pv_val.pv_str[0] == 'i');
        !           128:        Filename = pv[pc-1].pv_val.pv_str;
        !           129: 
        !           130:        /* relation must exist and not be a system relation */
        !           131:        /* in addition a copy "from" can't be done if the user */
        !           132:        /* doesn't own the relation */
        !           133:        /* and furthermore it can't have an index */
        !           134:        i = 0;  /* assume all is well */
        !           135:        if (op = openr(&Des, 2, Relname))
        !           136:        {
        !           137:                if (op == AMOPNVIEW_ERR)
        !           138:                        i = 5818;
        !           139:                else
        !           140:                {
        !           141:                        if (op < 0)
        !           142:                                syserr("COPY: openr 1 (%.14s) %d", Relname, op);
        !           143:                        else
        !           144:                                /* non-existant relation */
        !           145:                                i = 5800;
        !           146:                }
        !           147:        }
        !           148:        else
        !           149:        {
        !           150:                if (Into)
        !           151:                {
        !           152:                        if ((Des.reldum.relstat & S_PROTALL)
        !           153:                                && (Des.reldum.relstat & S_PROTRET)
        !           154:                                && !bequal(Usercode, Des.reldum.relowner, 2))
        !           155:                                i = 5822;
        !           156:                }
        !           157:                else
        !           158:                {
        !           159:                        /* extra checking if this is a copy "from" */
        !           160: 
        !           161:                        /* must be owned by the user */
        !           162:                        if (!bequal(Usercode, Des.reldum.relowner, 2))
        !           163:                                i = 5814;
        !           164:                        else
        !           165:                                /* must be updateable */
        !           166:                                if ((Des.reldum.relstat & S_NOUPDT) && Noupdt)
        !           167:                                        i = 5813;
        !           168:                                else
        !           169:                                        /* must not be indexed */
        !           170:                                        if (Des.reldum.relindxd > 0)
        !           171:                                                i = 5812;
        !           172:                }
        !           173:        }
        !           174:        if (i)
        !           175:        {
        !           176:                closer(&Des);
        !           177:                return (error(i, Relname, 0));  /* relation doesn't exist for this user */
        !           178:        }
        !           179: 
        !           180:        /* check that file name begins with a "/" */
        !           181:        cp = Filename;
        !           182:        while (*cp == ' ')
        !           183:                cp++;
        !           184:        if (*cp != '/')
        !           185:        {
        !           186:                closer(&Des);
        !           187:                return (error(5816, Filename, 0));
        !           188:        }
        !           189: 
        !           190:        /* fill map structures with transfer information */
        !           191:        if (i = mapfill(&pv[1]))
        !           192:        {
        !           193:                closer(&Des);
        !           194:                return (i);     /* error in user semantics */
        !           195:        }
        !           196: 
        !           197:        /* fork a child process which will run as the real user */
        !           198:        /* that child will complete the copy and exit */
        !           199:        if (pipe(Piped))
        !           200:                syserr("copy:can't make pipe");
        !           201:        if ((pid = fork()) < 0)
        !           202:                syserr("copy:can't fork");
        !           203:        if (pid)
        !           204:        {
        !           205:                /* the ingres parent */
        !           206:                close(Piped[1]);
        !           207:                ruboff(0);      /* interrupts off */
        !           208:                stat = fullwait(pid, "copy");
        !           209:                if (read(Piped[0], &Des.reladds, 4) != 4)
        !           210:                        syserr("copy:can't read pipe");
        !           211:                close(Piped[0]);
        !           212:                closer(&Des);   /* close the rel */
        !           213:                rubon();
        !           214:                /* if stat is != 0 then add on 5800 for error */
        !           215:                if (stat)
        !           216:                        stat += 5800;
        !           217:                return (stat);  /* done */
        !           218:        }
        !           219: 
        !           220:        /* the child. change to run as the real user */
        !           221:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !           222:                signal(SIGINT, copydone);       /* clean up on rubout */
        !           223:        setuid(getuid());
        !           224: #      ifndef xB_UNIX
        !           225:        setgid(getgid());
        !           226: #      endif
        !           227:        if (Into)       /* from relation into file */
        !           228:        {
        !           229:                if ((File_iop = fopen(Filename, "w")) == NULL) /* create file for user */
        !           230:                        i = nferror(5806, Filename, 0); /* cant create file */
        !           231:                else
        !           232:                {
        !           233:                        if (Lockrel)    /* set a shared lock on relation*/
        !           234:                                setrll(A_SLP, Des.reltid.ltid, M_SHARE);
        !           235:                        i = rel_file();
        !           236:                }
        !           237:        }
        !           238:        else            /* from UNIX file into relation */
        !           239:        {
        !           240:                if ((File_iop = fopen(Filename, "r")) == NULL)
        !           241:                        i = nferror(5805, Filename, 0); /* cant open user file */
        !           242:                else
        !           243:                {
        !           244:                        if (Lockrel)    /* set an exclusive lock on relat*/
        !           245:                                setrll(A_SLP, Des.reltid.ltid, M_EXCL);
        !           246:                        i = file_rel();
        !           247:                        if (Duptuple)
        !           248:                                nferror(5819, locv(Duptuple), 0);       /* warning only */
        !           249:                        if (Baddoms)
        !           250:                                nferror(5820, locv(Baddoms), 0);        /* warning only */
        !           251:                }
        !           252:        }
        !           253:        copydone(i);
        !           254: }
        !           255: /*
        !           256: **     Finish up and exit after a copy or interrupt
        !           257: **
        !           258: **     I is the return code. Since only a byte can be
        !           259: **     returned, only the least significant 2 decimal
        !           260: **     digits are returned. i is either 0 or a number like 58??
        !           261: */
        !           262: 
        !           263: copydone(i)
        !           264: int    i;
        !           265: {
        !           266:        if (Lockrel)    /* unlock relation */
        !           267:                unlrl(Des.reltid.ltid);
        !           268:        if (Truncount)
        !           269:                nferror(5821, locv(Truncount), 0);      /* warning only */
        !           270:        /*  force the updates to be flushed */
        !           271:        cleanrel(&Des);
        !           272:        if (File_iop)
        !           273:                fclose(File_iop);
        !           274:        if (write(Piped[1], &Des.reladds, 4) != 4)
        !           275:                syserr("copyc:can't writepipe");
        !           276:        exit (i % 100);
        !           277: }
        !           278: /*
        !           279: **  REL_FILE -- copy from relation to file
        !           280: */
        !           281: 
        !           282: rel_file()
        !           283: {
        !           284:        int                     j;
        !           285:        struct tup_id           tid, limtid;
        !           286:        char                    *cp, save;
        !           287:        register int            offset;
        !           288:        register int            i;
        !           289:        register struct map     *mp;
        !           290: 
        !           291:        /* set scan limits to scan the entire relation */
        !           292:        if (find(&Des, NOKEY, &tid, &limtid))
        !           293:                syserr("find error");
        !           294: 
        !           295:        while ((i = get(&Des, &tid, &limtid, Inbuf, 1)) == 0)
        !           296:        {
        !           297:                mp = Map;
        !           298:                offset = 0;
        !           299:                for (i = 0; i < Mapcount; i++)
        !           300:                {
        !           301:                        /*
        !           302:                        ** For cases of char to numeric conversion,
        !           303:                        ** there must be a null byte at the end of the
        !           304:                        ** string. The character just past the current
        !           305:                        ** domain is saved an a null byte inserted 
        !           306:                        */
        !           307: 
        !           308:                        cp = &Inbuf[mp->roffset + mp->rlen];    /* compute address */
        !           309:                        save = *cp;     /* get the character */
        !           310:                        *cp = '\0';     /* insert a null */
        !           311: 
        !           312:                        /*
        !           313:                        ** Special case, we want to copy the tid
        !           314:                        */
        !           315:                        if ( mp->roffset == -1 )
        !           316:                                j = transfer(&tid,mp->rtype,mp->rlen,
        !           317:                                             mp->ftype,mp->flen,offset);
        !           318:                        else
        !           319:                                j = transfer(&Inbuf[mp->roffset], mp->rtype,
        !           320:                                         mp->rlen, mp->ftype, mp->flen, offset);
        !           321:                        if (j)
        !           322:                        {
        !           323:                                /* bad ascii to numeric conversion or field length too small */
        !           324:                                return (nferror(j, mp->paramname, &Inbuf[mp->roffset], locv(Tupcount), Relname, Filename, 0));
        !           325:                        }
        !           326:                        *cp = save;     /* restore the saved character */
        !           327:                        offset += mp->flen;
        !           328:                        mp++;
        !           329:                }
        !           330:                Tupcount++;
        !           331:                if (fwrite(Outbuf, 1, offset, File_iop) != offset)
        !           332:                        syserr("copy:cant write to user file %s", Filename);
        !           333:        }
        !           334:        if (i < 0)
        !           335:                syserr("bad get from rel %d", i);
        !           336:        return (0);
        !           337: }
        !           338: /*
        !           339: **     file_rel is called to transfer tuples from
        !           340: **     the input file and append them to the relation
        !           341: **
        !           342: **     Char domains are initialized to blank and numeric
        !           343: **     domains are initialized to zero.
        !           344: */
        !           345: 
        !           346: file_rel()
        !           347: {
        !           348:        register int            i, j;
        !           349:        register struct map     *mp;
        !           350:        struct tup_id           tid;
        !           351: 
        !           352:        clr_tuple(&Des, Outbuf);
        !           353: 
        !           354:        /* copy domains until an end of file or an error */
        !           355:        for (;;)
        !           356:        {
        !           357:                mp = Map;
        !           358:                for (i = 0; i < Mapcount; i++)
        !           359:                {
        !           360:                        if ((j = bread(mp)) <= 0)
        !           361:                        {
        !           362:                                if (j < 0)
        !           363:                                {
        !           364:                                        i = 1;  /* force an error */
        !           365:                                        j = 5815;       /* unterminated string */
        !           366:                                }
        !           367:                                else
        !           368:                                        j = 5810;       /* end of file */
        !           369:                                if (i)  /* error only if end of file during a tuple or unterminated string */
        !           370:                                {
        !           371:                                        i = nferror(j, mp->paramname, locv(Tupcount), Filename, Relname, 0);
        !           372:                                }
        !           373:                                return (i);
        !           374:                        }
        !           375:                        j = transfer(Inbuf, mp->ftype, mp->flen, mp->rtype, mp->rlen, mp->roffset);
        !           376:                        if (j)
        !           377:                        {
        !           378:                                /* bad ascii to numeric or field length too small */
        !           379:                                return (nferror(j, mp->paramname, Inbuf, locv(Tupcount), Filename, Relname, 0));
        !           380:                        }
        !           381:                        mp++;
        !           382:                }
        !           383:                Tupcount++;
        !           384:                if ((j = insert(&Des, &tid, Outbuf, 1)) < 0)
        !           385:                        syserr("insert error %d rel=%s", j, Relname);
        !           386:                if (j == 1)
        !           387:                        Duptuple++;
        !           388:                mp++;
        !           389:        }
        !           390:        /* 
        !           391:        ** This statement was here -- i don'T think it does anything, but we'll see
        !           392:        ** return (0); 
        !           393:        */
        !           394: }
        !           395: /*
        !           396: **     transfer copies data from "*in" to
        !           397: **     Outbuf doing conversions whenever
        !           398: **     necessary
        !           399: */
        !           400: 
        !           401: transfer(in, sf, sl, df, dl, doff)
        !           402: ANYTYPE        *in;    /* pointer to input chars */
        !           403: char   sf;     /* source format */
        !           404: int    sl;     /* source length */
        !           405: char   df;     /* destination format */
        !           406: int    dl;     /* destination length */
        !           407: int    doff;   /* destination offset */
        !           408: {
        !           409:        register char           *outp;
        !           410:        register ANYTYPE        *inp;
        !           411:        register int            i;
        !           412:        int                     j;
        !           413:        char                    temp[MAXFIELD]; /* holds char during conversions to ascii */
        !           414:        float                   f;
        !           415:        double                  d;
        !           416:        long                    l;
        !           417: 
        !           418: 
        !           419:        outp = &Outbuf[doff];
        !           420:        inp = in;
        !           421: 
        !           422:        if (sf == DUMMY)
        !           423:                /* if source format is a dummy fields then
        !           424:                   nothing else need be done */
        !           425:                return (0);
        !           426: 
        !           427:        if (df == DUMMY)
        !           428:        {
        !           429:                /* fill field with dummy domain character */
        !           430:                i = dl; /* i equals the number of chars */
        !           431:                while (i--)
        !           432:                        *outp++ = sf;   /* sf holds dummy char */
        !           433:                return (0);
        !           434:        }
        !           435: 
        !           436:        if (sf != CHAR)
        !           437:        {
        !           438:                if (df == CHAR) /* numeric to char conversion */
        !           439:                {
        !           440:                        switch (sl)
        !           441:                        {
        !           442:                          /* int of size 1 or 2 */
        !           443:                          case 1:
        !           444:                                itoa(inp->i1type, temp);
        !           445:                                break;
        !           446: 
        !           447:                          case 2:
        !           448:                                itoa(inp->i2type, temp);        /* convert to ascii */
        !           449:                                break;
        !           450: 
        !           451:                          /* int or float of size 4 */
        !           452:                          case 4:
        !           453:                                if (sf == INT)
        !           454:                                {
        !           455:                                        smove(locv(inp->i4type), temp); /* convert and copy */
        !           456:                                }
        !           457: 
        !           458:                                else
        !           459:                                {
        !           460:                                        ftoa(inp->f4type, temp, dl, Out_arg.f4prec, Out_arg.f4style);
        !           461:                                }
        !           462:                                break;
        !           463: 
        !           464:                          /* float of size 8 */
        !           465:                          case 8:
        !           466:                                ftoa(inp->f8type, temp, dl, Out_arg.f8prec, Out_arg.f8style);
        !           467:                                break;
        !           468: 
        !           469:                          /* there is no possible default */
        !           470:                          default:
        !           471:                                syserr("bad domain length %d",sl);
        !           472:                        }
        !           473: 
        !           474:                        j = length(temp);
        !           475:                        if ((i = dl - j) < 0)
        !           476:                                return (5808);  /* field won't fit */
        !           477: 
        !           478:                        /* blank pad from left. Number will be right justified */
        !           479:                        while (i--)
        !           480:                                *outp++ = ' ';
        !           481: 
        !           482:                        bmove(temp, outp, j);
        !           483:                        return (0);
        !           484:                }
        !           485: 
        !           486:                if (convert(inp, outp, sf, sl, df, dl)) /* numeric to numeric transfer */
        !           487:                        return (5808);  /* numeric truncation error */
        !           488:                return (0);
        !           489:        }
        !           490: 
        !           491:        /* character to numeric conversion */
        !           492:        /* and character to character conversion */
        !           493:        switch (df)
        !           494:        {
        !           495: 
        !           496:          case CHAR:
        !           497:                i = sl;
        !           498:                if (!i)
        !           499:                {
        !           500:                        i = length(inp->c0type);
        !           501:                }
        !           502:                if (i > dl)
        !           503:                        i = dl;
        !           504:                if (charmove(inp->c0type, outp, i))
        !           505:                        Baddoms++;
        !           506:                for (outp += i; i<dl; i++)
        !           507:                        *outp++ = ' ';
        !           508:                return (0);
        !           509: 
        !           510:          case FLOAT:
        !           511:                if (atof(inp->c0type, &d))
        !           512:                        return (5809);  /* bad conversion to numeric */
        !           513:                if (dl == 8)
        !           514:                        bmove(&d, outp, dl);
        !           515:                else
        !           516:                {
        !           517:                        f = d;  /* f8 to f4 conversion */
        !           518:                        bmove(&f, outp, dl);
        !           519:                }
        !           520:                return (0);
        !           521: 
        !           522:          case INT:
        !           523:                if (dl == 4)
        !           524:                {
        !           525:                        if (atol(inp->c0type, &l))
        !           526:                                return (5809);
        !           527:                        bmove(&l, outp, 4);
        !           528:                        return (0);
        !           529:                }
        !           530:                j = atoi(inp->c0type);
        !           531:                if ((dl == 1) && ((j < -128) || (j > 127)))
        !           532:                        return (5809);
        !           533:                bmove(&j, outp, dl);
        !           534:                return (0);
        !           535:        }
        !           536: }
        !           537: /*
        !           538: **     moves a character string from "in"
        !           539: **     to "out" removing any control characters.
        !           540: **     returns true if any control characters were found
        !           541: */
        !           542: 
        !           543: charmove(in, out, length)
        !           544: char   *in, *out;
        !           545: int    length;
        !           546: {
        !           547:        register char   *ip, *op;
        !           548:        register int    l;
        !           549:        int             bad;
        !           550: 
        !           551:        bad = FALSE;
        !           552:        ip = in;
        !           553:        op = out;
        !           554:        l = length;
        !           555: 
        !           556:        while (l--)
        !           557:                if ((*op++ = *ip++) < ' ')
        !           558:                {
        !           559:                        *(op-1) = ' ';
        !           560:                        bad = TRUE;
        !           561:                }
        !           562:        return (bad);
        !           563: }
        !           564: /*
        !           565: **     Mapfill fills the Map structure with the list
        !           566: **     of user supplied attributes. It then reads
        !           567: **     the list of relation attributes and checks
        !           568: **     for matching attribute names.
        !           569: **
        !           570: **     if an error occures then mapfill returns -1
        !           571: **             else it returns 0
        !           572: **
        !           573: **     Mapfill performs special processing on
        !           574: **     dummy domains.
        !           575: **
        !           576: **     If no user attributes are given, then "given"=FALSE
        !           577: **     and each attribute in the relation is set up to be
        !           578: **     copied in the formats and order in which they
        !           579: **     exist in the relation
        !           580: */
        !           581: 
        !           582: mapfill(aptr)
        !           583: PARM   aptr[];
        !           584: {
        !           585:        register PARM           *ap;
        !           586:        register struct map     *mp;
        !           587:        register int            i;
        !           588:        char                    *fp;
        !           589:        extern DESC             Attdes;
        !           590:        struct attribute        att;
        !           591:        struct tup_id           tid, limtid;
        !           592:        int                     given, cnt;
        !           593:        char                    *zcheck();
        !           594:        char                    *dumvalue();
        !           595: 
        !           596:        Mapcount = 0;
        !           597:        mp = Map;
        !           598:        ap = aptr;
        !           599: 
        !           600:        /* Gather list of user supplied attributes */
        !           601: 
        !           602:        while (*(ap->pv_val.pv_str) != '\0')
        !           603:        {
        !           604:                /* check for overflow */
        !           605:                if (Mapcount == MAXMAP)
        !           606:                        return (error(5803, 0));        /* more than MAXMAP specifiers */
        !           607: 
        !           608:                mp->paramname = (ap->pv_val).pv_str;    /* save pointer to user supplied name */
        !           609:                pmove(((ap++)->pv_val).pv_str, mp->name, MAXNAME, ' ');
        !           610:                fp = ((ap++)->pv_val).pv_str;   /* fp points to format string */
        !           611:                mp->used = 0;
        !           612:                mp->rlen = 0;   /* zero in case this is a dummy domain */
        !           613:                mp->roffset = 0;
        !           614:                mp->fdelim = 0;
        !           615:                /* check domain type in *fp */
        !           616:                switch (*fp++)
        !           617:                {
        !           618: 
        !           619:                  case 'c':
        !           620:                        i =  CHAR;
        !           621:                        if ((mp->fdelim = zcheck(fp)) == 0)
        !           622:                                return (-1);    /* bad delimitor */
        !           623:                        break;
        !           624: 
        !           625:                  case 'f':
        !           626:                        i = FLOAT;
        !           627:                        break;
        !           628: 
        !           629:                  case 'i':
        !           630:                        i = INT;
        !           631:                        break;
        !           632: 
        !           633:                  case DUMMY:
        !           634:                        i = DUMMY;
        !           635:                        if ((mp->fdelim = zcheck(fp)) == 0)
        !           636:                                return (-1);
        !           637:                        break;
        !           638: 
        !           639:                  default:
        !           640:                        return (error(5811, mp->paramname, --fp, 0));
        !           641:                }
        !           642:                mp->ftype = i;
        !           643: 
        !           644: 
        !           645:                /* convert format length to binary */
        !           646:                mp->flen = atoi(fp);
        !           647:                if (mp->flen < 0 ||
        !           648:                    mp->flen > 511 ||
        !           649:                    (mp->ftype == FLOAT && mp->flen != 4 && mp->flen != 8) ||
        !           650:                    (mp->ftype == INT && mp->flen != 1 && mp->flen != 2 && mp->flen != 4))
        !           651:                {
        !           652:                        return (error(5804, mp->paramname, --fp, 0));   /* bad length for attribute */
        !           653:                }
        !           654: 
        !           655:                /* process dummy domain if any */
        !           656:                if (Into && mp->ftype == DUMMY && mp->flen)
        !           657:                {
        !           658:                        if ((fp = dumvalue(mp->paramname)) == 0)
        !           659:                                return (5807);  /* bad dummy name */
        !           660:                        mp->rtype = *fp;        /* use first char of string */
        !           661:                }
        !           662: 
        !           663:                /* check for format of type "c0delim" on copy "into" */
        !           664:                if (Into && mp->flen == 0 && mp->fdelim != Delimitor)
        !           665:                {
        !           666:                        fp = mp->fdelim;
        !           667: 
        !           668:                        /* is there room for a dummy domain? */
        !           669:                        mp++;
        !           670:                        if (++Mapcount == MAXMAP)
        !           671:                                return (error(5803, 0));        /* no room */
        !           672: 
        !           673:                        /* create a dummy entry */
        !           674:                        mp->ftype = DUMMY;
        !           675:                        mp->flen = 1;
        !           676:                        mp->rtype = *fp;
        !           677:                        mp->roffset = mp->rlen = 0;
        !           678:                }
        !           679: 
        !           680:                mp++;
        !           681:                Mapcount++;
        !           682:        }
        !           683:        /* if no atributes were given, set flag */
        !           684:        if (Mapcount)
        !           685:                given = TRUE;
        !           686:        else
        !           687:                given = FALSE;
        !           688: 
        !           689:        /* open attribute relation and prepare for scan */
        !           690:        opencatalog("attribute", 0);
        !           691: 
        !           692:        setkey(&Attdes, &att, Des.reldum.relid, ATTRELID);
        !           693:        setkey(&Attdes, &att, Des.reldum.relowner, ATTOWNER);
        !           694: 
        !           695:        if (find(&Attdes, EXACTKEY, &tid, &limtid, &att))
        !           696:                syserr("find error for att-rel");
        !           697: 
        !           698:        /* scan Map for each relation attribute */
        !           699:        while ((i = get(&Attdes, &tid, &limtid, &att, 1)) == 0)
        !           700:        {
        !           701:                if (!bequal(&Des, &att, MAXNAME+2))
        !           702:                        continue;
        !           703:                /* if no user attributes were supplied, fake an entry */
        !           704:                if (!given)
        !           705:                {
        !           706:                        Mapcount++;
        !           707:                        mp = &Map[att.attid -1];
        !           708:                        mp->rtype = mp->ftype = att.attfrmt;
        !           709:                        mp->rlen = mp->flen = att.attfrml & 0377;
        !           710:                        mp->roffset = att.attoff;
        !           711:                        mp->used = 1;
        !           712:                        mp->paramname = mp->name;       /* point to name */
        !           713:                        bmove(att.attname, mp->name, MAXNAME);  /* copy name */
        !           714:                        continue;
        !           715:                }
        !           716:                mp = Map;
        !           717: 
        !           718:                /* check each user domain for match with relation domain */
        !           719:                for (i = Mapcount; i--;  mp++)
        !           720:                {
        !           721:                        if (mp->ftype == DUMMY)
        !           722:                                continue; /* ignore dummy */
        !           723:                        if (!bequal(mp->name, att.attname, 12))
        !           724:                                continue;
        !           725: 
        !           726:                        mp->rtype = att.attfrmt;
        !           727:                        mp->rlen = att.attfrml & 0377;
        !           728:                        mp->roffset = att.attoff;
        !           729:                        mp->used++;
        !           730: 
        !           731:                        /* check for special case of C0 in a copy "into" */
        !           732:                        if (Into && (mp->flen == 0) && mp->ftype == CHAR)
        !           733:                        {
        !           734:                                switch (mp->rtype)
        !           735:                                {
        !           736:                                  case CHAR:
        !           737:                                        mp->flen = mp->rlen;
        !           738:                                        break;
        !           739:        
        !           740:                                  case INT:
        !           741:                                        switch (mp->rlen)
        !           742:                                        {
        !           743: 
        !           744:                                          case 1:
        !           745:                                                mp->flen = Out_arg.i1width;
        !           746:                                                break;
        !           747: 
        !           748:                                          case 2:
        !           749:                                                mp->flen = Out_arg.i2width;
        !           750:                                                break;
        !           751: 
        !           752:                                          case 4:
        !           753:                                                mp->flen = Out_arg.i4width;
        !           754:                                        }
        !           755:                                        break;
        !           756:        
        !           757:                                  case FLOAT:
        !           758:                                        if (mp->rlen == 4)
        !           759:                                                mp->flen = Out_arg.f4width;
        !           760:                                        else
        !           761:                                                mp->flen = Out_arg.f8width;
        !           762:                                }
        !           763:                        }
        !           764:                        /*  if this is a copy "from" then break
        !           765:                            otherwise continue. In a copy "into"
        !           766:                            an attribute might be copied more than once */
        !           767:                        if (!Into)
        !           768:                                break;
        !           769:                }
        !           770:        }
        !           771:        if (i < 0)
        !           772:                syserr("bad get from att-rel %d", i);
        !           773: 
        !           774:        /* check that all user domains have been identified */
        !           775:        cnt = 0;
        !           776:        mp = Map;
        !           777:        for (i = Mapcount; i--; mp++)
        !           778:        {
        !           779:                cnt += mp->flen;
        !           780:                if (mp->ftype == DUMMY)
        !           781:                        continue;
        !           782:                if (!mp->used)
        !           783:                {
        !           784:                        if ( Into && bequal(mp->name,"tid           ",12) )
        !           785:                        {
        !           786:                                mp->flen = 4;
        !           787:                                mp->rtype = INT;
        !           788:                                mp->rlen = 4;
        !           789:                                mp->roffset = -1;
        !           790:                                mp->used++;
        !           791:                        }
        !           792:                        else
        !           793:                                return (error(5801, mp->paramname, Relname, 0));        /* unrecognizable domain name */
        !           794:                }
        !           795:        }
        !           796:        /* check that copy into doesn't exceed buffer size */
        !           797:        if (Into && cnt > BUFSIZ)
        !           798:                return (error(5817, 0));        /* cnt too large */
        !           799:        return (0);
        !           800: }
        !           801: /*
        !           802: **  BREAD
        !           803: */
        !           804: 
        !           805: bread(mp)
        !           806: struct map     *mp;
        !           807: {
        !           808:        register int    count,  i;
        !           809:        register char   *inp;
        !           810:        char            *dl;
        !           811:        int             esc;    /* escape flag */
        !           812: 
        !           813:        count = mp->flen;
        !           814:        inp = Inbuf;
        !           815: 
        !           816:        if (count)
        !           817:        {
        !           818:                /* block mode. read characters */
        !           819:                i = fread(inp, 1, count, File_iop);
        !           820: 
        !           821:                /* null terminate */
        !           822:                *(inp + count) = '\0';
        !           823: 
        !           824:                return (i == count);    /* true -> normal, false ->eof */
        !           825:        }
        !           826: 
        !           827:        /* string mode read */
        !           828:        /*
        !           829:        ** Determine the maximum size the C0 field being read can be.
        !           830:        ** In the case where it is being copied into a CHAR field, then
        !           831:        ** the size is that of the char field (+1 for the delimitor).
        !           832:        ** In the case of a numeric, it is limited only by the size of the
        !           833:        ** buffer area.
        !           834:        */
        !           835:        count = mp->rtype == CHAR ? mp->rlen + 1 : BUFSIZ;
        !           836:        esc = FALSE;
        !           837: 
        !           838:        for (;;)
        !           839:        {
        !           840:                if ((i = getc(File_iop)) == EOF)
        !           841:                        return (inp == Inbuf ? 0 : -1); /* -1 -> unexpected EOF, 0 -> normal EOF */
        !           842: 
        !           843:                if (count > 0)
        !           844:                {
        !           845:                        count--;
        !           846:                        *inp++ = i;
        !           847:                }
        !           848:                else
        !           849:                {
        !           850:                        if (count == 0)
        !           851:                        {
        !           852:                                /* determine type of overflow */
        !           853:                                if (mp->rtype == CHAR)
        !           854:                                {
        !           855:                                        Truncount++;
        !           856:                                        count--;        /* read until delim */
        !           857:                                }
        !           858:                                else
        !           859:                                {
        !           860:                                        return (-1);
        !           861:                                }
        !           862:                        }
        !           863:                }
        !           864:                if (esc)
        !           865:                {
        !           866:                        esc = FALSE;
        !           867:                        continue;
        !           868:                }
        !           869:                if (i == ESCAPE)
        !           870:                {
        !           871:                        esc = TRUE;
        !           872:                        /*
        !           873:                        ** If esc was stored, back it up.
        !           874:                        */
        !           875:                        if (count >= 0)
        !           876:                        {
        !           877:                                inp--;          /* remove escape char */
        !           878:                                count++;        /* restore counter */
        !           879:                        }
        !           880:                }
        !           881:                else
        !           882:                {
        !           883:                        for (dl = mp->fdelim; *dl; dl++)
        !           884:                                if (*dl == i)
        !           885:                                {
        !           886:                                        *(inp-1) = '\0';
        !           887:                                        return (1);
        !           888:                                }
        !           889:                }
        !           890:        }
        !           891: }
        !           892: /*
        !           893: **     Look for the existence of a param of the
        !           894: **     form "0nl" or "00comma" etc.
        !           895: **
        !           896: **     Returns the correct delim list or 0
        !           897: **     if there was a user error
        !           898: **
        !           899: **     If successful, a null is inserted at the
        !           900: **     rightmost '0' so the subsequent atoi will work.
        !           901: */
        !           902: 
        !           903: char *
        !           904: zcheck(param)
        !           905: char   *param;
        !           906: {
        !           907:        register char   *np, *ret;
        !           908: 
        !           909:        np = param;
        !           910:        ret = Delimitor;        /* assume default delimitors */
        !           911: 
        !           912:        if (*np++ == '0')
        !           913:        {
        !           914:                /* we have a starting zero. trim the rest */
        !           915:                while (*np == '0')
        !           916:                        np++;
        !           917: 
        !           918:                if (*np > '9' || (*np < '0' && *np >= ' '))
        !           919:                {
        !           920:                        /* we have a special delim on a 0 width field */
        !           921:                        if (ret = dumvalue(np))
        !           922:                                *(--np) = '\0'; /*
        !           923:                                                ** end string before delim
        !           924:                                                ** Do not alter delimitor but
        !           925:                                                ** instead destroy last '0'.
        !           926:                                                */
        !           927:                }
        !           928:        }
        !           929:        return (ret);
        !           930: }
        !           931: /*
        !           932: **     Search list of valid dummy names looking
        !           933: **     for 'name'. If 'name' is a single char
        !           934: **     then use just that name else it is
        !           935: **     an error if the name is not found
        !           936: */
        !           937: 
        !           938: char *
        !           939: dumvalue(name)
        !           940: char   *name;
        !           941: {
        !           942:        register char   **dp, *np, *ret;
        !           943: 
        !           944:        dp = Cpdomains; /* get list of valid dummy names */
        !           945:        np = name;
        !           946:        ret = 0;
        !           947: 
        !           948:        /* first look for a matching key word */
        !           949:        while (*dp)
        !           950:        {
        !           951:                if (sequal(np, *dp++))
        !           952:                {
        !           953:                        ret = *dp;
        !           954:                        break;
        !           955:                }
        !           956:                dp++;
        !           957:        }
        !           958: 
        !           959:        /* If single char, use that char */
        !           960:        if (length(np) == 1)
        !           961:                ret = np;       /* use first char of name */
        !           962:        if (ret == 0)
        !           963:                error(5807, np, 0);
        !           964: 
        !           965:        return (ret);
        !           966: }

unix.superglobalmegacorp.com

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