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

unix.superglobalmegacorp.com

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