Annotation of 43BSD/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: # 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.