/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:util.c 12.0$ */
/* $ACIS:util.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/rvd/client/RCS/util.c,v $ */

#ifndef lint
static char *rcsid = "$Header:util.c 12.0$";
#endif

#ifndef lint
static char *rcsid_util_c = "$Header:util.c 12.0$";
#endif
/*
 * $Author: root $
 * $Source: /ibm/acis/usr/src/ibm/rvd/client/RCS/util.c,v $
 */
#define _UTIL_C_

#include "util.h"

static int _dflag = FALSE;
#define debug if(_dflag)printf

util_debugOn()
{
    _dflag = TRUE;
}

util_debugOff()
{
    _dflag = FALSE;
}


caddr_t
util_skipNum(s)
    register char *s;
{
    while (*s == '-')
        s++;
    while (isdigit(*s))
        s++;
    return(s);
}


caddr_t
util_skipSpace(buf)
    char *buf;
{
    register char *cp = buf;

    /* skip past white space and comments, but never beyond the EOL */
    while (isData(*cp) && isspace(*cp))
        cp++;
    if (*cp == CC) {
        *cp++ = NIL;
        while (notNL(*cp))
            cp++;
    }
    return(cp);
}


caddr_t
util_skipLine(buf, bof)
    char *buf;
    int bof;
{
    register char *cp = buf;

Again:
    /* 'bof' means skip past any comments or null lines to the first byte of */
    /* data from the current pointer, usually the "beginning of file". */
    if (bof) {
        cp = util_skipSpace(cp);
        if (isData(*cp))
            return(cp);
    }
    while (notNL(*cp))
        cp++;
    if (*cp)
        *cp++ = NIL;
    cp = util_skipSpace(cp);
    if (isEOL(*cp))
        goto Again;
    return(cp);
}


int
util_countLines(buf, len)	     /* => # of "real" lines */
    char *buf;
    int len;
{
    register int i;
    register char *cp;
    register int lines;
    register int bol;

    debug("util$countLines: %d chars\n", len);
    for (i = len, cp = buf, lines = 0, bol = TRUE ; i > 0; i--, cp++) {
        if (bol) {
            /* don't count comment or null lines */
            if (isEOL(*cp))
                bol = FALSE, lines--;
            else if (!isspace(*cp))
                bol = FALSE;
        }
        if (*cp == NL)
            bol = TRUE, lines++;
    }
    debug("util$countLines: returns %d\n", lines);
    return(lines);
}


caddr_t				     /* => pointer to beginning of next field */
util_skipField(cp, sep)
    char *cp;
    char *sep;			     /* separator characters */
{
    /* skip past current field, but never past EOL */
    while (isData(*cp) && !indexc(sep, *cp))
        cp++;
    if (isData(*cp))		     /* replace separator with NULL */
        *cp++ = NIL;
    return(util_skipSpace(cp));
}


int				     /* => errno */
util_yankFile(iFname, oBuf, oLen, oFd)
    char *iFname;		     /* file to yank into memory */
    char **oBuf;		     /* (return) ptr to area */
    int *oLen;			     /* length of area or 0 */
    int *oFd;			     /* file desc of open file */
{
    register char *cp = *oBuf;
    register int cc = *oLen;
    register int fd;

    if ((fd = open(iFname, O_RDONLY, 0)) < 0) {
        debug("util$yankFile: can't open file '%s' (RO)\n", iFname);
        return(errno);
    }

    if (!cp) {			     /* user didnt supply buffer? */
        struct stat sb;
        if (stat(iFname, &sb) < 0) {
            debug("util$yankFile: can't stat file '%s'\n", iFname);
            return(errno);
        }
        debug("util$yankFile: %s (%d bytes)\n", iFname, sb.st_size);
        *oLen = 0;
        if (!(cp = *oBuf = malloc((cc = sb.st_size) + 2))) {
            debug("util$yankFile: malloc() ENOMEM\n");
            return(errno=ENOMEM);
        }
        cp[cc] = NL, cp[cc+1] = NIL;
    }

    if (cc > 0)
        cc = read(fd, cp, cc);
    if (cc < 0)
        cc = 0;

    if (oFd)			     /* user wants fd back? */
        *oFd = fd;
    else
        close(fd);

    if (*oLen == 0 && cc == 0)
        free(cp), *oBuf = NULL;
    else
        *oLen = cc;

    debug("util$yankFile: read %d bytes\n", cc);
    return(errno=0);
}


int				     /* => child exit status */
util_runFile(sync, iXfile, args)
    int sync;			     /* synchronous exec */
    char *iXfile;		     /* the thing to exec */
{
    register int pid;
    int status = 0;

    debug("util$runFile: '%s'\n", args);

    if ((pid = vfork()) == 0) {
        execv(iXfile, (char **)&args);
        _exit(errno);		     /* misbehavin'... */
    }

    if (pid < 0)
        return(errno);

    if (!sync)			     /* do we.. */
        return(0);		     /* abandon child? */

    while (wait(&status) != pid) ;   /* or be good parent? */

    debug("util$runFile: child status %d\n", status);
    return(status);
}
