xref: /illumos-gate/usr/src/cmd/saf/admutil.c (revision 86e5bb7983583c7ce83d5235abc95df1fb570d5e)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 /*
25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <signal.h>
33 #include <sac.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include "misc.h"
38 #include "structs.h"
39 #include "extern.h"
40 
41 
42 /*
43  * error - print out an error message and die
44  *
45  *	args:	msg - message to be printed, Saferrno previously set
46  */
47 
48 void
49 error(msg)
50 char *msg;
51 {
52 	(void) fprintf(stderr, "%s\n", msg);
53 	quit();
54 }
55 
56 
57 /*
58  * quit - exit the program with the status in Saferrno
59  */
60 
61 void
62 quit()
63 {
64 	exit(Saferrno);
65 }
66 
67 
68 /*
69  * make_tempname - generate a temp name to be used for updating files.
70  *		Names will be of the form HOME/xxx/.name, where HOME
71  *		is from misc.h
72  *
73  *	args:	bname - the basename of the file.  For example foo/_config
74  *		        will generate a tempname of HOME/foo/._config
75  */
76 
77 
78 char *
79 make_tempname(bname)
80 char *bname;
81 {
82 	static char buf[SIZE];	/* this is where we put the new name */
83 	char *p;			/* work pointer */
84 
85 	p = strrchr(bname, '/');
86 	if (p == NULL)
87 		(void) sprintf(buf, "%s/.%s", HOME, bname);
88 	else {
89 		(void) strcpy(buf, HOME);
90 		/* this zaps the trailing slash so the '.' can be stuck in */
91 		*p = '\0';
92 		(void) strcat(buf, "/");
93 		(void) strcat(buf, bname);
94 		(void) strcat(buf, "/.");
95 		(void) strcat(buf, (p + 1));
96 		*p = '/';
97 	}
98 	return(buf);
99 }
100 
101 
102 /*
103  * open_temp - open up a temp file
104  *
105  *	args:	tname - temp file name
106  */
107 
108 
109 
110 FILE *
111 open_temp(tname)
112 char *tname;
113 {
114 	FILE *fp;			/* fp associated with tname */
115 	struct sigaction sigact;	/* for signal handling */
116 
117 	sigact.sa_flags = 0;
118 	sigact.sa_handler = SIG_IGN;
119 	(void) sigemptyset(&sigact.sa_mask);
120 	(void) sigaddset(&sigact.sa_mask, SIGHUP);
121 	(void) sigaddset(&sigact.sa_mask, SIGINT);
122 	(void) sigaddset(&sigact.sa_mask, SIGQUIT);
123 	(void) sigaction(SIGHUP, &sigact, NULL);
124 	(void) sigaction(SIGINT, &sigact, NULL);
125 	(void) sigaction(SIGQUIT, &sigact, NULL);
126 	(void) umask(0333);
127 	if (access(tname, 0) != -1) {
128 		Saferrno = E_SAFERR;
129 		error("tempfile busy; try again later");
130 	}
131 	fp = fopen(tname, "w");
132 	if (fp == NULL) {
133 		Saferrno = E_SYSERR;
134 		error("cannot create tempfile");
135 	}
136 	return(fp);
137 }
138 
139 
140 /*
141  * replace - replace one file with another, only returns on success
142  *
143  *	args:	fname - name of target file
144  *		tname - name of source file
145  */
146 
147 
148 void
149 replace(fname, tname)
150 char *fname;
151 char *tname;
152 {
153 	char buf[SIZE];	/* scratch buffer */
154 
155 	(void) sprintf(buf, "%s/%s", HOME, fname);
156 	(void) unlink(buf);
157 	if (rename(tname, buf) < 0) {
158 		Saferrno = E_SYSERR;
159 		(void) unlink(tname);
160 		quit();
161 	}
162 }
163 
164 
165 /*
166  * copy_file - copy information from one file to another, return 0 on
167  *	success, -1 on failure
168  *
169  *	args:	fp - source file's file pointer
170  *		tfp - destination file's file pointer
171  *		start - starting line number
172  *		finish - ending line number (-1 indicates entire file)
173  */
174 
175 int
176 copy_file(FILE *fp, FILE *tfp, int start, int finish)
177 {
178 	int i;		/* loop variable */
179 	char dummy[SIZE];	/* scratch buffer */
180 
181 /*
182  * always start from the beginning because line numbers are absolute
183  */
184 
185 	rewind(fp);
186 
187 /*
188  * get to the starting point of interest
189  */
190 
191 	if (start != 1) {
192 		for (i = 1; i < start; i++)
193 			if (!fgets(dummy, SIZE, fp))
194 				return(-1);
195 	}
196 
197 /*
198  * copy as much as was requested
199  */
200 
201 	if (finish != -1) {
202 		for (i = start; i <= finish; i++) {
203 			if (!fgets(dummy, SIZE, fp))
204 				return(-1);
205 			if (fputs(dummy, tfp) == EOF)
206 				return(-1);
207 		}
208 	}
209 	else {
210 		for (;;) {
211 			if (fgets(dummy, SIZE, fp) == NULL) {
212 				if (feof(fp))
213 					break;
214 				else
215 					return(-1);
216 			}
217 			if (fputs(dummy, tfp) == EOF)
218 				return(-1);
219 		}
220 	}
221 	return(0);
222 }
223 
224 
225 /*
226  * find_pm - find an entry in _sactab for a particular port monitor
227  *
228  *	args:	fp - file pointer for _sactab
229  *		pmtag - tag of port monitor we're looking for
230  */
231 
232 int
233 find_pm(FILE *fp, char *pmtag)
234 {
235 	char *p;		/* working pointer */
236 	int line = 0;		/* line number we found entry on */
237 	struct sactab stab;	/* place to hold parsed info */
238 	char buf[SIZE];	/* scratch buffer */
239 
240 	while (fgets(buf, SIZE, fp)) {
241 		line++;
242 		p = trim(buf);
243 		if (*p == '\0')
244 			continue;
245 		parse(p, &stab);
246 		if (!(strcmp(stab.sc_tag, pmtag)))
247 			return(line);
248 	}
249 	if (!feof(fp)) {
250 		Saferrno = E_SYSERR;
251 		error("error reading _sactab");
252 		/* NOTREACHED */
253 		return (0);
254 	}
255 	else
256 		return(0);
257 }
258 
259 
260 /*
261  * do_config - take a config script and put it where it belongs or
262  *		output an existing one.  Saferrno is set if any errors
263  *		are encountered.  Calling routine may choose to quit or
264  *		continue, in which case Saferrno will stay set, but may
265  *		change value if another error is encountered.
266  *
267  *	args:	script - name of file containing script (if NULL, means output
268  *			 existing one instead)
269  *		basename - name of script (relative to HOME (from misc.h))
270  */
271 
272 int
273 do_config(char *script, char *basename)
274 {
275 	FILE *ifp;		/* file pointer for source file */
276 	FILE *ofp;		/* file pointer for target file */
277 	struct stat statbuf;	/* file status info */
278 	char *tname;		/* name of tempfile */
279 	char buf[SIZE];		/* scratch buffer */
280 
281 	if (script) {
282 		/* we're installing a new configuration script */
283 		if (access(script, 0) == 0) {
284 			if (stat(script, &statbuf) < 0) {
285 				Saferrno = E_SYSERR;
286 				(void) fprintf(stderr, "Could not stat <%s>\n", script);
287 				return(1);
288 			}
289 			if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
290 				(void) fprintf(stderr, "warning - %s not a regular file - ignored\n", script);
291 				return(1);
292 			}
293 		}
294 		else {
295 			Saferrno = E_NOEXIST;
296 			(void) fprintf(stderr, "Invalid request, %s does not exist\n", script);
297 			return(1);
298 		}
299 		ifp = fopen(script, "r");
300 		if (ifp == NULL) {
301 			(void) fprintf(stderr, "Invalid request, can not open %s\n", script);
302 			Saferrno = E_SYSERR;
303 			return(1);
304 		}
305 		tname = make_tempname(basename);
306 		/* note - open_temp only returns if successful */
307 		ofp = open_temp(tname);
308 		while(fgets(buf, SIZE, ifp)) {
309 			if (fputs(buf, ofp) == EOF) {
310 				(void) unlink(tname);
311 				Saferrno = E_SYSERR;
312 				error("error in writing tempfile");
313 			}
314 		}
315 		(void) fclose(ifp);
316 		if (fclose(ofp) == EOF) {
317 			(void) unlink(tname);
318 			Saferrno = E_SYSERR;
319 			error("error closing tempfile");
320 		}
321 		/* note - replace only returns if successful */
322 		replace(basename, tname);
323 		return(0);
324 	}
325 	else {
326 		/* we're outputting a configuration script */
327 		(void) sprintf(buf, "%s/%s", HOME, basename);
328 		if (access(buf, 0) < 0) {
329 			(void) fprintf(stderr, "Invalid request, script does not exist\n");
330 			Saferrno = E_NOEXIST;
331 			return(1);
332 		}
333 		ifp = fopen(buf, "r");
334 		if (ifp == NULL) {
335 			(void) fprintf(stderr, "Invalid request, can not open script\n");
336 			Saferrno = E_SYSERR;
337 			return(1);
338 		}
339 		while (fgets(buf, SIZE, ifp))
340 			(void) fputs(buf, stdout);
341 		(void) fclose(ifp);
342 		return(0);
343 	}
344 }
345