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

Defined functions

bread defined in line 778; used 1 times
charmove defined in line 516; used 1 times
copy defined in line 84; used 4 times
copydone defined in line 235; used 3 times
dumvalue defined in line 910; used 4 times
file_rel defined in line 310; used 1 times
mapfill defined in line 547; used 1 times
rel_file defined in line 262; used 1 times
transfer defined in line 366; used 2 times
zcheck defined in line 867; used 3 times

Defined variables

Baddoms defined in line 50; used 4 times
Cpdomains defined in line 53; used 1 times
Delimitor defined in line 68; used 2 times
Des defined in line 35; used 24 times
Duptuple defined in line 49; used 4 times
Filename defined in line 40; used 11 times
Inbuf defined in line 44; used 8 times
Into defined in line 42; used 8 times
Map defined in line 29; used 6 times
Mapcount defined in line 32; used 10 times
Outbuf defined in line 45; used 4 times
Piped defined in line 52; used 5 times
Relname defined in line 48; used 9 times
Truncount defined in line 51; used 4 times
Tupcount defined in line 47; used 6 times

Defined struct's

map defined in line 16; used 10 times

Defined macros

BUFSIZE defined in line 9; used 4 times
DUMMY defined in line 12; used 7 times
ESCAPE defined in line 13; used 1 times
MAXMAP defined in line 11; used 3 times
WBUFSIZE defined in line 10; never used
Last modified: 1995-02-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4702
Valid CSS Valid XHTML 1.0 Strict