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