ING_DB
This commit is contained in:
parent
d86a2ba4c1
commit
9f95488636
|
|
@ -0,0 +1,52 @@
|
|||
# include <stdio.h>
|
||||
|
||||
/*
|
||||
** FGETLINE -- get line from file
|
||||
**
|
||||
** This routine reads a single newline-terminated line from
|
||||
** a file.
|
||||
**
|
||||
** Parameters:
|
||||
** buf -- the buffer in which to place the result.
|
||||
** maxch -- the maximum number of characters the
|
||||
** buffer can hold.
|
||||
** iop -- the file from which to read the characters.
|
||||
**
|
||||
** Returns:
|
||||
** 0 -- end-of-file or error.
|
||||
** else -- 'buf'.
|
||||
*/
|
||||
char *fgetline(buf, maxch, iop)
|
||||
char *buf;
|
||||
int maxch;
|
||||
register FILE *iop;
|
||||
{
|
||||
register char *p;
|
||||
register int n;
|
||||
register int c;
|
||||
|
||||
p = buf;
|
||||
|
||||
for (n = maxch; n > 0; n--)
|
||||
{
|
||||
c = getc(iop);
|
||||
|
||||
/* test for end-of-file or error */
|
||||
if (c == EOF)
|
||||
{
|
||||
*p = 0;
|
||||
return ((char *) 0);
|
||||
}
|
||||
|
||||
/* test for newline */
|
||||
if (c == '\n')
|
||||
break;
|
||||
|
||||
/* insert character into buffer */
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
/* null-terminate the string */
|
||||
*p = 0;
|
||||
return (buf);
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
|
||||
/*
|
||||
** AAsyserr -- SYStem ERRor message print and abort
|
||||
**
|
||||
** AAsyserr acts like a printf with up to five arguments.
|
||||
**
|
||||
** If the first argument to AAsyserr is not zero,
|
||||
** the error messages are prepended.
|
||||
**
|
||||
** If the extern variable 'AAproc_name' is assigned to a
|
||||
** string, that string is prepended to the message.
|
||||
**
|
||||
** All arguments must be null-terminated.
|
||||
**
|
||||
** The function pointed to by 'AAexitfn' is then called.
|
||||
** It is initialized to be 'exit'.
|
||||
*/
|
||||
|
||||
char *AAproc_name;
|
||||
int AAccerror;
|
||||
extern exit();
|
||||
int (*AAexitfn)() = exit;
|
||||
|
||||
# ifdef P8000
|
||||
AAsyserr(err, p0, p1, p2, p3, p4, p5)
|
||||
# else
|
||||
AAsyserr(err, p0)
|
||||
# endif
|
||||
register int err;
|
||||
char *p0;
|
||||
# ifdef P8000
|
||||
char *p1;
|
||||
char *p2;
|
||||
char *p3;
|
||||
char *p4;
|
||||
char *p5;
|
||||
# endif
|
||||
{
|
||||
register int exitvalue;
|
||||
char buf[256];
|
||||
extern int errno;
|
||||
extern char *AAgetformat();
|
||||
# ifndef P8000
|
||||
register char **p;
|
||||
|
||||
p = &p0;
|
||||
# endif
|
||||
exitvalue = -1;
|
||||
|
||||
putchar('\n');
|
||||
if (err)
|
||||
{
|
||||
if (AAproc_name)
|
||||
printf("%s\n", AAproc_name);
|
||||
printf("\007DB\terror\t%d\n", err);
|
||||
if (errno)
|
||||
printf("BS\terror\t%d\n", exitvalue = errno);
|
||||
if (AAccerror)
|
||||
printf("ACCESS\terror\t%d\n", AAccerror);
|
||||
# ifdef P8000
|
||||
printf(AAgetformat(err, buf), p0, p1, p2, p3, p4, p5);
|
||||
# else
|
||||
printf(AAgetformat(err, buf), p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
# ifdef P8000
|
||||
printf(p0, p1, p2, p3, p4, p5);
|
||||
# else
|
||||
printf(p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
# endif
|
||||
printf("\007\n");
|
||||
AAunlall();
|
||||
fflush(stdout);
|
||||
sync();
|
||||
(*AAexitfn)(exitvalue);
|
||||
}
|
||||
|
||||
char *AAgetformat(err, buf)
|
||||
int err;
|
||||
char *buf;
|
||||
{
|
||||
register int c;
|
||||
register char *p;
|
||||
register FILE *iop;
|
||||
short i;
|
||||
# ifdef SETBUF
|
||||
char iobufx[BUFSIZ];
|
||||
# endif
|
||||
extern char *AAerrfn();
|
||||
|
||||
/* open the appropriate error file */
|
||||
if (!(iop = fopen(AAerrfn(err / 1000), "r")))
|
||||
return ("");
|
||||
# ifdef SETBUF
|
||||
setbuf(iop, iobufx);
|
||||
# endif
|
||||
|
||||
/* read in the code and check for correct */
|
||||
for ( ; ; )
|
||||
{
|
||||
p = buf;
|
||||
while ((c = getc(iop)) != '\t')
|
||||
{
|
||||
if (c <= 0)
|
||||
/* no code exists */
|
||||
goto fmt_err;
|
||||
*p++ = c;
|
||||
}
|
||||
*p = 0;
|
||||
if (AA_atoi(buf, &i))
|
||||
goto fmt_err;
|
||||
if (i != err)
|
||||
{
|
||||
while ((c = getc(iop)) != ERRDELIM)
|
||||
if (c <= 0)
|
||||
goto fmt_err;
|
||||
getc(iop); /* throw out the newline */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* got the correct line */
|
||||
p = buf;
|
||||
while ((c = getc(iop)) != ERRDELIM)
|
||||
{
|
||||
if (c <= 0)
|
||||
{
|
||||
fmt_err:
|
||||
fclose(iop);
|
||||
return ("");
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
*p = 0;
|
||||
fclose(iop);
|
||||
return (buf);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
|
||||
/*
|
||||
** GETNUSER -- get line from user file based on name
|
||||
**
|
||||
** Given a user name as a string, this routine returns the
|
||||
** corresponding line from AA_USERS into a buffer.
|
||||
**
|
||||
** Parameters:
|
||||
** name -- the name of the user
|
||||
** buf -- a buf to dump the line in (declare as
|
||||
** char buf[MAXLINE + 1]
|
||||
**
|
||||
** Returns:
|
||||
** zero -- success
|
||||
** one -- failure (user not present)
|
||||
*/
|
||||
getnuser(name, buf)
|
||||
char *name;
|
||||
char buf[];
|
||||
{
|
||||
register int c;
|
||||
register char *bp;
|
||||
register FILE *userf;
|
||||
# ifdef SETBUF
|
||||
char userbuf[BUFSIZ];
|
||||
# endif
|
||||
|
||||
if (!(userf = fopen(AAztack(AApath, AA_USERS), "r")))
|
||||
AAsyserr(15001);
|
||||
# ifdef SETBUF
|
||||
setbuf(userf, userbuf);
|
||||
# endif
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
bp = buf;
|
||||
while ((c = getc(userf)) != '\n')
|
||||
{
|
||||
if (c == EOF)
|
||||
{
|
||||
fclose(userf);
|
||||
return (1);
|
||||
}
|
||||
*bp++ = c;
|
||||
}
|
||||
*bp++ = '\0';
|
||||
bp = buf;
|
||||
while ((c = *bp++) != ':')
|
||||
if (!c)
|
||||
{
|
||||
fclose(userf);
|
||||
return (1);
|
||||
}
|
||||
*--bp = 0;
|
||||
if (AAsequal(buf, name))
|
||||
{
|
||||
fclose(userf);
|
||||
*bp = ':';
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
# include <stdio.h>
|
||||
# include "buf.h"
|
||||
# include "gen.h"
|
||||
|
||||
static char *Buf_flat;
|
||||
|
||||
/*
|
||||
** BUFFER MANIPULATION ROUTINES
|
||||
**
|
||||
**
|
||||
**
|
||||
** BUFPUT -- put character onto buffer
|
||||
**
|
||||
** The character 'c' is put onto the buffer 'bp'. If the buffer
|
||||
** need be extended it is.
|
||||
*/
|
||||
bufput(c, bp)
|
||||
int c;
|
||||
register struct buf **bp;
|
||||
{
|
||||
register struct buf *b;
|
||||
register struct buf *a;
|
||||
extern struct buf *bufalloc();
|
||||
|
||||
if (!(b = *bp) || b->ptr >= &b->buffer[BUFSIZE])
|
||||
{
|
||||
/* allocate new buffer segment */
|
||||
a = bufalloc(sizeof (struct buf));
|
||||
a->nextb = b;
|
||||
a->ptr = a->buffer;
|
||||
*bp = b = a;
|
||||
}
|
||||
|
||||
*b->ptr++ = c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFGET -- get character off of buffer
|
||||
**
|
||||
** The buffer is popped and the character is returned. If the
|
||||
** segment is then empty, it is returned to the free list.
|
||||
*/
|
||||
bufget(bp)
|
||||
register struct buf **bp;
|
||||
{
|
||||
register struct buf *b;
|
||||
register int c;
|
||||
|
||||
if (!(b = *bp) || b->ptr == b->buffer)
|
||||
return (0); /* buffer is empty -- return end of file */
|
||||
|
||||
c = *--(b->ptr);
|
||||
|
||||
/* check to see if we have emptied the (non-initial) segment */
|
||||
if (b->ptr == b->buffer && b->nextb)
|
||||
{
|
||||
/* deallocate segment */
|
||||
*bp = b->nextb;
|
||||
buffree(b);
|
||||
}
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFPURGE -- return an entire buffer to the free list
|
||||
**
|
||||
** The buffer is emptied and returned to the free list. This
|
||||
** routine should be called when the buffer is to no longer
|
||||
** be used.
|
||||
*/
|
||||
bufpurge(bp)
|
||||
register struct buf **bp;
|
||||
{
|
||||
register struct buf *b;
|
||||
register struct buf *a;
|
||||
|
||||
b = *bp;
|
||||
*bp = (struct buf *) 0;
|
||||
|
||||
/* return the segments to the free list */
|
||||
while (b)
|
||||
{
|
||||
a = b->nextb;
|
||||
buffree(b);
|
||||
b = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFFLUSH -- flush a buffer
|
||||
**
|
||||
** The named buffer is truncated to zero length. However, the
|
||||
** segments of the buffer are not returned to the system.
|
||||
*/
|
||||
bufflush(bp)
|
||||
register struct buf **bp;
|
||||
{
|
||||
register struct buf *b;
|
||||
|
||||
if (!(b = *bp))
|
||||
return;
|
||||
|
||||
/* return second and subsequent segments to the system */
|
||||
bufpurge(&b->nextb);
|
||||
|
||||
/* truncate this buffer to zero length */
|
||||
b->ptr = b->buffer;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFCRUNCH -- flatten a series of buffers to a string
|
||||
**
|
||||
** The named buffer is flattenned to a conventional C string,
|
||||
** null terminated. The buffer is deallocated. The string is
|
||||
** allocated "somewhere" off in memory, and a pointer to it
|
||||
** is returned.
|
||||
*/
|
||||
char *bufcrunch(buffer)
|
||||
register struct buf **buffer;
|
||||
{
|
||||
register char *p;
|
||||
extern char *bufflatten();
|
||||
|
||||
p = bufflatten(*buffer, 1);
|
||||
*p = 0;
|
||||
*buffer = (struct buf *) 0;
|
||||
return (Buf_flat);
|
||||
}
|
||||
|
||||
|
||||
char *bufflatten(b, length)
|
||||
register struct buf *b;
|
||||
int length;
|
||||
{
|
||||
register char *p;
|
||||
register char *q;
|
||||
extern char *bufflatten();
|
||||
extern struct buf *bufalloc();
|
||||
|
||||
/* see if we have advanced to beginning of buffer */
|
||||
if (!b) /* yes, allocate the string */
|
||||
return (Buf_flat = (char *) bufalloc(length));
|
||||
|
||||
/* no, keep moving back */
|
||||
p = (char *) bufflatten(b->nextb, length + (b->ptr - b->buffer));
|
||||
|
||||
/* copy buffer into string */
|
||||
for (q = b->buffer; q < b->ptr; )
|
||||
*p++ = *q++;
|
||||
|
||||
/* deallocate the segment */
|
||||
buffree(b);
|
||||
|
||||
/* process next segment */
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFALLOC -- allocate clear memory
|
||||
**
|
||||
** This is similar to the system alloc routine except that
|
||||
** it has no error return, and memory is guaranteed to be clear
|
||||
** when you return.
|
||||
**
|
||||
** It might be nice to rewrite this later to avoid the nasty
|
||||
** memory fragmentation that alloc() tends toward.
|
||||
**
|
||||
** The error processing might have to be modified if used anywhere
|
||||
** other than DBS.
|
||||
*/
|
||||
struct buf *bufalloc(size)
|
||||
register int size;
|
||||
{
|
||||
register struct buf *p;
|
||||
extern int (*AAexitfn)(); /* defined in AAsyserr.c */
|
||||
extern char *malloc();
|
||||
|
||||
if (!(p = (struct buf *) malloc(size)))
|
||||
{
|
||||
printf("%sMACRO processor: Speicherueberlauf\n", ERROR);
|
||||
fflush(stdout);
|
||||
(*AAexitfn)(-1);
|
||||
}
|
||||
|
||||
bufclear(p, size);
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFCLEAR -- clear a block of core memory
|
||||
**
|
||||
** Parameters:
|
||||
** buf -- pointer to area
|
||||
** size -- size in bytes
|
||||
*/
|
||||
bufclear(buf, size)
|
||||
register char *buf;
|
||||
register int size;
|
||||
{
|
||||
register char *b;
|
||||
|
||||
for (b = &buf[size]; buf < b; )
|
||||
*buf++ = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** BUFFREE -- free memory
|
||||
*/
|
||||
buffree(ptr)
|
||||
register char *ptr;
|
||||
{
|
||||
if (!ptr)
|
||||
AAsyserr(16000);
|
||||
|
||||
free(ptr);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/bs.h"
|
||||
# include "monitor.h"
|
||||
|
||||
/*
|
||||
** CALL TEXT EDITOR
|
||||
**
|
||||
** The BS text editor is called. The actual call is to
|
||||
** the macro EDITOR. If that fails, /bin/ed is called.
|
||||
** This routine suppressed the autoclear function.
|
||||
*/
|
||||
edit()
|
||||
{
|
||||
register int i;
|
||||
register char *p;
|
||||
register char *editfile;
|
||||
extern int exit();
|
||||
extern int (*AAexitfn)();
|
||||
extern char *getfilename();
|
||||
extern char *macro();
|
||||
|
||||
editfile = getfilename();
|
||||
if (!*editfile)
|
||||
editfile = Qbname;
|
||||
|
||||
Autoclear = 0;
|
||||
fclose(Qryiop);
|
||||
|
||||
/* FORK PROCESS & INVOKE THE EDITOR */
|
||||
fflush(stdout);
|
||||
if ((Xwaitpid = fork()) < 0)
|
||||
{
|
||||
printf("CANNOT FORK\n");
|
||||
return;
|
||||
}
|
||||
if (!Xwaitpid)
|
||||
{
|
||||
AAexitfn = exit;
|
||||
setuid(getuid());
|
||||
setgid(getgid());
|
||||
for (i = 3; i < MAXFILES; i++)
|
||||
close(i);
|
||||
# ifdef MACRO
|
||||
if (!(p = macro(EDITOR)))
|
||||
# endif
|
||||
p = BIN_ED;
|
||||
if (Nodayfile >= 0)
|
||||
printf(">>%s\n", p);
|
||||
fflush(stdout);
|
||||
execlp(p, p, editfile, (char *) 0);
|
||||
if (Nodayfile >= 0)
|
||||
{
|
||||
printf("CANNOT EXEC\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* WAIT FOR PROCESS TO DIE */
|
||||
xwait();
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "monitor.h"
|
||||
|
||||
/* list of fatal signals */
|
||||
static char *Siglist[] =
|
||||
{
|
||||
"Signal 0",
|
||||
"hangup",
|
||||
"interrupt",
|
||||
"quit",
|
||||
"illegal instruction",
|
||||
"trace trap",
|
||||
"IOT instruction",
|
||||
"EMT instruction",
|
||||
"floating point exception",
|
||||
"kill",
|
||||
"bus error",
|
||||
"segmentation violation",
|
||||
"bad argument to system call",
|
||||
"write on broken pipe or link with no one to read it",
|
||||
"alarm clock",
|
||||
"software termination signal"
|
||||
};
|
||||
|
||||
/*
|
||||
** QUIT DBS
|
||||
**
|
||||
** This routine starts the death of the other processes. It
|
||||
** then prints out the logout message, and then waits for the
|
||||
** rest of the system to die. Note, however, that no relations
|
||||
** are removed; this must be done using the PURGE command.
|
||||
*/
|
||||
quit()
|
||||
{
|
||||
register int ndx;
|
||||
register int pidptr;
|
||||
register int err;
|
||||
int status;
|
||||
int pidlist[50];
|
||||
char buf[100];
|
||||
char indexx[0400];
|
||||
extern int (*AAexitfn)();
|
||||
extern exit();
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
extern char *AAcustomer();
|
||||
extern long time();
|
||||
extern char *ctime();
|
||||
|
||||
# ifdef xMTR1
|
||||
AAtTfp(1, -1, "entered QUIT\n");
|
||||
# endif
|
||||
|
||||
/* INTERCEPT ALL FURTHER INTERRUPTS */
|
||||
signal(1, (int (*)()) 1);
|
||||
signal(2, (int (*)()) 1);
|
||||
signal(3, (int (*)()) 1);
|
||||
AAexitfn = exit;
|
||||
|
||||
close(W_down);
|
||||
|
||||
# ifdef xMTR3
|
||||
AAtTfp(1, 2, "unlinking %s\n", Qbname);
|
||||
# endif
|
||||
|
||||
/* REMOVE THE QUERY-BUFFER FILE */
|
||||
fclose(Qryiop);
|
||||
unlink(Qbname);
|
||||
# ifdef MACRO
|
||||
if (Trapfile)
|
||||
fclose(Trapfile);
|
||||
# endif
|
||||
pidptr = 0;
|
||||
err = 0;
|
||||
|
||||
/* clear out the system error index table */
|
||||
for (ndx = 0; ndx < 0400; ndx++)
|
||||
indexx[ndx] = 0;
|
||||
|
||||
/* wait for all process to terminate */
|
||||
while ((ndx = wait(&status)) != -1)
|
||||
{
|
||||
# ifdef xMTR2
|
||||
AAtTfp(1, 5, "QUIT: pid %u: 0%o/0%o\n", ndx, status >> 8, status & 0177);
|
||||
# endif
|
||||
pidlist[pidptr++] = ndx;
|
||||
if (status & 0177)
|
||||
{
|
||||
printf("%u: ", ndx);
|
||||
ndx = status & 0177;
|
||||
if (ndx > sizeof Siglist / sizeof Siglist[0])
|
||||
printf("Abnormal Termination %u", ndx);
|
||||
else
|
||||
printf("%s", Siglist[ndx]);
|
||||
if (status & 0200)
|
||||
printf(" -- Core Dumped");
|
||||
putchar('\n');
|
||||
err++;
|
||||
indexx[0377 - ndx]++;
|
||||
}
|
||||
else
|
||||
indexx[(status >> 8) & 0377]++;
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
printf("pid list:");
|
||||
for (ndx = 0; ndx < pidptr; ndx++)
|
||||
printf(" %u", pidlist[ndx]);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* print index of system errors */
|
||||
err = 0;
|
||||
for (ndx = 1; ndx <= 0377; ndx++)
|
||||
{
|
||||
if (!indexx[ndx])
|
||||
continue;
|
||||
if (ndx <= sys_nerr)
|
||||
{
|
||||
if (!err)
|
||||
printf("\nBS error dictionary:\n");
|
||||
printf("%3d: %s\n", ndx, sys_errlist[ndx]);
|
||||
}
|
||||
if (!err)
|
||||
err = ndx;
|
||||
}
|
||||
if (err > 0 && err <= sys_nerr)
|
||||
putchar('\n');
|
||||
|
||||
/* PRINT LOG CUE ? */
|
||||
if (Nodayfile >= 0)
|
||||
{
|
||||
printf(LOG_1, AAversion);
|
||||
time(buf);
|
||||
# ifdef ESER_VMX
|
||||
printf("%s\n%s", AAcustomer(), ctime(*((long *) buf)));
|
||||
# else
|
||||
printf("%s\n%s", AAcustomer(), ctime(buf));
|
||||
# endif
|
||||
if (!getuser(AAusercode, buf))
|
||||
{
|
||||
for (ndx = 0; buf[ndx]; ndx++)
|
||||
if (buf[ndx] == ':')
|
||||
break;
|
||||
buf[ndx] = 0;
|
||||
printf(LOG_21, buf);
|
||||
}
|
||||
else
|
||||
printf(LOG_22);
|
||||
printf(LOG_3);
|
||||
}
|
||||
# ifdef xMTR1
|
||||
AAtTfp(1, 3, "QUIT: exit(%d)\n", err);
|
||||
# endif
|
||||
AAunlall();
|
||||
fflush(stdout);
|
||||
exit(err);
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/bs.h"
|
||||
# include "monitor.h"
|
||||
|
||||
/*
|
||||
** CALL BS SHELL
|
||||
**
|
||||
** The BS shell is called. Shell() first tries to call an
|
||||
** alternate shell defined by the macro SHELL, and if it fails
|
||||
** calls BIN_SH.
|
||||
**
|
||||
** If an argument is supplied, it is a shell file which is
|
||||
** supplied to the shell.
|
||||
*/
|
||||
shell()
|
||||
{
|
||||
register int i;
|
||||
register char *shellfile;
|
||||
register char *sh_arg;
|
||||
extern int exit();
|
||||
extern int (*AAexitfn)();
|
||||
extern char *macro();
|
||||
extern char *getfilename();
|
||||
|
||||
sh_arg = "-c";
|
||||
shellfile = getfilename();
|
||||
if (!*shellfile)
|
||||
{
|
||||
# ifdef MACRO
|
||||
if (!(shellfile = macro(SHELL)))
|
||||
# endif
|
||||
sh_arg = "-i";
|
||||
}
|
||||
|
||||
fclose(Qryiop);
|
||||
|
||||
fflush(stdout);
|
||||
if ((Xwaitpid = fork()) == -1)
|
||||
{
|
||||
printf("CANNOT FORK\n");
|
||||
return;
|
||||
}
|
||||
if (!Xwaitpid)
|
||||
{
|
||||
AAexitfn = exit;
|
||||
setuid(getuid());
|
||||
setgid(getgid());
|
||||
for (i = 3; i < MAXFILES; i++)
|
||||
close(i);
|
||||
if (Nodayfile >= 0)
|
||||
printf(">>%s\n", shellfile? shellfile: BIN_SH);
|
||||
fflush(stdout);
|
||||
execlp(BIN_SH, BIN_SH, sh_arg, shellfile, (char *) 0);
|
||||
if (Nodayfile >= 0)
|
||||
{
|
||||
printf("CANNOT EXEC\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* wait for shell to complete */
|
||||
xwait();
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "monitor.h"
|
||||
|
||||
/*
|
||||
** WRITE OUT QUERY BUFFER TO BS FILE
|
||||
**
|
||||
** The logical buffer is written to a BS file, the name of which
|
||||
** must follow the \w command.
|
||||
*/
|
||||
writeout()
|
||||
{
|
||||
register int i;
|
||||
register char *file;
|
||||
register int source;
|
||||
register int dest;
|
||||
char buf[BUFSIZ];
|
||||
extern char *getfilename();
|
||||
|
||||
file = getfilename();
|
||||
if (!*file || *file == '-')
|
||||
{
|
||||
printf("%sUnakzeptabler file name `%s'\n", ERROR, file);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dest = creat(file, 0644)) < 0)
|
||||
{
|
||||
printf("%screate WRITE file `%s'\n", ERROR, file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Nautoclear)
|
||||
Autoclear = 1;
|
||||
|
||||
if ((source = open(Qbname, 0)) < 0)
|
||||
AAsyserr(16025, Qbname);
|
||||
|
||||
fflush(Qryiop);
|
||||
|
||||
while ((i = read(source, buf, sizeof buf)) > 0)
|
||||
write(dest, buf, i);
|
||||
|
||||
close(source);
|
||||
close(dest);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/access.h"
|
||||
|
||||
/*
|
||||
** SYSTEM RELATION DESCRIPTOR CACHE DEFINITION
|
||||
**
|
||||
** *** TOOLED FOR QUERY MODIFICATION PROCESS ***
|
||||
*/
|
||||
|
||||
DESC Reldes;
|
||||
DESC Prodes;
|
||||
DESC Intdes;
|
||||
DESC Treedes;
|
||||
|
||||
struct desxx Desxx[] =
|
||||
{
|
||||
AA_REL, &Reldes, &AAdmin.adreld,
|
||||
AA_PROTECT, &Prodes, (DESC *) 0,
|
||||
AA_INTEG, &Intdes, (DESC *) 0,
|
||||
AA_TREE, &Treedes, (DESC *) 0,
|
||||
(char *) 0
|
||||
};
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/catalog.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
extern QTREE *Treeroot;
|
||||
extern DESC Reldes;
|
||||
extern struct pipfrmt Pipe;
|
||||
|
||||
/*
|
||||
** D_VIEW -- define view
|
||||
**
|
||||
** This procedure connects the tree in with the AA_REL catalog
|
||||
** and inserts the view tree into the AA_TREE catalog.
|
||||
**
|
||||
** The information in the pipe is expected to come as follows:
|
||||
** create for view, with S_VIEW bit set so that a
|
||||
** physical relation is not created.
|
||||
** define tree, which will put the translation tree
|
||||
** into the AA_TREE catalog.
|
||||
** define view, which will connect the two together.
|
||||
** The first two absolutely must be done before
|
||||
** this step can be called.
|
||||
*/
|
||||
d_view()
|
||||
{
|
||||
char viewid[MAXNAME + 1];
|
||||
|
||||
/*
|
||||
** Read parameters.
|
||||
** Only parameter is view name (which must match the
|
||||
** name of the Resultvar).
|
||||
*/
|
||||
|
||||
if (rdpipe(P_NORM, &Pipe, R_up, viewid, 0) > MAXNAME + 1)
|
||||
AAsyserr(19019);
|
||||
AApad(viewid, MAXNAME);
|
||||
|
||||
/* done with pipe... */
|
||||
rdpipe(P_SYNC, &Pipe, R_up);
|
||||
|
||||
# ifdef xQTR3
|
||||
/* do some extra validation */
|
||||
if (!Treeroot)
|
||||
AAsyserr(19020);
|
||||
if (Qmode != mdDEFINE)
|
||||
AAsyserr(19021, Qmode);
|
||||
if (Resultvar < 0)
|
||||
AAsyserr(19022, Resultvar);
|
||||
if (!Rangev[Resultvar].rused || !AAbequal(Rangev[Resultvar].relid, viewid, MAXNAME))
|
||||
AAsyserr(19023, Rangev[Resultvar].rused, Rangev[Resultvar].relid);
|
||||
# endif
|
||||
|
||||
Rangev[Resultvar].rused = FALSE;
|
||||
Resultvar = -1;
|
||||
Qmode = -1;
|
||||
|
||||
/* output tree to AA_TREE catalog */
|
||||
puttree(Treeroot, viewid, AAusercode, mdVIEW);
|
||||
|
||||
/* clear Treeroot to detect some errors */
|
||||
Treeroot = (QTREE *) 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/bs.h"
|
||||
# include "../h/catalog.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
extern struct pipfrmt Pipe;
|
||||
|
||||
/*
|
||||
** FILLPROTUP -- fill the protection tuple from pipe.
|
||||
**
|
||||
** This routine is broken off from d_prot.c so that we
|
||||
** don't get symbol table overflows.
|
||||
**
|
||||
** Parameters:
|
||||
** protup -- pointer to the protection tuple to fill.
|
||||
**
|
||||
** Returns:
|
||||
** A bool telling whether we have PERMIT ALL TO ALL
|
||||
** permission.
|
||||
**
|
||||
** Side Effects:
|
||||
** The R_up pipe is flushed.
|
||||
*/
|
||||
fillprotup(protup)
|
||||
struct protect *protup;
|
||||
{
|
||||
register struct protect *pt;
|
||||
register int i;
|
||||
register char *p;
|
||||
char buf[30];
|
||||
int all_pro;
|
||||
short ix;
|
||||
char ubuf[MAXLINE + 1];
|
||||
|
||||
/*
|
||||
** Fill in the protection tuple with the information
|
||||
** from the parser, validating as we go.
|
||||
**
|
||||
** Also, determine if we have a PERMIT xx to ALL
|
||||
** with no further qualification case. The variable
|
||||
** 'all_pro' is set to reflect this.
|
||||
*/
|
||||
|
||||
all_pro = TRUE;
|
||||
pt = protup;
|
||||
|
||||
/* read operation set */
|
||||
if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) <= 0)
|
||||
AAsyserr(19030);
|
||||
if (AA_atoi(buf, &ix))
|
||||
AAsyserr(19031, buf);
|
||||
pt->proopset = ix;
|
||||
if ((ctoi(pt->proopset) & PRO_RETR) != 0)
|
||||
pt->proopset |= PRO_TEST | PRO_AGGR;
|
||||
|
||||
/* read relation name */
|
||||
if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) > MAXNAME + 1)
|
||||
AAsyserr(19032);
|
||||
AApmove(buf, pt->prorelid, MAXNAME, ' ');
|
||||
|
||||
/* read relation owner */
|
||||
if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) != 3)
|
||||
AAsyserr(19033);
|
||||
AAbmove(buf, pt->prorelown, 2);
|
||||
|
||||
/* read user name */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
if (AAsequal(buf, "all"))
|
||||
AAbmove(" ", pt->prouser, 2);
|
||||
else
|
||||
{
|
||||
/* look up user in AA_USERS */
|
||||
if (getnuser(buf, ubuf))
|
||||
far_error(3591, -1, Resultvar, buf, (char *) 0);
|
||||
for (p = ubuf; *p != ':' && *p != 0; p++)
|
||||
continue;
|
||||
AAbmove(++p, pt->prouser, 2);
|
||||
if (p[0] == ':' || p[1] == ':' || p[2] != ':')
|
||||
AAsyserr(19034, ubuf);
|
||||
all_pro = FALSE;
|
||||
}
|
||||
|
||||
/* read terminal id */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
if (AAsequal(buf, "all"))
|
||||
{
|
||||
AAbmove(" ", pt->proterm, PROTERM);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AAbequal(buf, "tty", 3))
|
||||
AApmove(&buf[3], pt->proterm, PROTERM, ' ');
|
||||
else
|
||||
AApmove(buf, pt->proterm, PROTERM, ' ');
|
||||
all_pro = FALSE;
|
||||
}
|
||||
|
||||
/* read starting time of day */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
if (AA_atoi(buf, &ix))
|
||||
AAsyserr(19035, buf);
|
||||
pt->protodbgn = ix;
|
||||
if (ix > 0)
|
||||
all_pro = FALSE;
|
||||
|
||||
/* read ending time of day */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
if (AA_atoi(buf, &ix))
|
||||
AAsyserr(19036, buf);
|
||||
pt->protodend = ix;
|
||||
if (ix < 24 * 60 - 1)
|
||||
all_pro = FALSE;
|
||||
|
||||
/* read beginning day of week */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
i = cvt_dow(buf);
|
||||
if (i < 0)
|
||||
far_error(3594, -1, Resultvar, buf, (char *) 0); /* bad dow */
|
||||
pt->prodowbgn = i;
|
||||
if (i > 0)
|
||||
all_pro = FALSE;
|
||||
|
||||
/* read ending day of week */
|
||||
rdpipe(P_NORM, &Pipe, R_up, buf, 0);
|
||||
i = cvt_dow(buf);
|
||||
if (i < 0)
|
||||
far_error(3594, -1, Resultvar, buf, (char *) 0); /* bad dow */
|
||||
pt->prodowend = i;
|
||||
if (i < 6)
|
||||
all_pro = FALSE;
|
||||
|
||||
/* finished with pipe... */
|
||||
rdpipe(P_SYNC, &Pipe, R_up);
|
||||
|
||||
return (all_pro);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/tree.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** QRYMOD -- main driver for query modification
|
||||
**
|
||||
** Reads in the query tree, performs the modifications, writes
|
||||
** it out, and does process syncronization with below. The
|
||||
** calling routine must sync with the process above.
|
||||
**
|
||||
** Parameters:
|
||||
** root1 -- a pointer to the tree to modify.
|
||||
**
|
||||
** Returns:
|
||||
** A pointer to the modified tree.
|
||||
*/
|
||||
QTREE *qrymod(root1)
|
||||
QTREE *root1;
|
||||
{
|
||||
register QTREE *root;
|
||||
extern QTREE *view();
|
||||
extern QTREE *integrity();
|
||||
extern QTREE *protect();
|
||||
|
||||
root = root1;
|
||||
|
||||
# ifdef xQTR1
|
||||
if (AAtTf(1, 0))
|
||||
treepr(root, "->QRYMOD");
|
||||
# endif
|
||||
|
||||
/* view processing */
|
||||
root = view(root);
|
||||
|
||||
/* integrity processing */
|
||||
root = integrity(root);
|
||||
|
||||
/* protection processing */
|
||||
root = protect(root);
|
||||
|
||||
return (root);
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** RANGE.C -- range table manipulation
|
||||
**
|
||||
** Defines:
|
||||
** declare -- declare variable
|
||||
** clrrange -- clear range table
|
||||
** mapvars -- map varno's in a tree to unique numbers
|
||||
** Remap[] -- a mapping from specified (preferred) varno's
|
||||
** to actual varno's. -1 indicates no mapping.
|
||||
** Presumably this cannot be set when reading an
|
||||
** original query tree, but can happen easily when
|
||||
** reading a tree from AA_TREE catalog.
|
||||
** Rangev[] -- the range table.
|
||||
*/
|
||||
|
||||
int Remap[MAXVAR + 1];
|
||||
struct rngtab Rangev[MAXVAR + 1];
|
||||
|
||||
/*
|
||||
** CLRRANGE -- clear range table(s)
|
||||
**
|
||||
** The range table (Rangev) and range table map (Remap) are
|
||||
** initialized in one of two ways.
|
||||
**
|
||||
** Parameters:
|
||||
** prim -- if TRUE, the primary range table (Rangev)
|
||||
** is cleared and Remap is set to be FULL (for
|
||||
** reading in an initial query). If FALSE,
|
||||
** Rangev is untouched, but Remap is cleared.
|
||||
**
|
||||
** Side Effects:
|
||||
** Rangev[i].rused set to FALSE for all entries.
|
||||
** Remap[i] set to -1 or MAXVAR + 1 for all entries.
|
||||
*/
|
||||
clrrange(prim)
|
||||
register int prim;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < MAXVAR + 1; i++)
|
||||
{
|
||||
if (prim)
|
||||
{
|
||||
Rangev[i].rused = FALSE;
|
||||
Remap[i] = MAXVAR + 1;
|
||||
}
|
||||
else
|
||||
Remap[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** DECLARE -- declare a range variable
|
||||
**
|
||||
** A range variable is declared. If possible, the preferred varno
|
||||
** stated is used (this is the one already in the tree). This
|
||||
** should always be possible when reading the original tree (and
|
||||
** should probably stay this way to make debugging easier). When
|
||||
** not possible, a new varno is chosen, and Remap[oldvarno] is
|
||||
** set to newvarno, so that the tree can later be patched up by
|
||||
** 'mapvars' (below).
|
||||
**
|
||||
** Parameters:
|
||||
** varno -- the preferred varno.
|
||||
** name -- the relation name.
|
||||
** stat -- the 'relstat' of this relation.
|
||||
**
|
||||
** Side Effects:
|
||||
** Rangev and possible Remap are updated. No Rangev
|
||||
** entry is ever touched if the 'rused' field
|
||||
** is set.
|
||||
*/
|
||||
declare(varno, name, owner, stat)
|
||||
int varno;
|
||||
char *name;
|
||||
char owner[2];
|
||||
int stat;
|
||||
{
|
||||
register int i;
|
||||
register int vn;
|
||||
register int s;
|
||||
|
||||
vn = varno;
|
||||
s = stat;
|
||||
|
||||
/* check for preferred slot in range table available */
|
||||
if (Rangev[vn].rused)
|
||||
{
|
||||
/* used: check if really redeclared */
|
||||
if (Remap[vn] >= 0)
|
||||
AAsyserr(19047, vn);
|
||||
|
||||
/* try to find another slot */
|
||||
for (i = 0; i < MAXVAR + 1; i++)
|
||||
if (!Rangev[i].rused)
|
||||
break;
|
||||
|
||||
if (i >= MAXVAR + 1)
|
||||
{
|
||||
far_error(3100, Qmode, -1, name, (char *) 0); /* too many variables */
|
||||
}
|
||||
|
||||
Remap[vn] = i;
|
||||
vn = i;
|
||||
}
|
||||
|
||||
/* declare variable in the guaranteed empty slot */
|
||||
AAbmove(name, Rangev[vn].relid, MAXNAME);
|
||||
AAbmove(owner, Rangev[vn].rowner, 2);
|
||||
Rangev[vn].rstat = s;
|
||||
Rangev[vn].rused = TRUE;
|
||||
|
||||
# ifdef xQTR2
|
||||
AAtTfp(11, 0, "DECLARE: %d, %.12s, %.2s, 0%o into slot %d\n",
|
||||
varno, name, owner, s, vn);
|
||||
# endif
|
||||
# ifdef xQTR3
|
||||
AAtTfp(11, 1, "DECLARE: %.12s%.2s 0%o %d\n", Rangev[vn].relid,
|
||||
Rangev[vn].rowner, Rangev[vn].rstat, Rangev[vn].rused);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** MAPVARS -- remap varno's to be unique in AA_TREE tree
|
||||
**
|
||||
** A tree is scanned for VAR nodes; when found, the
|
||||
** mapping defined in Remap[] is applied. This is done so that
|
||||
** varno's as defined in trees in the AA_TREE catalog will be
|
||||
** unique with respect to varno's in the user's query tree. For
|
||||
** example, if the view definition uses variable 1 and the user's
|
||||
** query also uses variable 1, the routine 'declare' will (when
|
||||
** called to define the view definition varno 1) allocate a new
|
||||
** varno (e.g. 3) in a free slot in the range table, and put
|
||||
** the index of the new slot into the corresponding word of Remap;
|
||||
** in this example, Remap[1] == 3. This routine does the actual
|
||||
** mapping in the tree.
|
||||
**
|
||||
** Parameters:
|
||||
** tree -- pointer to tree to be remapped.
|
||||
**
|
||||
** Side Effects:
|
||||
** the tree pointed to by 'tree' is modified according
|
||||
** to Remap[].
|
||||
*/
|
||||
mapvars(tree)
|
||||
QTREE *tree;
|
||||
{
|
||||
register QTREE *t;
|
||||
register int i;
|
||||
|
||||
t = tree;
|
||||
# ifdef xQTR3
|
||||
if (AAtTf(12, 0) && t != NULL && t->sym.type == ROOT)
|
||||
{
|
||||
treepr(t, "mapvars:");
|
||||
for (i = 0; i < MAXVAR + 1; i++)
|
||||
if (Rangev[i].rused && Remap[i] >= 0)
|
||||
printf("\t%d => %d\n", i, Remap[i]);
|
||||
}
|
||||
# endif
|
||||
|
||||
while (t != NULL)
|
||||
{
|
||||
/* map right subtree */
|
||||
mapvars(t->right);
|
||||
|
||||
/* check this node */
|
||||
if (t->sym.type == VAR)
|
||||
{
|
||||
i = ((VAR_NODE *) t)->varno;
|
||||
if ((i = Remap[i]) >= 0)
|
||||
((VAR_NODE *) t)->varno = i;
|
||||
}
|
||||
|
||||
/* map left subtree (iteratively) */
|
||||
t = t->left;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/catalog.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** READTREE.C -- query tree input procedures
|
||||
**
|
||||
** This file contains routines to read trees from pipes and
|
||||
** catalogs.
|
||||
**
|
||||
** Defines:
|
||||
** readqry
|
||||
** readsymbol
|
||||
** readtree
|
||||
** pipetrrd
|
||||
** relntrrd
|
||||
** gettree
|
||||
** Qmode
|
||||
** Resultvar
|
||||
*/
|
||||
|
||||
extern struct pipfrmt Pipe;
|
||||
extern struct pipfrmt Outpipe;
|
||||
|
||||
int Qmode; /* Query mode */
|
||||
int Resultvar; /* Result variable number */
|
||||
|
||||
/*
|
||||
** READQRY
|
||||
**
|
||||
** Reads in query symbols from input pipe into core
|
||||
** locations and sets up information needed for later
|
||||
** processing.
|
||||
**
|
||||
** Returns ptr to root of querytree
|
||||
**
|
||||
** Locbuf is a 'struct srcid' since that is the largest node of
|
||||
** a QMODE, SOURCEID, or RESULTVAR node.
|
||||
*/
|
||||
QTREE *readqry(rdfn, initialize)
|
||||
int (*rdfn)(); /* tree read function */
|
||||
int initialize; /* if set, initialize Qbuf */
|
||||
{
|
||||
register SYMBOL *s;
|
||||
SRCID locbuf;
|
||||
register QTREE *rtval;
|
||||
register char *p;
|
||||
extern xerror();
|
||||
extern char *readtree();
|
||||
extern QTREE *trbuild();
|
||||
|
||||
# ifdef xQTR1
|
||||
AAtTfp(70, 0, "READQRY:\n");
|
||||
# endif
|
||||
|
||||
if (initialize)
|
||||
{
|
||||
/* initialize for new query block */
|
||||
initbuf(Qbuf, QBUFSIZ, QBUFFULL, xerror);
|
||||
clrrange(TRUE);
|
||||
Resultvar = -1;
|
||||
Qmode = -1;
|
||||
}
|
||||
else
|
||||
clrrange(FALSE);
|
||||
|
||||
s = (SYMBOL *) &locbuf;
|
||||
|
||||
/* read symbols from input */
|
||||
for ( ; ; )
|
||||
{
|
||||
readsymbol(s, rdfn);
|
||||
# ifdef xQTR1
|
||||
if (AAtTfp(70, 1, "%d, %d, %d/",
|
||||
s->type, s->len, ctou(s->value[0])))
|
||||
{
|
||||
if (s->type == SOURCEID)
|
||||
printf("%.12s", ((SRCID *) s)->srcname);
|
||||
putchar('\n');
|
||||
}
|
||||
# endif
|
||||
switch (s->type)
|
||||
{
|
||||
case QMODE:
|
||||
if (Qmode != -1)
|
||||
AAsyserr(19048);
|
||||
Qmode = s->value[0];
|
||||
break;
|
||||
|
||||
case RESULTVAR:
|
||||
if (Resultvar != -1)
|
||||
AAsyserr(19049);
|
||||
Resultvar = s->value[0];
|
||||
break;
|
||||
|
||||
case SOURCEID:
|
||||
declare(((SRCID *) s)->srcvar, ((SRCID *) s)->srcname, ((SRCID *) s)->srcown, ((SRCID *) s)->srcstat);
|
||||
break;
|
||||
|
||||
case TREE: /* beginning of tree, no more other stuff */
|
||||
p = readtree(s, rdfn);
|
||||
rtval = trbuild(p);
|
||||
if (!rtval)
|
||||
far_error(STACKFULL, -1, -1, (char *) 0);
|
||||
return (rtval);
|
||||
|
||||
default:
|
||||
AAsyserr(19050, s->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** READSYMBOL
|
||||
** reads in one symbol from pipe into symbol struct.
|
||||
*/
|
||||
readsymbol(dest, rdfn)
|
||||
char *dest; /* if non-zero, pts to allocated space */
|
||||
int (*rdfn)(); /* tree read function */
|
||||
{
|
||||
register int len;
|
||||
register SYMBOL *p;
|
||||
extern char *need();
|
||||
|
||||
/* check if enough space for type and len of sym */
|
||||
p = (SYMBOL *) (dest? dest: need(Qbuf, SYM_HDR_SIZ));
|
||||
if ((*rdfn)(p, TYP_LEN_SIZ) < TYP_LEN_SIZ)
|
||||
goto err3;
|
||||
len = ctou(p->len);
|
||||
if (len)
|
||||
{
|
||||
if (!dest)
|
||||
{
|
||||
/* this will be contiguous with above need call */
|
||||
need(Qbuf, len);
|
||||
}
|
||||
if ((*rdfn)(p->value, len) < len)
|
||||
goto err3;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err3:
|
||||
AAsyserr(19051);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** READTREE
|
||||
** reads in tree symbols into a buffer up to a root (end) symbol
|
||||
*/
|
||||
char *readtree(tresym, rdfn)
|
||||
SYMBOL *tresym;
|
||||
int (*rdfn)();
|
||||
{
|
||||
register QTREE *nod;
|
||||
register char *rtval;
|
||||
extern char *need();
|
||||
|
||||
rtval = need(Qbuf, QT_HDR_SIZ);
|
||||
AAbmove(tresym, &(((QTREE *) rtval)->sym), TYP_LEN_SIZ); /* insert type and len of TREE node */
|
||||
for ( ; ; )
|
||||
{
|
||||
/* space for left & right pointers */
|
||||
nod = (QTREE *) need(Qbuf, QT_PTR_SIZ);
|
||||
readsymbol((char *) 0, rdfn);
|
||||
# ifdef xQTR1
|
||||
if (AAtTf(70, 2))
|
||||
nodepr(nod, TRUE);
|
||||
# endif
|
||||
if (nod->sym.type == ROOT)
|
||||
return (rtval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** PIPETRRD -- read tree from R_up pipe
|
||||
**
|
||||
** This routine looks like a rdpipe with only the last two
|
||||
** parameters.
|
||||
**
|
||||
** Parameters:
|
||||
** ptr -- pointer to data area
|
||||
** cnt -- byte count
|
||||
**
|
||||
** Returns:
|
||||
** actual number of bytes read
|
||||
*/
|
||||
pipetrrd(ptr, cnt)
|
||||
register char *ptr;
|
||||
register int cnt;
|
||||
{
|
||||
return (rdpipe(P_NORM, &Pipe, R_up, ptr, cnt));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** RELNTRRD -- read tree from AA_TREE relation
|
||||
**
|
||||
** This looks exactly like the 'pipetrrd' call, except that info
|
||||
** comes from the AA_TREE catalog instead of from the pipe. It
|
||||
** must be initialized by calling it with a NULL pointer and
|
||||
** the segment name wanted as 'treeid'.
|
||||
**
|
||||
** Parameters:
|
||||
** ptr -- NULL -- "initialize".
|
||||
** else -- pointer to read area.
|
||||
** cnt -- count of number of bytes to read.
|
||||
** treeid -- if ptr == NULL, this is the tree id,
|
||||
** otherwise this parameter is not supplied.
|
||||
**
|
||||
** Returns:
|
||||
** count of actual number of bytes read.
|
||||
**
|
||||
** Side Effects:
|
||||
** static variables are adjusted correctly. Note that
|
||||
** this routine can be used on only one tree
|
||||
** at one time.
|
||||
*/
|
||||
relntrrd(ptr, cnt, treerelid, treeowner, treetype, treeid)
|
||||
char *ptr;
|
||||
int cnt;
|
||||
char *treerelid;
|
||||
char *treeowner;
|
||||
char treetype;
|
||||
int treeid;
|
||||
{
|
||||
static struct tree trseg;
|
||||
static char *trp;
|
||||
static short seqno;
|
||||
register char *p;
|
||||
register int n;
|
||||
register int i;
|
||||
struct tree trkey;
|
||||
struct tup_id tid;
|
||||
|
||||
p = ptr;
|
||||
n = cnt;
|
||||
|
||||
if (!p)
|
||||
{
|
||||
/* initialize -- make buffer appear empty */
|
||||
trp = &trseg.treetree[sizeof trseg.treetree];
|
||||
AAbmove(treerelid, trseg.treerelid, MAXNAME);
|
||||
AAbmove(treeowner, trseg.treeowner, 2);
|
||||
trseg.treetype = treetype;
|
||||
trseg.treeid = treeid;
|
||||
seqno = 0;
|
||||
opencatalog(AA_TREE, 0);
|
||||
|
||||
# ifdef xQTR2
|
||||
AAtTfp(70, 6, "RELNTRRD: n=%.12s o=%.2s t=%d i=%d\n",
|
||||
treerelid, treeowner, treetype, treeid);
|
||||
# endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* fetch characters */
|
||||
while (n-- > 0)
|
||||
{
|
||||
/* check for segment empty */
|
||||
if (trp >= &trseg.treetree[sizeof trseg.treetree])
|
||||
{
|
||||
/* then read new segment */
|
||||
AAam_clearkeys(&Treedes);
|
||||
AAam_setkey(&Treedes, &trkey, trseg.treerelid, TREERELID);
|
||||
AAam_setkey(&Treedes, &trkey, trseg.treeowner, TREEOWNER);
|
||||
AAam_setkey(&Treedes, &trkey, &trseg.treetype, TREETYPE);
|
||||
AAam_setkey(&Treedes, &trkey, &trseg.treeid, TREEID);
|
||||
AAam_setkey(&Treedes, &trkey, &seqno, TREESEQ);
|
||||
seqno++;
|
||||
if (i = AAgetequal(&Treedes, &trkey, &trseg, &tid))
|
||||
AAsyserr(19052, i);
|
||||
trp = &trseg.treetree[0];
|
||||
}
|
||||
|
||||
/* do actual character fetch */
|
||||
*p++ = *trp++;
|
||||
}
|
||||
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GETTREE -- get tree from AA_TREE catalog
|
||||
**
|
||||
** This function, given an internal treeid, fetches and builds
|
||||
** that tree from the AA_TREE catalog. There is nothing exciting
|
||||
** except the mapping of variables, done by mapvars().
|
||||
**
|
||||
** Parameters:
|
||||
** treeid -- internal id of tree to fetch and build.
|
||||
** init -- passed to 'readqry' to tell whether or not
|
||||
** to initialize the query buffer.
|
||||
**
|
||||
** Returns:
|
||||
** Pointer to root of tree.
|
||||
*/
|
||||
QTREE *gettree(treerelid, treeowner, treetype, treeid, init)
|
||||
char *treerelid;
|
||||
char *treeowner;
|
||||
char treetype;
|
||||
int treeid;
|
||||
int init;
|
||||
{
|
||||
register QTREE *t;
|
||||
extern int relntrrd();
|
||||
|
||||
/* initialize relntrrd() for this treeid */
|
||||
relntrrd(NULL, 0, treerelid, treeowner, treetype, treeid);
|
||||
|
||||
/* read and build query tree */
|
||||
t = readqry(relntrrd, init);
|
||||
|
||||
/* remap varno's to be unique */
|
||||
if (!init)
|
||||
mapvars(t);
|
||||
|
||||
return (t);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** TREE -- create new tree node.
|
||||
**
|
||||
** This is a stripped down version of the same thing in the
|
||||
** parser.
|
||||
**
|
||||
** It only knows about lengths of zero and two.
|
||||
**
|
||||
** Parameters:
|
||||
** lptr -- the left pointer.
|
||||
** rptr -- the right pointer.
|
||||
** typ -- the node type.
|
||||
** len -- the node length.
|
||||
** value -- the node value.
|
||||
**
|
||||
** Returns:
|
||||
** A pointer to the created node.
|
||||
*/
|
||||
QTREE *tree(lptr, rptr, typ, len, value)
|
||||
QTREE *lptr;
|
||||
QTREE *rptr;
|
||||
char typ;
|
||||
int len;
|
||||
int value;
|
||||
{
|
||||
register QTREE *tptr;
|
||||
extern char *need();
|
||||
register int l;
|
||||
|
||||
l = len;
|
||||
|
||||
tptr = (QTREE *) need(Qbuf, l + QT_HDR_SIZ);
|
||||
tptr->left = lptr;
|
||||
tptr->right = rptr;
|
||||
tptr->sym.type = typ;
|
||||
tptr->sym.len = l;
|
||||
|
||||
if (l > 0)
|
||||
tptr->sym.value[0] = value;
|
||||
return (tptr);
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/aux.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** TREEPR -- print tree for debugging
|
||||
**
|
||||
** This module prints a tree for debugging purposes. There are
|
||||
** two interfaces: treepr prints an entire treeree, and nodepr
|
||||
** prints a single node.
|
||||
**
|
||||
** Defines:
|
||||
** treepr -- tree print interface.
|
||||
** rcsvtrpr -- the recursive part to traverse the tree.
|
||||
** nodepr -- node print interface.
|
||||
*/
|
||||
|
||||
extern char *Qmdname[]; /* defined in util.c */
|
||||
|
||||
/*
|
||||
** TREEPR -- print tree for debugging
|
||||
**
|
||||
** This routine prints a tree for debugging.
|
||||
**
|
||||
** Parameters:
|
||||
** t -- root of tree to be printed
|
||||
** label -- label to print for identifying the tree. NULL
|
||||
** is OK and produces a default label.
|
||||
*/
|
||||
treepr(tree, label)
|
||||
register QTREE *tree;
|
||||
register char *label;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* print label */
|
||||
putchar('\n');
|
||||
if (label != (char *) 0)
|
||||
printf("%s ", label);
|
||||
printf("Querytree @ 0%o:\n", tree);
|
||||
|
||||
/* print range table */
|
||||
for (i = 0; i < MAXVAR + 1; i++)
|
||||
{
|
||||
if (!Rangev[i].rused)
|
||||
continue;
|
||||
printf("range of %d is %.12s [O=%.2s, S=0%o]\n",
|
||||
i, Rangev[i].relid, Rangev[i].rowner, Rangev[i].rstat);
|
||||
}
|
||||
|
||||
/* print query type */
|
||||
if (Qmode >= 0)
|
||||
printf("%s ", Qmdname[Qmode]);
|
||||
|
||||
/* print result relation if realistic */
|
||||
if (Resultvar >= 0)
|
||||
printf("Resultvar %d ", Resultvar);
|
||||
putchar('\n');
|
||||
|
||||
/* print tree */
|
||||
rcsvtrpr(tree);
|
||||
|
||||
/* print exciting final stuff */
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** RCSVTRPR -- traverse and print tree
|
||||
**
|
||||
** This function does the real stuff for treepr. It recursively
|
||||
** traverses the tree in postfix order, printing each node.
|
||||
**
|
||||
** Parameters:
|
||||
** tree -- the root of the tree to print.
|
||||
*/
|
||||
rcsvtrpr(tree)
|
||||
register QTREE *tree;
|
||||
{
|
||||
while (tree != (QTREE *) 0)
|
||||
{
|
||||
rcsvtrpr(tree->left);
|
||||
nodepr(tree, FALSE);
|
||||
tree = tree->right;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** NODEPR -- print node for debugging
|
||||
**
|
||||
** Parameters:
|
||||
** tree -- the node to print.
|
||||
*/
|
||||
nodepr(tree)
|
||||
register QTREE *tree;
|
||||
{
|
||||
register int ty;
|
||||
register int l;
|
||||
register char *cp;
|
||||
|
||||
ty = tree->sym.type;
|
||||
l = ctou(tree->sym.len);
|
||||
|
||||
printf("0%o: 0%o, 0%o/ ", tree, tree->left, tree->right);
|
||||
printf("%d, %d: ", ty, l);
|
||||
|
||||
switch (ty)
|
||||
{
|
||||
case VAR:
|
||||
printf("%d.%d [%d/%d]",
|
||||
((VAR_NODE *) tree)->varno, ((VAR_NODE *) tree)->attno,
|
||||
((VAR_NODE *) tree)->frmt, ctou(((VAR_NODE *) tree)->frml));
|
||||
break;
|
||||
|
||||
case RESDOM:
|
||||
printf("%d [%d/%d]", ((RES_NODE *) tree)->resno,
|
||||
((VAR_NODE *) tree)->frmt, ((VAR_NODE *) tree)->frml);
|
||||
break;
|
||||
|
||||
case AOP:
|
||||
printf("%d [%d/%d] [%d/%d]", ((RES_NODE *) tree)->resno,
|
||||
((VAR_NODE *) tree)->frmt, ((VAR_NODE *) tree)->frml,
|
||||
((AOP_NODE *) tree)->agfrmt, ((AOP_NODE *) tree)->agfrml);
|
||||
break;
|
||||
|
||||
case UOP:
|
||||
case BOP:
|
||||
case COP:
|
||||
case INT:
|
||||
switch (tree->sym.len)
|
||||
{
|
||||
case sizeof (char):
|
||||
case sizeof (short):
|
||||
printf("%d", tree->sym.value[0]);
|
||||
break;
|
||||
|
||||
case sizeof (long):
|
||||
printf("%ld", ((I4TYPE *) tree->sym.value)->i4type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
printf("%.10f", ((I4TYPE *) tree->sym.value)->i4type);
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
cp = (char *) tree->sym.value;
|
||||
while (l--)
|
||||
{
|
||||
putchar(*cp);
|
||||
cp++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TREE:
|
||||
case AND:
|
||||
case OR:
|
||||
case QLEND:
|
||||
case BYHEAD:
|
||||
case ROOT:
|
||||
case AGHEAD:
|
||||
break;
|
||||
|
||||
default:
|
||||
AAsyserr(19053, ty);
|
||||
}
|
||||
printf("/\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "qrymod.h"
|
||||
|
||||
/*
|
||||
** WRITETREE.C -- query tree output routines
|
||||
**
|
||||
** These routines write out a query tree in internal format.
|
||||
**
|
||||
** Defines:
|
||||
** writetree
|
||||
** writeqry
|
||||
** writesym
|
||||
*/
|
||||
|
||||
extern struct pipfrmt Pipe;
|
||||
extern struct pipfrmt Outpipe;
|
||||
|
||||
/*
|
||||
** WRITETREE -- write a query tree
|
||||
**
|
||||
** A query tree is written to the down pipe. The parameter is
|
||||
** the root of the tree to be written.
|
||||
**
|
||||
** Parameters:
|
||||
** q1 -- the root of the tree to write.
|
||||
** wrfn -- the function to call to do physical
|
||||
** writes.
|
||||
*/
|
||||
writetree(q1, wrfn)
|
||||
QTREE *q1;
|
||||
int (*wrfn)();
|
||||
{
|
||||
register QTREE *q;
|
||||
register int l;
|
||||
register char t;
|
||||
|
||||
q = q1;
|
||||
|
||||
/* write the subtrees */
|
||||
if (q->left != NULL)
|
||||
writetree(q->left, wrfn);
|
||||
if (q->right != NULL)
|
||||
writetree(q->right, wrfn);
|
||||
|
||||
/* write this node */
|
||||
t = q->sym.type;
|
||||
if (t == AND || t == ROOT || t == AGHEAD)
|
||||
q->sym.len = 0;
|
||||
(*wrfn)(&(q->sym), TYP_LEN_SIZ);
|
||||
if (l = ctou(q->sym.len))
|
||||
(*wrfn)(q->sym.value, l);
|
||||
# ifdef xQTR1
|
||||
if (AAtTf(70, 5))
|
||||
nodepr(q, TRUE);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** WRITEQRY -- write a whole query
|
||||
**
|
||||
** An entire query is written, including range table, and so
|
||||
** forth.
|
||||
**
|
||||
** Parameters:
|
||||
** root -- the root of the tree to write.
|
||||
** wrfn -- the function to do the physical write.
|
||||
*/
|
||||
writeqry(root, wrfn)
|
||||
QTREE *root;
|
||||
int (*wrfn)();
|
||||
{
|
||||
register int i;
|
||||
short resvar;
|
||||
SRCID sid;
|
||||
|
||||
/* write the query mode */
|
||||
if (Qmode >= 0)
|
||||
{
|
||||
resvar = Qmode;
|
||||
writesym(QMODE, sizeof (short), &resvar, wrfn);
|
||||
}
|
||||
|
||||
/* write the range table */
|
||||
for (i = 0; i < MAXVAR + 1; i++)
|
||||
{
|
||||
if (Rangev[i].rused)
|
||||
{
|
||||
((SYMBOL *) &sid)->type = SOURCEID;
|
||||
((SYMBOL *) &sid)->len = SRC_SIZ;
|
||||
AApmove(Rangev[i].relid, sid.srcname, MAXNAME, ' ');
|
||||
sid.srcvar = i;
|
||||
sid.srcstat = Rangev[i].rstat;
|
||||
AAbmove(Rangev[i].rowner, sid.srcown, 2);
|
||||
(*wrfn)(&sid, TYP_LEN_SIZ);
|
||||
(*wrfn)(&sid.srcvar, SRC_SIZ);
|
||||
}
|
||||
}
|
||||
|
||||
/* write a possible result variable */
|
||||
if (Resultvar >= 0)
|
||||
{
|
||||
resvar = Resultvar;
|
||||
writesym(RESULTVAR, sizeof (short), &resvar, wrfn);
|
||||
}
|
||||
|
||||
/* write the tree */
|
||||
writetree(root, wrfn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** WRITESYM -- write a symbol block
|
||||
**
|
||||
** A single symbol entry of the is written.
|
||||
** a 'value' of zero will not be written.
|
||||
*/
|
||||
writesym(typ, len, value, wrfn)
|
||||
int typ;
|
||||
int len;
|
||||
char *value;
|
||||
int (*wrfn)();
|
||||
{
|
||||
SYMBOL sym;
|
||||
register char *v;
|
||||
register int l;
|
||||
|
||||
sym.type = ctou(typ);
|
||||
sym.len = l = ctou(len);
|
||||
(*wrfn)(&sym, TYP_LEN_SIZ);
|
||||
v = value;
|
||||
if (v != 0)
|
||||
(*wrfn)(v, l);
|
||||
}
|
||||
Loading…
Reference in New Issue