summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common/pkgparam.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libadm/common/pkgparam.c')
-rw-r--r--usr/src/lib/libadm/common/pkgparam.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/pkgparam.c b/usr/src/lib/libadm/common/pkgparam.c
new file mode 100644
index 0000000000..816e6a1622
--- /dev/null
+++ b/usr/src/lib/libadm/common/pkgparam.c
@@ -0,0 +1,451 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * Copyright (c) 1995-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+/*LINTLIBRARY*/
+
+/* 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>
+#include <stdlib.h>
+#include <unistd.h>
+#include "libadm.h"
+
+#define VALSIZ 128
+#define NEWLINE '\n'
+#define ESCAPE '\\'
+
+static char sepset[] = ":=\n";
+static char qset[] = "'\"";
+static char *pkg_inst_root = NULL;
+
+char *pkgdir = NULL;
+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 */
+
+/*
+ * 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 *pkg_dir, char *pkginst)
+{
+ /* Construct the temporary pkginfo file name. */
+ (void) sprintf(path, "%s/.save.%s/pkginfo", pkg_dir, pkginst);
+ if (access(path, 0)) {
+ /*
+ * This isn't a temporary directory, so we look for a
+ * regular one.
+ */
+ (void) sprintf(path, "%s/%s/pkginfo", pkg_dir, 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 *pkg_dir, char *pkginst)
+{
+ FILE *fp = NULL;
+ char temp[PATH_MAX];
+
+ if (pkginfofind(temp, pkg_dir, pkginst))
+ fp = fopen(temp, "r");
+
+ return (fp);
+}
+
+
+char *
+fpkgparam(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 = realloc(mempt,
+ (n+VALSIZ)*sizeof (char));
+ if (!mempt)
+ return (NULL);
+ } else {
+ mempt = calloc((size_t)(2*VALSIZ),
+ sizeof (char));
+ if (!mempt)
+ return (NULL);
+ (void) 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((unsigned char)*(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(char *pkg, char *param)
+{
+ static char lastfname[PATH_MAX];
+ static FILE *fp = NULL;
+ char *pt, *copy, *value, line[PATH_MAX];
+
+ if (!pkgdir)
+ pkgdir = get_PKGLOC();
+
+ if (!pkg) {
+ /* request to close file */
+ if (fp) {
+ (void) fclose(fp);
+ fp = NULL;
+ }
+ 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 = NULL;
+ }
+ 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((unsigned char)*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(char *);
+
+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);
+ set_install_root(path);
+ } 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(void)
+{
+ if (Adm_pkgloc[0] == NULL)
+ return (PKGLOC);
+ else
+ return (Adm_pkgloc);
+}
+
+char *
+get_PKGOLD(void)
+{
+ if (Adm_pkgold[0] == NULL)
+ return (PKGOLD);
+ else
+ return (Adm_pkgold);
+}
+
+char *
+get_PKGADM(void)
+{
+ if (Adm_pkgadm[0] == NULL)
+ return (PKGADM);
+ else
+ return (Adm_pkgadm);
+}
+
+void
+set_PKGADM(char *newpath)
+{
+ (void) strcpy(Adm_pkgadm, newpath);
+}
+
+void
+set_PKGLOC(char *newpath)
+{
+ (void) strcpy(Adm_pkgloc, newpath);
+}
+
+#define isdot(x) ((x[0] == '.')&&(!x[1]||(x[1] == '/')))
+#define isdotdot(x) ((x[0] == '.')&&(x[1] == '.')&&(!x[2]||(x[2] == '/')))
+
+static void
+canonize_name(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';
+}
+
+void
+set_install_root(char *path)
+{
+ pkg_inst_root = strdup(path);
+}
+
+char *
+get_install_root()
+{
+ return (pkg_inst_root);
+}