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
82static char	*Rlist[] = {
83	"/install/install/Rlist",
84	"/install/install/RLIST",
85	"/install/install/rlist",
86	NULL
87};
88
89static 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
102static 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
195static 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
220int
221exception_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
284void
285psvr4pkg(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
338void
339psvr4cnflct(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
386void
387psvr4mail(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