Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/* POSIX DEPENDENT PROCEDURES */
#include "defs.h"
#include <sys/stat.h>
#include <ar.h>

#define NAMESPERBLOCK   32

/* DEFAULT RULES FOR POSIX */

char *dfltmacro[] =
        {
        ".SUFFIXES : .o .c .y .l .a .sh .f",
        "MAKE=make",
        "AR=ar",
        "ARFLAGS=rv",
        "YACC=yacc",
        "YFLAGS=",
        "LEX=lex",
        "LFLAGS=",
        "LDFLAGS=",
        "CC=c89",
        "CFLAGS=-O",
        "FC=fort77",
        "FFLAGS=-O 1",
        0 };

char *dfltpat[] =
        {
        "%.o : %.c",
        "\t$(CC) $(CFLAGS) -c $<",

        "%.o : %.y",
        "\t$(YACC) $(YFLAGS) $<",
        "\t$(CC) $(CFLAGS) -c y.tab.c",
        "\trm y.tab.c",
        "\tmv y.tab.o $@",

        "%.o : %.l",
        "\t$(LEX) $(LFLAGS) $<",
        "\t$(CC) $(CFLAGS) -c lex.yy.c",
        "\trm lex.yy.c",
        "\tmv lex.yy.o $@",

        "%.c : %.y",
        "\t$(YACC) $(YFLAGS) $<",
        "\tmv y.tab.c $@",

        "%.c : %.l",
        "\t$(LEX) $(LFLAGS) $<",
        "\tmv lex.yy.c $@",

        "% : %.o",
        "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",

        "% : %.c",
        "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",

        0 };



char *dfltsuff[] =
        {
        ".SUFFIXES : .o .c .y .l .a .sh .f",
        ".c.o :",
        "\t$(CC) $(CFLAGS) -c $<",

        ".f.o :",
        "\t$(FC) $(FFLAGS) -c $<",

        ".y.o :",
        "\t$(YACC) $(YFLAGS) $<",
        "\t$(CC) $(CFLAGS) -c y.tab.c",
        "\trm -f y.tab.c",
        "\tmv y.tab.o $@",

        ".l.o :",
        "\t$(LEX) $(LFLAGS) $<",
        "\t$(CC) $(CFLAGS) -c lex.yy.c",
        "\trm -f lex.yy.c",
        "\tmv lex.yy.o $@",

        ".y.c :",
        "\t$(YACC) $(YFLAGS) $<",
        "\tmv y.tab.c $@",

        ".l.c :",
        "\t$(LEX) $(LFLAGS) $<",
        "\tmv lex.yy.c $@",

        ".c.a:",
        "\t$(CC) -c $(CFLAGS) $<",
        "\t$(AR) $(ARFLAGS) $@ $*.o",
        "\trm -f $*.o",

        ".f.a:",
        "\t$(FC) -c $(FFLAGS) $<",
        "\t$(AR) $(ARFLAGS) $@ $*.o",
        "\trm -f $*.o",

        ".c:",
        "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",

        ".f:",
        "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<",

        ".sh:",
        "\tcp $< $@",
        "\tchmod a+x $@",

        0 };


static struct dirhd     *opdir(char *, int);
static void             cldir(struct dirhd *, int);
static int              amatch(char *, char *);
static int              umatch(char *, char *);
static void             clarch(void);
static int              openarch(char *);
static int              getarch(void);

time_t
exists(char *filename)
{
struct stat buf;
char *s;

for(s = filename ; *s!='\0' && *s!='(' &&  *s!=')' ; ++s)
        ;

if(*s != '\0')
        return lookarch(filename);

if(stat(filename,&buf) < 0) 
        return 0;
else    return buf.st_mtime;
}


time_t
prestime(void)
{
time_t t;
time(&t);
return t;
}

static char nmtemp[MAXNAMLEN+1];        /* guarantees a null after the name */
static char *tempend = nmtemp + MAXNAMLEN;



