get_vdir.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:14k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /*
- * Copyright (c) 1989, 1990, 1991 by the University of Washington
- *
- * For copying and distribution information, please see the file
- * <copyright.h>.
- */
- #include "pmachine.h"
- #include "pfs.h"
- #include "pprot.h"
- #include "perrno.h"
- #include "pcompat.h"
- #include "pauthent.h"
- #ifdef DEBUG
- extern int pfs_debug;
- #endif
- extern int pwarn;
- extern char p_warn_string[];
- extern int perrno;
- extern char p_err_string[];
- /*
- * get_vdir - Get contents of a directory given its location
- *
- * GET_VDIR takes a directory location, a list of desired
- * components, a pointer to a directory structure to be
- * filled in, and flags. It then queries the appropriate
- * directory server and retrieves the desired information.
- *
- * ARGS: dhost - Host on which directory resides
- * dfile - Directory on that host
- * components - The names from the directory we want
- * dir - Structure to be filled in
- * flags - Options. See FLAGS
- * filters - filters to be applied to result
- * acomp - Pointer to remaining components
- *
- * FLAGS: GVD_UNION - Do not expand union links
- * GVD_EXPAND - Expand union links locally
- * GVD_REMEXP - Request remote expansion (& local if refused)
- * GVD_LREMEXP - Request remote expansion of local union links
- * GVD_VERIFY - Only verify that args are for a directory
- * GVD_ATTRIB - Request attributes from directory server
- * GVD_NOSORT - Do not sort links when adding to directory
- *
- * RETURNS: PSUCCESS (0) or error code
- * On some codes addition information in p_err_string
- *
- * NOTES: If acomp is non-null the string it points to might be modified
- *
- * If the directory passed as an argument already has
- * links or union links, then those lists will be freed
- * before the new contents are filled in.
- *
- * If a filter is passed to the procedure, and application of
- * the filter results in additional union link, then those links
- * will (or will not) be expanded as specified in the FLAGS field.
- *
- * If the list of components in NULL, or the null string, then
- * get_vdir will return all links in the requested directory.
- *
- * BUGS: Doesn't process union links yet
- * Doesn't process errors returned from server
- * Doesn't expand union links if requested to
- */
- int
- get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
- char *dhost; /* Host on which directory resides */
- char *dfile; /* Name of file on that host */
- char *components; /* Component name (wildcards allowed) */
- PVDIR dir; /* Structure to be filled in */
- long flags; /* Flags */
- VLINK filters; /* Filters to be applied to result */
- char *acomp; /* Components left to be resolved */
- {
- PTEXT request; /* Text of request to dir server */
- PTEXT resp; /* Response from dir server */
- char ulcomp[MAX_VPATH];/* Work space for new current component */
- char *comp = components;
- VLINK cur_link = NULL;/* Current link being filled in */
- VLINK exp = NULL; /* The current ulink being expanded */
- VLINK pul = NULL; /* Prev union link (insert new one after it) */
- VLINK l; /* Temp link pointer */
- int mcomp; /* Flag - check multiple components */
- int unresp; /* Flag - received unresolved response */
- int getattrib = 0; /* Get attributes from server */
- int vl_insert_flag; /* Flags to vl_insert */
- int fwdcnt = MAX_FWD_DEPTH;
- int no_links = 0; /* Count of number of links found */
- char options[40]; /* LIST option */
- char *opt; /* After leading + */
- PAUTH authinfo;
- /* Treat null string like NULL (return entire directory) */
- if(!components || !*components) comp = NULL;
- if(acomp && !filters) mcomp = 1;
- else mcomp = 0;
- if(flags&GVD_ATTRIB) {
- getattrib++;
- flags &= (~GVD_ATTRIB);
- }
- if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
- else vl_insert_flag = VLI_ALLOW_CONF;
- flags &= (~GVD_NOSORT);
- if(filters) comp = NULL;
- perrno = 0;
- authinfo = get_pauth(PFSA_UNAUTHENTICATED);
- *options = ' ';
- if(getattrib) {
- strcat(options,"+ATTRIBUTES");
- flags &= (~GVD_ATTRIB);
- }
- if(!filters) { /* Can't do remote expansion if filters to be applied */
- if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
- if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
- }
- /* If all we are doing is verifying that dfile is a directory */
- /* then we do not want a big response from the directory */
- /* server. A NOT-FOUND is sufficient. */
- if(flags == GVD_VERIFY)
- #ifdef NEWVERIFYOPT
- strcat(options,"+VERIFY");
- #else
- comp = "%#$PRobably_nOn_existaNT$#%";
- #endif
- if(*options) opt = options+1;
- else opt = "''";
- startover:
- request = ptalloc();
- sprintf(request->start,
- "VERSION %d %snAUTHENTICATOR %s %snDIRECTORY ASCII %snLIST %s COMPONENTS %s%s%sn",
- VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
- authinfo->authenticator, dfile, opt,
- (comp ? comp : ""), (mcomp ? "/" : ""),
- (mcomp ? acomp : ""));
- request->length = strlen(request->start);
- #ifdef DEBUG
- if(pfs_debug > 2)
- fprintf(stderr,"Sending message to dirsrv:n%s",request->start);
- #endif
- resp = dirsend(request,dhost,0);
- #ifdef DEBUG
- if(pfs_debug && (resp == NULL)) {
- fprintf(stderr,"Dirsend failed: %dn",perrno);
- }
- #endif
- /* If we don't get a response, then if the requested */
- /* directory, return error, if a ulink, mark it unexpanded */
- if(resp == NULL) {
- if(exp) exp->expanded = FAILED;
- else return(perrno);
- }
- unresp = 0;
- /* Here we must parse reponse and put in directory */
- /* While looking at each packet */
- while(resp) {
- PTEXT vtmp;
- char *line;
- vtmp = resp;
- #ifdef DEBUG
- if(pfs_debug > 3) fprintf(stderr,"%sn",resp->start);
- #endif
- /* Look at each line in packet */
- for(line = resp->start;line != NULL;line = nxtline(line)) {
- switch (*line) {
- /* Temporary variables to hold link info */
- char l_linktype;
- char l_name[MAX_DIR_LINESIZE];
- char l_type[MAX_DIR_LINESIZE];
- char l_htype[MAX_DIR_LINESIZE];
- char l_host[MAX_DIR_LINESIZE];
- char l_ntype[MAX_DIR_LINESIZE];
- char l_fname[MAX_DIR_LINESIZE];
- int l_version;
- char t_unresolved[MAX_DIR_LINESIZE];
- int l_magic;
- int tmp;
- case 'L': /* LINK or LINK-INFO */
- if(strncmp(line,"LINK-INFO",9) == 0) {
- PATTRIB at;
- PATTRIB last_at;
- at = parse_attribute(line);
- if(!at) break;
- /* Cant have link info without a link */
- if(!cur_link) {
- perrno = DIRSRV_BAD_FORMAT;
- atfree(at);
- break;
- }
- if(cur_link->lattrib) {
- last_at = cur_link->lattrib;
- while(last_at->next) last_at = last_at->next;
- at->previous = last_at;
- last_at->next = at;
- }
- else {
- cur_link->lattrib = at;
- at->previous = NULL;
- }
- break;
- }
- /* Not LINK-INFO, must be LINK - if not check for error */
- if(strncmp(line,"LINK",4) != 0) goto scanerr;
- /* If only verifying, don't want to change dir */
- if(flags == GVD_VERIFY) {
- break;
- }
- /* If first link and some links in dir, free them */
- if(!no_links++) {
- if(dir->links) vllfree(dir->links); dir->links=NULL;
- if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
- }
- cur_link = vlalloc();
- /* parse and insert file info */
- tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %ld %ld", &l_linktype,
- l_type,l_name,l_htype,l_host,l_ntype,l_fname,
- &(cur_link->version),
- &(cur_link->f_magic_no));
- if(tmp != 9) {
- perrno = DIRSRV_BAD_FORMAT;
- vlfree(cur_link);
- break;
- }
- cur_link->linktype = l_linktype;
- cur_link->type = stcopyr(l_type,cur_link->type);
- cur_link->name = stcopyr(unquote(l_name),cur_link->name);
- cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
- cur_link->host = stcopyr(l_host,cur_link->host);
- cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
- cur_link->filename = stcopyr(l_fname,cur_link->filename);
- /* Double check to make sure we don't get */
- /* back unwanted components */
- /* OK to keep if special (URP) links */
- /* or if mcomp specified */
- if(!mcomp && (cur_link->linktype == 'L') &&
- (!wcmatch(cur_link->name,comp))) {
- vlfree(cur_link);
- break;
- }
- /* If other optional info was sent back, it must */
- /* also be parsed before inserting link *** */
- if(cur_link->linktype == 'L')
- vl_insert(cur_link,dir,vl_insert_flag);
- else {
- tmp = ul_insert(cur_link,dir,pul);
- /* If inserted after pul, next one after cur_link */
- if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
- pul = cur_link;
- }
- break;
- case 'F': /* FILTER, FAILURE or FORWARDED */
- /* FORWARDED */
- if(strncmp(line,"FORWARDED",9) == 0) {
- if(fwdcnt-- <= 0) {
- ptlfree(resp);
- perrno = PFS_MAX_FWD_DEPTH;
- return(perrno);
- }
- /* parse and start over */
- tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d",
- l_htype,l_host,l_ntype,l_fname,
- &l_version, &l_magic);
- dhost = stcopy(l_host);
- dfile = stcopy(l_fname);
- if(tmp < 4) {
- perrno = DIRSRV_BAD_FORMAT;
- break;
- }
- ptlfree(resp);
- goto startover;
- }
- if(strncmp(line,"FILTER",6) != 0) goto scanerr;
- break;
- case 'M': /* MULTI-PACKET (processed by dirsend) */
- case 'P': /* PACKET (processed by dirsend) */
- break;
- case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
- /* NONE-FOUND, we just have no links to insert */
- /* It is not an error, but we must clear any */
- /* old links in the directory arg */
- if(strncmp(line,"NONE-FOUND",10) == 0) {
- /* If only verifying, don't want to change dir */
- if(flags == GVD_VERIFY) {
- break;
- }
- /* If first link and some links in dir, free them */
- if(!no_links++) {
- if(dir->links) vllfree(dir->links);
- if(dir->ulinks) vllfree(dir->ulinks);
- dir->links = NULL;
- dir->ulinks = NULL;
- }
- break;
- }
- /* If NOT-A-DIRECTORY or anything else, scan error */
- goto scanerr;
- case 'U': /* UNRESOLVED */
- if(strncmp(line,"UNRESOLVED",10) != 0) {
- goto scanerr;
- }
- tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
- if(tmp < 1) {
- perrno = DIRSRV_BAD_FORMAT;
- break;
- }
- /* If multiple components were resolved */
- if(strlen(t_unresolved) < strlen(acomp)) {
- strcpy(ulcomp,acomp);
- /* ulcomp is the components that were resolved */
- *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = ' ';
- /* Comp gets the last component resolved */
- comp = (char *) rindex(ulcomp,'/');
- if(comp) comp++;
- else comp = ulcomp;
- /* Let rd_vdir know what remains */
- strcpy(acomp,t_unresolved);
- }
- unresp = 1;
- break;
- case 'V': /* VERSION-NOT-SUPPORTED */
- if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
- perrno = DIRSRV_BAD_VERS;
- return(perrno);
- }
- goto scanerr;
- scanerr:
- default:
- if(*line && (tmp = scan_error(line))) {
- ptlfree(resp);
- return(tmp);
- }
- break;
- }
- }
- resp = resp->next;
- ptfree(vtmp);
- }
- /* We sent multiple components and weren't told any */
- /* were unresolved */
- if(mcomp && !unresp) {
- /* ulcomp is the components that were resolved */
- strcpy(ulcomp,acomp);
- /* Comp gets the last component resolved */
- comp = (char *) rindex(ulcomp,'/');
- if(comp) comp++;
- else comp = ulcomp;
- /* If we have union links to resolve, only one component remains */
- mcomp = 0;
- /* Let rd_vdir know what remains */
- *acomp = ' ';
- }
- /* If only verifying, we already know it is a directory */
- if(flags == GVD_VERIFY) return(PSUCCESS);
- /* Don't return if matching was delayed by the need to filter */
- /* if FIND specified, and dir->links is non null, then we have */
- /* found a match, and should return. */
- if((flags & GVD_FIND) && dir->links && (!filters))
- return(PSUCCESS);
- /* If expand specified, and ulinks must be expanded, making sure */
- /* that the order of the links is maintained properly */
- if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
- l = dir->ulinks;
- /* Find first unexpanded ulink */
- while(l && l->expanded && (l->linktype == 'U')) l = l->next;
- /* Only expand if a FILE or DIRECTORY - Mark as */
- /* failed otherwise */
- /* We must still add support for symbolic ulinks */
- if(l) {
- if ((strcmp(l->type,"DIRECTORY") == 0) ||
- (strcmp(l->type,"FILE") == 0)) {
- l->expanded = TRUE;
- exp = l;
- pul = l;
- dhost = l->host;
- dfile = l->filename;
- goto startover; /* was get_contents; */
- }
- else l->expanded = FAILED;
- }
- }
- /* Double check to make sure we don't get */
- /* back unwanted components */
- /* OK to keep if special (URP) links */
- if(components && *components) {
- l = dir->links;
- while(l) {
- VLINK ol;
- if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
- if(l == dir->links)
- dir->links = l->next;
- else l->previous->next = l->next;
- if(l->next) l->next->previous = l->previous;
- ol = l;
- l = l->next;
- vlfree(ol);
- }
- else l = l->next;
- }
- }
- return(PSUCCESS);
- }