1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 32*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate /* 5-20-92 added newroot functions */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include <stdio.h> 37*7c478bd9Sstevel@tonic-gate #include <limits.h> 38*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 39*7c478bd9Sstevel@tonic-gate #include <unistd.h> 40*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 41*7c478bd9Sstevel@tonic-gate #include <ctype.h> 42*7c478bd9Sstevel@tonic-gate #include <string.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 45*7c478bd9Sstevel@tonic-gate #include <dirent.h> 46*7c478bd9Sstevel@tonic-gate #include <pkginfo.h> 47*7c478bd9Sstevel@tonic-gate #include <pkgstrct.h> 48*7c478bd9Sstevel@tonic-gate #include <pkglocs.h> 49*7c478bd9Sstevel@tonic-gate #include <errno.h> 50*7c478bd9Sstevel@tonic-gate #include "libadm.h" 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static void initpkg(struct pkginfo *); 53*7c478bd9Sstevel@tonic-gate static char *svr4inst(char *); 54*7c478bd9Sstevel@tonic-gate static int rdconfig(struct pkginfo *, char *, char *); 55*7c478bd9Sstevel@tonic-gate static int svr4info(struct pkginfo *, char *, char *); 56*7c478bd9Sstevel@tonic-gate static int ckinfo(char *, char *, char *); 57*7c478bd9Sstevel@tonic-gate static int ckinst(char *, char *, char *, char *, char *); 58*7c478bd9Sstevel@tonic-gate static int verscmp(char *, char *); 59*7c478bd9Sstevel@tonic-gate static int archcmp(char *, char *); 60*7c478bd9Sstevel@tonic-gate static int compver(char *, char *); 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* 63*7c478bd9Sstevel@tonic-gate * Globals: 64*7c478bd9Sstevel@tonic-gate * pkgdir - specifies the directory where information about packages 65*7c478bd9Sstevel@tonic-gate * resides, i.e. the pkginfo file is located in a subdirectory 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * Caveats: 68*7c478bd9Sstevel@tonic-gate * The structure provided via "info" will contain malloc'd information; 69*7c478bd9Sstevel@tonic-gate * this will be free'd upon the next call to pkginfo with this 70*7c478bd9Sstevel@tonic-gate * same structure. Application calls must make sure this structure 71*7c478bd9Sstevel@tonic-gate * is null on the first call, or else we'll free static memory areas 72*7c478bd9Sstevel@tonic-gate * If the "pkg" argument is a wildcard specification, the next found 73*7c478bd9Sstevel@tonic-gate * instance available which matches the request will be returned 74*7c478bd9Sstevel@tonic-gate * If the "pkg" argument is a NULL pointer, the structure pointed to 75*7c478bd9Sstevel@tonic-gate * via "info" will have its elements deallocated and all files 76*7c478bd9Sstevel@tonic-gate * associated with this routine will be closed 77*7c478bd9Sstevel@tonic-gate * 78*7c478bd9Sstevel@tonic-gate * Return codes: 79*7c478bd9Sstevel@tonic-gate * A non-zero exit code indicates error with "errno" appropriately set: 80*7c478bd9Sstevel@tonic-gate * EINVAL - invalid argument 81*7c478bd9Sstevel@tonic-gate * ESRCH - there are no more instances of this package around 82*7c478bd9Sstevel@tonic-gate * EACCESS - unable to access files which should have been there 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /*VARARGS*/ 86*7c478bd9Sstevel@tonic-gate int 87*7c478bd9Sstevel@tonic-gate pkginfo(struct pkginfo *info, char *pkginst, ...) 88*7c478bd9Sstevel@tonic-gate { 89*7c478bd9Sstevel@tonic-gate char *ckarch, *ckvers; 90*7c478bd9Sstevel@tonic-gate int check; 91*7c478bd9Sstevel@tonic-gate va_list ap; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate va_start(ap, pkginst); 94*7c478bd9Sstevel@tonic-gate if (info == NULL) { 95*7c478bd9Sstevel@tonic-gate errno = EINVAL; 96*7c478bd9Sstevel@tonic-gate return (-1); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate if (pkginst == NULL) { 99*7c478bd9Sstevel@tonic-gate info->pkginst = NULL; 100*7c478bd9Sstevel@tonic-gate (void) fpkginfo(info, NULL); 101*7c478bd9Sstevel@tonic-gate (void) fpkginst(NULL); 102*7c478bd9Sstevel@tonic-gate return (0); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate ckarch = va_arg(ap, char *); 105*7c478bd9Sstevel@tonic-gate ckvers = va_arg(ap, char *); 106*7c478bd9Sstevel@tonic-gate va_end(ap); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate check = 0; 109*7c478bd9Sstevel@tonic-gate if (pkgnmchk(pkginst, "all", 1)) { 110*7c478bd9Sstevel@tonic-gate /* wild card specification */ 111*7c478bd9Sstevel@tonic-gate pkginst = fpkginst(pkginst, ckarch, ckvers); 112*7c478bd9Sstevel@tonic-gate if (pkginst == NULL) 113*7c478bd9Sstevel@tonic-gate return (-1); 114*7c478bd9Sstevel@tonic-gate } else { 115*7c478bd9Sstevel@tonic-gate /* request to check indicated instance */ 116*7c478bd9Sstevel@tonic-gate if (ckarch || ckvers) 117*7c478bd9Sstevel@tonic-gate check++; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate info->pkginst = NULL; 121*7c478bd9Sstevel@tonic-gate if (fpkginfo(info, pkginst)) 122*7c478bd9Sstevel@tonic-gate return (-1); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate if (check) { 125*7c478bd9Sstevel@tonic-gate /* 126*7c478bd9Sstevel@tonic-gate * verify that the provided instance matches 127*7c478bd9Sstevel@tonic-gate * any arch & vers specs that were provided 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate if (ckinst(pkginst, info->arch, info->version, ckarch, 130*7c478bd9Sstevel@tonic-gate ckvers)) { 131*7c478bd9Sstevel@tonic-gate errno = ESRCH; 132*7c478bd9Sstevel@tonic-gate return (-1); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate return (0); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate int 140*7c478bd9Sstevel@tonic-gate fpkginfo(struct pkginfo *info, char *pkginst) 141*7c478bd9Sstevel@tonic-gate { 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate if (info == NULL) { 144*7c478bd9Sstevel@tonic-gate errno = EINVAL; 145*7c478bd9Sstevel@tonic-gate return (-1); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate initpkg(info); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (pkginst == NULL) 151*7c478bd9Sstevel@tonic-gate return (0); 152*7c478bd9Sstevel@tonic-gate else if (pkgnmchk(pkginst, "all", 1)) { 153*7c478bd9Sstevel@tonic-gate errno = EINVAL; /* not an instance identifier */ 154*7c478bd9Sstevel@tonic-gate return (-1); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate if (pkgdir == NULL) 157*7c478bd9Sstevel@tonic-gate pkgdir = get_PKGLOC(); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (rdconfig(info, pkginst, NULL)) { 160*7c478bd9Sstevel@tonic-gate initpkg(info); 161*7c478bd9Sstevel@tonic-gate return (-1); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate return (0); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate static void 167*7c478bd9Sstevel@tonic-gate initpkg(struct pkginfo *info) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate /* free previously allocated space */ 170*7c478bd9Sstevel@tonic-gate if (info->pkginst) { 171*7c478bd9Sstevel@tonic-gate free(info->pkginst); 172*7c478bd9Sstevel@tonic-gate if (info->arch) 173*7c478bd9Sstevel@tonic-gate free(info->arch); 174*7c478bd9Sstevel@tonic-gate if (info->version) 175*7c478bd9Sstevel@tonic-gate free(info->version); 176*7c478bd9Sstevel@tonic-gate if (info->basedir) 177*7c478bd9Sstevel@tonic-gate free(info->basedir); 178*7c478bd9Sstevel@tonic-gate if (info->name) 179*7c478bd9Sstevel@tonic-gate free(info->name); 180*7c478bd9Sstevel@tonic-gate if (info->vendor) 181*7c478bd9Sstevel@tonic-gate free(info->vendor); 182*7c478bd9Sstevel@tonic-gate if (info->catg) 183*7c478bd9Sstevel@tonic-gate free(info->catg); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate info->pkginst = NULL; 187*7c478bd9Sstevel@tonic-gate info->arch = info->version = NULL; 188*7c478bd9Sstevel@tonic-gate info->basedir = info->name = NULL; 189*7c478bd9Sstevel@tonic-gate info->vendor = info->catg = NULL; 190*7c478bd9Sstevel@tonic-gate info->status = PI_UNKNOWN; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static int 194*7c478bd9Sstevel@tonic-gate rdconfig(struct pkginfo *info, char *pkginst, char *ckvers) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate FILE *fp; 197*7c478bd9Sstevel@tonic-gate char temp[256]; 198*7c478bd9Sstevel@tonic-gate char *value, *pt, *copy, **memloc; 199*7c478bd9Sstevel@tonic-gate int count; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if ((fp = pkginfopen(pkgdir, pkginst)) == NULL) { 202*7c478bd9Sstevel@tonic-gate if ((errno == ENOENT) && strcmp(pkgdir, get_PKGLOC()) == 0) 203*7c478bd9Sstevel@tonic-gate return (svr4info(info, pkginst, ckvers)); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate errno = EACCES; 206*7c478bd9Sstevel@tonic-gate return (-1); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate *temp = '\0'; 210*7c478bd9Sstevel@tonic-gate count = 0; 211*7c478bd9Sstevel@tonic-gate while (value = fpkgparam(fp, temp)) { 212*7c478bd9Sstevel@tonic-gate if (strcmp(temp, "ARCH") == 0 || 213*7c478bd9Sstevel@tonic-gate strcmp(temp, "CATEGORY") == 0) { 214*7c478bd9Sstevel@tonic-gate /* remove all whitespace from value */ 215*7c478bd9Sstevel@tonic-gate pt = copy = value; 216*7c478bd9Sstevel@tonic-gate while (*pt) { 217*7c478bd9Sstevel@tonic-gate if (!isspace((unsigned char)*pt)) 218*7c478bd9Sstevel@tonic-gate *copy++ = *pt; 219*7c478bd9Sstevel@tonic-gate pt++; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate *copy = '\0'; 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate count++; 224*7c478bd9Sstevel@tonic-gate memloc = NULL; 225*7c478bd9Sstevel@tonic-gate if (strcmp(temp, "NAME") == 0) 226*7c478bd9Sstevel@tonic-gate memloc = &info->name; 227*7c478bd9Sstevel@tonic-gate else if (strcmp(temp, "VERSION") == 0) 228*7c478bd9Sstevel@tonic-gate memloc = &info->version; 229*7c478bd9Sstevel@tonic-gate else if (strcmp(temp, "ARCH") == 0) 230*7c478bd9Sstevel@tonic-gate memloc = &info->arch; 231*7c478bd9Sstevel@tonic-gate else if (strcmp(temp, "VENDOR") == 0) 232*7c478bd9Sstevel@tonic-gate memloc = &info->vendor; 233*7c478bd9Sstevel@tonic-gate else if (strcmp(temp, "BASEDIR") == 0) 234*7c478bd9Sstevel@tonic-gate memloc = &info->basedir; 235*7c478bd9Sstevel@tonic-gate else if (strcmp(temp, "CATEGORY") == 0) 236*7c478bd9Sstevel@tonic-gate memloc = &info->catg; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate temp[0] = '\0'; 239*7c478bd9Sstevel@tonic-gate if (memloc == NULL) 240*7c478bd9Sstevel@tonic-gate continue; /* not a parameter we're looking for */ 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate *memloc = strdup(value); 243*7c478bd9Sstevel@tonic-gate if (!*memloc) { 244*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 245*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 246*7c478bd9Sstevel@tonic-gate return (-1); /* malloc from strdup failed */ 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if (!count) { 252*7c478bd9Sstevel@tonic-gate errno = ESRCH; 253*7c478bd9Sstevel@tonic-gate return (-1); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate info->status = (strcmp(pkgdir, get_PKGLOC()) ? PI_SPOOLED : 257*7c478bd9Sstevel@tonic-gate PI_INSTALLED); 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (info->status == PI_INSTALLED) { 260*7c478bd9Sstevel@tonic-gate (void) sprintf(temp, "%s/%s/!I-Lock!", pkgdir, pkginst); 261*7c478bd9Sstevel@tonic-gate if (access(temp, 0) == 0) 262*7c478bd9Sstevel@tonic-gate info->status = PI_PARTIAL; 263*7c478bd9Sstevel@tonic-gate else { 264*7c478bd9Sstevel@tonic-gate (void) sprintf(temp, "%s/%s/!R-Lock!", pkgdir, pkginst); 265*7c478bd9Sstevel@tonic-gate if (access(temp, 0) == 0) 266*7c478bd9Sstevel@tonic-gate info->status = PI_PARTIAL; 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate info->pkginst = strdup(pkginst); 270*7c478bd9Sstevel@tonic-gate return (0); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate static int 274*7c478bd9Sstevel@tonic-gate svr4info(struct pkginfo *info, char *pkginst, char *ckvers) 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate static DIR *pdirfp; 277*7c478bd9Sstevel@tonic-gate struct stat64 status; 278*7c478bd9Sstevel@tonic-gate FILE *fp; 279*7c478bd9Sstevel@tonic-gate char *pt, path[128], line[128]; 280*7c478bd9Sstevel@tonic-gate char temp[PKGSIZ+1]; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (strcmp(pkginst, "all")) { 283*7c478bd9Sstevel@tonic-gate if (pdirfp) { 284*7c478bd9Sstevel@tonic-gate (void) closedir(pdirfp); 285*7c478bd9Sstevel@tonic-gate pdirfp = NULL; 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate /* determine pkginst - remove '.*' extension, if any */ 288*7c478bd9Sstevel@tonic-gate (void) strncpy(temp, pkginst, PKGSIZ); 289*7c478bd9Sstevel@tonic-gate if (((pt = strchr(temp, '.')) != NULL) && strcmp(pt, ".*") == 0) 290*7c478bd9Sstevel@tonic-gate *pt = '\0'; 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* look in /usr/options direcotry for 'name' file */ 294*7c478bd9Sstevel@tonic-gate (void) sprintf(path, "%s/%s.name", get_PKGOLD(), temp); 295*7c478bd9Sstevel@tonic-gate if (lstat64(path, &status)) { 296*7c478bd9Sstevel@tonic-gate errno = (errno == ENOENT) ? ESRCH : EACCES; 297*7c478bd9Sstevel@tonic-gate return (-1); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate if ((status.st_mode & S_IFMT) != S_IFREG) { 300*7c478bd9Sstevel@tonic-gate errno = ESRCH; 301*7c478bd9Sstevel@tonic-gate return (-1); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate if ((fp = fopen(path, "r")) == NULL) { 304*7c478bd9Sstevel@tonic-gate errno = (errno == ENOENT) ? ESRCH : EACCES; 305*7c478bd9Sstevel@tonic-gate return (-1); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* /usr/options/xxx.name exists */ 309*7c478bd9Sstevel@tonic-gate (void) fgets(line, 128, fp); 310*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 311*7c478bd9Sstevel@tonic-gate if (pt = strchr(line, '\n')) 312*7c478bd9Sstevel@tonic-gate *pt = '\0'; /* remove trailing newline */ 313*7c478bd9Sstevel@tonic-gate if (pt = strchr(line, ':')) 314*7c478bd9Sstevel@tonic-gate *pt++ = '\0'; /* assumed version specification */ 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate if (info) { 317*7c478bd9Sstevel@tonic-gate info->name = strdup(line); 318*7c478bd9Sstevel@tonic-gate info->pkginst = strdup(temp); 319*7c478bd9Sstevel@tonic-gate if (!info->name || !info->pkginst) { 320*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 321*7c478bd9Sstevel@tonic-gate return (-1); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate info->status = PI_PRESVR4; 324*7c478bd9Sstevel@tonic-gate info->version = NULL; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (pt) { 328*7c478bd9Sstevel@tonic-gate /* eat leading space off of version spec */ 329*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*pt)) 330*7c478bd9Sstevel@tonic-gate pt++; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate if (ckvers && verscmp(ckvers, pt)) { 333*7c478bd9Sstevel@tonic-gate errno = ESRCH; 334*7c478bd9Sstevel@tonic-gate return (-1); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate if (info && *pt) 337*7c478bd9Sstevel@tonic-gate info->version = strdup(pt); 338*7c478bd9Sstevel@tonic-gate return (0); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate static int 342*7c478bd9Sstevel@tonic-gate ckinst(char *pkginst, char *pkgarch, char *pkgvers, char *ckarch, char *ckvers) 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate if (ckarch && archcmp(ckarch, pkgarch)) 345*7c478bd9Sstevel@tonic-gate return (-1); 346*7c478bd9Sstevel@tonic-gate if (ckvers) { 347*7c478bd9Sstevel@tonic-gate /* Check for exact version match */ 348*7c478bd9Sstevel@tonic-gate if (verscmp(ckvers, pkgvers)) { 349*7c478bd9Sstevel@tonic-gate /* Check for compatable version */ 350*7c478bd9Sstevel@tonic-gate if (compver(pkginst, ckvers)) 351*7c478bd9Sstevel@tonic-gate return (-1); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate return (0); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /*VARARGS*/ 358*7c478bd9Sstevel@tonic-gate char * 359*7c478bd9Sstevel@tonic-gate fpkginst(char *pkg, ...) 360*7c478bd9Sstevel@tonic-gate { 361*7c478bd9Sstevel@tonic-gate static char pkginst[PKGSIZ+1]; 362*7c478bd9Sstevel@tonic-gate static DIR *pdirfp; 363*7c478bd9Sstevel@tonic-gate struct dirent64 *dp; 364*7c478bd9Sstevel@tonic-gate char *pt, *ckarch, *ckvers; 365*7c478bd9Sstevel@tonic-gate va_list ap; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate va_start(ap, pkg); 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (pkg == NULL) { 370*7c478bd9Sstevel@tonic-gate /* request to close or rewind the file */ 371*7c478bd9Sstevel@tonic-gate if (pdirfp) { 372*7c478bd9Sstevel@tonic-gate (void) closedir(pdirfp); 373*7c478bd9Sstevel@tonic-gate pdirfp = NULL; 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate (void) svr4inst(NULL); /* close any files used here */ 376*7c478bd9Sstevel@tonic-gate return (NULL); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate ckarch = va_arg(ap, char *); 380*7c478bd9Sstevel@tonic-gate ckvers = va_arg(ap, char *); 381*7c478bd9Sstevel@tonic-gate va_end(ap); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate if (!pkgdir) 384*7c478bd9Sstevel@tonic-gate pkgdir = get_PKGLOC(); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if (!pdirfp && ((pdirfp = opendir(pkgdir)) == NULL)) { 387*7c478bd9Sstevel@tonic-gate errno = EACCES; 388*7c478bd9Sstevel@tonic-gate return (NULL); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate while ((dp = readdir64(pdirfp)) != NULL) { 392*7c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') 393*7c478bd9Sstevel@tonic-gate continue; 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate if (pkgnmchk(dp->d_name, pkg, 0)) 396*7c478bd9Sstevel@tonic-gate continue; /* ignore invalid SVR4 package names */ 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate if (ckinfo(dp->d_name, ckarch, ckvers)) 399*7c478bd9Sstevel@tonic-gate continue; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * Leave directory open in case user requests another 403*7c478bd9Sstevel@tonic-gate * instance. 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate (void) strcpy(pkginst, dp->d_name); 406*7c478bd9Sstevel@tonic-gate return (pkginst); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * If we are searching the directory which contains info about 411*7c478bd9Sstevel@tonic-gate * installed packages, check the pre-svr4 directory for an instance 412*7c478bd9Sstevel@tonic-gate * and be sure it matches any version specification provided to us 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate if (strcmp(pkgdir, get_PKGLOC()) == 0 && (ckarch == NULL)) { 415*7c478bd9Sstevel@tonic-gate /* search for pre-SVR4 instance */ 416*7c478bd9Sstevel@tonic-gate if (pt = svr4inst(pkg)) 417*7c478bd9Sstevel@tonic-gate return (pt); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate errno = ESRCH; 420*7c478bd9Sstevel@tonic-gate /* close any file we might have open */ 421*7c478bd9Sstevel@tonic-gate (void) closedir(pdirfp); 422*7c478bd9Sstevel@tonic-gate pdirfp = NULL; 423*7c478bd9Sstevel@tonic-gate return (NULL); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate static char * 428*7c478bd9Sstevel@tonic-gate svr4inst(char *pkg) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate static char pkginst[PKGSIZ]; 431*7c478bd9Sstevel@tonic-gate static DIR *pdirfp; 432*7c478bd9Sstevel@tonic-gate struct dirent64 *dp; 433*7c478bd9Sstevel@tonic-gate struct stat64 status; /* file status buffer */ 434*7c478bd9Sstevel@tonic-gate char *pt; 435*7c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (pkg == NULL) { 438*7c478bd9Sstevel@tonic-gate if (pdirfp) { 439*7c478bd9Sstevel@tonic-gate (void) closedir(pdirfp); 440*7c478bd9Sstevel@tonic-gate pdirfp = NULL; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate return (NULL); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate if (!pdirfp && ((pdirfp = opendir(get_PKGOLD())) == NULL)) 446*7c478bd9Sstevel@tonic-gate return (NULL); 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate while ((dp = readdir64(pdirfp)) != NULL) { 449*7c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') 450*7c478bd9Sstevel@tonic-gate continue; 451*7c478bd9Sstevel@tonic-gate pt = strchr(dp->d_name, '.'); 452*7c478bd9Sstevel@tonic-gate if (pt && strcmp(pt, ".name") == 0) { 453*7c478bd9Sstevel@tonic-gate /* the pkgnmchk function works on .name extensions */ 454*7c478bd9Sstevel@tonic-gate if (pkgnmchk(dp->d_name, pkg, 1)) 455*7c478bd9Sstevel@tonic-gate continue; 456*7c478bd9Sstevel@tonic-gate (void) sprintf(path, "%s/%s", get_PKGOLD(), dp->d_name); 457*7c478bd9Sstevel@tonic-gate if (lstat64(path, &status)) 458*7c478bd9Sstevel@tonic-gate continue; 459*7c478bd9Sstevel@tonic-gate if ((status.st_mode & S_IFMT) != S_IFREG) 460*7c478bd9Sstevel@tonic-gate continue; 461*7c478bd9Sstevel@tonic-gate *pt = '\0'; 462*7c478bd9Sstevel@tonic-gate (void) strcpy(pkginst, dp->d_name); 463*7c478bd9Sstevel@tonic-gate return (pkginst); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate (void) closedir(pdirfp); 467*7c478bd9Sstevel@tonic-gate pdirfp = NULL; 468*7c478bd9Sstevel@tonic-gate return (NULL); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate static int 472*7c478bd9Sstevel@tonic-gate verscmp(char *request, char *actual) 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate /* eat leading white space */ 475*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*actual)) 476*7c478bd9Sstevel@tonic-gate actual++; 477*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*request)) 478*7c478bd9Sstevel@tonic-gate request++; 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate while (*request || *actual) { 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Once the pointers don't match, return an error condition. 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate if (*request++ != *actual++) 486*7c478bd9Sstevel@tonic-gate return (-1); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* eat white space if any in both the strings */ 489*7c478bd9Sstevel@tonic-gate if (isspace((unsigned char)*request)) { 490*7c478bd9Sstevel@tonic-gate if (*actual && !isspace((unsigned char)*actual)) 491*7c478bd9Sstevel@tonic-gate return (-1); 492*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*request)) 493*7c478bd9Sstevel@tonic-gate request++; 494*7c478bd9Sstevel@tonic-gate while (isspace((unsigned char)*actual)) 495*7c478bd9Sstevel@tonic-gate actual++; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate return (0); 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate static int 504*7c478bd9Sstevel@tonic-gate compver(char *pkginst, char *version) 505*7c478bd9Sstevel@tonic-gate { 506*7c478bd9Sstevel@tonic-gate FILE *fp; 507*7c478bd9Sstevel@tonic-gate char temp[256]; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate (void) sprintf(temp, "%s/%s/install/compver", get_PKGLOC(), pkginst); 510*7c478bd9Sstevel@tonic-gate if ((fp = fopen(temp, "r")) == NULL) 511*7c478bd9Sstevel@tonic-gate return (-1); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate while (fgets(temp, 256, fp)) { 514*7c478bd9Sstevel@tonic-gate if (*temp == '#') 515*7c478bd9Sstevel@tonic-gate continue; 516*7c478bd9Sstevel@tonic-gate if (verscmp(temp, version) == 0) { 517*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 518*7c478bd9Sstevel@tonic-gate return (0); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 522*7c478bd9Sstevel@tonic-gate return (-1); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate static int 526*7c478bd9Sstevel@tonic-gate archcmp(char *arch, char *archlist) 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate char *pt; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if (arch == NULL) 531*7c478bd9Sstevel@tonic-gate return (0); 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* arch and archlist must not contain whitespace! */ 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate while (*archlist) { 536*7c478bd9Sstevel@tonic-gate for (pt = arch; *pt && (*pt == *archlist); ) 537*7c478bd9Sstevel@tonic-gate pt++, archlist++; 538*7c478bd9Sstevel@tonic-gate if (!*pt && (!*archlist || (*archlist == ','))) 539*7c478bd9Sstevel@tonic-gate return (0); 540*7c478bd9Sstevel@tonic-gate while (*archlist) { 541*7c478bd9Sstevel@tonic-gate if (*archlist++ == ',') 542*7c478bd9Sstevel@tonic-gate break; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate return (-1); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate static int 549*7c478bd9Sstevel@tonic-gate ckinfo(char *inst, char *arch, char *vers) 550*7c478bd9Sstevel@tonic-gate { 551*7c478bd9Sstevel@tonic-gate FILE *fp; 552*7c478bd9Sstevel@tonic-gate char temp[128]; 553*7c478bd9Sstevel@tonic-gate char file[PATH_MAX]; 554*7c478bd9Sstevel@tonic-gate char *pt, *copy, *value, *myarch, *myvers; 555*7c478bd9Sstevel@tonic-gate int errflg; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate (void) sprintf(file, "%s/%s/pkginfo", pkgdir, inst); 558*7c478bd9Sstevel@tonic-gate if ((fp = fopen(file, "r")) == NULL) 559*7c478bd9Sstevel@tonic-gate return (1); 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate if ((arch == NULL) && (vers == NULL)) { 562*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 563*7c478bd9Sstevel@tonic-gate return (0); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate temp[0] = '\0'; 566*7c478bd9Sstevel@tonic-gate myarch = myvers = NULL; 567*7c478bd9Sstevel@tonic-gate while (value = fpkgparam(fp, temp)) { 568*7c478bd9Sstevel@tonic-gate if (strcmp(temp, "ARCH") == 0) { 569*7c478bd9Sstevel@tonic-gate /* remove all whitespace from value */ 570*7c478bd9Sstevel@tonic-gate pt = copy = value; 571*7c478bd9Sstevel@tonic-gate while (*pt) { 572*7c478bd9Sstevel@tonic-gate if (!isspace((unsigned char)*pt)) 573*7c478bd9Sstevel@tonic-gate *copy++ = *pt; 574*7c478bd9Sstevel@tonic-gate pt++; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate *copy = '\0'; 577*7c478bd9Sstevel@tonic-gate myarch = value; 578*7c478bd9Sstevel@tonic-gate if (myvers) 579*7c478bd9Sstevel@tonic-gate break; 580*7c478bd9Sstevel@tonic-gate } else if (strcmp(temp, "VERSION") == 0) { 581*7c478bd9Sstevel@tonic-gate myvers = value; 582*7c478bd9Sstevel@tonic-gate if (myarch) 583*7c478bd9Sstevel@tonic-gate break; 584*7c478bd9Sstevel@tonic-gate } else 585*7c478bd9Sstevel@tonic-gate free(value); 586*7c478bd9Sstevel@tonic-gate temp[0] = '\0'; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 589*7c478bd9Sstevel@tonic-gate errflg = 0; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate if (ckinst(inst, myarch, myvers, arch, vers)) 592*7c478bd9Sstevel@tonic-gate errflg++; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate if (myarch) 595*7c478bd9Sstevel@tonic-gate free(myarch); 596*7c478bd9Sstevel@tonic-gate if (myvers) 597*7c478bd9Sstevel@tonic-gate free(myvers); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate return (errflg); 600*7c478bd9Sstevel@tonic-gate } 601