Annotation of 42BSD/ingres/source/dbu/copy.c, revision 1.1.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.