/* */ /* * Copyright (c) 1989, 1990, 1991 by the University of Washington */ /* * */ /* * For copying and distribution information, please see the file */ /* * . */ /* * Miscellaneous routines pulled from ~beta/lib/pfs and ~beta/lib/filters */ #include "pmachine.h" #include #include "pfs.h" #include "pprot.h" #include "perrno.h" #include "pcompat.h" #include "pauthent.h" #include "regex.h" int pfs_enable = PMAP_ATSIGN; /* */ /* * wcmatch - Match string s against template containing widlcards */ /* * */ /* * WCMATCH takes a string and a template, and returns */ /* * true if the string matches the template, and */ /* * FALSE otherwise. */ /* * */ /* * ARGS: s - string to be tested */ /* * template - Template containing optional wildcards */ /* * */ /* * RETURNS: TRUE (non-zero) on match. FALSE (0) otherwise. */ /* * */ /* * NOTE: If template is NULL, will return TRUE. */ /* * */ int wcmatch(s,template) char *s; char *template; { char temp[200]; char *p = temp; if(!template) return(TRUE); *p++ = '^'; while(*template) { if(*template == '*') {*(p++)='.'; *(p++) = *(template++);} else if(*template == '?') {*(p++)='.';template++;} else if(*template == '.') {*(p++)='\\';*(p++)='.';template++;} else if(*template == '[') {*(p++)='\\';*(p++)='[';template++;} else if(*template == '$') {*(p++)='\\';*(p++)='$';template++;} else if(*template == '^') {*(p++)='\\';*(p++)='^';template++;} else if(*template == '\\') {*(p++)='\\';*(p++)='\\';template++;} else *(p++) = *(template++); } *p++ = '$'; *p++ = '\0'; if(re_comp(temp)) return(FALSE); #ifdef AUX if (re_exec(s) == (char *)NULL) return 0; return 1; #else return(re_exec(s)); #endif } /* */ /* * ul_insert - Insert a union link at the right location */ /* * */ /* * UL_INSERT takes a directory and a union link to be added */ /* * to a the list of union links in the directory. It then */ /* * inserts the union link in the right spot in the linked */ /* * list of union links associated with that directory. */ /* * */ /* * If an identical link already exists, then the link which */ /* * would be evaluated earlier (closer to the front of the list) */ /* * wins and the other one is freed. If this happens, an error */ /* * will also be returned. */ /* * */ /* * ARGS: ul - link to be inserted */ /* * vd - directory to get link */ /* * p - vl that this link will apper after */ /* * NULL - This vl will go at end of list */ /* * vd - This vl will go at head of list */ /* * */ /* * RETURNS: Success, or UL_INSERT_ALREADY_THERE or UL_INSERT_SUPERSEDING */ int ul_insert(ul,vd,p) VLINK ul; /* Link to be inserted */ PVDIR vd; /* Directory to receive link */ VLINK p; /* Union link to appear prior to new one */ { VLINK current; /* This is the first ul in the directory */ if(vd->ulinks == NULL) { vd->ulinks = ul; ul->previous = NULL; ul->next = NULL; return(PSUCCESS); } /* This ul will go at the head of the list */ if(p == (VLINK) vd) { ul->next = vd->ulinks; ul->next->previous = ul; vd->ulinks = ul; ul->previous = NULL; } /* Otherwise, decide if it must be inserted at all If an identical */ /* link appears before the position at which the new one is to be */ /* inserted, we can return without inserting it */ else { current = vd->ulinks; while(current) { /* p == NULL means we insert after last link */ if(!p && (current->next == NULL)) p = current; if(vl_comp(current,ul) == 0) { vlfree(ul); return(UL_INSERT_ALREADY_THERE); } if(current == p) break; current = current->next; } /* If current is null, p was not found */ if(current == NULL) return(UL_INSERT_POS_NOTFOUND); /* Insert ul */ ul->next = p->next; p->next = ul; ul->previous = p; if(ul->next) ul->next->previous = ul; } /* Check for identical links after ul */ current = ul->next; while(current) { if(vl_comp(current,ul) == 0) { current->previous->next = current->next; if(current->next) current->next->previous = current->previous; vlfree(current); return(UL_INSERT_SUPERSEDING); } current = current->next; } return(PSUCCESS); } /* */ /* * vl_insert - Insert a directory link at the right location */ /* * */ /* * VL_INSERT takes a directory and a link to be added to a */ /* * directory and inserts it in the linked list of links for */ /* * that directory. */ /* * */ /* * If a link already exists with the same name, and if the */ /* * information associated with the new link matches that in */ /* * the existing link, an error is returned. If the information */ /* * associated with the new link is different, but the magic numbers */ /* * match, then the new link will be added as a replica of the */ /* * existing link. If the magic numbers do not match, the new */ /* * link will only be added to the list of "replicas" if the */ /* * allow_conflict flag has been set. */ /* * */ /* * If the link is not added, an error is returned and the link */ /* * is freed. Ordering for the list of links is by the link name. */ /* * */ /* * If vl is a union link, then VL_INSERT calls ul_insert with an */ /* * added argument indicating the link is to be included at the */ /* * end of the union link list. */ /* * */ /* * ARGS: vl - Link to be inserted, vd - directory to get link */ /* * allow_conflict - insert links with conflicting names */ /* * */ /* * RETURNS: Success, or VL_INSERT_ALREADY_THERE */ int vl_insert(vl,vd,allow_conflict) VLINK vl; /* Link to be inserted */ PVDIR vd; /* Directory to receive link */ int allow_conflict; /* Allow duplicate names */ { VLINK current; /* To step through list */ VLINK crep; /* To step through list of replicas */ int retval; /* Temp for checking returned values */ /* This can also be used to insert union links at end of list */ if(vl->linktype == 'U') return(ul_insert(vl,vd,NULL)); /* If this is the first link in the directory */ if(vd->links == NULL) { vd->links = vl; vl->previous = NULL; vl->next = NULL; vd->lastlink = vl; return(PSUCCESS); } /* If no sorting is to be done, just insert at end of list */ if(allow_conflict == VLI_NOSORT) { vd->lastlink->next = vl; vl->previous = vd->lastlink; vl->next = NULL; vd->lastlink = vl; return(PSUCCESS); } /* If it is to be inserted at start of list */ if(vl_comp(vl,vd->links) < 0) { vl->next = vd->links; vl->previous = NULL; vl->next->previous = vl; vd->links = vl; return(PSUCCESS); } current = vd->links; /* Otherwise, we must find the right spot to insert it */ while((retval = vl_comp(vl,current)) > 0) { if(!current->next) { /* insert at end */ vl->previous = current; vl->next = NULL; current->next = vl; vd->lastlink = vl; return(PSUCCESS); } current = current->next; } /* If we found an equivilant entry already in list */ if(!retval) { if(vl_equal(vl,current)) { vlfree(vl); return(VL_INSERT_ALREADY_THERE); } if((allow_conflict == VLI_NOCONFLICT) && ((vl->f_magic_no != current->f_magic_no) || (vl->f_magic_no==0))) return(VL_INSERT_CONFLICT); /* Insert the link into the list of "replicas" If magic is 0, */ /* then create a pseudo magic number */ if(vl->f_magic_no == 0) vl->f_magic_no = -1; crep = current->replicas; if(!crep) { current->replicas = vl; vl->next = NULL; vl->previous = NULL; } else { while(crep->next) { /* If magic was 0, then we need a unique magic number */ if((crep->f_magic_no < 0) && (vl->f_magic_no < 1)) (vl->f_magic_no)--; crep = crep->next; } /* If magic was 0, then we need a unique magic number */ if((crep->f_magic_no < 0) && (vl->f_magic_no < 1)) (vl->f_magic_no)--; crep->next = vl; vl->previous = crep; vl->next = NULL; } return(PSUCCESS); } /* We found the spot where vl is to be inserted */ vl->next = current; vl->previous = current->previous; current->previous = vl; vl->previous->next = vl; return(PSUCCESS); } /* */ /* * nlsindex - Find first instance of string 2 in string 1 following */ /* newline */ /* * */ /* * NLSINDEX scans string 1 for the first instance of string */ /* * 2 that immediately follows a newline. If found, NLSINDEX */ /* * returns a pointer to the first character of that instance. */ /* * If no instance is found, NLSINDEX returns NULL (0). */ /* * */ /* * NOTE: This function is only useful for searching strings that */ /* * consist of multiple lines. s1 is assumed to be preceeded */ /* * by a newline. Thus, if s2 is at the start of s1, it will */ /* * be found. */ /* * ARGS: s1 - string to be searched */ /* * s2 - string to be found */ /* * RETURNS: First instance of s2 in s1, or NULL (0) if not found */ char * nlsindex(s1,s2) char *s1; /* String to be searched */ char *s2; /* String to be found */ { register int s2len = strlen(s2); char *curline = s1; /* Pointer to start of current line */ /* In case s2 appears at start of s1 */ if(strncmp(curline,s2,s2len) == 0) return(curline); /* Check remaining lines of s1 */ while((curline = (char *) index(curline,'\n')) != NULL) { curline++; if(strncmp(curline,s2,s2len) == 0) return(curline); } /* We didn't find it */ return(NULL); } /* */ /* * month_sname - Return a month name from it's number */ /* * */ /* * MONTH_SNAME takes a number in the range 0 */ /* * to 12 and returns a pointer to a string */ /* * representing the three letter abbreviation */ /* * for that month. If the argument is out of */ /* * range, MONTH_SNAME returns a pointer to "Unk". */ /* * */ /* * ARGS: n - Number of the month */ /* * RETURNS: Abbreviation for selected month */ char *month_sname(n) int n; /* Month number */ { static char *name[] = { "Unk", "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; return((n < 1 || n > 12) ? name[0] : name[n]); } /* */ /* * sindex - Find first instance of string 2 in string 1 */ /* * */ /* * SINDEX scans string 1 for the first instance of string */ /* * 2. If found, SINDEX returns a pointer to the first */ /* * character of that instance. If no instance is found, */ /* * SINDEX returns NULL (0). */ /* * */ /* * ARGS: s1 - string to be searched */ /* * s2 - string to be found */ /* * RETURNS: First instance of s2 in s1, or NULL (0) if not found */ char * sindex(s1,s2) char *s1; /* String to be searched */ char *s2; /* String to be found */ { register int s2len = strlen(s2); char *s = s1; /* Temp pointer to string */ /* Check for first character of s2 */ while((s = (char *) index(s,*s2)) != NULL) { if(strncmp(s,s2,s2len) == 0) return(s); s++; } /* We didn't find it */ return(NULL); } int scan_error(erst) char *erst; { *p_err_string = '\0'; if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0) return(DIRSRV_NOT_DIRECTORY); if(strncmp(erst,"UNIMPLEMENTED",13) == 0) { perrno = DIRSRV_UNIMPLEMENTED; sscanf(erst+13,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string); return(perrno); } if(strncmp(erst,"WARNING ",8) == 0) { erst += 8; *p_warn_string = '\0'; sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_warn_string); /* Return values for warnings are negative */ if(strncmp(erst,"OUT-OF-DATE",11) == 0) { pwarn = PWARN_OUT_OF_DATE; return(PSUCCESS); } if(strncmp(erst,"MESSAGE",7) == 0) { pwarn = PWARN_MSG_FROM_SERVER; return(PSUCCESS); } pwarn = PWARNING; sscanf(erst,"%[^\n]",p_warn_string); return(PSUCCESS); } else if(strncmp(erst,"ERROR",5) == 0) { if(*(erst+5)) sscanf(erst+6,"%[^\n]",p_err_string); perrno = DIRSRV_ERROR; return(perrno); } /* The rest start with "FAILURE" */ else if(strncmp(erst,"FAILURE",7) != 0) { /* Unrecognized - Give warning, but return PSUCCESS */ if(pwarn == 0) { *p_warn_string = '\0'; pwarn = PWARN_UNRECOGNIZED_RESP; sscanf(erst,"%[^\n]",p_warn_string); } return(PSUCCESS); } if(strncmp(erst,"FAILURE ",8) != 0) { perrno = PFAILURE; return(perrno); } erst += 8; sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string); /* Still to add */ /* DIRSRV_AUTHENT_REQ 242 */ /* DIRSRV_BAD_VERS 245 */ if(strncmp(erst,"NOT-FOUND",9) == 0) perrno = DIRSRV_NOT_FOUND; else if(strncmp(erst,"NOT-AUTHORIZED",13) == 0) perrno = DIRSRV_NOT_AUTHORIZED; else if(strncmp(erst,"ALREADY-EXISTS",14) == 0) perrno = DIRSRV_ALREADY_EXISTS; else if(strncmp(erst,"NAME-CONFLICT",13) == 0) perrno = DIRSRV_NAME_CONFLICT; else if(strncmp(erst,"SERVER-FAILED",13) == 0) perrno = DIRSRV_SERVER_FAILED; /* Use it whether it starts with FAILURE or not */ else if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0) perrno = DIRSRV_NOT_DIRECTORY; else perrno = PFAILURE; return(perrno); } PATTRIB parse_attribute(line) char *line; { char l_precedence[MAX_DIR_LINESIZE]; char l_name[MAX_DIR_LINESIZE]; char l_type[MAX_DIR_LINESIZE]; char l_value[MAX_DIR_LINESIZE]; PATTRIB at; int tmp; tmp = sscanf(line,"OBJECT-INFO %s %s %[^\n]", l_name, l_type, l_value); if(tmp < 3) { tmp = sscanf(line,"LINK-INFO %s %s %s %[^\n]", l_precedence, l_name, l_type, l_value); if(tmp < 4) { perrno = DIRSRV_BAD_FORMAT; return(NULL); } } at = atalloc(); if(tmp == 4) { if(strcmp(l_precedence,"CACHED") == 0) at->precedence = ATR_PREC_CACHED; else if(strcmp(l_precedence,"LINK") == 0) at->precedence = ATR_PREC_LINK; else if(strcmp(l_precedence,"REPLACEMENT") == 0) at->precedence = ATR_PREC_REPLACE; else if(strcmp(l_precedence,"ADDITIONAL") == 0) at->precedence = ATR_PREC_ADD; } at->aname = stcopy(l_name); at->avtype = stcopy(l_type); if(strcmp(l_type,"ASCII") == 0) at->value.ascii = stcopy(l_value); else if(strcmp(l_type,"LINK") == 0) { char ftype[MAX_DIR_LINESIZE]; char lname[MAX_DIR_LINESIZE]; char htype[MAX_DIR_LINESIZE]; char host[MAX_DIR_LINESIZE]; char ntype[MAX_DIR_LINESIZE]; char fname[MAX_DIR_LINESIZE]; VLINK al; al = vlalloc(); at->value.link = al; tmp = sscanf(l_value,"%c %s %s %s %s %s %s %ld %ld", &(al->linktype), ftype,lname,htype,host,ntype,fname, &(al->version), &(al->f_magic_no)); if(tmp == 9) { al->type = stcopyr(ftype,al->type); al->name = stcopyr(unquote(lname),al->name); al->hosttype = stcopyr(htype,al->hosttype); al->host = stcopyr(host,al->host); al->nametype = stcopyr(ntype,al->nametype); al->filename = stcopyr(fname,al->filename); } else { perrno = DIRSRV_BAD_FORMAT; return(NULL); } } return(at); } /* */ /* * nxtline - Find the next line in the string */ /* * */ /* * NXTLINE takes a string and returns a pointer to */ /* * the character immediately following the next newline. */ /* * */ /* * ARGS: s - string to be searched */ /* * */ /* * RETURNS: Next line or NULL (0) on failure */ char * nxtline(s) char *s; /* String to be searched */ { s = (char *) index(s,'\n'); if(s) return(++s); else return(NULL); } /* */ /* * unquote - unquote string if necessary */ /* * */ /* * UNQUOTE takes a string and unquotes it if it has been quoted. */ /* * */ /* * ARGS: s - string to be unquoted */ /* * */ /* * RETURNS: The original string. If the string has been quoted, then the */ /* * result appears in static storage, and must be copied if */ /* * it is to last beyond the next call to quote. */ /* * */ char * unquote(s) char *s; /* String to be quoted */ { static char unquoted[200]; char *c = unquoted; if(*s != '\'') return(s); s++; /* This should really treat a quote followed by other */ /* than a quote or a null as an error */ while(*s) { if(*s == '\'') s++; if(*s) *c++ = *s++; } *c++ = '\0'; return(unquoted); } #if defined(DEBUG) && !defined(HAVE_STRSPN) /* needed for -D option parsing */ /* */ /* * strspn - Count initial characters from chrs in s */ /* * */ /* * STRSPN counts the occurances of chacters from chrs */ /* * in the string s preceeding the first occurance of */ /* * a character not in s. */ /* * */ /* * ARGS: s - string to be checked */ /* * chrs - string of characters we are looking for */ /* * */ /* * RETURNS: Count of initial characters from chrs in s */ strspn(s,chrs) char *s; /* String to search */ char *chrs; /* String of characters we are looking for */ { char *cp; /* Pointer to the current character in chrs */ int count; /* Count of characters seen so far */ count = 0; while(*s) { for(cp = chrs;*cp;cp++) if(*cp == *s) { s++; count++; goto done; } return(count); done: ; } return(count); } #endif #ifndef HAVE_GETENV /* */ /* * Copyright (c) 1987 Regents of the University of California. */ /* * All rights reserved. */ /* * */ /* * Redistribution and use in source and binary forms are permitted */ /* * provided that: (1) source distributions retain this entire copyright */ /* * notice and comment, and (2) distributions including binaries display */ /* * the following acknowledgement: ``This product includes software */ /* * developed by the University of California, Berkeley and its */ /* contributors'' */ /* * in the documentation or other materials provided with the distribution */ /* * and in all advertising materials mentioning features or use of this */ /* * software. Neither the name of the University nor the names of its */ /* * contributors may be used to endorse or promote products derived */ /* * from this software without specific prior written permission. */ /* * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getenv.c 5.7 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ #include #include /* */ /* * getenv -- */ /* * Returns ptr to value associated with name, if any, else NULL. */ char * getenv(name) const char *name; { int offset; char *_findenv(); return(_findenv(name, &offset)); } /* */ /* * _findenv -- */ /* * Returns pointer to value associated with name, if any, else NULL. */ /* * Sets offset to be the offset of the name/value combination in the */ /* * environmental array, for use by setenv(3) and unsetenv(3). */ /* * Explicitly removes '=' in argument name. */ /* * */ /* * This routine *should* be a static; don't use it. */ char * _findenv(name, offset) register const char *name; int *offset; { extern char **environ; register int len; register const char *C; register char **P; for (C = name, len = 0; *C && *C != '='; ++C, ++len); for (P = environ; *P; ++P) if (!strncmp(*P, name, len)) if (*(C = *P + len) == '=') { *offset = P - environ; return(++C); } return(NULL); } #endif