depblkp
srchdir(char *pat, int mkchain, depblkp nextdbl)
{
DIR *dirf;
struct dirhd *dirptr;
char *dirname, *dirpref, *endir, *filepat, *p, temp[100];
char fullname[100];
nameblkp q;
depblkp thisdbl;
struct pattern *patp;

struct dirent *dptr;

thisdbl = 0;

if(mkchain == NO)
        for(patp=firstpat ; patp ; patp = patp->nxtpattern)
                if(equal(pat, patp->patval)) return 0;

patp = ALLOC(pattern);
patp->nxtpattern = firstpat;
firstpat = patp;
patp->patval = copys(pat);

endir = 0;

for(p=pat; *p!='\0'; ++p)
        if(*p=='/') endir = p;

if(endir==0)
        {
        dirname = ".";
        dirpref = "";
        filepat = pat;
        }
else    {
        dirname = pat;
        *endir = '\0';
        dirpref = concat(dirname, "/", temp);
        filepat = endir+1;
        }

dirptr = opdir(dirname,YES);
dirf = dirptr->dirfc;

for( dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) )
        {
        char *p1, *p2;
        p1 = dptr->d_name;
        p2 = nmtemp;
        while( (p2<tempend) && (*p2++ = *p1++)!='\0')
                ;
        if( amatch(nmtemp,filepat) )
                {
                concat(dirpref,nmtemp,fullname);
                if( (q=srchname(fullname)) ==0)
                        q = makename(copys(fullname));
                if(mkchain)
                        {
                        thisdbl = ALLOC(depblock);
                        thisdbl->nxtdepblock = nextdbl;
                        thisdbl->depname = q;
                        nextdbl = thisdbl;
                        }
                }
        }


if(endir)
        *endir = '/';

cldir(dirptr, YES);

return thisdbl;
}

static struct dirhd *
opdir(char *dirname, int stopifbad)
{
struct dirhd *od;

for(od = firstod; od; od = od->nxtdirhd)
        if(equal(dirname, od->dirn) )
                break;

if(od == NULL)
        {
        ++nopdir;
        od = ALLOC(dirhd);
        od->nxtdirhd = firstod;
        firstod = od;
        od->dirn = copys(dirname);
        }

if(od->dirfc==NULL && (od->dirfc = opendir(dirname)) == NULL && stopifbad)
        {
        fprintf(stderr, "Directory %s: ", dirname);
        fatal("Cannot open");
        }

return od;
}


static void
cldir(struct dirhd *dp, int used)
{
if(nopdir >= MAXDIR)
        {
        closedir(dp->dirfc);
        dp->dirfc = NULL;
        }
else if(used)
        rewinddir(dp->dirfc); /* start over at the beginning  */
}

/* stolen from glob through find */

static int
amatch(char *s, char *p)
{
        int cc, scc, k;
        int c, lc;

        scc = *s;
        lc = 077777;
        switch (c = *p) {

        case '[':
                k = 0;
                while (cc = *++p) {
                        switch (cc) {

                        case ']':
                                if (k)
                                        return amatch(++s, ++p);
                                else
                                        return 0;

                        case '-':
                                k |= (lc <= scc)  & (scc <= (cc=p[1]) ) ;
                        }
                        if (scc==(lc=cc)) k++;
                }
                return 0;

        case '?':
        caseq:
                if(scc) return amatch(++s, ++p);
                return 0;
        case '*':
                return umatch(s, ++p);
        case 0:
                return !scc;
        }
        if (c==scc) goto caseq;
        return 0;
}

static int
umatch(char *s, char *p)
{
        if(*p==0) return 1;
        while(*s)
                if (amatch(s++,p)) return 1;
        return 0;
}

#ifdef METERFILE
#include <pwd.h>
int meteron     = 0;    /* default: metering off */

extern void meter(char *file)
{
time_t tvec;
char *p;
FILE * mout;
struct passwd *pwd;

if(file==0 || meteron==0) return;

pwd = getpwuid(getuid());

time(&tvec);

if( mout = fopen(file,"a") )
        {
        p = ctime(&tvec);
        p[16] = '\0';
        fprintf(mout, "User %s, %s\n", pwd->pw_name, p+4);
        fclose(mout);
        }
}
#endif


/* look inside archives for notation a(b)
        a(b)    is file member   b   in archive a
*/

static long arflen;
static long arfdate;
static char arfname[16];
FILE *arfd;
long int arpos, arlen;

