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
preinstall_verify(char ** a_pkglist,zoneList_t a_zlst,char * a_zoneTempDir)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
getyorn(char * a_msg,char * a_pkg,int a_nocheck,int a_quit,char * a_helpMsg,char * a_adminMsg)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
ckprereqinc(char * a_msg,char * a_pkg)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
ckprereqinst(char * a_msg,char * a_pkg)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
ckpartinst(char * a_msg,char * a_pkg)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
ckpartrem(char * a_msg,char * a_pkg)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
ckrunlevel(char * a_msg,char * a_pkg)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
ckcfcontent(char * a_msg,char * a_pkg)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
ckinstance(char * a_msg,char * a_pkg)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
ckdepend(char * a_msg,char * a_pkg)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
ckspace(char * a_msg,char * a_pkg)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
ckpkgdirs(char * a_msg,char * a_pkg)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
ckdirs(char * a_msg,char * a_pkg)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
ckpkgfilebad(char * a_msg,char * a_pkg)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
ckconflict(char * a_msg,char * a_pkg)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
cksetuid(char * a_msg,char * a_pkg)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
ckpriv(char * a_msg,char * a_pkg)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
ckpkgfiles(char * a_msg,char * a_pkg)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
attrib(char * a_msg,char * a_pkg)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
setuidf(char * a_msg,char * a_pkg)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
setgidf(char * a_msg,char * a_pkg)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
overwr(char * a_msg,char * a_pkg)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