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