1*9781SMoriah.Waterland@Sun.COM /* 2*9781SMoriah.Waterland@Sun.COM * CDDL HEADER START 3*9781SMoriah.Waterland@Sun.COM * 4*9781SMoriah.Waterland@Sun.COM * The contents of this file are subject to the terms of the 5*9781SMoriah.Waterland@Sun.COM * Common Development and Distribution License (the "License"). 6*9781SMoriah.Waterland@Sun.COM * You may not use this file except in compliance with the License. 7*9781SMoriah.Waterland@Sun.COM * 8*9781SMoriah.Waterland@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9781SMoriah.Waterland@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*9781SMoriah.Waterland@Sun.COM * See the License for the specific language governing permissions 11*9781SMoriah.Waterland@Sun.COM * and limitations under the License. 12*9781SMoriah.Waterland@Sun.COM * 13*9781SMoriah.Waterland@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*9781SMoriah.Waterland@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9781SMoriah.Waterland@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*9781SMoriah.Waterland@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*9781SMoriah.Waterland@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*9781SMoriah.Waterland@Sun.COM * 19*9781SMoriah.Waterland@Sun.COM * CDDL HEADER END 20*9781SMoriah.Waterland@Sun.COM */ 21*9781SMoriah.Waterland@Sun.COM 22*9781SMoriah.Waterland@Sun.COM /* 23*9781SMoriah.Waterland@Sun.COM * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*9781SMoriah.Waterland@Sun.COM * Use is subject to license terms. 25*9781SMoriah.Waterland@Sun.COM */ 26*9781SMoriah.Waterland@Sun.COM 27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */ 29*9781SMoriah.Waterland@Sun.COM 30*9781SMoriah.Waterland@Sun.COM 31*9781SMoriah.Waterland@Sun.COM #include <stdio.h> 32*9781SMoriah.Waterland@Sun.COM #include <errno.h> 33*9781SMoriah.Waterland@Sun.COM #include <string.h> 34*9781SMoriah.Waterland@Sun.COM #include <limits.h> 35*9781SMoriah.Waterland@Sun.COM #include <stdlib.h> 36*9781SMoriah.Waterland@Sun.COM #include <unistd.h> 37*9781SMoriah.Waterland@Sun.COM #include <sys/types.h> 38*9781SMoriah.Waterland@Sun.COM #include <pkgstrct.h> 39*9781SMoriah.Waterland@Sun.COM #include <locale.h> 40*9781SMoriah.Waterland@Sun.COM #include <libintl.h> 41*9781SMoriah.Waterland@Sun.COM #include <pkglib.h> 42*9781SMoriah.Waterland@Sun.COM #include <install.h> 43*9781SMoriah.Waterland@Sun.COM #include <libinst.h> 44*9781SMoriah.Waterland@Sun.COM #include <libadm.h> 45*9781SMoriah.Waterland@Sun.COM #include "installf.h" 46*9781SMoriah.Waterland@Sun.COM 47*9781SMoriah.Waterland@Sun.COM #define LSIZE 1024 48*9781SMoriah.Waterland@Sun.COM #define MALSIZ 164 49*9781SMoriah.Waterland@Sun.COM 50*9781SMoriah.Waterland@Sun.COM #define ERR_MAJOR "invalid major number <%s> specified for <%s>" 51*9781SMoriah.Waterland@Sun.COM #define ERR_MINOR "invalid minor number <%s> specified for <%s>" 52*9781SMoriah.Waterland@Sun.COM #define ERR_MODE "invalid mode <%s> specified for <%s>" 53*9781SMoriah.Waterland@Sun.COM #define ERR_RELPATH "relative pathname <%s> not permitted" 54*9781SMoriah.Waterland@Sun.COM #define ERR_NULLPATH "NULL or garbled pathname" 55*9781SMoriah.Waterland@Sun.COM #define ERR_LINK "invalid link specification <%s>" 56*9781SMoriah.Waterland@Sun.COM #define ERR_LINKFTYPE "ftype <%c> does not match link specification <%s>" 57*9781SMoriah.Waterland@Sun.COM #define ERR_LINKARGS "extra arguments in link specification <%s>" 58*9781SMoriah.Waterland@Sun.COM #define ERR_LINKREL "relative pathname in link specification <%s>" 59*9781SMoriah.Waterland@Sun.COM #define ERR_FTYPE "invalid ftype <%c> for <%s>" 60*9781SMoriah.Waterland@Sun.COM #define ERR_ARGC "invalid number of arguments for <%s>" 61*9781SMoriah.Waterland@Sun.COM #define ERR_SPECALL "ftype <%c> requires all fields to be specified" 62*9781SMoriah.Waterland@Sun.COM 63*9781SMoriah.Waterland@Sun.COM static int validate(struct cfextra *ext, int argc, char *argv[]); 64*9781SMoriah.Waterland@Sun.COM static void checkPaths(char *argv[]); 65*9781SMoriah.Waterland@Sun.COM 66*9781SMoriah.Waterland@Sun.COM int 67*9781SMoriah.Waterland@Sun.COM installf(int argc, char *argv[]) 68*9781SMoriah.Waterland@Sun.COM { 69*9781SMoriah.Waterland@Sun.COM struct cfextra *new; 70*9781SMoriah.Waterland@Sun.COM char line[LSIZE]; 71*9781SMoriah.Waterland@Sun.COM char *largv[8]; 72*9781SMoriah.Waterland@Sun.COM int myerror; 73*9781SMoriah.Waterland@Sun.COM 74*9781SMoriah.Waterland@Sun.COM if (strcmp(argv[0], "-") != 0) { 75*9781SMoriah.Waterland@Sun.COM if (argc < 1) 76*9781SMoriah.Waterland@Sun.COM usage(); /* at least pathname is required */ 77*9781SMoriah.Waterland@Sun.COM extlist = calloc(2, sizeof (struct cfextra *)); 78*9781SMoriah.Waterland@Sun.COM extlist[0] = new = calloc(1, sizeof (struct cfextra)); 79*9781SMoriah.Waterland@Sun.COM eptnum = 1; 80*9781SMoriah.Waterland@Sun.COM 81*9781SMoriah.Waterland@Sun.COM /* There is only one filename on the command line. */ 82*9781SMoriah.Waterland@Sun.COM checkPaths(argv); 83*9781SMoriah.Waterland@Sun.COM if (validate(new, argc, argv)) 84*9781SMoriah.Waterland@Sun.COM quit(1); 85*9781SMoriah.Waterland@Sun.COM return (0); 86*9781SMoriah.Waterland@Sun.COM } 87*9781SMoriah.Waterland@Sun.COM 88*9781SMoriah.Waterland@Sun.COM /* Read stdin to obtain entries, which need to be sorted. */ 89*9781SMoriah.Waterland@Sun.COM eptnum = 0; 90*9781SMoriah.Waterland@Sun.COM myerror = 0; 91*9781SMoriah.Waterland@Sun.COM extlist = calloc(MALSIZ, sizeof (struct cfextra *)); 92*9781SMoriah.Waterland@Sun.COM while (fgets(line, LSIZE, stdin) != NULL) { 93*9781SMoriah.Waterland@Sun.COM argc = 0; 94*9781SMoriah.Waterland@Sun.COM argv = largv; 95*9781SMoriah.Waterland@Sun.COM argv[argc++] = strtok(line, " \t\n"); 96*9781SMoriah.Waterland@Sun.COM while (argv[argc] = strtok(NULL, " \t\n")) 97*9781SMoriah.Waterland@Sun.COM argc++; 98*9781SMoriah.Waterland@Sun.COM 99*9781SMoriah.Waterland@Sun.COM if (argc < 1) 100*9781SMoriah.Waterland@Sun.COM usage(); /* at least pathname is required */ 101*9781SMoriah.Waterland@Sun.COM 102*9781SMoriah.Waterland@Sun.COM new = calloc(1, sizeof (struct cfextra)); 103*9781SMoriah.Waterland@Sun.COM if (new == NULL) { 104*9781SMoriah.Waterland@Sun.COM progerr(strerror(errno)); 105*9781SMoriah.Waterland@Sun.COM quit(99); 106*9781SMoriah.Waterland@Sun.COM } 107*9781SMoriah.Waterland@Sun.COM 108*9781SMoriah.Waterland@Sun.COM checkPaths(argv); 109*9781SMoriah.Waterland@Sun.COM 110*9781SMoriah.Waterland@Sun.COM if (validate(new, argc, argv)) 111*9781SMoriah.Waterland@Sun.COM myerror++; 112*9781SMoriah.Waterland@Sun.COM 113*9781SMoriah.Waterland@Sun.COM extlist[eptnum] = new; 114*9781SMoriah.Waterland@Sun.COM if ((++eptnum % MALSIZ) == 0) { 115*9781SMoriah.Waterland@Sun.COM extlist = realloc(extlist, 116*9781SMoriah.Waterland@Sun.COM (sizeof (struct cfextra *) * (eptnum+MALSIZ))); 117*9781SMoriah.Waterland@Sun.COM if (!extlist) { 118*9781SMoriah.Waterland@Sun.COM progerr(strerror(errno)); 119*9781SMoriah.Waterland@Sun.COM quit(99); 120*9781SMoriah.Waterland@Sun.COM } 121*9781SMoriah.Waterland@Sun.COM } 122*9781SMoriah.Waterland@Sun.COM } 123*9781SMoriah.Waterland@Sun.COM extlist[eptnum] = (struct cfextra *)NULL; 124*9781SMoriah.Waterland@Sun.COM qsort((char *)extlist, (unsigned)eptnum, sizeof (struct cfextra *), 125*9781SMoriah.Waterland@Sun.COM cfentcmp); 126*9781SMoriah.Waterland@Sun.COM return (myerror); 127*9781SMoriah.Waterland@Sun.COM } 128*9781SMoriah.Waterland@Sun.COM 129*9781SMoriah.Waterland@Sun.COM static int 130*9781SMoriah.Waterland@Sun.COM validate(struct cfextra *ext, int argc, char *argv[]) 131*9781SMoriah.Waterland@Sun.COM { 132*9781SMoriah.Waterland@Sun.COM char *ret, *pt; 133*9781SMoriah.Waterland@Sun.COM int n, allspec, is_a_link; 134*9781SMoriah.Waterland@Sun.COM struct cfent *ept; 135*9781SMoriah.Waterland@Sun.COM 136*9781SMoriah.Waterland@Sun.COM ept = &(ext->cf_ent); 137*9781SMoriah.Waterland@Sun.COM 138*9781SMoriah.Waterland@Sun.COM /* initialize cfent structure */ 139*9781SMoriah.Waterland@Sun.COM ept->pinfo = NULL; 140*9781SMoriah.Waterland@Sun.COM (void) gpkgmapvfp(ept, (VFP_T *)NULL); /* This just clears stuff. */ 141*9781SMoriah.Waterland@Sun.COM 142*9781SMoriah.Waterland@Sun.COM n = allspec = 0; 143*9781SMoriah.Waterland@Sun.COM if (classname) 144*9781SMoriah.Waterland@Sun.COM (void) strncpy(ept->pkg_class, classname, CLSSIZ); 145*9781SMoriah.Waterland@Sun.COM 146*9781SMoriah.Waterland@Sun.COM if (argv[n] == NULL || *(argv[n]) == '\000') { 147*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_NULLPATH)); 148*9781SMoriah.Waterland@Sun.COM return (1); 149*9781SMoriah.Waterland@Sun.COM } 150*9781SMoriah.Waterland@Sun.COM 151*9781SMoriah.Waterland@Sun.COM /* 152*9781SMoriah.Waterland@Sun.COM * It would be a good idea to figure out how to get much of 153*9781SMoriah.Waterland@Sun.COM * this done using facilities in procmap.c - JST 154*9781SMoriah.Waterland@Sun.COM */ 155*9781SMoriah.Waterland@Sun.COM if (pt = strchr(argv[n], '=')) { 156*9781SMoriah.Waterland@Sun.COM *pt = '\0'; /* cut off pathname at the = sign */ 157*9781SMoriah.Waterland@Sun.COM is_a_link = 1; 158*9781SMoriah.Waterland@Sun.COM } else 159*9781SMoriah.Waterland@Sun.COM is_a_link = 0; 160*9781SMoriah.Waterland@Sun.COM 161*9781SMoriah.Waterland@Sun.COM if (RELATIVE(argv[n])) { 162*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_RELPATH), 163*9781SMoriah.Waterland@Sun.COM (argv[n] == NULL) ? "unknown" : argv[n]); 164*9781SMoriah.Waterland@Sun.COM return (1); 165*9781SMoriah.Waterland@Sun.COM } 166*9781SMoriah.Waterland@Sun.COM 167*9781SMoriah.Waterland@Sun.COM /* get the pathnames */ 168*9781SMoriah.Waterland@Sun.COM if (eval_path(&(ext->server_path), &(ext->client_path), 169*9781SMoriah.Waterland@Sun.COM &(ext->map_path), argv[n++]) == 0) 170*9781SMoriah.Waterland@Sun.COM return (1); 171*9781SMoriah.Waterland@Sun.COM 172*9781SMoriah.Waterland@Sun.COM ept->path = ext->client_path; 173*9781SMoriah.Waterland@Sun.COM 174*9781SMoriah.Waterland@Sun.COM /* This isn't likely to happen; but, better safe than sorry. */ 175*9781SMoriah.Waterland@Sun.COM if (RELATIVE(ept->path)) { 176*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_RELPATH), ept->path); 177*9781SMoriah.Waterland@Sun.COM return (1); 178*9781SMoriah.Waterland@Sun.COM } 179*9781SMoriah.Waterland@Sun.COM 180*9781SMoriah.Waterland@Sun.COM if (is_a_link) { 181*9781SMoriah.Waterland@Sun.COM /* links specifications should be handled right here */ 182*9781SMoriah.Waterland@Sun.COM ept->ftype = ((n >= argc) ? 'l' : argv[n++][0]); 183*9781SMoriah.Waterland@Sun.COM 184*9781SMoriah.Waterland@Sun.COM /* If nothing follows the '=', it's invalid */ 185*9781SMoriah.Waterland@Sun.COM if (!pt[1]) { 186*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_LINK), ept->path); 187*9781SMoriah.Waterland@Sun.COM return (1); 188*9781SMoriah.Waterland@Sun.COM } 189*9781SMoriah.Waterland@Sun.COM 190*9781SMoriah.Waterland@Sun.COM /* Test for an argument after the link. */ 191*9781SMoriah.Waterland@Sun.COM if (argc != n) { 192*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_LINKARGS), ept->path); 193*9781SMoriah.Waterland@Sun.COM return (1); 194*9781SMoriah.Waterland@Sun.COM } 195*9781SMoriah.Waterland@Sun.COM 196*9781SMoriah.Waterland@Sun.COM /* 197*9781SMoriah.Waterland@Sun.COM * If it's a link but it's neither hard nor symbolic then 198*9781SMoriah.Waterland@Sun.COM * it's bad. 199*9781SMoriah.Waterland@Sun.COM */ 200*9781SMoriah.Waterland@Sun.COM if (!strchr("sl", ept->ftype)) { 201*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_LINKFTYPE), ept->ftype, ept->path); 202*9781SMoriah.Waterland@Sun.COM return (1); 203*9781SMoriah.Waterland@Sun.COM } 204*9781SMoriah.Waterland@Sun.COM 205*9781SMoriah.Waterland@Sun.COM ext->server_local = pathdup(pt+1); 206*9781SMoriah.Waterland@Sun.COM ext->client_local = ext->server_local; 207*9781SMoriah.Waterland@Sun.COM 208*9781SMoriah.Waterland@Sun.COM ept->ainfo.local = ext->client_local; 209*9781SMoriah.Waterland@Sun.COM 210*9781SMoriah.Waterland@Sun.COM return (0); 211*9781SMoriah.Waterland@Sun.COM } else if (n >= argc) { 212*9781SMoriah.Waterland@Sun.COM /* we are expecting to change object's contents */ 213*9781SMoriah.Waterland@Sun.COM return (0); 214*9781SMoriah.Waterland@Sun.COM } 215*9781SMoriah.Waterland@Sun.COM 216*9781SMoriah.Waterland@Sun.COM ept->ftype = argv[n++][0]; 217*9781SMoriah.Waterland@Sun.COM if (strchr("sl", ept->ftype)) { 218*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_LINK), ept->path); 219*9781SMoriah.Waterland@Sun.COM return (1); 220*9781SMoriah.Waterland@Sun.COM } else if (!strchr("?fvedxcbp", ept->ftype)) { 221*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_FTYPE), ept->ftype, ept->path); 222*9781SMoriah.Waterland@Sun.COM return (1); 223*9781SMoriah.Waterland@Sun.COM } 224*9781SMoriah.Waterland@Sun.COM 225*9781SMoriah.Waterland@Sun.COM if (ept->ftype == 'b' || ept->ftype == 'c') { 226*9781SMoriah.Waterland@Sun.COM if (n < argc) { 227*9781SMoriah.Waterland@Sun.COM ept->ainfo.major = strtol(argv[n++], &ret, 0); 228*9781SMoriah.Waterland@Sun.COM if (ret && *ret) { 229*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_MAJOR), argv[n-1], 230*9781SMoriah.Waterland@Sun.COM ept->path); 231*9781SMoriah.Waterland@Sun.COM return (1); 232*9781SMoriah.Waterland@Sun.COM } 233*9781SMoriah.Waterland@Sun.COM } 234*9781SMoriah.Waterland@Sun.COM if (n < argc) { 235*9781SMoriah.Waterland@Sun.COM ept->ainfo.minor = strtol(argv[n++], &ret, 0); 236*9781SMoriah.Waterland@Sun.COM if (ret && *ret) { 237*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_MINOR), argv[n-1], 238*9781SMoriah.Waterland@Sun.COM ept->path); 239*9781SMoriah.Waterland@Sun.COM return (1); 240*9781SMoriah.Waterland@Sun.COM } 241*9781SMoriah.Waterland@Sun.COM allspec++; 242*9781SMoriah.Waterland@Sun.COM } 243*9781SMoriah.Waterland@Sun.COM } 244*9781SMoriah.Waterland@Sun.COM 245*9781SMoriah.Waterland@Sun.COM allspec = 0; 246*9781SMoriah.Waterland@Sun.COM if (n < argc) { 247*9781SMoriah.Waterland@Sun.COM ept->ainfo.mode = strtol(argv[n++], &ret, 8); 248*9781SMoriah.Waterland@Sun.COM if (ret && *ret) { 249*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_MODE), argv[n-1], ept->path); 250*9781SMoriah.Waterland@Sun.COM return (1); 251*9781SMoriah.Waterland@Sun.COM } 252*9781SMoriah.Waterland@Sun.COM } 253*9781SMoriah.Waterland@Sun.COM if (n < argc) 254*9781SMoriah.Waterland@Sun.COM (void) strncpy(ept->ainfo.owner, argv[n++], ATRSIZ); 255*9781SMoriah.Waterland@Sun.COM if (n < argc) { 256*9781SMoriah.Waterland@Sun.COM (void) strncpy(ept->ainfo.group, argv[n++], ATRSIZ); 257*9781SMoriah.Waterland@Sun.COM allspec++; 258*9781SMoriah.Waterland@Sun.COM } 259*9781SMoriah.Waterland@Sun.COM if (strchr("dxbcp", ept->ftype) && !allspec) { 260*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_ARGC), ept->path); 261*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_SPECALL), ept->ftype); 262*9781SMoriah.Waterland@Sun.COM return (1); 263*9781SMoriah.Waterland@Sun.COM } 264*9781SMoriah.Waterland@Sun.COM if (n < argc) { 265*9781SMoriah.Waterland@Sun.COM progerr(gettext(ERR_ARGC), ept->path); 266*9781SMoriah.Waterland@Sun.COM return (1); 267*9781SMoriah.Waterland@Sun.COM } 268*9781SMoriah.Waterland@Sun.COM return (0); 269*9781SMoriah.Waterland@Sun.COM } 270*9781SMoriah.Waterland@Sun.COM 271*9781SMoriah.Waterland@Sun.COM int 272*9781SMoriah.Waterland@Sun.COM cfentcmp(const void *p1, const void *p2) 273*9781SMoriah.Waterland@Sun.COM { 274*9781SMoriah.Waterland@Sun.COM struct cfextra *ext1 = *((struct cfextra **)p1); 275*9781SMoriah.Waterland@Sun.COM struct cfextra *ext2 = *((struct cfextra **)p2); 276*9781SMoriah.Waterland@Sun.COM 277*9781SMoriah.Waterland@Sun.COM return (strcmp(ext1->cf_ent.path, ext2->cf_ent.path)); 278*9781SMoriah.Waterland@Sun.COM } 279*9781SMoriah.Waterland@Sun.COM 280*9781SMoriah.Waterland@Sun.COM /* 281*9781SMoriah.Waterland@Sun.COM * If the path at argv[0] has the value of 282*9781SMoriah.Waterland@Sun.COM * PKG_INSTALL_ROOT prepended, remove it 283*9781SMoriah.Waterland@Sun.COM */ 284*9781SMoriah.Waterland@Sun.COM static void 285*9781SMoriah.Waterland@Sun.COM checkPaths(char *argv[]) 286*9781SMoriah.Waterland@Sun.COM { 287*9781SMoriah.Waterland@Sun.COM char *root; 288*9781SMoriah.Waterland@Sun.COM int rootLen; 289*9781SMoriah.Waterland@Sun.COM 290*9781SMoriah.Waterland@Sun.COM /* 291*9781SMoriah.Waterland@Sun.COM * Note- No local copy of argv is needed since this 292*9781SMoriah.Waterland@Sun.COM * function is guaranteed to replace argv with a subset of 293*9781SMoriah.Waterland@Sun.COM * the original argv. 294*9781SMoriah.Waterland@Sun.COM */ 295*9781SMoriah.Waterland@Sun.COM 296*9781SMoriah.Waterland@Sun.COM /* We only want to canonize the path if it contains multiple '/'s */ 297*9781SMoriah.Waterland@Sun.COM 298*9781SMoriah.Waterland@Sun.COM canonize_slashes(argv[0]); 299*9781SMoriah.Waterland@Sun.COM 300*9781SMoriah.Waterland@Sun.COM if ((root = get_inst_root()) == NULL) 301*9781SMoriah.Waterland@Sun.COM return; 302*9781SMoriah.Waterland@Sun.COM if (strcmp(root, "/") != 0) { 303*9781SMoriah.Waterland@Sun.COM rootLen = strlen(root); 304*9781SMoriah.Waterland@Sun.COM if (strncmp(argv[0], root, rootLen) == 0) { 305*9781SMoriah.Waterland@Sun.COM argv[0] += rootLen; 306*9781SMoriah.Waterland@Sun.COM } 307*9781SMoriah.Waterland@Sun.COM } 308*9781SMoriah.Waterland@Sun.COM } 309