📄 aquery.c
字号:
/* *//* * aquery.c : Programmatic Prospero interface to Archie *//* * *//* * Copyright (c) 1991 by the University of Washington *//* * *//* * For copying and distribution information, please see the file *//* * <copyright.h>. */#include "pmachine.h"#include "pfs.h"#include "perrno.h"#include "archie.h"static void translateArchieResponse();inline static int hostnamecmp();extern int pwarn;extern char p_warn_string[];/* *//* * archie_query : Sends a request to _host_, telling it to search for *//* * _string_ using _query_ as the search method. *//* * No more than _max_hits_ matches are to be returned *//* * skipping over _offset_ matches. *//* * *//* * archie_query returns a linked list of virtual links. *//* * If _flags_ does not include AQ_NOTRANS, then the Archie *//* * responses will be translated. If _flags_ does not include *//* * AQ_NOSORT, then the list will be sorted using _cmp_proc_ to *//* * compare pairs of links. If _cmp_proc_ is NULL or AQ_DEFCMP, *//* * then the default comparison procedure, defcmplink(), is used *//* * sorting by host, then filename. If cmp_proc is AQ_INVDATECMP *//* * then invdatecmplink() is used, sorting inverted by date. *//* * otherwise a user-defined comparison procedure is called. *//* * *//* * archie_query returns NULL and sets perrno if the query *//* * failed. Note that it can return NULL with perrno == PSUCCESS *//* * if the query didn't fail but there were simply no matches. *//* * *//* * query: S Substring search ignoring case *//* * C Substring search with case significant *//* * R Regular expression search *//* * = Exact String Match *//* * s,c,e Tries exact match first and falls back to S, C, or R *//* * if not found. *//* * *//* * cmp_proc: AQ_DEFCMP Sort by host, then filename *//* * AQ_INVDATECMP Sort inverted by date *//* * *//* * flags: AQ_NOSORT Don't sort results *//* * AQ_NOTRANS Don't translate results */VLINK archie_query(host,string,max_hits,offset,query,cmp_proc,flags) char *host,*string; int max_hits,offset; Query query; int (*cmp_proc)(); int flags; { char qstring[MAX_VPATH]; /* For construting the query */ VLINK links; /* Matches returned by server */ VDIR_ST dir_st; /* Filled in by get_vdir */ PVDIR dir= &dir_st; VLINK p,q,r,lowest,nextp,pnext,pprev; int tmp; /* Set the cmp_proc if not given */ if (cmp_proc == NULL) cmp_proc = defcmplink; /* Make the query string */ sprintf(qstring,"ARCHIE/MATCH(%d,%d,%c)/%s", max_hits,offset, (char) query,string); /* Initialize Prospero structures */ perrno = PSUCCESS; *p_err_string = '\0'; pwarn = PNOWARN; *p_warn_string = '\0'; vdir_init(dir); /* Retrieve the list of matches, return error if there was one */ if((tmp = get_vdir(host,qstring,"",dir,GVD_ATTRIB|GVD_NOSORT,NULL,NULL))) { perrno = tmp; return(NULL); } /* Save the links, and clear in dir in case it's used again */ links = dir->links; dir->links = NULL; /* As returned, list is sorted by suffix, and conflicting suffixes */ /* appear on a list of "replicas". We want to create a */ /* one-dimensional list sorted by host then filename and maybe by */ /* some other parameter */ /* First flatten the doubly-linked list */ for (p = links; p != NULL; p = nextp) { nextp = p->next; if (p->replicas != NULL) { p->next = p->replicas; p->next->previous = p; for (r = p->replicas; r->next != NULL; r = r->next) /*EMPTY*/ ; r->next = nextp; nextp->previous = r; p->replicas = NULL; } } /* Translate the filenames unless NOTRANS was given */ if (!(flags & AQ_NOTRANS)) for (p = links; p != NULL; p = p->next) translateArchieResponse(p); /* If NOSORT given, then just hand it back */ if (flags & AQ_NOSORT) { perrno = PSUCCESS; return(links); } /* Otherwise sort it using a selection sort and the given cmp_proc */ for (p = links; p != NULL; p = nextp) { nextp = p->next; lowest = p; for (q = p->next; q != NULL; q = q->next) if ((*cmp_proc)(q,lowest) < 0) lowest = q; if (p != lowest) { /* swap the two links */ pnext = p->next; pprev = p->previous; if (lowest->next != NULL) lowest->next->previous = p; p->next = lowest->next; if (nextp == lowest) { p->previous = lowest; } else { lowest->previous->next = p; p->previous = lowest->previous; } if (nextp == lowest) { lowest->next = p; } else { pnext->previous = lowest; lowest->next = pnext; } if (pprev != NULL) pprev->next = lowest; lowest->previous = pprev; /* keep the head of the list in the right place */ if (links == p) links = lowest; } } /* Return the links */ perrno = PSUCCESS; return(links); }/* *//* * translateArchieResponse: *//* * *//* * If the given link is for an archie-pseudo directory, fix it. *//* * This is called unless AQ_NOTRANS was given to archie_query(). */static voidtranslateArchieResponse(l) VLINK l; { char *slash; if (strcmp(l->type,"DIRECTORY") == 0) { if (strncmp(l->filename,"ARCHIE/HOST",11) == 0) { l->type = stcopyr("EXTERNAL(AFTP,DIRECTORY)",l->type); l->host = stcopyr(l->filename+12,l->host); slash = (char *)index(l->host,'/'); if (slash) { l->filename = stcopyr(slash,l->filename); *slash++ = '\0'; } else l->filename = stcopyr("",l->filename); } } }/* hostnamecmp: Compare two hostnames based on domain, *//* * right-to-left. Returns <0 if a belongs before b, >0 *//* * if b belongs before a, and 0 if they are identical. *//* * Contributed by asami@cs.berkeley.edu (Satoshi ASAMI). */inline static inthostnamecmp(a,b) char *a,*b; { char *pa, *pb; int result; for (pa = a ; *pa ; pa++) ; for (pb = b ; *pb ; pb++) ; while (pa > a && pb > b) { for (; pa > a ; pa--) if (*pa == '.') { pa++; break; } for (; pb > b ; pb--) if (*pb == '.') { pb++; break; } if ((result = strcmp(pa, pb))) return (result); pa -= 2; pb -= 2; } if (pa <= a) { if (pb <= b) return (0); else return (-1); } else return (1); }/* *//* * defcmplink: The default link comparison function for sorting. Compares *//* * links p and q first by host then by filename. Returns < 0 if p *//* * belongs before q, > 0 if p belongs after q, and == 0 if their *//* * host and filename fields are identical. */intdefcmplink(p,q) VLINK p,q; { int result; if ((result=hostnamecmp(p->host,q->host)) != 0) return(result); else return(strcmp(p->filename,q->filename)); }/* *//* * invdatecmplink: An alternative comparison function for sorting that *//* * compares links p and q first by LAST-MODIFIED date, *//* * if they both have that attribute. If both links *//* * don't have that attribute or the dates are the *//* * same, it then calls defcmplink() and returns its *//* * value. */intinvdatecmplink(p,q) VLINK p,q; { PATTRIB pat,qat; char *pdate,*qdate; int result; pdate = qdate = NULL; for (pat = p->lattrib; pat; pat = pat->next) if(strcmp(pat->aname,"LAST-MODIFIED") == 0) pdate = pat->value.ascii; for (qat = q->lattrib; qat; qat = qat->next) if(strcmp(qat->aname,"LAST-MODIFIED") == 0) qdate = qat->value.ascii; if(!pdate && !qdate) return(defcmplink(p,q)); if(!pdate) return(1); if(!qdate) return(-1); if((result=strcmp(qdate,pdate)) == 0) return(defcmplink(p,q)); else return(result); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -