Files
Arquivotheca.Solaris-2.5/lib/libadm/pkgparam.c
seta75D 7c4988eac0 Init
2021-10-11 19:38:01 -03:00

420 lines
9.2 KiB
C
Executable File

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
/*LINTLIBRARY*/
#ident "@(#)pkgparam.c 1.11 95/04/04 SMI" /* SVr4.0 1.1 */
/* 5-20-92 newroot support added */
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <pkgstrct.h>
#include <pkginfo.h>
#include <pkglocs.h>
extern int errno;
extern void *calloc(), *realloc();
extern void free();
#define VALSIZ 128
#define NEWLINE '\n'
#define ESCAPE '\\'
static char sepset[] = ":=\n";
static char qset[] = "'\"";
char *pkgdir = PKGLOC;
char *pkgfile = NULL;
static char Adm_pkgold[PATH_MAX] = { 0 }; /* added for newroot */
static char Adm_pkgloc[PATH_MAX] = { 0 }; /* added for newroot */
static char Adm_pkgadm[PATH_MAX] = { 0 }; /* added for newroot */
FILE *pkginfopen(char *pkgdir, char *pkginst);
int pkginfofind(char *path, char *pkgdir, char *pkginst);
char *get_PKGADM();
char *get_PKGLOC();
char *get_PKGOLD();
void set_PKGpaths();
/*
* This looks in a directory that might be the top level directory of a
* package. It tests a temporary install directory first and then for a
* standard directory. This looks a little confusing, so here's what's
* happening. If this pkginfo is being openned in a script during a pkgadd
* which is updating an existing package, the original pkginfo file is in a
* directory that has been renamed from <pkginst> to .save.<pkginst>. If the
* pkgadd fails it will be renamed back to <pkginst>. We are always interested
* in the OLD pkginfo data because the new pkginfo data is already in our
* environment. For that reason, we try to open the backup first - that has
* the old data. This returns the first accessible path in "path" and a "1"
* if an appropriate pkginfo file was found. It returns a 0 if no type of
* pkginfo was located.
*/
int
pkginfofind(char *path, char *pkgdir, char *pkginst)
{
/* Construct the temporary pkginfo file name. */
(void) sprintf(path, "%s/.save.%s/pkginfo", pkgdir, pkginst);
if (access(path, 0)) {
/*
* This isn't a temporary directory, so we look for a
* regular one.
*/
(void) sprintf(path, "%s/%s/pkginfo", pkgdir, pkginst);
if (access(path, 0))
return (0); /* doesn't appear to be a package */
}
return (1);
}
/*
* This opens the appropriate pkginfo file for a particular package.
*/
FILE *
pkginfopen(char *pkgdir, char *pkginst)
{
FILE *fp = NULL;
char temp[PATH_MAX];
if (pkginfofind(temp, pkgdir, pkginst))
fp = fopen(temp, "r");
return (fp);
}
char *
fpkgparam(fp, param)
FILE *fp;
char *param;
{
char ch, buffer[VALSIZ];
char *mempt, *copy;
int c, n, escape, begline, quoted;
if (param == NULL) {
errno = ENOENT;
return (NULL);
}
mempt = NULL;
for (;;) { /* for each entry in the file fp */
copy = buffer;
n = 0;
/* Get the next token. */
while ((c = getc(fp)) != EOF) {
ch = (char) c;
if (strchr(sepset, ch))
break;
if (++n < VALSIZ)
*copy++ = ch;
}
/* If it's the end of the file, exit the for() loop */
if (c == EOF) {
errno = EINVAL;
return (NULL); /* no more entries left */
/* If it's end of line, look for the next parameter. */
} else if (c == NEWLINE)
continue;
/* At this point copy points to the end of a valid parameter. */
*copy = '\0'; /* Terminate the string. */
if (buffer[0] == '#') /* If it's a comment, drop thru. */
copy = NULL; /* Comments don't get buffered. */
else {
/* If parameter is NULL, we return whatever we got. */
if (param[0] == '\0') {
(void) strcpy(param, buffer);
copy = buffer;
/* If this doesn't match the parameter, drop thru. */
} else if (strcmp(param, buffer))
copy = NULL;
/* Otherwise, this is our boy. */
else
copy = buffer;
}
n = quoted = escape = 0;
begline = 1;
/* Now read the parameter value. */
while ((c = getc(fp)) != EOF) {
ch = (char) c;
if (begline && ((ch == ' ') || (ch == '\t')))
continue; /* ignore leading white space */
if (ch == NEWLINE) {
if (!escape)
break; /* end of entry */
if (copy) {
if (escape) {
copy--; /* eat previous esc */
n--;
}
*copy++ = NEWLINE;
}
escape = 0;
begline = 1; /* new input line */
} else {
if (!escape && strchr(qset, ch)) {
/* handle quotes */
if (begline) {
quoted++;
begline = 0;
continue;
} else if (quoted) {
quoted = 0;
continue;
}
}
if (ch == ESCAPE)
escape++;
else if (escape)
escape = 0;
if (copy) *copy++ = ch;
begline = 0;
}
if (copy && ((++n % VALSIZ) == 0)) {
if (mempt) {
mempt = (char *) realloc(mempt,
(n+VALSIZ)*sizeof (char));
if (!mempt)
return (NULL);
} else {
mempt = calloc(2*VALSIZ, sizeof (char));
if (!mempt)
return (NULL);
strncpy(mempt, buffer, n);
}
copy = &mempt[n];
}
}
/*
* Don't allow trailing white space.
* NOTE : White space in the middle is OK, since this may
* be a list. At some point it would be a good idea to let
* this function know how to validate such a list. -- JST
*
* Now while there's a parametric value and it ends in a
* space and the actual remaining string length is still
* greater than 0, back over the space.
*/
while (copy && isspace(*(copy - 1)) && n-- > 0)
copy--;
if (quoted) {
if (mempt)
(void) free(mempt);
errno = EFAULT; /* missing closing quote */
return (NULL);
}
if (copy) {
*copy = '\0';
break;
}
if (c == EOF) {
errno = EINVAL; /* parameter not found */
return (NULL);
}
}
if (!mempt)
mempt = strdup(buffer);
else
mempt = realloc(mempt, (strlen(mempt)+1)*sizeof (char));
return (mempt);
}
char *
pkgparam(pkg, param)
char *pkg;
char *param;
{
static char lastfname[PATH_MAX];
static FILE *fp = (FILE *)0;
char *pt, *copy, *value, line[PATH_MAX];
if (!pkgdir)
pkgdir = get_PKGLOC();
if (!pkg) {
/* request to close file */
if (fp) {
(void) fclose(fp);
fp = (FILE *)0;
}
return (NULL);
}
if (!param) {
errno = ENOENT;
return (NULL);
}
if (pkgfile)
(void) strcpy(line, pkgfile); /* filename was passed */
else
(void) pkginfofind(line, pkgdir, pkg);
if (fp && strcmp(line, lastfname)) {
/* different filename implies need for different fp */
(void) fclose(fp);
fp = (FILE *)0;
}
if (!fp) {
(void) strcpy(lastfname, line);
if ((fp = fopen(lastfname, "r")) == NULL)
return (NULL);
}
/*
* if parameter is a null string, then the user is requesting us
* to find the value of the next available parameter for this
* package and to copy the parameter name into the provided string;
* if it is not, then it is a request for a specified parameter, in
* which case we rewind the file to start search from beginning
*/
if (param[0]) {
/* new parameter request, so reset file position */
if (fseek(fp, 0L, 0))
return (NULL);
}
if (pt = fpkgparam(fp, param)) {
if (strcmp(param, "ARCH") == NULL ||
strcmp(param, "CATEGORY") == NULL) {
/* remove all whitespace from value */
value = copy = pt;
while (*value) {
if (!isspace(*value))
*copy++ = *value;
value++;
}
*copy = '\0';
}
return (pt);
}
return (NULL);
}
/*
* This routine sets adm_pkgloc and adm_pkgadm which are the
* replacement location for PKGLOC and PKGADM.
*/
static void canonize_name();
void
set_PKGpaths(char *path)
{
if (path && *path) {
(void) sprintf(Adm_pkgloc, "%s%s", path, PKGLOC);
(void) sprintf(Adm_pkgold, "%s%s", path, PKGOLD);
(void) sprintf(Adm_pkgadm, "%s%s", path, PKGADM);
} else {
(void) sprintf(Adm_pkgloc, "%s", PKGLOC);
(void) sprintf(Adm_pkgold, "%s", PKGOLD);
(void) sprintf(Adm_pkgadm, "%s", PKGADM);
}
canonize_name(Adm_pkgloc);
canonize_name(Adm_pkgold);
canonize_name(Adm_pkgadm);
pkgdir = Adm_pkgloc;
}
char *
get_PKGLOC()
{
if (Adm_pkgloc[0] == NULL)
return (PKGLOC);
else
return (Adm_pkgloc);
}
char *
get_PKGOLD()
{
if (Adm_pkgold[0] == NULL)
return (PKGOLD);
else
return (Adm_pkgold);
}
char *
get_PKGADM()
{
if (Adm_pkgadm[0] == NULL)
return (PKGADM);
else
return (Adm_pkgadm);
}
#define isdot(x) ((x[0] == '.')&&(!x[1]||(x[1] == '/')))
#define isdotdot(x) ((x[0] == '.')&&(x[1] == '.')&&(!x[2]||(x[2] == '/')))
static void
canonize_name(file)
char *file;
{
char *pt, *last;
int level;
/* Remove references such as "./" and "../" and "//" */
for (pt = file; *pt; ) {
if (isdot(pt))
(void) strcpy(pt, pt[1] ? pt+2 : pt+1);
else if (isdotdot(pt)) {
level = 0;
last = pt;
do {
level++;
last += 2;
if (*last)
last++;
} while (isdotdot(last));
--pt; /* point to previous '/' */
while (level--) {
if (pt <= file)
return;
while ((*--pt != '/') && (pt > file))
;
}
if (*pt == '/')
pt++;
(void) strcpy(pt, last);
} else {
while (*pt && (*pt != '/'))
pt++;
if (*pt == '/') {
while (pt[1] == '/')
(void) strcpy(pt, pt+1);
pt++;
}
}
}
if ((--pt > file) && (*pt == '/'))
*pt = '\0';
}