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