xref: /titanic_53/usr/src/cmd/bnu/permission.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate /*
26*7c478bd9Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
27*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
28*7c478bd9Sstevel@tonic-gate  */
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* from SVR4 bnu:permission.c 2.12 */
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #ifndef UUCHECK
33*7c478bd9Sstevel@tonic-gate #include "uucp.h"
34*7c478bd9Sstevel@tonic-gate #endif
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*  field array indexes for PERMISSIONS parameters */
38*7c478bd9Sstevel@tonic-gate #define U_LOGNAME	0
39*7c478bd9Sstevel@tonic-gate #define U_MACHINE	1
40*7c478bd9Sstevel@tonic-gate #define U_CALLBACK	2
41*7c478bd9Sstevel@tonic-gate #define U_REQUEST	3
42*7c478bd9Sstevel@tonic-gate #define U_SENDFILES	4
43*7c478bd9Sstevel@tonic-gate #define U_READPATH	5
44*7c478bd9Sstevel@tonic-gate #define U_WRITEPATH	6
45*7c478bd9Sstevel@tonic-gate #define U_NOREADPATH	7
46*7c478bd9Sstevel@tonic-gate #define U_NOWRITEPATH	8
47*7c478bd9Sstevel@tonic-gate #define U_MYNAME	9
48*7c478bd9Sstevel@tonic-gate #define U_COMMANDS	10
49*7c478bd9Sstevel@tonic-gate #define U_VALIDATE	11
50*7c478bd9Sstevel@tonic-gate #define U_PUBDIR	12
51*7c478bd9Sstevel@tonic-gate #define U_DIRECT	13
52*7c478bd9Sstevel@tonic-gate #define U_ALIAS		14
53*7c478bd9Sstevel@tonic-gate #define U_PATH		15
54*7c478bd9Sstevel@tonic-gate /*  NUMFLDS should be one more than the highest U_ value */
55*7c478bd9Sstevel@tonic-gate #define NUMFLDS		16
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /* fields found in PERMISSIONS for requested system/login */
58*7c478bd9Sstevel@tonic-gate static char *_Flds[NUMFLDS];
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /* keyword/value structure */
61*7c478bd9Sstevel@tonic-gate struct keywords {
62*7c478bd9Sstevel@tonic-gate 	char* kword;
63*7c478bd9Sstevel@tonic-gate 	int kvalue;
64*7c478bd9Sstevel@tonic-gate };
65*7c478bd9Sstevel@tonic-gate static struct keywords _Kwords[] = {
66*7c478bd9Sstevel@tonic-gate 	{"LOGNAME", U_LOGNAME},
67*7c478bd9Sstevel@tonic-gate 	{"MACHINE", U_MACHINE},
68*7c478bd9Sstevel@tonic-gate 	{"CALLBACK", U_CALLBACK},
69*7c478bd9Sstevel@tonic-gate 	{"REQUEST", U_REQUEST},
70*7c478bd9Sstevel@tonic-gate 	{"SENDFILES", U_SENDFILES},
71*7c478bd9Sstevel@tonic-gate 	{"READ", U_READPATH},
72*7c478bd9Sstevel@tonic-gate 	{"WRITE", U_WRITEPATH},
73*7c478bd9Sstevel@tonic-gate 	{"NOREAD", U_NOREADPATH},
74*7c478bd9Sstevel@tonic-gate 	{"NOWRITE", U_NOWRITEPATH},
75*7c478bd9Sstevel@tonic-gate 	{"MYNAME", U_MYNAME},
76*7c478bd9Sstevel@tonic-gate 	{"COMMANDS", U_COMMANDS},
77*7c478bd9Sstevel@tonic-gate 	{"VALIDATE", U_VALIDATE},
78*7c478bd9Sstevel@tonic-gate 	{"PUBDIR", U_PUBDIR},
79*7c478bd9Sstevel@tonic-gate 	{"DIRECT", U_DIRECT},
80*7c478bd9Sstevel@tonic-gate 	{"ALIAS", U_ALIAS},
81*7c478bd9Sstevel@tonic-gate 	{"PATH", U_PATH},
82*7c478bd9Sstevel@tonic-gate };
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate #define MAXCMDS		30
85*7c478bd9Sstevel@tonic-gate #define MAXPATHS	20
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /* for all options on paths - read, write, noread, nowrite */
88*7c478bd9Sstevel@tonic-gate /* NB: all pointers assumed to point to static data */
89*7c478bd9Sstevel@tonic-gate static char *_RPaths[MAXPATHS+1];
90*7c478bd9Sstevel@tonic-gate static char *_WPaths[MAXPATHS+1];
91*7c478bd9Sstevel@tonic-gate static char *_NoRPaths[MAXPATHS+1];
92*7c478bd9Sstevel@tonic-gate static char *_NoWPaths[MAXPATHS+1];
93*7c478bd9Sstevel@tonic-gate static char *_Commands[MAXCMDS+1];
94*7c478bd9Sstevel@tonic-gate static char _Cmd_defaults[BUFSIZ];
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /* option variables */
97*7c478bd9Sstevel@tonic-gate static int _Request;	/* TRUE can request, FALSE can not request files */
98*7c478bd9Sstevel@tonic-gate static int _Switch;	/* FALSE requires a call back to send any files */
99*7c478bd9Sstevel@tonic-gate static int _CallBack;	/* TRUE for call back for any transaction */
100*7c478bd9Sstevel@tonic-gate static int _NoSpool;	/* TRUE if delivering directly to destination file */
101*7c478bd9Sstevel@tonic-gate static char _MyName[MAXBASENAME+1];	/* Myname from PERMISSIONS file */
102*7c478bd9Sstevel@tonic-gate /* NB: _Pubdir and _Path assumed to point to dynamic data */
103*7c478bd9Sstevel@tonic-gate static char *_Pubdir = NULL;		/* PUBDIR from PERMISSIONS file */
104*7c478bd9Sstevel@tonic-gate static char *_Path = NULL;		/* PATH from PERMISSIONS file */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate struct name_value
107*7c478bd9Sstevel@tonic-gate {
108*7c478bd9Sstevel@tonic-gate 	char *name;
109*7c478bd9Sstevel@tonic-gate 	char *value;
110*7c478bd9Sstevel@tonic-gate };
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate /* file pointer for PERMISSIONS */
113*7c478bd9Sstevel@tonic-gate static FILE *Fp = NULL;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate /* functions */
116*7c478bd9Sstevel@tonic-gate extern char *next_token(), *nextarg();
117*7c478bd9Sstevel@tonic-gate extern int parse_tokens(), canPath(), mkdirs();
118*7c478bd9Sstevel@tonic-gate static void fillFlds();
119*7c478bd9Sstevel@tonic-gate static void fillList();
120*7c478bd9Sstevel@tonic-gate static int cmdMatch(), listMatch(), nameMatch(),
121*7c478bd9Sstevel@tonic-gate 	userFind(), validateFind();
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate int
124*7c478bd9Sstevel@tonic-gate noSpool()
125*7c478bd9Sstevel@tonic-gate {
126*7c478bd9Sstevel@tonic-gate 	return(_NoSpool);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * fill in fields for login name
131*7c478bd9Sstevel@tonic-gate  * name - the login id
132*7c478bd9Sstevel@tonic-gate  * rmtname - remote system name
133*7c478bd9Sstevel@tonic-gate  *
134*7c478bd9Sstevel@tonic-gate  * return:
135*7c478bd9Sstevel@tonic-gate  *	0 -> found login name
136*7c478bd9Sstevel@tonic-gate  *	FAIL -> did not find login
137*7c478bd9Sstevel@tonic-gate  */
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate int
140*7c478bd9Sstevel@tonic-gate logFind(name, rmtname)
141*7c478bd9Sstevel@tonic-gate char *name, *rmtname;
142*7c478bd9Sstevel@tonic-gate {
143*7c478bd9Sstevel@tonic-gate 	int ret;
144*7c478bd9Sstevel@tonic-gate 	DEBUG(5, "logFind called (name: %s, ", name);
145*7c478bd9Sstevel@tonic-gate 	DEBUG(5, "rmtname: %s)\n", rmtname);
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	ret = validateFind (rmtname);
148*7c478bd9Sstevel@tonic-gate 	if (ret == SUCCESS) { /* found VALIDATE entry */
149*7c478bd9Sstevel@tonic-gate 	    ret = userFind (name, rmtname, U_VALIDATE);
150*7c478bd9Sstevel@tonic-gate 	    if (ret) {
151*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "machine/login match failed%s", "");
152*7c478bd9Sstevel@tonic-gate 		return(FAIL);
153*7c478bd9Sstevel@tonic-gate 	    }
154*7c478bd9Sstevel@tonic-gate 	}
155*7c478bd9Sstevel@tonic-gate 	else
156*7c478bd9Sstevel@tonic-gate 	    ret = userFind (name, "", U_LOGNAME);
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_Request (%s), ",
159*7c478bd9Sstevel@tonic-gate 	    requestOK() ? "TRUE" : "FALSE");
160*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_Switch (%s), ",
161*7c478bd9Sstevel@tonic-gate 	    switchRole() ? "TRUE" : "FALSE");
162*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_CallBack (%s), ",
163*7c478bd9Sstevel@tonic-gate 	    callBack() ? "TRUE" : "FALSE");
164*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_MyName (%s), ", _MyName);
165*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_NoSpool (%s), ",
166*7c478bd9Sstevel@tonic-gate 	    noSpool() ? "TRUE" : "FALSE");
167*7c478bd9Sstevel@tonic-gate 	return(ret);
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate /*
171*7c478bd9Sstevel@tonic-gate  * fill in fields for machine name
172*7c478bd9Sstevel@tonic-gate  * return:
173*7c478bd9Sstevel@tonic-gate  *	0 -> found machine name
174*7c478bd9Sstevel@tonic-gate  *	FAIL -> did not find machine
175*7c478bd9Sstevel@tonic-gate  */
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate int
178*7c478bd9Sstevel@tonic-gate mchFind(name)
179*7c478bd9Sstevel@tonic-gate char *name;
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	register i, ret;
182*7c478bd9Sstevel@tonic-gate 	DEBUG(5, "mchFind called (%s)\n", name);
183*7c478bd9Sstevel@tonic-gate 	if ( (ret = userFind (name, "", U_MACHINE)) == FAIL)
184*7c478bd9Sstevel@tonic-gate 	    /* see if there is a default line */
185*7c478bd9Sstevel@tonic-gate 	    (void) userFind ("OTHER", "", U_MACHINE);
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	/*  mchFind is from MASTER mode - switch role is always ok */
188*7c478bd9Sstevel@tonic-gate 	_Switch = TRUE;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_Request (%s), ",
191*7c478bd9Sstevel@tonic-gate 	    requestOK() ? "TRUE" : "FALSE");
192*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_Switch (%s), ",
193*7c478bd9Sstevel@tonic-gate 	    switchRole() ? "TRUE" : "FALSE");
194*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_CallBack (%s), ",
195*7c478bd9Sstevel@tonic-gate 	    callBack() ? "TRUE" : "FALSE");
196*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_MyName (%s), ", _MyName);
197*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "_NoSpool (%s), ",
198*7c478bd9Sstevel@tonic-gate 	    noSpool() ? "TRUE" : "FALSE");
199*7c478bd9Sstevel@tonic-gate 	for (i=0; _Commands[i] != NULL; i++)
200*7c478bd9Sstevel@tonic-gate 	    DEBUG(7, "_Commands %s\n",  _Commands[i]);
201*7c478bd9Sstevel@tonic-gate 	return(ret);
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate  * this function will find a login name in the LOGNAME
206*7c478bd9Sstevel@tonic-gate  * field.
207*7c478bd9Sstevel@tonic-gate  * input:
208*7c478bd9Sstevel@tonic-gate  *	name	-> who the remote says he/she is
209*7c478bd9Sstevel@tonic-gate  * return:
210*7c478bd9Sstevel@tonic-gate  *	SUCCESS	-> found
211*7c478bd9Sstevel@tonic-gate  *	FAIL	-> not found
212*7c478bd9Sstevel@tonic-gate  */
213*7c478bd9Sstevel@tonic-gate static int
214*7c478bd9Sstevel@tonic-gate nameMatch(name, fld)
215*7c478bd9Sstevel@tonic-gate char *name, *fld;
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	char *arg;
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	if (fld == NULL)
220*7c478bd9Sstevel@tonic-gate 	    return(FAIL);
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 	while (*fld) {
223*7c478bd9Sstevel@tonic-gate 	    fld = nextarg(fld, &arg);
224*7c478bd9Sstevel@tonic-gate 	    if (EQUALS(arg, name))
225*7c478bd9Sstevel@tonic-gate 		return(SUCCESS);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 	return (FAIL);
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate /*
232*7c478bd9Sstevel@tonic-gate  * interpret the _Flds options and set the option variables
233*7c478bd9Sstevel@tonic-gate  */
234*7c478bd9Sstevel@tonic-gate static void
235*7c478bd9Sstevel@tonic-gate fillFlds()
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_REQUEST] != NULL) {
239*7c478bd9Sstevel@tonic-gate 		if (EQUALS(_Flds[U_REQUEST], "yes"))
240*7c478bd9Sstevel@tonic-gate 			_Request = TRUE;
241*7c478bd9Sstevel@tonic-gate 		else
242*7c478bd9Sstevel@tonic-gate 			_Request = FALSE;
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_SENDFILES] != NULL) {
246*7c478bd9Sstevel@tonic-gate 		if (EQUALS(_Flds[U_SENDFILES], "yes"))
247*7c478bd9Sstevel@tonic-gate 			_Switch = TRUE;
248*7c478bd9Sstevel@tonic-gate 		else
249*7c478bd9Sstevel@tonic-gate 			_Switch = FALSE;
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_CALLBACK] != NULL) {
253*7c478bd9Sstevel@tonic-gate 		if (EQUALS(_Flds[U_CALLBACK], "yes"))
254*7c478bd9Sstevel@tonic-gate 			_CallBack = TRUE;
255*7c478bd9Sstevel@tonic-gate 		else
256*7c478bd9Sstevel@tonic-gate 			_CallBack = FALSE;
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_DIRECT] != NULL) {
260*7c478bd9Sstevel@tonic-gate 		if (EQUALS(_Flds[U_DIRECT], "yes"))
261*7c478bd9Sstevel@tonic-gate 			_NoSpool = TRUE;
262*7c478bd9Sstevel@tonic-gate 		else
263*7c478bd9Sstevel@tonic-gate 			_NoSpool = FALSE;
264*7c478bd9Sstevel@tonic-gate 	}
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_MYNAME] != NULL) {
267*7c478bd9Sstevel@tonic-gate 		strncpy(_MyName, _Flds[U_MYNAME], MAXBASENAME);
268*7c478bd9Sstevel@tonic-gate 		_MyName[MAXBASENAME] = NULLCHAR;
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_PUBDIR] != NULL) {
272*7c478bd9Sstevel@tonic-gate 		if (_Pubdir != NULL)
273*7c478bd9Sstevel@tonic-gate 		    free(_Pubdir);	/* get rid of previous one */
274*7c478bd9Sstevel@tonic-gate 		_Pubdir = strdup(_Flds[U_PUBDIR]);
275*7c478bd9Sstevel@tonic-gate #ifndef UUCHECK
276*7c478bd9Sstevel@tonic-gate 		ASSERT(_Pubdir != NULL, Ct_ALLOCATE, _Flds[U_PUBDIR], 0);
277*7c478bd9Sstevel@tonic-gate #else /* UUCHECK */
278*7c478bd9Sstevel@tonic-gate 		if (_Pubdir == NULL) {
279*7c478bd9Sstevel@tonic-gate 		    perror(gettext("malloc() error"));
280*7c478bd9Sstevel@tonic-gate 		    exit(1);
281*7c478bd9Sstevel@tonic-gate 		}
282*7c478bd9Sstevel@tonic-gate #endif /* UUCHECK */
283*7c478bd9Sstevel@tonic-gate 		Pubdir = _RPaths[0] = _WPaths[0] = _Pubdir; /* reset default */
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	if (_Flds[U_PATH] != NULL) {
287*7c478bd9Sstevel@tonic-gate 		if (_Path != NULL)
288*7c478bd9Sstevel@tonic-gate 		    free(_Path);	/* get rid of previous one */
289*7c478bd9Sstevel@tonic-gate 		_Path = strdup(_Flds[U_PATH]);
290*7c478bd9Sstevel@tonic-gate #ifndef UUCHECK
291*7c478bd9Sstevel@tonic-gate 		ASSERT(_Path != NULL, Ct_ALLOCATE, _Flds[U_PATH], 0);
292*7c478bd9Sstevel@tonic-gate #else /* UUCHECK */
293*7c478bd9Sstevel@tonic-gate 		if (_Path == NULL) {
294*7c478bd9Sstevel@tonic-gate 		    perror(gettext("malloc() error"));
295*7c478bd9Sstevel@tonic-gate 		    exit(1);
296*7c478bd9Sstevel@tonic-gate 		}
297*7c478bd9Sstevel@tonic-gate #endif /* UUCHECK */
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	return;
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate /*
304*7c478bd9Sstevel@tonic-gate  * fill in the list vector for the system/login
305*7c478bd9Sstevel@tonic-gate  * input:
306*7c478bd9Sstevel@tonic-gate  *	type - list type (read, write, noread, nowrite, command)
307*7c478bd9Sstevel@tonic-gate  * output:
308*7c478bd9Sstevel@tonic-gate  *	list - filled in with items.
309*7c478bd9Sstevel@tonic-gate  * return:
310*7c478bd9Sstevel@tonic-gate  *	number of items in list
311*7c478bd9Sstevel@tonic-gate  */
312*7c478bd9Sstevel@tonic-gate static void
313*7c478bd9Sstevel@tonic-gate fillList(type, list)
314*7c478bd9Sstevel@tonic-gate int type;
315*7c478bd9Sstevel@tonic-gate char *list[];
316*7c478bd9Sstevel@tonic-gate {
317*7c478bd9Sstevel@tonic-gate 	register char *p;
318*7c478bd9Sstevel@tonic-gate 	register num;
319*7c478bd9Sstevel@tonic-gate 	int maxlist = 0;
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	p = _Flds[type];
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	/* find list limit */
324*7c478bd9Sstevel@tonic-gate 	if (type == U_READPATH || type == U_WRITEPATH
325*7c478bd9Sstevel@tonic-gate 	 || type == U_NOREADPATH || type == U_NOWRITEPATH)
326*7c478bd9Sstevel@tonic-gate 		maxlist = MAXPATHS;
327*7c478bd9Sstevel@tonic-gate 	else if (type == U_COMMANDS)
328*7c478bd9Sstevel@tonic-gate 		maxlist = MAXCMDS;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	if (p == NULL || !*p) {
331*7c478bd9Sstevel@tonic-gate 		 /* no names specified, default already setup */
332*7c478bd9Sstevel@tonic-gate 		return;
333*7c478bd9Sstevel@tonic-gate 	}
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	num = 0;
336*7c478bd9Sstevel@tonic-gate 	while (*p && num < maxlist) {
337*7c478bd9Sstevel@tonic-gate 		list[num] = p;
338*7c478bd9Sstevel@tonic-gate 		if (*p == ':') {	/* null path */
339*7c478bd9Sstevel@tonic-gate 			*p++ = NULLCHAR;
340*7c478bd9Sstevel@tonic-gate 			continue;
341*7c478bd9Sstevel@tonic-gate 		}
342*7c478bd9Sstevel@tonic-gate 		while (*p && *p != ':')
343*7c478bd9Sstevel@tonic-gate 			p++;
344*7c478bd9Sstevel@tonic-gate 		if (*p == ':')
345*7c478bd9Sstevel@tonic-gate 			*p++ = NULLCHAR;
346*7c478bd9Sstevel@tonic-gate 		DEBUG(7, "list (%s) ", list[num]);
347*7c478bd9Sstevel@tonic-gate 		num++;
348*7c478bd9Sstevel@tonic-gate 	}
349*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "num = %d\n", num);
350*7c478bd9Sstevel@tonic-gate 	list[num] = NULL;
351*7c478bd9Sstevel@tonic-gate 	return;
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate /*
355*7c478bd9Sstevel@tonic-gate  * Find the line of PERMISSIONS for login.
356*7c478bd9Sstevel@tonic-gate  * The search is determined by the type field
357*7c478bd9Sstevel@tonic-gate  * (type=U_LOGNAME, U_MACHINE or U_VALIDATE)
358*7c478bd9Sstevel@tonic-gate  * For U_LOGNAME:
359*7c478bd9Sstevel@tonic-gate  *	search for "name" in a LOGNAME= option
360*7c478bd9Sstevel@tonic-gate  * For U_MACHINE:
361*7c478bd9Sstevel@tonic-gate  *	search for "name" in a MACHINE= option
362*7c478bd9Sstevel@tonic-gate  * For U_VALIDATE:
363*7c478bd9Sstevel@tonic-gate  *	search for "rmtname" in a VALIDATE= option and
364*7c478bd9Sstevel@tonic-gate  *	for the same entry see if "name" is in the LOGNAME= option
365*7c478bd9Sstevel@tonic-gate  * input:
366*7c478bd9Sstevel@tonic-gate  *	name -> search name
367*7c478bd9Sstevel@tonic-gate  *	logname -> for validate entry
368*7c478bd9Sstevel@tonic-gate  *	type -> U_MACHINE or U_LOGNAME
369*7c478bd9Sstevel@tonic-gate  * output:
370*7c478bd9Sstevel@tonic-gate  *	The global values of all options will be set
371*7c478bd9Sstevel@tonic-gate  *	(e.g. _RPaths, _WPaths,  _Request, ...)
372*7c478bd9Sstevel@tonic-gate  * return:
373*7c478bd9Sstevel@tonic-gate  *	0 -> ok
374*7c478bd9Sstevel@tonic-gate  *	FAIL -> no match found
375*7c478bd9Sstevel@tonic-gate  */
376*7c478bd9Sstevel@tonic-gate static int
377*7c478bd9Sstevel@tonic-gate userFind(name, rmtname, type)
378*7c478bd9Sstevel@tonic-gate char *name, *rmtname;
379*7c478bd9Sstevel@tonic-gate int type;
380*7c478bd9Sstevel@tonic-gate {
381*7c478bd9Sstevel@tonic-gate 	char *p, *arg, *buf = NULL;
382*7c478bd9Sstevel@tonic-gate 	static char default_buf[BUFSIZ];
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	if (name != NULL && strcmp(name, "DEFAULT") != 0) {
385*7c478bd9Sstevel@tonic-gate 		/* call ourself recursively to set defaults */
386*7c478bd9Sstevel@tonic-gate 		(void) userFind("DEFAULT", "", U_MACHINE);
387*7c478bd9Sstevel@tonic-gate 	} else {
388*7c478bd9Sstevel@tonic-gate 		/*
389*7c478bd9Sstevel@tonic-gate 		 * Handle case where looking for DEFAULT entry.
390*7c478bd9Sstevel@tonic-gate 		 * First initialize all defaults to their "base"
391*7c478bd9Sstevel@tonic-gate 		 * values.  Then the DEFAULT entry, if found,
392*7c478bd9Sstevel@tonic-gate 		 * will override these settings.
393*7c478bd9Sstevel@tonic-gate 		 */
394*7c478bd9Sstevel@tonic-gate 		_Request = FALSE;
395*7c478bd9Sstevel@tonic-gate 		_CallBack = FALSE;
396*7c478bd9Sstevel@tonic-gate 		_Switch = FALSE;
397*7c478bd9Sstevel@tonic-gate 		_NoSpool = FALSE;
398*7c478bd9Sstevel@tonic-gate 		_MyName[0] = NULLCHAR;
399*7c478bd9Sstevel@tonic-gate 		_RPaths[0] = _WPaths[0] = PUBDIR;	/* default is public */
400*7c478bd9Sstevel@tonic-gate 		_RPaths[1] = _WPaths[1] = NULLCHAR;
401*7c478bd9Sstevel@tonic-gate 		_NoRPaths[0] = NULLCHAR;
402*7c478bd9Sstevel@tonic-gate 		_NoWPaths[0] = NULLCHAR;
403*7c478bd9Sstevel@tonic-gate 		if (_Pubdir != NULL)
404*7c478bd9Sstevel@tonic-gate 			free(_Pubdir);
405*7c478bd9Sstevel@tonic-gate 		Pubdir = _Pubdir = strdup(PUBDIR);
406*7c478bd9Sstevel@tonic-gate 		if (_Path != NULL)
407*7c478bd9Sstevel@tonic-gate 			free(_Path);
408*7c478bd9Sstevel@tonic-gate 		_Path = strdup(PATH);
409*7c478bd9Sstevel@tonic-gate 		/* set up Commands defaults */
410*7c478bd9Sstevel@tonic-gate 		_Flds[U_COMMANDS] = strcpy(_Cmd_defaults, DEFAULTCMDS);
411*7c478bd9Sstevel@tonic-gate 		fillList(U_COMMANDS, _Commands);
412*7c478bd9Sstevel@tonic-gate 		/*
413*7c478bd9Sstevel@tonic-gate 		 * put defaults we read in in here so they're not overwritten
414*7c478bd9Sstevel@tonic-gate 		 * by non-DEFAULT entries.
415*7c478bd9Sstevel@tonic-gate 		 */
416*7c478bd9Sstevel@tonic-gate 		buf = default_buf;
417*7c478bd9Sstevel@tonic-gate 	}
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	if (name == NULL)	/* use defaults */
420*7c478bd9Sstevel@tonic-gate 		return(0);	/* I don't think this will ever happen */
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	if ( (Fp = fopen(PERMISSIONS, "r")) == NULL) {
423*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "can't open %s\n", PERMISSIONS);
424*7c478bd9Sstevel@tonic-gate 		return(FAIL);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	for (;;) {
428*7c478bd9Sstevel@tonic-gate 	    if (parse_tokens (_Flds, buf) != 0) {
429*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
430*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "name (%s) not found; return FAIL\n", name);
431*7c478bd9Sstevel@tonic-gate 		return(FAIL);
432*7c478bd9Sstevel@tonic-gate 	    }
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	    p = _Flds[type];
435*7c478bd9Sstevel@tonic-gate 	    while (p && *p) {
436*7c478bd9Sstevel@tonic-gate 		p = nextarg(p, &arg);
437*7c478bd9Sstevel@tonic-gate 		switch (type) {
438*7c478bd9Sstevel@tonic-gate 		case U_VALIDATE:
439*7c478bd9Sstevel@tonic-gate 		    if (EQUALS(arg, rmtname)
440*7c478bd9Sstevel@tonic-gate 			&& nameMatch(name, _Flds[U_LOGNAME])==SUCCESS)
441*7c478bd9Sstevel@tonic-gate 				break;
442*7c478bd9Sstevel@tonic-gate 		    continue;
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 		case U_LOGNAME:
445*7c478bd9Sstevel@tonic-gate 		    if (EQUALS(arg, name))
446*7c478bd9Sstevel@tonic-gate 				break;
447*7c478bd9Sstevel@tonic-gate 		    continue;
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 		case U_MACHINE:
450*7c478bd9Sstevel@tonic-gate 		    if (EQUALSN(arg, name, MAXBASENAME))
451*7c478bd9Sstevel@tonic-gate 				break;
452*7c478bd9Sstevel@tonic-gate 		    continue;
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
456*7c478bd9Sstevel@tonic-gate 		fillFlds();
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 		/* fill in path lists */
459*7c478bd9Sstevel@tonic-gate 		fillList(U_READPATH, _RPaths);
460*7c478bd9Sstevel@tonic-gate 		fillList(U_WRITEPATH, _WPaths);
461*7c478bd9Sstevel@tonic-gate 		if (!requestOK())
462*7c478bd9Sstevel@tonic-gate 		    _Flds[U_NOREADPATH] = "/";
463*7c478bd9Sstevel@tonic-gate 		fillList(U_NOREADPATH, _NoRPaths);
464*7c478bd9Sstevel@tonic-gate 		fillList(U_NOWRITEPATH, _NoWPaths);
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 		/* fill in command list */
467*7c478bd9Sstevel@tonic-gate 		fillList(U_COMMANDS, _Commands);
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 		return(0);
470*7c478bd9Sstevel@tonic-gate 	    }
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate }
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate /*
475*7c478bd9Sstevel@tonic-gate  * see if name is in a VALIDATE option
476*7c478bd9Sstevel@tonic-gate  * return:
477*7c478bd9Sstevel@tonic-gate  *	FAIL -> not found
478*7c478bd9Sstevel@tonic-gate  *	SUCCESS -> found
479*7c478bd9Sstevel@tonic-gate  */
480*7c478bd9Sstevel@tonic-gate static int
481*7c478bd9Sstevel@tonic-gate validateFind(name)
482*7c478bd9Sstevel@tonic-gate char *name;
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if ( (Fp = fopen(PERMISSIONS, "r")) == NULL) {
486*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "can't open %s\n", PERMISSIONS);
487*7c478bd9Sstevel@tonic-gate 		return(FAIL);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	for (;;) {
491*7c478bd9Sstevel@tonic-gate 	    if (parse_tokens (_Flds, NULL) != 0) {
492*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "validateFind (%s) FAIL\n", name);
493*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
494*7c478bd9Sstevel@tonic-gate 		return(FAIL);
495*7c478bd9Sstevel@tonic-gate 	    }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	    if (_Flds[U_VALIDATE] == NULL)
498*7c478bd9Sstevel@tonic-gate 		continue;
499*7c478bd9Sstevel@tonic-gate 	    if (nameMatch(name, _Flds[U_VALIDATE])==SUCCESS) {
500*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
501*7c478bd9Sstevel@tonic-gate 		return (SUCCESS);
502*7c478bd9Sstevel@tonic-gate 	    }
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate }
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate /*
508*7c478bd9Sstevel@tonic-gate  * see if name is in an ALIAS option
509*7c478bd9Sstevel@tonic-gate  * return:
510*7c478bd9Sstevel@tonic-gate  *	NULL -> not found
511*7c478bd9Sstevel@tonic-gate  *	otherwise -> machine name
512*7c478bd9Sstevel@tonic-gate  */
513*7c478bd9Sstevel@tonic-gate char *
514*7c478bd9Sstevel@tonic-gate aliasFind(name)
515*7c478bd9Sstevel@tonic-gate char *name;
516*7c478bd9Sstevel@tonic-gate {
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	if ( (Fp = fopen(PERMISSIONS, "r")) == NULL) {
519*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "can't open %s\n", PERMISSIONS);
520*7c478bd9Sstevel@tonic-gate 		return(NULL);
521*7c478bd9Sstevel@tonic-gate 	}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	for (;;) {
524*7c478bd9Sstevel@tonic-gate 	    if (parse_tokens (_Flds, NULL) != 0) {
525*7c478bd9Sstevel@tonic-gate 		DEBUG(5, "aliasFind (%s) FAIL\n", name);
526*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
527*7c478bd9Sstevel@tonic-gate 		return(NULL);
528*7c478bd9Sstevel@tonic-gate 	    }
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 	    if (_Flds[U_ALIAS] == NULL)
531*7c478bd9Sstevel@tonic-gate 		continue;
532*7c478bd9Sstevel@tonic-gate 	    if (nameMatch(name, _Flds[U_ALIAS])==SUCCESS) {
533*7c478bd9Sstevel@tonic-gate 		(void) fclose(Fp);
534*7c478bd9Sstevel@tonic-gate #ifndef UUCHECK
535*7c478bd9Sstevel@tonic-gate 		ASSERT(strchr(_Flds[U_MACHINE], ':') == NULL,
536*7c478bd9Sstevel@tonic-gate 		    "PERMISSIONS file: ALIAS is one-to-many:",
537*7c478bd9Sstevel@tonic-gate 		    _Flds[U_MACHINE], 0);
538*7c478bd9Sstevel@tonic-gate #else /* UUCHECK */
539*7c478bd9Sstevel@tonic-gate 		if (strchr(_Flds[U_MACHINE], ':') != NULL) {
540*7c478bd9Sstevel@tonic-gate 		    printf(gettext("ALIAS is one-to-many: %s -> %s\n"),
541*7c478bd9Sstevel@tonic-gate 			name, _Flds[U_MACHINE]);
542*7c478bd9Sstevel@tonic-gate 		    return(NULL);
543*7c478bd9Sstevel@tonic-gate 		}
544*7c478bd9Sstevel@tonic-gate #endif /* UUCHECK */
545*7c478bd9Sstevel@tonic-gate 		return(_Flds[U_MACHINE]);
546*7c478bd9Sstevel@tonic-gate 	    }
547*7c478bd9Sstevel@tonic-gate 	}
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate }
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate /*
552*7c478bd9Sstevel@tonic-gate  * parse a line in PERMISSIONS and return a vector
553*7c478bd9Sstevel@tonic-gate  * of fields (flds)
554*7c478bd9Sstevel@tonic-gate  *
555*7c478bd9Sstevel@tonic-gate  * return:
556*7c478bd9Sstevel@tonic-gate  *	0 - OK
557*7c478bd9Sstevel@tonic-gate  *	EOF - at end of file
558*7c478bd9Sstevel@tonic-gate  */
559*7c478bd9Sstevel@tonic-gate int
560*7c478bd9Sstevel@tonic-gate parse_tokens(flds, buf)
561*7c478bd9Sstevel@tonic-gate char *flds[];
562*7c478bd9Sstevel@tonic-gate char *buf;
563*7c478bd9Sstevel@tonic-gate {
564*7c478bd9Sstevel@tonic-gate 	register i;
565*7c478bd9Sstevel@tonic-gate 	register char *p;
566*7c478bd9Sstevel@tonic-gate 	struct name_value pair;
567*7c478bd9Sstevel@tonic-gate 	static char _line[BUFSIZ];
568*7c478bd9Sstevel@tonic-gate 	register char *line = buf;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	if (buf == NULL)
571*7c478bd9Sstevel@tonic-gate 		line = _line;	/* if no buffer specified, use default */
572*7c478bd9Sstevel@tonic-gate 	/* initialize defaults  in case parameter is not specified */
573*7c478bd9Sstevel@tonic-gate 	for (i=0;i<NUMFLDS;i++)
574*7c478bd9Sstevel@tonic-gate 		flds[i] = NULL;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	if (getuline(Fp, line) == 0)
577*7c478bd9Sstevel@tonic-gate 		return(EOF);
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 	for (p=line;p && *p;) {
580*7c478bd9Sstevel@tonic-gate 		p = next_token (p, &pair);
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		for (i=0; i<NUMFLDS; i++) {
583*7c478bd9Sstevel@tonic-gate 			if (EQUALS(pair.name, _Kwords[i].kword)) {
584*7c478bd9Sstevel@tonic-gate 				flds[i] = pair.value;
585*7c478bd9Sstevel@tonic-gate 				break;
586*7c478bd9Sstevel@tonic-gate 			}
587*7c478bd9Sstevel@tonic-gate 		}
588*7c478bd9Sstevel@tonic-gate #ifndef UUCHECK
589*7c478bd9Sstevel@tonic-gate 		ASSERT(i<NUMFLDS, "PERMISSIONS file: BAD OPTION--",
590*7c478bd9Sstevel@tonic-gate 		    pair.name, NUMFLDS);
591*7c478bd9Sstevel@tonic-gate #else /* UUCHECK */
592*7c478bd9Sstevel@tonic-gate 		if (i >= NUMFLDS) {
593*7c478bd9Sstevel@tonic-gate 			DEBUG(3, "bad option (%s) in PERMISSIONS\n",pair.name);
594*7c478bd9Sstevel@tonic-gate 			(void) printf("\n*****************************\n");
595*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext("**BAD OPTION in PERMISSIONS file: %s\n"),
596*7c478bd9Sstevel@tonic-gate 				pair.name);
597*7c478bd9Sstevel@tonic-gate 			(void) printf("*****************************\n");
598*7c478bd9Sstevel@tonic-gate 			Uerrors++;
599*7c478bd9Sstevel@tonic-gate 			return(0);
600*7c478bd9Sstevel@tonic-gate 		}
601*7c478bd9Sstevel@tonic-gate #endif /* UUCHECK */
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 	return(0);
605*7c478bd9Sstevel@tonic-gate }
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate /*
608*7c478bd9Sstevel@tonic-gate  * return a name value pair
609*7c478bd9Sstevel@tonic-gate  *	string	-> input pointer
610*7c478bd9Sstevel@tonic-gate  *	pair	-> name value pair
611*7c478bd9Sstevel@tonic-gate  * return:
612*7c478bd9Sstevel@tonic-gate  *	pointer to next character
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate char *
615*7c478bd9Sstevel@tonic-gate next_token (string, pair)
616*7c478bd9Sstevel@tonic-gate register char *string;
617*7c478bd9Sstevel@tonic-gate struct name_value *pair;
618*7c478bd9Sstevel@tonic-gate {
619*7c478bd9Sstevel@tonic-gate 	char	*prev = _uu_setlocale(LC_ALL, "C");
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	while ( (*string) && ((*string == '\t') || (*string == ' ')) )
622*7c478bd9Sstevel@tonic-gate 		string++;
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	pair->name = string;
625*7c478bd9Sstevel@tonic-gate 	while ((*string) && (*string != '='))
626*7c478bd9Sstevel@tonic-gate 		string++;
627*7c478bd9Sstevel@tonic-gate 	if (*string)
628*7c478bd9Sstevel@tonic-gate 		*string++ = NULLCHAR;
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 	pair->value = string;
631*7c478bd9Sstevel@tonic-gate 	while ((*string) && (*string != '\t') && (*string != ' ')
632*7c478bd9Sstevel@tonic-gate 	    && (*string != '\n'))
633*7c478bd9Sstevel@tonic-gate 		string++;
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 	if (*string)
636*7c478bd9Sstevel@tonic-gate 		*string++ = NULLCHAR;
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	(void) _uu_resetlocale(LC_ALL, prev);
639*7c478bd9Sstevel@tonic-gate 	return (string);
640*7c478bd9Sstevel@tonic-gate }
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate /*
643*7c478bd9Sstevel@tonic-gate  * get a line from the PERMISSIONS
644*7c478bd9Sstevel@tonic-gate  * take care of comments (#) in col 1
645*7c478bd9Sstevel@tonic-gate  * and continuations (\) in last col
646*7c478bd9Sstevel@tonic-gate  * return:
647*7c478bd9Sstevel@tonic-gate  *	len of line
648*7c478bd9Sstevel@tonic-gate  *	0 -> end of file
649*7c478bd9Sstevel@tonic-gate  */
650*7c478bd9Sstevel@tonic-gate int
651*7c478bd9Sstevel@tonic-gate getuline(fp, line)
652*7c478bd9Sstevel@tonic-gate FILE *fp;
653*7c478bd9Sstevel@tonic-gate char *line;
654*7c478bd9Sstevel@tonic-gate {
655*7c478bd9Sstevel@tonic-gate 	register char *p, *c;
656*7c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	p = line;
659*7c478bd9Sstevel@tonic-gate 	for (;fgets(buf, BUFSIZ, fp) != NULL;) {
660*7c478bd9Sstevel@tonic-gate 		/* remove trailing white space */
661*7c478bd9Sstevel@tonic-gate 		c = &buf[strlen(buf)-1];
662*7c478bd9Sstevel@tonic-gate 		while (c>=buf && (*c == '\n' || *c == '\t' || *c == ' ') )
663*7c478bd9Sstevel@tonic-gate 			*c-- = NULLCHAR;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 		if (buf[0] == '#' || buf[0] == '\n' || buf[0] == NULLCHAR)
666*7c478bd9Sstevel@tonic-gate 			continue;
667*7c478bd9Sstevel@tonic-gate 		(void) strcpy(p, buf);
668*7c478bd9Sstevel@tonic-gate 		p += strlen(buf);
669*7c478bd9Sstevel@tonic-gate 		if ( *(p-1) == '\\')
670*7c478bd9Sstevel@tonic-gate 			p--;
671*7c478bd9Sstevel@tonic-gate 		else
672*7c478bd9Sstevel@tonic-gate 			break;
673*7c478bd9Sstevel@tonic-gate 	}
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	return(p-line);
676*7c478bd9Sstevel@tonic-gate }
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate #define SMAX	15
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate /*
682*7c478bd9Sstevel@tonic-gate  * get the next colon separated argument from the list
683*7c478bd9Sstevel@tonic-gate  * return:
684*7c478bd9Sstevel@tonic-gate  *	p -> pointer to next arg in string
685*7c478bd9Sstevel@tonic-gate  * input:
686*7c478bd9Sstevel@tonic-gate  *	str -> pointer to input string
687*7c478bd9Sstevel@tonic-gate  * output:
688*7c478bd9Sstevel@tonic-gate  *	name -> pointer to arg string
689*7c478bd9Sstevel@tonic-gate  */
690*7c478bd9Sstevel@tonic-gate char *
691*7c478bd9Sstevel@tonic-gate nextarg(str, name)
692*7c478bd9Sstevel@tonic-gate char *str, **name;
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate 	register char *p, *b;
695*7c478bd9Sstevel@tonic-gate 	static char buf[SMAX+1];
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	for(b=buf,p=str; *p != ':' && *p && b < buf+SMAX;)
698*7c478bd9Sstevel@tonic-gate 		*b++ = *p++;
699*7c478bd9Sstevel@tonic-gate 	*b++ = NULLCHAR;
700*7c478bd9Sstevel@tonic-gate 	if (*p == ':')
701*7c478bd9Sstevel@tonic-gate 		p++;
702*7c478bd9Sstevel@tonic-gate 	*name = buf;
703*7c478bd9Sstevel@tonic-gate 	return(p);
704*7c478bd9Sstevel@tonic-gate }
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate /*
707*7c478bd9Sstevel@tonic-gate  * check if requesting files is permitted
708*7c478bd9Sstevel@tonic-gate  * return
709*7c478bd9Sstevel@tonic-gate  *	TRUE -> request permitted
710*7c478bd9Sstevel@tonic-gate  *	FALSE -> request denied
711*7c478bd9Sstevel@tonic-gate  */
712*7c478bd9Sstevel@tonic-gate int
713*7c478bd9Sstevel@tonic-gate requestOK()
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	return(_Request);
716*7c478bd9Sstevel@tonic-gate }
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate /*
719*7c478bd9Sstevel@tonic-gate  * myName - return my name from PERMISSIONS file
720*7c478bd9Sstevel@tonic-gate  *	or if not there, from  uucpname()
721*7c478bd9Sstevel@tonic-gate  * return: none
722*7c478bd9Sstevel@tonic-gate  */
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate void
725*7c478bd9Sstevel@tonic-gate myName(name)
726*7c478bd9Sstevel@tonic-gate char *name;
727*7c478bd9Sstevel@tonic-gate {
728*7c478bd9Sstevel@tonic-gate 	if (*_MyName)
729*7c478bd9Sstevel@tonic-gate 		strcpy(name, _MyName);
730*7c478bd9Sstevel@tonic-gate 	else
731*7c478bd9Sstevel@tonic-gate 		uucpname(name);
732*7c478bd9Sstevel@tonic-gate 	return;
733*7c478bd9Sstevel@tonic-gate }
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate /*
736*7c478bd9Sstevel@tonic-gate  * check for callback required for any transaction
737*7c478bd9Sstevel@tonic-gate  * return:
738*7c478bd9Sstevel@tonic-gate  *	TRUE -> callback required
739*7c478bd9Sstevel@tonic-gate  *	FALSE-> callback NOT required
740*7c478bd9Sstevel@tonic-gate  */
741*7c478bd9Sstevel@tonic-gate int
742*7c478bd9Sstevel@tonic-gate callBack()
743*7c478bd9Sstevel@tonic-gate {
744*7c478bd9Sstevel@tonic-gate 	return(_CallBack);
745*7c478bd9Sstevel@tonic-gate }
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate /*
748*7c478bd9Sstevel@tonic-gate  * check for callback to send any files from here
749*7c478bd9Sstevel@tonic-gate  * This means that the called (SLAVE) system will not switch roles.
750*7c478bd9Sstevel@tonic-gate  * return:
751*7c478bd9Sstevel@tonic-gate  *	TRUE -> callback requried to send files
752*7c478bd9Sstevel@tonic-gate  *	FALSE-> callback NOT required to send files
753*7c478bd9Sstevel@tonic-gate  */
754*7c478bd9Sstevel@tonic-gate int
755*7c478bd9Sstevel@tonic-gate switchRole()
756*7c478bd9Sstevel@tonic-gate {
757*7c478bd9Sstevel@tonic-gate 	return(_Switch);
758*7c478bd9Sstevel@tonic-gate }
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate /*
761*7c478bd9Sstevel@tonic-gate  * Check to see if command is valid for a specific machine.
762*7c478bd9Sstevel@tonic-gate  * The PERMISSIONS file has an option COMMANDS=name1:name2:... for
763*7c478bd9Sstevel@tonic-gate  * any machine that does not have the default list which is
764*7c478bd9Sstevel@tonic-gate  * rmail
765*7c478bd9Sstevel@tonic-gate  * Note that the PERMISSIONS file is read once for each system
766*7c478bd9Sstevel@tonic-gate  * at the time the Rmtname is set in xprocess().
767*7c478bd9Sstevel@tonic-gate  * Return codes:
768*7c478bd9Sstevel@tonic-gate  *	ok: TRUE
769*7c478bd9Sstevel@tonic-gate  *	fail: FALSE
770*7c478bd9Sstevel@tonic-gate  */
771*7c478bd9Sstevel@tonic-gate int
772*7c478bd9Sstevel@tonic-gate cmdOK(cmd, fullcmd)
773*7c478bd9Sstevel@tonic-gate char	*cmd, *fullcmd;
774*7c478bd9Sstevel@tonic-gate {
775*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "cmdOK(%s, )\n", cmd);
776*7c478bd9Sstevel@tonic-gate 	return(cmdMatch(cmd, fullcmd));
777*7c478bd9Sstevel@tonic-gate }
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate /*
781*7c478bd9Sstevel@tonic-gate  * check a name against a list
782*7c478bd9Sstevel@tonic-gate  * input:
783*7c478bd9Sstevel@tonic-gate  *	name	-> name
784*7c478bd9Sstevel@tonic-gate  *	list	-> list of names
785*7c478bd9Sstevel@tonic-gate  * return:
786*7c478bd9Sstevel@tonic-gate  *	TRUE	-> found path
787*7c478bd9Sstevel@tonic-gate  *	FALSE	-> not found
788*7c478bd9Sstevel@tonic-gate  */
789*7c478bd9Sstevel@tonic-gate static int
790*7c478bd9Sstevel@tonic-gate listMatch(name, list)
791*7c478bd9Sstevel@tonic-gate register char *name, *list[];
792*7c478bd9Sstevel@tonic-gate {
793*7c478bd9Sstevel@tonic-gate     register i;
794*7c478bd9Sstevel@tonic-gate     char *temp, *tend;
795*7c478bd9Sstevel@tonic-gate     struct stat statbuf;
796*7c478bd9Sstevel@tonic-gate     dev_t _dev[MAXPATHS+1];
797*7c478bd9Sstevel@tonic-gate     ino_t _ino[MAXPATHS+1];
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate     /* ino set to 0 so stat is only done first time */
800*7c478bd9Sstevel@tonic-gate     for (i=0; list[i] != NULL; i++)
801*7c478bd9Sstevel@tonic-gate 	_ino[i] = 0;
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate     /* try to match inodes */
804*7c478bd9Sstevel@tonic-gate     if ( (temp = strdup(name)) != NULL ) {
805*7c478bd9Sstevel@tonic-gate 	for ( tend = temp + strlen(temp) ; *temp; ) {
806*7c478bd9Sstevel@tonic-gate 	    if ( stat(temp, &statbuf) == 0 ) {
807*7c478bd9Sstevel@tonic-gate 		for (i=0; list[i] != NULL; i++) {
808*7c478bd9Sstevel@tonic-gate 		    if ( _ino[i] == 0 ) {
809*7c478bd9Sstevel@tonic-gate 			struct stat tempbuf;
810*7c478bd9Sstevel@tonic-gate 			if ( stat(list[i], &tempbuf) == 0 ) {
811*7c478bd9Sstevel@tonic-gate 			    _dev[i] = tempbuf.st_dev;
812*7c478bd9Sstevel@tonic-gate 			    _ino[i] = tempbuf.st_ino;
813*7c478bd9Sstevel@tonic-gate 			}
814*7c478bd9Sstevel@tonic-gate 		    }
815*7c478bd9Sstevel@tonic-gate 		    if ( _dev[i] == statbuf.st_dev
816*7c478bd9Sstevel@tonic-gate 		      && _ino[i] == statbuf.st_ino ) {
817*7c478bd9Sstevel@tonic-gate 			free(temp);
818*7c478bd9Sstevel@tonic-gate 			return(TRUE);
819*7c478bd9Sstevel@tonic-gate 		    }
820*7c478bd9Sstevel@tonic-gate 		}
821*7c478bd9Sstevel@tonic-gate 	    }
822*7c478bd9Sstevel@tonic-gate 	    *tend = '\0';
823*7c478bd9Sstevel@tonic-gate 	    if ( (tend = strrchr(temp, '/')) == NULL ) {
824*7c478bd9Sstevel@tonic-gate 		free(temp);
825*7c478bd9Sstevel@tonic-gate 		break;
826*7c478bd9Sstevel@tonic-gate 	    } else
827*7c478bd9Sstevel@tonic-gate 		*(tend+1) = '\0';
828*7c478bd9Sstevel@tonic-gate 	}
829*7c478bd9Sstevel@tonic-gate     }
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate     return(FALSE);
832*7c478bd9Sstevel@tonic-gate }
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate /*
836*7c478bd9Sstevel@tonic-gate  * Check "name" against a BASENAME or full name of _Commands list.
837*7c478bd9Sstevel@tonic-gate  * If "name" specifies full path, check full, else check BASENAME.
838*7c478bd9Sstevel@tonic-gate  *  e.g. "name" rmail matches list item /usr/bin/rmail
839*7c478bd9Sstevel@tonic-gate  * input:
840*7c478bd9Sstevel@tonic-gate  *	name	-> name
841*7c478bd9Sstevel@tonic-gate  * output:
842*7c478bd9Sstevel@tonic-gate  *	fullname -> copy full command name into fullname if
843*7c478bd9Sstevel@tonic-gate  *		    a full path was specified in _Commands;
844*7c478bd9Sstevel@tonic-gate  *		    if not, put name into fullname.
845*7c478bd9Sstevel@tonic-gate  * return:
846*7c478bd9Sstevel@tonic-gate  *	TRUE	-> found path
847*7c478bd9Sstevel@tonic-gate  *	FALSE	-> not found
848*7c478bd9Sstevel@tonic-gate  */
849*7c478bd9Sstevel@tonic-gate static int
850*7c478bd9Sstevel@tonic-gate cmdMatch(name, fullname)
851*7c478bd9Sstevel@tonic-gate register char *name;
852*7c478bd9Sstevel@tonic-gate char *fullname;
853*7c478bd9Sstevel@tonic-gate {
854*7c478bd9Sstevel@tonic-gate 	register i;
855*7c478bd9Sstevel@tonic-gate 	char *bname;
856*7c478bd9Sstevel@tonic-gate 	int allok = FALSE;
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	for (i=0; _Commands[i] != NULL; i++) {
859*7c478bd9Sstevel@tonic-gate 		if (EQUALS(_Commands[i], "ALL")) {
860*7c478bd9Sstevel@tonic-gate 			/* if ALL specified in the list
861*7c478bd9Sstevel@tonic-gate 			 * set allok and continue in case
862*7c478bd9Sstevel@tonic-gate 			 * a full path name is specified for the command
863*7c478bd9Sstevel@tonic-gate 			 */
864*7c478bd9Sstevel@tonic-gate 			allok = TRUE;
865*7c478bd9Sstevel@tonic-gate 			continue;
866*7c478bd9Sstevel@tonic-gate 		}
867*7c478bd9Sstevel@tonic-gate 		if (name[0] != '/')
868*7c478bd9Sstevel@tonic-gate 			bname = BASENAME(_Commands[i], '/');
869*7c478bd9Sstevel@tonic-gate 		else
870*7c478bd9Sstevel@tonic-gate 			bname = _Commands[i];
871*7c478bd9Sstevel@tonic-gate 		DEBUG(7, "bname=%s\n", bname);
872*7c478bd9Sstevel@tonic-gate 		if (EQUALS(bname, name)) {
873*7c478bd9Sstevel@tonic-gate 			(void) strcpy(fullname, _Commands[i]);
874*7c478bd9Sstevel@tonic-gate 			return(TRUE);
875*7c478bd9Sstevel@tonic-gate 		}
876*7c478bd9Sstevel@tonic-gate 	}
877*7c478bd9Sstevel@tonic-gate 	if (allok == TRUE) {
878*7c478bd9Sstevel@tonic-gate 		/* ALL was specified and the command was not found in list */
879*7c478bd9Sstevel@tonic-gate 		(void) strcpy(fullname, name);
880*7c478bd9Sstevel@tonic-gate 		return(TRUE);
881*7c478bd9Sstevel@tonic-gate 	}
882*7c478bd9Sstevel@tonic-gate 	(void) strcpy(fullname, "NuLL");	/* this is a dummy command */
883*7c478bd9Sstevel@tonic-gate 	return(FALSE);
884*7c478bd9Sstevel@tonic-gate }
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate /*
888*7c478bd9Sstevel@tonic-gate  * check the paths for this login/machine
889*7c478bd9Sstevel@tonic-gate  * input:
890*7c478bd9Sstevel@tonic-gate  *	path	pathname
891*7c478bd9Sstevel@tonic-gate  *	flag	CK_READ or CK_WRITE
892*7c478bd9Sstevel@tonic-gate  * output:
893*7c478bd9Sstevel@tonic-gate  *	path	may be modified to canonical form
894*7c478bd9Sstevel@tonic-gate  *		(../, ./, // will be interpreted/removed)
895*7c478bd9Sstevel@tonic-gate  * returns:
896*7c478bd9Sstevel@tonic-gate  *	0		-> success
897*7c478bd9Sstevel@tonic-gate  *	FAIL		-> failure - not a valid path for access
898*7c478bd9Sstevel@tonic-gate  */
899*7c478bd9Sstevel@tonic-gate int
900*7c478bd9Sstevel@tonic-gate chkpth(path, flag)
901*7c478bd9Sstevel@tonic-gate char *path;
902*7c478bd9Sstevel@tonic-gate {
903*7c478bd9Sstevel@tonic-gate 	register char *s;
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate 	/*
906*7c478bd9Sstevel@tonic-gate 	 * this is probably redundant,
907*7c478bd9Sstevel@tonic-gate 	 * because expfile did it, but that's ok
908*7c478bd9Sstevel@tonic-gate 	 * Note - the /../ check is not required because of canPath
909*7c478bd9Sstevel@tonic-gate 	 */
910*7c478bd9Sstevel@tonic-gate 	if (canPath(path) == FAIL)
911*7c478bd9Sstevel@tonic-gate 		return(FAIL);
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	if (flag == CK_READ)
914*7c478bd9Sstevel@tonic-gate 		if (listMatch(path, _RPaths)
915*7c478bd9Sstevel@tonic-gate 		&& !listMatch(path, _NoRPaths))
916*7c478bd9Sstevel@tonic-gate 			return(0);
917*7c478bd9Sstevel@tonic-gate 	if (flag == CK_WRITE)
918*7c478bd9Sstevel@tonic-gate 		if (listMatch(path, _WPaths)
919*7c478bd9Sstevel@tonic-gate 		&& !listMatch(path, _NoWPaths))
920*7c478bd9Sstevel@tonic-gate 			return(0);
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate 	/* ok if uucp generated D. or X. name for the spool directory */
924*7c478bd9Sstevel@tonic-gate 	if (PREFIX(RemSpool, path) ) {
925*7c478bd9Sstevel@tonic-gate     		s = &path[strlen(RemSpool)];
926*7c478bd9Sstevel@tonic-gate 		if ( (*s++ == '/')
927*7c478bd9Sstevel@tonic-gate 		  && (*s == DATAPRE || *s == XQTPRE)
928*7c478bd9Sstevel@tonic-gate 		  && (*(++s) == '.')
929*7c478bd9Sstevel@tonic-gate 		  && (strchr(s, '/') == NULL) )
930*7c478bd9Sstevel@tonic-gate 			return(0);
931*7c478bd9Sstevel@tonic-gate 	}
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 	/*  path name not valid */
934*7c478bd9Sstevel@tonic-gate 	return(FAIL);
935*7c478bd9Sstevel@tonic-gate }
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate /*
938*7c478bd9Sstevel@tonic-gate  * check write permission of file.
939*7c478bd9Sstevel@tonic-gate  * if mopt != NULL and permissions are ok,
940*7c478bd9Sstevel@tonic-gate  * a side effect of this routine is to make
941*7c478bd9Sstevel@tonic-gate  * directories up to the last part of the
942*7c478bd9Sstevel@tonic-gate  * "to" ( if they do not exit).
943*7c478bd9Sstevel@tonic-gate  * Input:
944*7c478bd9Sstevel@tonic-gate  *	to - a path name of the destination file or directory
945*7c478bd9Sstevel@tonic-gate  *	from - full path name of source file
946*7c478bd9Sstevel@tonic-gate  *	opt - create directory option (NULL - don't create)
947*7c478bd9Sstevel@tonic-gate  * Output:
948*7c478bd9Sstevel@tonic-gate  *	to - will be the full path name of the destination file
949*7c478bd9Sstevel@tonic-gate  * returns:
950*7c478bd9Sstevel@tonic-gate  *	0	->success
951*7c478bd9Sstevel@tonic-gate  *	FAIL	-> failure
952*7c478bd9Sstevel@tonic-gate  */
953*7c478bd9Sstevel@tonic-gate int
954*7c478bd9Sstevel@tonic-gate chkperm(from, to, opt)
955*7c478bd9Sstevel@tonic-gate char *from, *to, *opt;
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate 	register char *lxp, *p;
958*7c478bd9Sstevel@tonic-gate 	struct stat s;
959*7c478bd9Sstevel@tonic-gate 	char dir[MAXFULLNAME];
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate 	if (*(p = LASTCHAR(to)) == '/') {
962*7c478bd9Sstevel@tonic-gate 	    if (strlcpy(p+1, BASENAME(from, '/'), MAXFULLNAME - strlen(to)) >=
963*7c478bd9Sstevel@tonic-gate 		MAXFULLNAME - strlen(to)) {
964*7c478bd9Sstevel@tonic-gate 		    return(FAIL);
965*7c478bd9Sstevel@tonic-gate 	    }
966*7c478bd9Sstevel@tonic-gate 	} else if (DIRECTORY(to)) {
967*7c478bd9Sstevel@tonic-gate 	    *++p = '/';
968*7c478bd9Sstevel@tonic-gate 	    if (strlcpy(p+1, BASENAME(from, '/'), MAXFULLNAME - strlen(to)) >=
969*7c478bd9Sstevel@tonic-gate 		MAXFULLNAME - strlen(to)) {
970*7c478bd9Sstevel@tonic-gate 		    return(FAIL);
971*7c478bd9Sstevel@tonic-gate 	    }
972*7c478bd9Sstevel@tonic-gate 	}
973*7c478bd9Sstevel@tonic-gate 
974*7c478bd9Sstevel@tonic-gate 	/* to is now the full path name of the destination file */
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate 	if (WRITEANY(to))
977*7c478bd9Sstevel@tonic-gate 	    return(0);
978*7c478bd9Sstevel@tonic-gate 	if (stat(to, &s) == 0)
979*7c478bd9Sstevel@tonic-gate 	    return(FAIL);	/* file exists, but not writeable */
980*7c478bd9Sstevel@tonic-gate 
981*7c478bd9Sstevel@tonic-gate 	/* file does not exist--check directory and make when necessary */
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 	(void) strcpy(dir, to);
984*7c478bd9Sstevel@tonic-gate 	if ( (lxp=strrchr(dir, '/')) == NULL)
985*7c478bd9Sstevel@tonic-gate 	    return(FAIL);	/* no directory part of name */
986*7c478bd9Sstevel@tonic-gate 	if (lxp == dir)	/* at root */
987*7c478bd9Sstevel@tonic-gate 	    lxp++;
988*7c478bd9Sstevel@tonic-gate 	*lxp = NULLCHAR;
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 	/* should check WRITEANY on parent before mkdirs() */
991*7c478bd9Sstevel@tonic-gate 	if (!DIRECTORY(dir)) {
992*7c478bd9Sstevel@tonic-gate 	    if (opt == NULL)
993*7c478bd9Sstevel@tonic-gate 		return(FAIL);	/* no directory and no opt to make them */
994*7c478bd9Sstevel@tonic-gate 	    else if (mkdirs(dir, PUBMASK) == FAIL)
995*7c478bd9Sstevel@tonic-gate 		return(FAIL);
996*7c478bd9Sstevel@tonic-gate 	}
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 	/* the directory now exists--check for writability */
999*7c478bd9Sstevel@tonic-gate 	if (EQUALS(RemSpool, dir) || WRITEANY(dir))
1000*7c478bd9Sstevel@tonic-gate 	    return(0);
1001*7c478bd9Sstevel@tonic-gate 
1002*7c478bd9Sstevel@tonic-gate 	return(FAIL);
1003*7c478bd9Sstevel@tonic-gate }
1004