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
51void
52error(msg)
53char *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
64void
65quit()
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
81char *
82make_tempname(bname)
83char *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
113FILE *
114open_temp(tname)
115char *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
151void
152replace(fname, tname)
153char *fname;
154char *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
178int
179copy_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
235int
236find_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
275int
276do_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