xref: /onnv-gate/usr/src/cmd/svr4pkg/libinst/psvr4ck.c (revision 9781:ccf49524d5dc)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <dirent.h>
37 #include <ctype.h>
38 #include <sys/utsname.h>
39 #include <locale.h>
40 #include <libintl.h>
41 #include <pkglib.h>
42 #include <libinst.h>
43 #include <libadm.h>
44 
45 #ifdef	MAILCMD
46 #undef  MAILCMD
47 #define	MAILCMD		"/bin/mail"
48 #endif	/* MAILCMD */
49 #define	ERR_MAIL	"unable to send electronic mail notification"
50 #define	ERR_OVERWRITE	"unable to determine overwrite list"
51 #define	ERR_PIPE	"unable to open pipe to process <%s>"
52 #define	ASK_CONT	"Do you want to continue processing this package"
53 #define	MSG_CONFLICT	"The following files are currently being used by " \
54 			"other packages on the system, and may be " \
55 			"overwritten by the installation of this pre-SVR4 " \
56 			"package:"
57 #define	HLP_CONFLICT	"If you choose to continue installation, it is " \
58 			"possible that you will overwrite files which are " \
59 			"part of another package that is already installed " \
60 			"on the system.  If you want to assure that the " \
61 			"files are not overwritten, answer 'n' to stop the " \
62 			"installation process."
63 #define	MSG_NOTVER	"The media being processed is in an old (pre-SVR4) " \
64 			"format and it is not possible to verify that the " \
65 			"inserted media belongs to the <%s> package."
66 #define	HLP_NOTVER	"If you choose to continue installation, it is " \
67 			"possible that you will install the wrong package.  " \
68 			"If you are sure the media being installed contains " \
69 			"the package you wish to install, answer 'y' to " \
70 			"continue the installation process."
71 #define	MSG_CONFIRM	"The media being processed is in an old (pre-SVR4) " \
72 			"format and appears to be part of the <%s> package."
73 #define	HLP_CONFIRM	"The installation of older-style (pre-SVR4) packages " \
74 			"is, in general, not as robust as installing " \
75 			"standard packages.  Older packages may attempt " \
76 			"things during installation which overwrite existing " \
77 			"files or otherwise modify the system without your " \
78 			"approval.  If you wish to allow installation of " \
79 			"identified pre-SVR4 package, answer 'y' to continue " \
80 			"the installation process."
81 
82 static char	*Rlist[] = {
83 	"/install/install/Rlist",
84 	"/install/install/RLIST",
85 	"/install/install/rlist",
86 	NULL
87 };
88 
89 static char	ckcmd[] = "/usr/sbin/pkgchk -L -i %s";
90 
91 /*
92  * Remove the list & both #defines below for on1095 -- JST
93  * Further, please note :
94  * This is NOT a database (Oh, yeah it looks like it, but it isn't). For that
95  * reason these are in alphabetical order. Any additions must maintain this
96  * order and must not increase the list length beyond 120.
97  */
98 #define	TREEHEIGHT	7
99 #define	TREEFILL	4	/* number of fill entries per side */
100 
101 #ifdef	ALLOW_EXCEPTION_PKG_LIST
102 static char *x_pkg[] =
103 {
104 	"AAAA1",	/* fill to avoid constraint tests in loop */
105 	"AAAA2",
106 	"AAAA3",
107 	"AAAA4",
108 	/* '+' means packages known to be non-compliant */
109 	"SPROcpl",	/* + bugID 1133962 */
110 	"SPROlklnt",	/* + SW Lock_Lint */
111 	"SPROltool",	/* + SW Loop Profiling Tools */
112 	"SPROssbd",	/* + SW ssbd component for SC 3.0 */
113 	"SPROtha",	/* + Performance Analzyer */
114 	"SUNW3270c",	/* + SunLink Client 3270 */
115 	"SUNW3270g",	/* SunLink CG3270 8.0 */
116 	"SUNW3270t",	/* + SunLink TN3270*Server */
117 	"SUNW86nma",	/* SunNet Manager Core Tools for x86 */
118 	"SUNW86nmc",	/* SunNet Manager Agents & Libraries for x86 */
119 	"SUNW86nmp",	/* SunNet Manager SNMP daemon for x86 */
120 	"SUNWabcg",	/* SunLink CG320 8.0 User's Guide */
121 	"SUNWbf",	/* + 2.0 FDDI/S Beta */
122 	"SUNWbsccu",	/* SunLink BSC Core Util */
123 	"SUNWbscdr",	/* SunLink BSC Drivers */
124 	"SUNWcosiA",	/* OSI Core Stack Kernel Files 1 */
125 	"SUNWcosiC",	/* Stack Mgmnt Utilities 2 */
126 	"SUNWcosia",	/* + OSI Core Stack Kernel Files */
127 	"SUNWcosib",	/* OSI Core Stack Configuration Files */
128 	"SUNWcosic",	/* OSI Core Stack Utilities */
129 	"SUNWcosid",	/* OSI Core Stack Development Kit (new pakage) */
130 	"SUNWcosij",	/* OSI Core Stack User Space Utilities */
131 	"SUNWdniCU",	/* + SunLink DNI Core Utilities 8.0 */
132 	"SUNWdniKR",	/* + SunLink DNI Kernel 8.0 */
133 	"SUNWdniMA",	/* SunLink DNI Mail Agent 8.0 */
134 	"SUNWflex",	/* + FLEX LM DEVEL PKG */
135 	"SUNWftama",	/* OSI FTAM Configuration Files */
136 	"SUNWftamb",	/* OSI FTAM Executable, Libraries and Man Pages */
137 	"SUNWhsis",	/* SunConnect HSI/S */
138 	"SUNWjaCL",	/* + Frances Ho confirms for SUNpics */
139 	"SUNWjncmt",	/* SunNet Manager Core Tools(Japan) */
140 	"SUNWjnmag",	/* SunNet Manager Agents & Libraries (Japan) */
141 	"SUNWjnmpd",	/* SunNet Manager SNMP daemon(Japan) */
142 	"SUNWlicsw",	/* + FLEXlm */
143 	"SUNWlit",	/* STE LIC INSTALL TOOL */
144 	"SUNWllc2a",	/* X.25 LLC2 KRNL MOD, INCLDS FL */
145 	"SUNWllc2b",	/* X.25 USR PROG, MAN PAGES */
146 	"SUNWmd",	/* + Suhas Patil request 1994-07-12 */
147 	"SUNWmhs1a",	/* MHS Message Transfer Agent Configuration Files */
148 	"SUNWmhs1b",	/* MHS Message Transfer Agent Executable and Man Pgs */
149 	"SUNWomgta",	/* OSI Mgmnt Configuration Files */
150 	"SUNWomgtb",	/* OSI Mgmnt Configuration Files */
151 	"SUNWomgtc",	/* OSI Mgmnt SunNet Mgr Proxy Agent Executable Files */
152 	"SUNWomgtd",	/* OSI Mgmnt SunNet Mgr Proxy Agent Config Files */
153 	"SUNWp2pnm",	/* SunLink SNA Peer-to-Peer Network Management */
154 	"SUNWprsto",	/* + Varun Mehta request 1994-07-11 */
155 	"SUNWrup2p",	/* Sunlink SNA Peer-to-Peer Run Time Environment */
156 	"SUNWs3270",	/* + SunLink SNA3270/RJE */
157 	"SUNWscmmd",	/* SunLink Comm Daemon */
158 	"SUNWsdlc",	/* SunLink IBM SDLC */
159 	"SUNWsm-ml",	/* ShowMe Motif Libs */
160 	"SUNWsm-ol",	/* ShowMe Online help */
161 	"SUNWsmCmg",
162 	"SUNWsmap",	/* SunLink Mapper */
163 	"SUNWsmaud",	/* ShowMe Audio */
164 	"SUNWsmsha",	/* ShowMe SharedApp */
165 	"SUNWsmvid",	/* ShowMe Video */
166 	"SUNWsmwtb",	/* ShowMe Whiteboard */
167 	"SUNWsnmag",	/* + Steve Wong request 1994-02-15 */
168 	"SUNWsnmct",	/* + Steve Wong request 1994-02-15 */
169 	"SUNWsnmja",	/* SunNet Manager 2.2 Japanese feature */
170 	"SUNWsnmpd",	/* SunNet Manager SNMP daemon */
171 	"SUNWsnp2p",	/* + SunLink SNA P-to-P */
172 	"SUNWspii",	/* 1.0 SPARCprinterII */
173 	"SUNWsrjec",	/* + SunLink Client SNA RJE */
174 	"SUNWsteCL",	/* + Frances Ho confirms for SUNPics */
175 	"SUNWsteNP",	/* 2.5 NeWSprint */
176 	"SUNWte320",	/* + TE320 8.0 */
177 	"SUNWtris",	/* SunConnect TRI/S */
178 	"SUNWvtcfg",	/* OSI Virtual Terminal Configuration Files */
179 	"SUNWvtexe",	/* OSI Virtual Terminal User Program and Man Pages */
180 	"SUNWx25a",	/* + X.25 KRNL MOD, INCLDS FLS */
181 	"SUNWx25b",	/* + X.25 USR PROG AND LIB */
182 	"zzzz1",	/* fill to avoid constraint tests in loop */
183 	"zzzz2",
184 	"zzzz3",
185 	"zzzz4"
186 };
187 #endif
188 
189 /*
190  * Structure to hold the list of pkg names that are known to not behave
191  * properly when sym link destinations are not followed.
192  */
193 
194 #ifdef	ALLOW_EXCEPTION_PKG_LIST
195 static char *x_pkg_link[] =
196 {
197 	"AAAA1",	/* fill to avoid constraint tests in loop */
198 	"AAAA2",
199 	"AAAA3",
200 	"AAAA4",
201 	/* '+' means packages known to be non-compliant */
202 	"SUNWixfta",
203 	"SUNWixsna",
204 	"zzzz1",	/* fill to avoid constraint tests in loop */
205 	"zzzz2",
206 	"zzzz3",
207 	"zzzz4"
208 };
209 #endif
210 
211 /*
212  * This function determines if the package being added is a known old-style
213  * package which requires user interaction during procedure scripts. It is
214  * to be removed for on1095. -- JST
215  * It also is used for the determining if a pkg is known to have symlinks
216  * that need to be processed the old way.
217  */
218 
219 #ifdef	ALLOW_EXCEPTION_PKG_LIST
220 int
exception_pkg(char * pkginst,int pkg_list)221 exception_pkg(char *pkginst, int pkg_list)
222 {
223 	int	retvalue = 0;
224 	int	list_sz;
225 	int	list_cntr;	/* starting point for binary search */
226 	register int	pos;		/* current position */
227 	register int	level;		/* current height in the tree */
228 	register int 	incr;		/* increment for step */
229 	int	result;		/* result of strcmp */
230 	register char **x_ptr = x_pkg;
231 	register char **x_ptr_link = x_pkg_link;
232 	char	*pkgend;
233 	char	*pkgname = strdup(pkginst);
234 
235 	/*
236 	 * NOTE : If more structures need to be defined the following if
237 	 * statement needs to be revised to handle multiple flags
238 	 */
239 
240 	if (pkg_list)
241 		list_sz = (sizeof (x_pkg_link) / sizeof (char *));
242 	else
243 		list_sz = (sizeof (x_pkg) / sizeof (char *));
244 
245 	/*
246 	 * NOTE : shifts are used instead of integer division to save
247 	 * time. Numerous other checks are omitted also. This tree
248 	 * contains double nodes but is entirely connected and closed.
249 	 */
250 
251 	list_cntr = list_sz >> 1;
252 	incr = list_cntr - TREEFILL;
253 
254 	pkgend = strchr(pkgname, '.');
255 
256 	if (pkgend)
257 		*pkgend = '\0';	/* terminate the instance to a name */
258 
259 	for (level = TREEHEIGHT, 	/* start at the top level */
260 	    pos = list_cntr;		/*   ... in the middle */
261 	    level;		/* for as long as we're in the tree */
262 	    level--, pos += (result > 0) ? incr : -incr) {
263 
264 		if (pkg_list)
265 			result = strcmp(pkgname, *(x_ptr_link + pos));
266 		else
267 			result = strcmp(pkgname, *(x_ptr + pos));
268 
269 		if (result == 0) {
270 			retvalue = 1;
271 			break;
272 		}
273 
274 		incr = (incr & 0x0001) | (incr >> 1);	/* halve it & rnd up */
275 	}
276 
277 	free(pkgname);
278 
279 	return (retvalue);
280 }
281 
282 #endif
283 
284 void
psvr4pkg(char ** ppkg)285 psvr4pkg(char	**ppkg)
286 {
287 	struct dirent *drp;
288 	DIR	*dirfp;
289 	char	*pt;
290 	int	n;
291 	char	ans[MAX_INPUT], path[PATH_MAX];
292 
293 	if (*ppkg) {
294 		(void) snprintf(path, sizeof (path),
295 				"/install/new/usr/options/%s.name",
296 				*ppkg);
297 		if (access(path, 0)) {
298 			ptext(stderr, gettext(MSG_NOTVER), *ppkg);
299 			if (n = ckyorn(ans, NULL, NULL, gettext(HLP_NOTVER),
300 			    gettext(ASK_CONT)))
301 				quit(n);
302 			if (strchr("yY", *ans) == NULL)
303 				quit(3);
304 		}
305 		return;
306 	}
307 
308 	if (dirfp = opendir("/install/new/usr/options")) {
309 		while (drp = readdir(dirfp)) {
310 			if (drp->d_name[0] == '.')
311 				continue;
312 			if (pt = strchr(drp->d_name, '.')) {
313 				if (strcmp(pt, ".name") == 0) {
314 					*pt = '\0';
315 					*ppkg = qstrdup(drp->d_name);
316 					break;
317 				}
318 			}
319 		}
320 		(void) closedir(dirfp);
321 	}
322 
323 	if (*ppkg) {
324 		ptext(stderr, gettext(MSG_CONFIRM), *ppkg);
325 		if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONFIRM),
326 		    gettext(ASK_CONT)))
327 			quit(n);
328 	} else {
329 		ptext(stderr, gettext(MSG_NOTVER), *ppkg);
330 		if (n = ckyorn(ans, NULL, NULL, gettext(HLP_NOTVER),
331 		    gettext(ASK_CONT)))
332 			quit(n);
333 	}
334 	if (strchr("yY", *ans) == NULL)
335 		quit(3);
336 }
337 
338 void
psvr4cnflct(void)339 psvr4cnflct(void)
340 {
341 	FILE	*pp;
342 	int	n, found;
343 	char	*pt,
344 		ans[MAX_INPUT],
345 		cmd[PATH_MAX+sizeof (ckcmd)],
346 		path[PATH_MAX];
347 
348 	for (n = 0; Rlist[n] != NULL; n++) {
349 		if (access(Rlist[n], 0) == 0)
350 			break;
351 	}
352 	if (Rlist[n] == NULL)
353 		return; /* Rlist file not found on device */
354 
355 	(void) sprintf(cmd, ckcmd, Rlist[n]);
356 	echo(gettext("## Checking for conflicts with installed packages"));
357 	echo(gettext("   (using %s provided by pre-SVR4 package)"), Rlist[n]);
358 	if ((pp = popen(cmd, "r")) == NULL) {
359 		progerr(gettext(ERR_PIPE), cmd);
360 		progerr(gettext(ERR_OVERWRITE));
361 		quit(99);
362 	}
363 
364 	found = 0;
365 	while (fgets(path, PATH_MAX, pp)) {
366 		if (!found++)
367 			ptext(stderr, gettext(MSG_CONFLICT));
368 		if (pt = strpbrk(path, " \t\n"))
369 			*pt = '\0';
370 		echo("\t%s", path);
371 	}
372 	if (pclose(pp)) {
373 		progerr(gettext(ERR_OVERWRITE));
374 		quit(99);
375 	}
376 
377 	if (found) {
378 		if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONFLICT),
379 		    gettext(ASK_CONT)))
380 			quit(n);
381 		if (strchr("yY", *ans) == NULL)
382 			quit(3);
383 	}
384 }
385 
386 void
psvr4mail(char * list,char * msg,int retcode,char * pkg)387 psvr4mail(char *list, char *msg, int retcode, char *pkg)
388 {
389 	struct utsname utsbuf;
390 	FILE	*pp;
391 	char	cmd[BUFSIZ];
392 
393 	if (list == NULL)
394 		return;
395 
396 	while (isspace(*list))
397 		list++;
398 	if (*list == '\0')
399 		return;
400 
401 	/* send e-mail notifications */
402 	(void) snprintf(cmd, sizeof (cmd), "%s %s", MAILCMD, list);
403 	if ((pp = popen(cmd, "w")) == NULL) {
404 		progerr(gettext(ERR_PIPE), MAILCMD);
405 		progerr(gettext(ERR_MAIL));
406 		quit(99);
407 	}
408 
409 	(void) strcpy(utsbuf.nodename, gettext("(unknown)"));
410 	(void) uname(&utsbuf);
411 	ptext(pp, msg, pkg, utsbuf.nodename, retcode);
412 
413 	if (pclose(pp)) {
414 		progerr(gettext(ERR_MAIL));
415 		quit(99);
416 	}
417 }
418