1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <limits.h> 29 #include <string.h> 30 #include <stdlib.h> 31 #include <sys/stat.h> 32 #include <unistd.h> 33 #include <errno.h> 34 #include <dirent.h> 35 #include <sys/types.h> 36 #include <locale.h> 37 #include <libintl.h> 38 #include <pkgstrct.h> 39 #include <pkglocs.h> 40 #include <assert.h> 41 42 #include <instzones_api.h> 43 #include <pkglib.h> 44 #include <messages.h> 45 46 #include <install.h> 47 #include <libinst.h> 48 #include <libadm.h> 49 50 extern int npkgs; /* the number of packages yet to be installed */ 51 52 /* 53 * ckquit is a global that controls 'ckyorn' (defined in libadm) 54 * If ckquit is non-zero, then "quit" is allowed as an answer when 55 * ckyorn is called. If is it zero, then "quit" is not an allowed answer. 56 */ 57 extern int ckquit; 58 59 extern struct admin adm; 60 61 /* 62 * each one of these represents a single kind of dependency check 63 */ 64 65 static depckError_t er_ckconflict = {0, (depckErrorRecord_t *)NULL}; 66 static depckError_t er_ckdepend = {0, (depckErrorRecord_t *)NULL}; 67 static depckError_t er_ckcfcontent = {0, (depckErrorRecord_t *)NULL}; 68 static depckError_t er_ckinstance = {0, (depckErrorRecord_t *)NULL}; 69 static depckError_t er_ckdirs = {0, (depckErrorRecord_t *)NULL}; 70 static depckError_t er_ckpartinst = {0, (depckErrorRecord_t *)NULL}; 71 static depckError_t er_ckpartrem = {0, (depckErrorRecord_t *)NULL}; 72 static depckError_t er_ckpkgdirs = {0, (depckErrorRecord_t *)NULL}; 73 static depckError_t er_ckpkgfilebad = {0, (depckErrorRecord_t *)NULL}; 74 static depckError_t er_ckpkgfiles = {0, (depckErrorRecord_t *)NULL}; 75 static depckError_t er_ckpriv = {0, (depckErrorRecord_t *)NULL}; 76 static depckError_t er_ckrunlevel = {0, (depckErrorRecord_t *)NULL}; 77 static depckError_t er_cksetuid = {0, (depckErrorRecord_t *)NULL}; 78 static depckError_t er_ckspace = {0, (depckErrorRecord_t *)NULL}; 79 static depckError_t er_newonly = {0, (depckErrorRecord_t *)NULL}; 80 static depckError_t er_prereqinc = {0, (depckErrorRecord_t *)NULL}; 81 static depckError_t er_prereqinst = {0, (depckErrorRecord_t *)NULL}; 82 static depckError_t er_runlevel = {0, (depckErrorRecord_t *)NULL}; 83 static depckError_t er_same = {0, (depckErrorRecord_t *)NULL}; 84 static depckError_t er_overwrite = {0, (depckErrorRecord_t *)NULL}; 85 static depckError_t er_uniq1 = {0, (depckErrorRecord_t *)NULL}; 86 static depckError_t er_attrib = {0, NULL}; 87 static depckError_t er_setuidf = {0, NULL}; 88 static depckError_t er_setgidf = {0, NULL}; 89 static depckError_t er_overwr = {0, NULL}; 90 91 /* 92 * each one of these represents a localized message for a single kind 93 * of dependency check 94 */ 95 96 static char *IMSG_ABADFILE = (char *)NULL; 97 static char *IMSG_BADFILE = (char *)NULL; 98 static char *IMSG_CKRUNLVL = (char *)NULL; 99 static char *IMSG_CNFFAILED = (char *)NULL; 100 static char *IMSG_DEPEND = (char *)NULL; 101 static char *IMSG_CFCONTENT = (char *)NULL; 102 static char *IMSG_INSTANCE = "INSTANCE %s <%s> on %s <%s>"; 103 static char *IMSG_DIRS = (char *)NULL; 104 static char *IMSG_NEWONLY = (char *)NULL; 105 static char *IMSG_PARTINST = (char *)NULL; 106 static char *IMSG_PARTREM = (char *)NULL; 107 static char *IMSG_PKGDIRS = (char *)NULL; 108 static char *IMSG_PRENCI = (char *)NULL; 109 static char *IMSG_PREREQ = (char *)NULL; 110 static char *IMSG_PRIV = (char *)NULL; 111 static char *IMSG_RUNLEVEL = (char *)NULL; 112 static char *IMSG_SAME = (char *)NULL; 113 static char *IMSG_OVERWRITE = (char *)NULL; 114 static char *IMSG_UNIQ1 = (char *)NULL; 115 static char *IMSG_SETUID = (char *)NULL; 116 static char *IMSG_SPCFAILED = (char *)NULL; 117 static char *IMSG_ATTRIB; 118 static char *IMSG_SETUIDF; 119 static char *IMSG_SETGIDF; 120 static char *IMSG_OVERWR; 121 122 /* 123 * each one of these represents a function to handle a single kind of 124 * dependency check 125 */ 126 127 static int ckconflict(char *a_msg, char *a_pkg); 128 static int ckdepend(char *a_msg, char *a_pkg); 129 static int ckcfcontent(char *a_msg, char *a_pkg); 130 static int ckinstance(char *a_msg, char *a_pkg); 131 static int ckdirs(char *a_msg, char *a_pkg); 132 static int ckpartinst(char *a_msg, char *a_pkg); 133 static int ckpartrem(char *a_msg, char *a_pkg); 134 static int ckpkgfilebad(char *a_msg, char *a_pkg); 135 static int ckpkgdirs(char *a_msg, char *a_pkg); 136 static int ckpkgfiles(char *a_msg, char *a_pkg); 137 static int ckprereqinc(char *a_msg, char *a_pkg); 138 static int ckprereqinst(char *a_msg, char *a_pkg); 139 static int ckpriv(char *a_msg, char *a_pkg); 140 static int ckrunlevel(char *a_msg, char *a_pkg); 141 static int cksetuid(char *a_msg, char *a_pkg); 142 static int ckspace(char *a_msg, char *a_pkg); 143 static int attrib(char *a_msg, char *a_pkg); 144 static int setuidf(char *a_msg, char *a_pkg); 145 static int setgidf(char *a_msg, char *a_pkg); 146 static int overwr(char *a_msg, char *a_pkg); 147 148 static depckl_t DEPCKL[] = { 149 /* 150 * name, ignore_values, err_msg, depcklFunc, recrd 151 * --- 152 * ignore_values == NULL: 153 * package and zone information is collected in the "record" object for 154 * each occurance - then a message is constructed for each zone that 155 * reported the condition - the message includes that portion of the 156 * check past the "=" - then the specified "depcklFunc" is called to 157 * process each message. 158 * Message format: 159 * %s %s <%s> %s <%s> 160 * Message arguments: 161 * value, "package", package-name, "zone/zones", zone-name 162 * --- 163 * ignore-values == "???": 164 * these checks are ignored if they return one of the listed values 165 * if they do NOT return one of the listed values, then the package 166 * and zone information is collected in the "record" object for each 167 * occurance - then a single unified message is constructed for all 168 * zones that report the same condition; then the specified "depcklFunc" 169 * is called to process the resulting combined message. 170 * Message format: 171 * %s <%s> %s <%s> 172 * Message arguments: 173 * "package", package-name, "zone/zones", zone-name(s) 174 * --- 175 * ignore-values="": 176 * same as above BUT no check to ignore is done; message always reported 177 */ 178 179 { "install-same-instance=true", "", &IMSG_SAME, 180 NULL, &er_same 181 }, 182 { "ckpkgfilebad=", NULL, &IMSG_ABADFILE, 183 &ckpkgfilebad, &er_ckpkgfilebad 184 }, 185 { "ckdirs=", NULL, &IMSG_DIRS, 186 &ckdirs, &er_ckdirs 187 }, 188 { "prerequisite-incomplete=", NULL, &IMSG_PRENCI, 189 &ckprereqinc, &er_prereqinc 190 }, 191 { "prerequisite-installed=", NULL, &IMSG_PREREQ, 192 &ckprereqinst, &er_prereqinst 193 }, 194 { "runlevel=", NULL, &IMSG_RUNLEVEL, 195 NULL, &er_runlevel 196 }, 197 { "conflict-contents=", NULL, &IMSG_CFCONTENT, 198 &ckcfcontent, &er_ckcfcontent 199 }, 200 { "ckconflict=", "0", &IMSG_CNFFAILED, 201 &ckconflict, &er_ckconflict 202 }, 203 { "ckdepend=", "0", &IMSG_DEPEND, 204 &ckdepend, &er_ckdepend 205 }, 206 { "ckpartialinstall=", "0", &IMSG_PARTINST, 207 &ckpartinst, &er_ckpartinst 208 }, 209 { "ckpartialremove=", "0", &IMSG_PARTREM, 210 &ckpartrem, &er_ckpartrem 211 }, 212 { "ckpkgdirs=", "0", &IMSG_PKGDIRS, 213 &ckpkgdirs, &er_ckpkgdirs 214 }, 215 { "ckpkgfiles=", "0", &IMSG_BADFILE, 216 &ckpkgfiles, &er_ckpkgfiles 217 }, 218 { "ckpriv=", "0", &IMSG_PRIV, 219 &ckpriv, &er_ckpriv 220 }, 221 { "ckrunlevel=", "0", &IMSG_CKRUNLVL, 222 &ckrunlevel, &er_ckrunlevel 223 }, 224 { "cksetuid=", "0", &IMSG_SETUID, 225 &cksetuid, &er_cksetuid 226 }, 227 { "ckspace=", "0", &IMSG_SPCFAILED, 228 &ckspace, &er_ckspace 229 }, 230 { "install-new-only=true", "", &IMSG_NEWONLY, 231 NULL, &er_newonly 232 }, 233 { "install-ovewrite=true", "", &IMSG_OVERWRITE, 234 NULL, &er_overwrite 235 }, 236 { "install-too-many-instances=true", "", &IMSG_UNIQ1, 237 NULL, &er_uniq1 238 }, 239 { "ckinstance=", "0", &IMSG_INSTANCE, 240 &ckinstance, &er_ckinstance 241 }, 242 { "conflict-attributes=", NULL, &IMSG_ATTRIB, 243 &attrib, &er_attrib 244 }, 245 { "setuid=", NULL, &IMSG_SETUIDF, 246 &setuidf, &er_setuidf 247 }, 248 { "setgid=", NULL, &IMSG_SETGIDF, 249 &setgidf, &er_setgidf 250 }, 251 { "setuid-overwrite=true", "", &IMSG_OVERWR, 252 &overwr, &er_overwr 253 }, 254 255 { NULL, NULL, NULL, 256 NULL, NULL } 257 }; 258 259 /* 260 * Name: preinstall_verify 261 * Description: verify results of preinstallation dependency checking 262 * Arguments: a_pkglist - pointer to array of strings representing the names 263 * of all the packages that have been checked 264 * a_zlst - list of zones that dependencies were checked on 265 * a_zoneTempDir - pointer to string representing the path where 266 * the files containing the preinstallation dependency 267 * check data are located 268 * Returns: int 269 * == 0 - continue processing 270 * != 0 - do not continue processing 271 */ 272 273 int 274 preinstall_verify(char **a_pkglist, zoneList_t a_zlst, char *a_zoneTempDir) 275 { 276 char *pkginst; 277 int i; 278 int savenpkgs = npkgs; 279 280 /* 281 * entry assertions 282 */ 283 284 assert(a_pkglist != (char **)NULL); 285 assert(a_zlst != (zoneList_t)NULL); 286 assert(a_zoneTempDir != (char *)NULL); 287 288 /* 289 * entry debugging info 290 */ 291 292 echoDebug(DBG_PREIVFY_ENTRY); 293 294 /* 295 * localize messages 296 */ 297 298 IMSG_ABADFILE = MSG_PKGADDCHK_ABADFILE; 299 IMSG_BADFILE = MSG_PKGADDCHK_BADFILE; 300 IMSG_CFCONTENT = MSG_PKGADDCHK_CFCONTENT; 301 IMSG_CKRUNLVL = MSG_PKGADDCHK_CKRUNLVL; 302 IMSG_CNFFAILED = MSG_PKGADDCHK_CNFFAILED; 303 IMSG_DEPEND = MSG_PKGADDCHK_DEPEND; 304 IMSG_DIRS = MSG_PKGADDCHK_DIRS; 305 IMSG_NEWONLY = MSG_PKGADDCHK_NEWONLY; 306 IMSG_OVERWRITE = MSG_PKGADDCHK_OVERWRITE; 307 IMSG_PARTINST = MSG_PKGADDCHK_PARTINST; 308 IMSG_PARTREM = MSG_PKGADDCHK_PARTREM; 309 IMSG_PKGDIRS = MSG_PKGADDCHK_PKGDIRS; 310 IMSG_PRENCI = MSG_PKGADDCHK_PRENCI; 311 IMSG_PREREQ = MSG_PKGADDCHK_PREREQ; 312 IMSG_PRIV = MSG_PKGADDCHK_PRIV; 313 IMSG_RUNLEVEL = MSG_PKGADDCHK_RUNLEVEL; 314 IMSG_SAME = MSG_PKGADDCHK_SAME; 315 IMSG_SETUID = MSG_PKGADDCHK_SETUID; 316 IMSG_SPCFAILED = MSG_PKGADDCHK_SPCFAILED; 317 IMSG_UNIQ1 = MSG_PKGADDCHK_UNIQ1; 318 IMSG_ATTRIB = gettext("\\nattribute change for %s <%s> on %s <%s>\n"); 319 IMSG_SETUIDF = gettext("\\nsetuid %s in %s <%s> on %s <%s>\n"); 320 IMSG_SETGIDF = gettext("\\nsetgid %s in %s <%s> on %s <%s>\n"); 321 IMSG_OVERWR = gettext("\\nFiles that are setuid will be overwritten " 322 "by installation of %s\n<%s> on %s <%s>.\n"); 323 324 /* 325 * outer loop - process each package first 326 */ 327 328 for (i = 0; (pkginst = a_pkglist[i]) != NULL; i++) { 329 330 char *zoneName; 331 int zoneIndex; 332 333 /* 334 * if this package is marked "install in this zone only", then 335 * do not check dependencies in any zone 336 */ 337 338 if (pkgPackageIsThisZone(pkginst) == B_TRUE) { 339 echoDebug(DBG_PREIVFY_SKIP_THISZONE, pkginst); 340 continue; 341 } 342 343 /* 344 * inner loop - for each package process each zone second 345 */ 346 347 for (zoneIndex = 0; 348 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != 349 (char *)NULL; zoneIndex++) { 350 351 FILE *fp; 352 char line[PATH_MAX+1]; 353 char preinstallcheckPath[PATH_MAX+1]; 354 int len; 355 356 /* skip the zone if it is NOT bootable */ 357 358 if (z_zlist_is_zone_runnable(a_zlst, 359 zoneIndex) == B_FALSE) { 360 continue; 361 } 362 363 /* create path to this packages preinstall check data */ 364 365 len = snprintf(preinstallcheckPath, 366 sizeof (preinstallcheckPath), 367 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, 368 pkginst, zoneName); 369 370 if (len > sizeof (preinstallcheckPath)) { 371 progerr(ERR_CREATE_PATH_3, a_zoneTempDir, 372 pkginst, zoneName); 373 continue; 374 } 375 376 /* error if preinstall check data path is not a file */ 377 378 if (isfile((char *)NULL, preinstallcheckPath) != 0) { 379 echoDebug(DBG_PREIVFY_NOFILE, 380 pkginst, zoneName, preinstallcheckPath, 381 strerror(errno)); 382 progerr(ERR_PREIVFY_NOFILE, 383 pkginst, zoneName); 384 continue; 385 } 386 387 /* open the preinstall check data file */ 388 389 fp = fopen(preinstallcheckPath, "r"); 390 if (fp == (FILE *)NULL) { 391 progerr(ERR_PREIVFY_OPEN_FILE, 392 preinstallcheckPath, pkginst, zoneName, 393 strerror(errno)); 394 continue; 395 } 396 397 /* read and process each preinstall check data line */ 398 399 while (fgets(line, sizeof (line), fp) != (char *)NULL) { 400 int j; 401 int len; 402 403 /* remove all new-lines from end of line */ 404 405 len = strlen(line); 406 while ((len > 0) && (line[len-1] == '\n')) { 407 line[--len] = '\0'; 408 } 409 410 /* ignore comment lines */ 411 412 if (line[0] == '#') { 413 continue; 414 } 415 416 /* ignore empty lines */ 417 418 if (line[0] == '\0') { 419 continue; 420 } 421 422 /* scan dependency list for this item */ 423 424 for (j = 0; 425 DEPCKL[j].name != (char *)NULL; j++) { 426 len = strlen(DEPCKL[j].name); 427 428 if (strncmp(line, DEPCKL[j].name, 429 len) == 0) { 430 break; 431 } 432 } 433 434 echoDebug(DBG_PREIVFY_SCAN, line, pkginst, 435 zoneName); 436 437 /* ignore line if not found */ 438 439 if (DEPCKL[j].name == (char *)NULL) { 440 progerr(ERR_PREIVFY_UNKNOWN_LINE, line, 441 pkginst, zoneName); 442 continue; 443 } 444 445 if ((DEPCKL[j].ignore_values != (char *)NULL) && 446 (*(DEPCKL[j].ignore_values) != '\0') && 447 (strchr(DEPCKL[j].ignore_values, 448 line[len]) != (char *)NULL)) { 449 continue; 450 } 451 452 /* found match - record this dependency issue */ 453 454 depchkRecordError(DEPCKL[j].record, pkginst, 455 zoneName, &line[len]); 456 } 457 458 /* close preinstall check data file */ 459 460 (void) fclose(fp); 461 } 462 } 463 464 /* 465 * all dependency issues have been recorded; report results 466 */ 467 468 i = depchkReportErrors(DEPCKL); 469 470 /* restore "npkgs" */ 471 472 npkgs = savenpkgs; 473 474 /* return continue/dont dontinue results */ 475 476 return (i); 477 } 478 479 /* 480 * Name: getyorn 481 * Description: Deliver dependency check reason; ask question; return response 482 * Arguments: a_msg - pointer to string representing the message to output 483 * such as 'The package <..> contains <...>' 484 * a_pkg - pointer to string representing the package for which 485 * the question is being asked 486 * a_nocheck - should the message be output? 487 * == 0 - do not output the message 488 * != 0 - output the message 489 * a_quit - should the question NOT be asked? 490 * == 0 - ask the question 491 * != 0 - do not ask the question - return "no" 492 * a_helpMsg - pointer to string representing help message to be 493 * made available if the question is asked 494 * == NULL - no help message is available 495 * a_adminMsg - pointer to string representing the dependency check 496 * failure 'reason' - such as "Privilege checking failed." 497 * == NULL - no failure reason is available 498 * Returns: int - results of question/response actions 499 * 0 - success 500 * 1 - end of file 501 * 2 - undefined error 502 * 3 - answer was not "y"/was "q" 503 * 4 - quit action taken 504 * 5 - interactive mode required 505 */ 506 507 static int 508 getyorn(char *a_msg, char *a_pkg, int a_nocheck, int a_quit, 509 char *a_helpMsg, char *a_adminMsg) 510 { 511 char ans[MAX_INPUT]; 512 char ask_cont[MSG_MAX]; 513 int n; 514 int saveCkquit; 515 516 /* 517 * entry assertions 518 */ 519 520 assert(a_pkg != (char *)NULL); 521 assert(*a_pkg != '\0'); 522 523 /* 524 * entry debugging info 525 */ 526 527 echoDebug(DBG_PREIVFY_GETYORN_ARGS, a_pkg, a_nocheck, a_quit, a_msg, 528 a_adminMsg ? a_adminMsg : ""); 529 530 /* return success (0) if "nocheck" is non-zero */ 531 532 if (a_nocheck != 0) { 533 echoDebug(DBG_PREIVFY_GETYORN_NOCHECK, a_pkg); 534 return (0); 535 } 536 537 /* output reason for this particular failure */ 538 539 if ((a_msg != (char *)NULL) && (*a_msg != '\0')) { 540 ptext(stderr, "%s", a_msg); 541 } 542 543 /* return "4 (administration)" if "quit" is non-zero */ 544 545 if (a_quit != 0) { 546 /* output failure "admin reason" if available */ 547 if ((a_adminMsg != (char *)NULL) && (*a_adminMsg != '\0')) { 548 ptext(stderr, a_adminMsg); 549 } 550 echoDebug(DBG_PREIVFY_GETYORN_QUIT, a_pkg); 551 return (4); 552 } 553 554 /* return "5 (administration interaction required)" if -n */ 555 556 if (echoGetFlag() == B_FALSE) { 557 ptext(stderr, MSG_PREIVFY_GETYORN_SUSP, a_pkg); 558 echoDebug(DBG_PREIVFY_GETYORN_QUIT_USER, a_pkg); 559 return (5); 560 } 561 562 /* prepare question to ask "continue with pkg <xxx>?" */ 563 564 (void) snprintf(ask_cont, sizeof (ask_cont), gettext(ASK_CONT), a_pkg); 565 566 /* ask question */ 567 568 saveCkquit = ckquit; 569 ckquit = 0; 570 571 n = ckyorn(ans, NULL, NULL, a_helpMsg, ask_cont); 572 573 ckquit = saveCkquit; 574 575 if (n != 0) { 576 ptext(stderr, MSG_PREIVFY_GETYORN_TERM, a_pkg); 577 echoDebug(DBG_PREIVFY_GETYORN_CKYORN, a_pkg, n); 578 return (n); 579 } 580 581 /* return "3 (interruption) if not "y" or "Y" */ 582 583 if (strchr("yY", *ans) == NULL) { 584 ptext(stderr, MSG_PREIVFY_GETYORN_TERM_USER, a_pkg); 585 echoDebug(DBG_PREIVFY_GETYORN_NOT_Y, a_pkg, ans); 586 return (3); 587 } 588 589 /* return "0 - success" */ 590 591 echoDebug(DBG_PREIVFY_GETYORN_SUCCESS, a_pkg); 592 593 return (0); 594 } 595 596 /* 597 * Trigger: prerequisite-incomplete=<<package>> 598 * Sequence: - one or more: prerequisite-incomplete=<<package>> 599 * - one: ckdepend=<<n>> 600 * Actions: Output message if "idepend!=nocheck" 601 * Return 0 602 * Terminate when 'ckdepend' processed 603 */ 604 605 static int 606 ckprereqinc(char *a_msg, char *a_pkg) 607 { 608 echoDebug(DBG_PREIVFY_CKPRENCI, a_pkg, a_msg); 609 610 if (!(ADM(idepend, "nocheck"))) { 611 ptext(stderr, "%s", a_msg); 612 } 613 614 return (0); 615 } 616 617 /* 618 * Trigger: prerequisite-installed=<<package>> 619 * Sequence: - one or more: prerequisite-installed=<<package>> 620 * - one: ckdepend=<<n>> 621 * Actions: Output message if "idepend!=nocheck" 622 * Return 0 623 * Terminate when 'ckdepend' processed 624 */ 625 626 static int 627 ckprereqinst(char *a_msg, char *a_pkg) 628 { 629 echoDebug(DBG_PREIVFY_CKPREREQ, a_pkg, a_msg); 630 631 if (!(ADM(idepend, "nocheck"))) { 632 ptext(stderr, "%s", a_msg); 633 } 634 635 return (0); 636 } 637 638 /* 639 * Trigger: ckpartialinstall=<<n>> 640 * Sequence: - one: ckpartialinstall=<<n>> 641 * Actions: process according to settings 642 * Return value: int 643 * 0 - success 644 * 1 - end of file 645 * 2 - undefined error 646 * 3 - answer was not "y"/was "q" 647 * 4 - quit action taken 648 * 5 - interactive mode required 649 */ 650 651 static int 652 ckpartinst(char *a_msg, char *a_pkg) 653 { 654 echoDebug(DBG_PREIVFY_CKPARTIALINSTALL, a_pkg, a_msg); 655 656 return (getyorn(a_msg, a_pkg, ADM(partial, "nocheck"), 657 ADM(partial, "quit"), HLP_PKGADDCHK_PARTIAL, NULL)); 658 } 659 660 /* 661 * Trigger: ckpartialremove=<<n>> 662 * Sequence: - one: ckpartialremove=<<n>> 663 * Actions: process according to settings 664 * Return value: int 665 * 0 - success 666 * 1 - end of file 667 * 2 - undefined error 668 * 3 - answer was not "y"/was "q" 669 * 4 - quit action taken 670 * 5 - interactive mode required 671 */ 672 673 static int 674 ckpartrem(char *a_msg, char *a_pkg) 675 { 676 echoDebug(DBG_PREIVFY_CKPARTIALREMOVE, a_pkg, a_msg); 677 678 return (getyorn(a_msg, a_pkg, ADM(partial, "nocheck"), 679 ADM(partial, "quit"), HLP_PKGADDCHK_PARTIAL, NULL)); 680 } 681 682 /* 683 * Return value: int 684 * 0 - success 685 * 1 - end of file 686 * 2 - undefined error 687 * 3 - answer was not "y"/was "q" 688 * 4 - quit action taken 689 * 5 - interactive mode required 690 * 99 - fatal error 691 */ 692 693 static int 694 ckrunlevel(char *a_msg, char *a_pkg) 695 { 696 echoDebug(DBG_PREIVFY_CKRUNLEVEL, a_pkg, a_msg); 697 return (0); 698 } 699 700 /* 701 * Trigger: conflict-contents=<<n>> 702 * Sequence: - one or more of: 703 * -- conflict-contents=<<path>> 704 * -- conflict-attributes=<<path>> 705 * - one: ckconflict=<<n>> 706 * Actions: output message 707 * Return value: int 708 * 0 - success 709 */ 710 711 static int 712 ckcfcontent(char *a_msg, char *a_pkg) 713 { 714 echoDebug(DBG_PREIVFY_CKCFCONTENT, a_pkg, a_msg); 715 716 ptext(stderr, "%s", a_msg); 717 718 return (0); 719 } 720 721 /* 722 * Trigger: ckinstance=<<n>> 723 * Sequence: - one or more of: 724 * -- install-instance=true 725 * -- install-new-only=true\n 726 * -- install-same-instance=true\n 727 * -- install-ovewrite=true\n 728 * -- install-too-many-instances=true\n 729 * -- install-new-instance=true\n 730 * - one: ckpdepend=<<n>> 731 * Actions: process according to settings 732 * Return value: int 733 * 0 - success 734 * 1 - end of file 735 * 2 - undefined error 736 * 3 - answer was not "y"/was "q" 737 * 4 - quit action taken 738 * 5 - interactive mode required 739 */ 740 741 static int 742 ckinstance(char *a_msg, char *a_pkg) 743 { 744 echoDebug(DBG_PREIVFY_CKINSTANCE, a_pkg, a_msg); 745 746 return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"), 747 ADM(instance, "quit"), HLP_PKGADDCHK_DEPEND, 748 ERR_PKGADDCHK_DEPFAILED)); 749 } 750 751 /* 752 * Trigger: ckdepend=<<n>> 753 * Sequence: - one or more of: 754 * -- incompat=<<package>> 755 * -- prerequisite-incomplete=<<package>> 756 * -- prerequisite-installed=<<package>> 757 * -- dependson=<<package>> 758 * -- dependsonme=<<package>> 759 * - one: ckpdepend=<<n>> 760 * Actions: process according to settings 761 * Return value: int 762 * 0 - success 763 * 1 - end of file 764 * 2 - undefined error 765 * 3 - answer was not "y"/was "q" 766 * 4 - quit action taken 767 * 5 - interactive mode required 768 */ 769 770 static int 771 ckdepend(char *a_msg, char *a_pkg) 772 { 773 echoDebug(DBG_PREIVFY_CKDEPEND, a_pkg, a_msg); 774 775 return (getyorn(a_msg, a_pkg, ADM(idepend, "nocheck"), 776 ADM(idepend, "quit"), HLP_PKGADDCHK_DEPEND, 777 ERR_PKGADDCHK_DEPFAILED)); 778 } 779 780 /* 781 * Trigger: ckspace=<<n>> 782 * Sequence: - one: ckspace=<<n>> 783 * Actions: process according to settings 784 * Return value: int 785 * 0 - success 786 * 1 - end of file 787 * 2 - undefined error 788 * 3 - answer was not "y"/was "q" 789 * 4 - quit action taken 790 * 5 - interactive mode required 791 */ 792 793 static int 794 ckspace(char *a_msg, char *a_pkg) 795 { 796 echoDebug(DBG_PREIVFY_CKSPACE, a_pkg, a_msg); 797 798 return (getyorn(a_msg, a_pkg, ADM(space, "nocheck"), 799 ADM(space, "quit"), HLP_PKGADDCHK_SPACE, 800 ERR_PKGADDCHK_SPCFAILED)); 801 } 802 803 /* 804 * Trigger: ckpkgdirs=<<n>> 805 * Sequence: - one: ckpkgdirs=<<n>> 806 * Actions: output message 807 * Return 4 808 */ 809 810 static int 811 ckpkgdirs(char *a_msg, char *a_pkg) 812 { 813 echoDebug(DBG_PREIVFY_CKPKGDIRS, a_pkg, a_msg); 814 815 ptext(stderr, "%s", a_msg); 816 817 return (4); 818 } 819 820 /* 821 * Trigger: ckdirs=<<path>> 822 * Sequence: - one: ckdirs=<<path>> 823 * Actions: output message 824 * Return 4 825 */ 826 827 static int 828 ckdirs(char *a_msg, char *a_pkg) 829 { 830 echoDebug(DBG_PREIVFY_CKDIRS, a_pkg, a_msg); 831 832 ptext(stderr, "%s", a_msg); 833 834 ptext(stderr, ERR_PKGADDCHK_MKPKGDIR); 835 836 return (4); 837 } 838 839 /* 840 * Trigger: ckpkgfilebad=<<path>> 841 * Sequence: - one or more: 842 * -- ckpkgfilebad=<<path>> 843 * - one ckpkgfiles=<n> 844 * Actions: output message 845 * Return 0 846 */ 847 848 static int 849 ckpkgfilebad(char *a_msg, char *a_pkg) 850 { 851 echoDebug(DBG_PREIVFY_CKPKGFILEBAD, a_pkg, a_msg); 852 853 ptext(stderr, "%s", a_msg); 854 855 return (0); 856 } 857 858 /* 859 * Trigger: ckconflict=<<n>> 860 * Sequence: - one or more: 861 * -- conflict-contents=<<path>> 862 * -- conflict-attributes=<<path>> 863 * - one: ckconflict=<<n>> 864 * Actions: process according to settings 865 * Return value: int 866 * 0 - success 867 * 1 - end of file 868 * 2 - undefined error 869 * 3 - answer was not "y"/was "q" 870 * 4 - quit action taken 871 * 5 - interactive mode required 872 */ 873 874 static int 875 ckconflict(char *a_msg, char *a_pkg) 876 { 877 echoDebug(DBG_PREIVFY_CKCONFLICT, a_pkg, a_msg); 878 879 return (getyorn(a_msg, a_pkg, ADM(conflict, "nocheck"), 880 ADM(conflict, "quit"), HLP_PKGADDCHK_CONFLICT, 881 ERR_PKGADDCHK_CNFFAILED)); 882 } 883 884 /* 885 * Trigger: cksetuid=<<n>> 886 * Sequence: - one or more: 887 * -- setuid=<path>:<owner> 888 * -- setgid=<path>:<group> 889 * -- setuid-overwrite=true 890 * - one: cksetuid=<<n>> 891 * Actions: process according to settings 892 * Return value: int 893 * 0 - success 894 * 1 - end of file 895 * 2 - undefined error 896 * 3 - answer was not "y"/was "q" 897 * 4 - quit action taken 898 * 5 - interactive mode required 899 */ 900 901 static int 902 cksetuid(char *a_msg, char *a_pkg) 903 { 904 char ans[MAX_INPUT]; 905 char ask_cont[MSG_MAX]; 906 int n; 907 int saveCkquit; 908 909 echoDebug(DBG_PREIVFY_CKSETUID, a_pkg, a_msg); 910 911 n = getyorn(a_msg, a_pkg, ADM(setuid, "nocheck"), 912 ADM(setuid, "quit"), HLP_PKGADDCHK_SETUID, NULL); 913 914 /* if user did not answer "n" return answer given */ 915 916 if (n != 3) { 917 return (n); 918 } 919 920 (void) snprintf(ask_cont, sizeof (ask_cont), gettext(ASK_CONT), a_pkg); 921 922 saveCkquit = ckquit; 923 ckquit = 0; 924 925 n = ckyorn(ans, NULL, NULL, gettext(HLP_PKGADDCHK_CONT), ask_cont); 926 927 ckquit = saveCkquit; 928 929 if (n != 0) { 930 ptext(stderr, MSG_PREIVFY_GETYORN_TERM, a_pkg); 931 echoDebug(DBG_PREIVFY_GETYORN_CKYORN, a_pkg, n); 932 return (n); 933 } 934 935 /* return "3 (interruption) if not "y" or "Y" */ 936 937 if (strchr("yY", *ans) == NULL) { 938 ptext(stderr, MSG_PREIVFY_GETYORN_TERM_USER, a_pkg); 939 echoDebug(DBG_PREIVFY_GETYORN_NOT_Y, a_pkg, ans); 940 return (3); 941 } 942 943 /* return "0 - success" */ 944 945 echoDebug(DBG_PREIVFY_GETYORN_SUCCESS, a_pkg); 946 947 return (0); 948 } 949 950 /* 951 * Trigger: ckpriv=<<n>> 952 * Sequence: - one: ckpriv=<<n>> 953 * Actions: process according to settings 954 * Return value: int 955 * 0 - success 956 * 1 - end of file 957 * 2 - undefined error 958 * 3 - answer was not "y"/was "q" 959 * 4 - quit action taken 960 * 5 - interactive mode required 961 */ 962 963 static int 964 ckpriv(char *a_msg, char *a_pkg) 965 { 966 echoDebug(DBG_PREIVFY_CKPRIV, a_pkg, a_msg); 967 968 return (getyorn(a_msg, a_pkg, ADM(action, "nocheck"), 969 ADM(action, "quit"), HLP_PKGADDCHK_PRIV, 970 ERR_PKGADDCHK_PRIVFAILED)); 971 } 972 973 /* 974 * Trigger: ckpkgfiles=<<n>> 975 * Sequence: - one or more: 976 * -- ckpkgfilebad=<path> 977 * - one: ckpkgfiles=<<n>> 978 * Return value: int 979 * 0 - success 980 * 4 - failure 981 */ 982 983 static int 984 ckpkgfiles(char *a_msg, char *a_pkg) 985 { 986 echoDebug(DBG_PREIVFY_CKPKGFILES, a_pkg, a_msg); 987 988 ptext(stderr, "%s", a_msg); 989 990 return (4); 991 } 992 993 static int 994 attrib(char *a_msg, char *a_pkg) 995 { 996 return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"), 997 ADM(instance, "quit"), HLP_PKGADDCHK_CONT, 998 ERR_PKGADDCHK_DEPFAILED)); 999 } 1000 1001 /* ARGSUSED1 */ 1002 static int 1003 setuidf(char *a_msg, char *a_pkg) 1004 { 1005 char *cp; 1006 1007 if ((cp = strchr(a_msg, ':')) != NULL) 1008 *cp = ' '; 1009 return (0); 1010 } 1011 1012 /* ARGSUSED1 */ 1013 static int 1014 setgidf(char *a_msg, char *a_pkg) 1015 { 1016 char *cp; 1017 1018 if ((cp = strchr(a_msg, ':')) != NULL) 1019 *cp = ' '; 1020 return (0); 1021 } 1022 1023 static int 1024 overwr(char *a_msg, char *a_pkg) 1025 { 1026 return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"), 1027 ADM(instance, "quit"), HLP_PKGADDCHK_SETUID, 1028 ERR_PKGADDCHK_DEPFAILED)); 1029 } 1030