time_t
lookarch(char *filename)
{
char *p, *q, *send, s[15], pad;
int i, nc, nsym;

for(p = filename; *p!= '(' ; ++p)
        ;

*p = '\0';
if( ! openarch(filename) )
        {
        *p = '(';
        return 0L;
        }
*p++ = '(';
nc = 14;
pad = ' ';

send = s + nc;
for( q = s ; q<send && *p!='\0' && *p!=')' ; *q++ = *p++ )
        ;
if(p[0]==')' && p[1]!='\0')     /* forbid stuff after the paren */
        {
        clarch();
        return 0L;
        }
while(q < send)
        *q++ = pad;
while(getarch())
        {
        if( !strncmp(arfname, s, nc))
                {
                clarch();
/*TEMP fprintf(stderr, "found archive member %14s, time=%d\n", s, arfdate); */
                return arfdate;
                }
        }

clarch();
return  0L;
}

static void
clarch(void)
{
fclose( arfd );
}

static int
openarch(char *f)
{
char magic[SARMAG];
int word;
struct stat buf;
nameblkp p;

stat(f, &buf);
arlen = buf.st_size;

arfd = fopen(f, "r");
if(arfd == NULL)
        return NO;
        /* fatal1("cannot open %s", f); */

fread( (char *) &word, sizeof(word), 1, arfd);

fseek(arfd, 0L, 0);
fread(magic, SARMAG, 1, arfd);
arpos = SARMAG;
if( strncmp(magic, ARMAG, SARMAG) )
        fatal1("%s is not an archive", f);

if( !(p = srchname(f)) )
        p = makename( copys(f) );
p->isarch = YES;
arflen = 0;
return YES;
}


static int
getarch(void)
{
struct ar_hdr arhead;

arpos += (arflen + 1) & ~1L;    /* round archived file length up to even */
if(arpos >= arlen)
        return 0;
fseek(arfd, arpos, 0);

fread( (char *) &arhead, sizeof(arhead), 1, arfd);
arpos += sizeof(arhead);
arflen = atol(arhead.ar_size);
arfdate = atol(arhead.ar_date);
strncpy(arfname, arhead.ar_name, sizeof(arhead.ar_name));
return 1;
}

/* find the directory containing name.
   read it into the hash table if it hasn't been used before or if
   if might have changed since last reference
*/

void
dirsrch(char *name)
{
DIR *dirf;
struct dirhd *dirp;
time_t dirt, objt;
int dirused, hasparen;
char *dirname, *lastslash;
char *fullname, *filepart, *fileend, *s;
struct dirent *dptr;

lastslash = NULL;
hasparen = NO;

for(s=name; *s; ++s)
        if(*s == '/')
                lastslash = s;
        else if(*s=='(' || *s==')')
                hasparen = YES;

if(hasparen)
        {
        if(objt = lookarch(name))
                makename(name)->modtime = objt;
        return;
        }

if(lastslash)
        {
        dirname = name;
        *lastslash = '\0';
        }
else
        dirname = ".";

dirused = NO;
dirp = opdir(dirname, NO);
dirf = dirp->dirfc;
if(dirp->dirok || !dirf)
        goto ret;
dirt = exists(dirname);
if(dirp->dirtime == dirt)
        goto ret;

dirp->dirok = YES;
dirp->dirtime = dirt;
dirused = YES;

/* allocate buffer to hold full file name */
if(lastslash)
        {
        fullname = (char *) ckalloc(strlen(dirname)+MAXNAMLEN+2);
        concat(dirname, "/", fullname);
        filepart = fullname + strlen(fullname);
        }
else
        filepart = fullname = (char *) ckalloc(MAXNAMLEN+1);


fileend = filepart + MAXNAMLEN;
*fileend = '\0';
for(dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) )
        {
        char *p1, *p2;
        p1 = dptr->d_name;
        p2 = filepart;
        while( (p2<fileend) && (*p2++ = *p1++)!='\0')
                ;
        if( ! srchname(fullname) )
                (void) makename(copys(fullname));
        }

free(fullname);

ret:
        cldir(dirp, dirused);
        if(lastslash)
                *lastslash = '/';
}



void
baddirs(void)
{
struct dirhd *od;

for(od = firstod; od; od = od->nxtdirhd)
        od->dirok = NO;
}