home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / ARCHIE / CLIENTS / C_ARCHI1.TAR / archie / get_vdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-19  |  14.0 KB  |  490 lines

  1. /*
  2.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  3.  *
  4.  * For copying and distribution information, please see the file
  5.  * <copyright.h>.
  6.  *
  7.  * v1.2.2 - 11/19/91 (mmt) - added MSDOS & OS2 stuff
  8.  * v1.2.1 - 10/23/91 (bpk) - added missing code
  9.  * v1.2.0 - 09/17/91 (bpk) - added new get_vdir code
  10.  * v1.1.1 - 08/30/91 (bpk) - cast rindex()
  11.  */
  12.  
  13. #include <copyright.h>
  14. #include <stdio.h>
  15.  
  16. #include <pfs.h>
  17. #include <pprot.h>
  18. #include <perrno.h>
  19. #include <pcompat.h>
  20. #include <pauthent.h>
  21. #include <pmachine.h>
  22.  
  23. #ifdef NEED_STRING_H
  24. # include <string.h>
  25. #else
  26. # include <strings.h>
  27. #endif
  28.  
  29. #ifdef DEBUG
  30. extern int    pfs_debug;
  31. #endif
  32.  
  33. extern int    pwarn;
  34. extern char    p_warn_string[];
  35. extern int    perrno;
  36. extern char    p_err_string[];
  37.  
  38. /*
  39.  * get_vdir - Get contents of a directory given its location
  40.  *
  41.  *          GET_VDIR takes a directory location, a list of desired
  42.  *          components, a pointer to a directory structure to be 
  43.  *          filled in, and flags.  It then queries the appropriate 
  44.  *          directory server and retrieves the desired information.
  45.  *
  46.  *      ARGS:   dhost       - Host on which directory resides
  47.  *              dfile       - Directory on that host
  48.  *              components  - The names from the directory we want
  49.  *        dir        - Structure to be filled in
  50.  *            flags       - Options.  See FLAGS
  51.  *        filters     - filters to be applied to result 
  52.  *              acomp       - Pointer to remaining components
  53.  *
  54.  *     FLAGS:    GVD_UNION   - Do not expand union links
  55.  *        GVD_EXPAND  - Expand union links locally
  56.  *        GVD_REMEXP  - Request remote expansion (& local if refused)
  57.  *        GVD_LREMEXP - Request remote expansion of local union links
  58.  *        GVD_VERIFY  - Only verify that args are for a directory
  59.  *              GVD_ATTRIB  - Request attributes from directory server
  60.  *              GVD_NOSORT  - Do not sort links when adding to directory
  61.  *
  62.  *   RETURNS:   PSUCCESS (0) or error code
  63.  *        On some codes addition information in p_err_string
  64.  *
  65.  *     NOTES:   If acomp is non-null the string it points to might be modified
  66.  *
  67.  *              If the directory passed as an argument already has
  68.  *        links or union links, then those lists will be freed
  69.  *              before the new contents are filled in.
  70.  *
  71.  *              If a filter is passed to the procedure, and application of
  72.  *              the filter results in additional union link, then those links
  73.  *              will (or will not) be expanded as specified in the FLAGS field.
  74.  *
  75.  *              If the list of components in NULL, or the null string, then
  76.  *              get_vdir will return all links in the requested directory.
  77.  *
  78.  *      BUGS:   Doesn't process union links yet
  79.  *              Doesn't process errors returned from server
  80.  *        Doesn't expand union links if requested to
  81.  */
  82. int
  83. get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
  84.     char    *dhost;        /* Host on which directory resides           */
  85.     char    *dfile;        /* Name of file on that host                 */
  86.     char    *components;    /* Component name (wildcards allowed)        */
  87.     VDIR    dir;        /* Structure to be filled in             */
  88.     long    flags;        /* Flags                         */
  89.     VLINK    filters;    /* Filters to be applied to result           */
  90.     char    *acomp;        /* Components left to be resolved            */
  91.     {
  92.         PTEXT    request;    /* Text of request to dir server             */
  93.     PTEXT    resp;            /* Response from dir server                 */
  94.  
  95.     char    ulcomp[MAX_VPATH];/* Work space for new current component    */
  96.     char    *comp = components;
  97.  
  98.     VLINK    cur_link = NULL;/* Current link being filled in              */
  99.     VLINK     exp = NULL;     /* The current ulink being expanded         */
  100.     VLINK    pul = NULL;     /* Prev union link (insert new one after it) */
  101.     VLINK    l;        /* Temp link pointer                  */
  102.     int    mcomp;        /* Flag - check multiple components          */
  103.     int    unresp;        /* Flag - received unresolved response       */
  104.     int    getattrib = 0;  /* Get attributes from server                */
  105.     int    vl_insert_flag; /* Flags to vl_insert                        */
  106.  
  107.     int    fwdcnt = MAX_FWD_DEPTH;
  108.  
  109.     int    no_links = 0;   /* Count of number of links found         */
  110.  
  111.     char    options[40];    /* LIST option                               */
  112.     char    *opt;           /* After leading +                           */
  113.  
  114.     PAUTH    authinfo;
  115.  
  116.     /* Treat null string like NULL (return entire directory) */
  117.     if(!components || !*components) comp = NULL;
  118.  
  119.     if(acomp && !filters) mcomp = 1;
  120.     else mcomp = 0;
  121.  
  122.     if(flags&GVD_ATTRIB) {
  123.         getattrib++;
  124.         flags &= (~GVD_ATTRIB);
  125.     }
  126.  
  127.     if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
  128.     else vl_insert_flag = VLI_ALLOW_CONF;
  129.     flags &= (~GVD_NOSORT);
  130.  
  131.     if(filters) comp = NULL;
  132.  
  133.     perrno = 0;
  134.  
  135.     authinfo = get_pauth(PFSA_UNAUTHENTICATED);
  136.  
  137.     *options = '\0';
  138.  
  139.     if(getattrib) {
  140.         strcat(options,"+ATTRIBUTES");
  141.         flags &= (~GVD_ATTRIB);
  142.     }
  143.  
  144.     if(!filters) { /* Can't do remote expansion if filters to be applied */
  145.         if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
  146.         if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
  147.     }
  148.  
  149.     /* If all we are doing is verifying that dfile is a directory */
  150.     /* then we do not want a big response from the directory      */
  151.     /* server.  A NOT-FOUND is sufficient.                  */
  152.     if(flags == GVD_VERIFY)
  153. #ifdef NEWVERIFYOPT
  154.         strcat(options,"+VERIFY");
  155. #else
  156.     comp = "%#$PRobably_nOn_existaNT$#%";
  157. #endif
  158.  
  159.     if(*options) opt = options+1;
  160.     else opt = "''";
  161.  
  162.     startover:
  163.     request = ptalloc();
  164.  
  165.     sprintf(request->start,
  166.         "VERSION %d\nAUTHENTICATOR %s %s\nDIRECTORY ASCII %s\nLIST %s COMPONENTS %s%s%s\n",
  167.         VFPROT_VNO, authinfo->auth_type, authinfo->authenticator,
  168.         dfile,opt, (comp ? comp : ""), (mcomp ? "/" : ""),
  169.         (mcomp ? acomp : ""));
  170.  
  171.     request->length = strlen(request->start);
  172.  
  173. #ifdef DEBUG
  174.     if(pfs_debug > 2)
  175.         fprintf(stderr,"Sending message to dirsrv:\n%s",request->start);
  176. #endif
  177.  
  178. #if defined(MSDOS)
  179.     resp = dirsend(request,dhost,0L);
  180. #else
  181.     resp = dirsend(request,dhost,0);
  182. #endif
  183.  
  184. #ifdef DEBUG
  185.     if(pfs_debug && (resp == NULL)) {
  186.         fprintf(stderr,"Dirsend failed: %d\n",perrno);
  187.     }
  188. #endif
  189.  
  190.     /* If we don't get a response, then if the requested       */
  191.     /* directory, return error, if a ulink, mark it unexpanded */
  192.     if(resp == NULL) {
  193.         if(exp) exp->expanded = FAILED;
  194.         else return(perrno);
  195.     }
  196.  
  197.     unresp = 0;
  198.  
  199.     /* Here we must parse reponse and put in directory */
  200.     /* While looking at each packet            */
  201.     while(resp) {
  202.         PTEXT        vtmp;
  203.         char        *line;
  204.  
  205.         vtmp = resp;
  206. #ifdef DEBUG
  207.         if(pfs_debug > 3) fprintf(stderr,"%s\n",resp->start);
  208. #endif
  209.         /* Look at each line in packet */
  210.         for(line = resp->start;line != NULL;line = nxtline(line)) {
  211.         switch (*line) {
  212.             
  213.             /* Temporary variables to hold link info */
  214.             char    l_linktype;
  215.             char     l_name[MAX_DIR_LINESIZE];
  216.             char    l_type[MAX_DIR_LINESIZE];
  217.             char     l_htype[MAX_DIR_LINESIZE];
  218.             char     l_host[MAX_DIR_LINESIZE];
  219.             char     l_ntype[MAX_DIR_LINESIZE];
  220.             char     l_fname[MAX_DIR_LINESIZE];
  221.             int        l_version;
  222.             char     t_unresolved[MAX_DIR_LINESIZE];
  223.             int        l_magic;
  224.             int        tmp;
  225.  
  226.         case 'L': /* LINK or LINK-INFO */
  227.             if(strncmp(line,"LINK-INFO",9) == 0) {
  228.             PATTRIB        at;
  229.             PATTRIB        last_at;
  230.             at = parse_attribute(line);
  231.             if(!at) break;
  232.  
  233.             /* Cant have link info without a link */
  234.             if(!cur_link) {
  235.                 perrno = DIRSRV_BAD_FORMAT;
  236.                 atfree(at);
  237.                 break;
  238.             }
  239.             
  240.             if(cur_link->lattrib) {
  241.                 last_at = cur_link->lattrib;
  242.                 while(last_at->next) last_at = last_at->next;
  243.                 at->previous = last_at;
  244.                 last_at->next = at;
  245.             }
  246.             else {
  247.                 cur_link->lattrib = at;
  248.                 at->previous = NULL;
  249.             }
  250.             break;
  251.             }
  252.  
  253.             /* Not LINK-INFO, must be LINK - if not check for error */
  254.             if(strncmp(line,"LINK",4) != 0) goto scanerr;
  255.  
  256.             /* If only verifying, don't want to change dir */
  257.             if(flags == GVD_VERIFY) {
  258.             break;
  259.             }
  260.             /* If first link and some links in dir, free them */
  261.             if(!no_links++) {
  262.             if(dir->links) vllfree(dir->links); dir->links=NULL;
  263.             if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
  264.             }
  265.             
  266.             cur_link = vlalloc();
  267.  
  268.             /* parse and insert file info */
  269.             tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %d %d", &l_linktype,
  270.                  l_type, l_name, l_htype, l_host, 
  271.                  l_ntype, l_fname, &(cur_link->version),
  272.                  &(cur_link->f_magic_no));
  273.  
  274.             if(tmp != 9) {
  275.             perrno = DIRSRV_BAD_FORMAT;
  276.             vlfree(cur_link);
  277.             break;
  278.             }
  279.  
  280.             cur_link->linktype = l_linktype;
  281.             cur_link->type = stcopyr(l_type,cur_link->type);
  282.             cur_link->name = stcopyr(unquote(l_name),cur_link->name);
  283.             cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
  284.             cur_link->host = stcopyr(l_host,cur_link->host);
  285.             cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
  286.             cur_link->filename = stcopyr(l_fname,cur_link->filename);
  287.  
  288.             /* Double check to make sure we don't get */
  289.             /* back unwanted components              */
  290.             /* OK to keep if special (URP) links      */
  291.             /* or if mcomp specified                  */
  292.             if(!mcomp && (cur_link->linktype == 'L') && 
  293.                (!wcmatch(cur_link->name,comp))) {
  294.             vlfree(cur_link);
  295.             break;
  296.             }
  297.  
  298.             /* If other optional info was sent back, it must */
  299.             /* also be parsed before inserting link     ***  */
  300.             
  301.             
  302.             if(cur_link->linktype == 'L') 
  303.             vl_insert(cur_link,dir,vl_insert_flag);
  304.             else {
  305.             tmp = ul_insert(cur_link,dir,pul);
  306.  
  307.             /* If inserted after pul, next one after cur_link */
  308.             if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
  309.                 pul = cur_link;
  310.             }
  311.             
  312.             break;
  313.  
  314.         case 'F': /* FILTER, FAILURE or FORWARDED*/
  315.             /* FORWARDED */
  316.             if(strncmp(line,"FORWARDED",9) == 0) {
  317.             if(fwdcnt-- <= 0) {
  318.                 ptlfree(resp);
  319.                 perrno = PFS_MAX_FWD_DEPTH;
  320.                 return(perrno);
  321.             }
  322.             /* parse and start over */
  323.  
  324.             tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d", 
  325.                      l_htype,l_host,l_ntype,l_fname,
  326.                      &l_version, &l_magic);
  327.  
  328.             dhost = stcopy(l_host);
  329.             dfile = stcopy(l_fname);
  330.  
  331.             if(tmp < 4) {
  332.                 perrno = DIRSRV_BAD_FORMAT;
  333.                 break;
  334.             }
  335.  
  336.             ptlfree(resp);
  337.             goto startover;
  338.             }
  339.             if(strncmp(line,"FILTER",6) != 0) goto scanerr;
  340.             break;
  341.  
  342.  
  343.         case 'M': /* MULTI-PACKET (processed by dirsend) */
  344.         case 'P': /* PACKET (processed by dirsend) */
  345.             break;
  346.  
  347.         case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
  348.             /* NONE-FOUND, we just have no links to insert */
  349.             /* It is not an error, but we must clear any   */
  350.             /* old links in the directory arg              */
  351.             if(strncmp(line,"NONE-FOUND",10) == 0) {
  352.             /* If only verifying, don't want to change dir */
  353.             if(flags == GVD_VERIFY) {
  354.                 break;
  355.             }
  356.  
  357.             /* If first link and some links in dir, free them */
  358.             if(!no_links++) {
  359.                 if(dir->links) vllfree(dir->links);
  360.                 if(dir->ulinks) vllfree(dir->ulinks);
  361.                 dir->links = NULL;
  362.                 dir->ulinks = NULL;
  363.             }
  364.             break;
  365.             }
  366.             /* If NOT-A-DIRECTORY or anything else, scan error */
  367.             goto scanerr;
  368.  
  369.         case 'U': /* UNRESOLVED */
  370.             if(strncmp(line,"UNRESOLVED",10) != 0) {
  371.             goto scanerr;
  372.             }
  373.             tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
  374.             if(tmp < 1) {
  375.             perrno = DIRSRV_BAD_FORMAT;
  376.             break;
  377.             }
  378.             /* If multiple components were resolved */
  379.             if(strlen(t_unresolved) < strlen(acomp)) {
  380.             strcpy(ulcomp,acomp);
  381.             /* ulcomp is the components that were resolved */
  382.             *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '\0';
  383.             /* Comp gets the last component resolved */
  384.             comp = (char *) rindex(ulcomp,'/');
  385.             if(comp) comp++;
  386.             else comp = ulcomp;
  387.             /* Let rd_vdir know what remains */
  388.             strcpy(acomp,t_unresolved);
  389.             }
  390.             unresp = 1;
  391.             break;
  392.  
  393.         case 'V': /* VERSION-NOT-SUPPORTED */
  394.             if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
  395.             perrno = DIRSRV_BAD_VERS;
  396.             return(perrno);
  397.             }
  398.             goto scanerr;
  399.  
  400.         scanerr:
  401.         default:
  402.             if(*line && (tmp = scan_error(line))) {
  403.             ptlfree(resp);
  404.             return(tmp);
  405.             }
  406.             break;
  407.         }
  408.         }
  409.  
  410.         resp = resp->next;
  411.  
  412.         ptfree(vtmp);
  413.     }
  414.  
  415.     /* We sent multiple components and weren't told any */
  416.     /* were unresolved                                  */
  417.     if(mcomp && !unresp) {
  418.         /* ulcomp is the components that were resolved */
  419.         strcpy(ulcomp,acomp);
  420.         /* Comp gets the last component resolved */
  421.         comp = (char *) rindex(ulcomp,'/');
  422.         if(comp) comp++;
  423.         else comp = ulcomp;
  424.         /* If we have union links to resolve, only one component remains */
  425.         mcomp = 0;
  426.         /* Let rd_vdir know what remains */
  427.         *acomp = '\0';
  428.     }
  429.  
  430.     /* If only verifying, we already know it is a directory */
  431.     if(flags == GVD_VERIFY) return(PSUCCESS);
  432.  
  433.     /* Don't return if matching was delayed by the need to filter    */
  434.     /* if FIND specified, and dir->links is non null, then we have   */
  435.     /* found a match, and should return.                             */
  436.     if((flags & GVD_FIND) && dir->links && (!filters))
  437.         return(PSUCCESS);
  438.  
  439.     /* If expand specified, and ulinks must be expanded, making sure */
  440.         /* that the order of the links is maintained properly            */
  441.  
  442. expand_ulinks:
  443.  
  444.     if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
  445.  
  446.         l = dir->ulinks;
  447.  
  448.         /* Find first unexpanded ulink */
  449.         while(l && l->expanded && (l->linktype == 'U')) l = l->next;
  450.         
  451.         /* Only expand if a FILE or DIRECTORY -  Mark as  */
  452.             /* failed otherwise                               */
  453.         /* We must still add support for symbolic ulinks */
  454.         if(l) {
  455.         if ((strcmp(l->type,"DIRECTORY") == 0) || 
  456.             (strcmp(l->type,"FILE") == 0)) {
  457.             l->expanded = TRUE;
  458.             exp = l;
  459.             pul = l;
  460.             dhost = l->host;
  461.             dfile = l->filename;
  462.             goto startover; /* was get_contents; */
  463.         }
  464.         else l->expanded = FAILED;
  465.         }
  466.     }
  467.  
  468.     /* Double check to make sure we don't get */
  469.     /* back unwanted components          */
  470.     /* OK to keep if special (URP) links      */
  471.     if(components && *components) {
  472.         l = dir->links;
  473.         while(l) {
  474.         VLINK    ol;
  475.         if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
  476.             if(l == dir->links)
  477.             dir->links = l->next;
  478.             else l->previous->next = l->next;
  479.             if(l->next) l->next->previous = l->previous;
  480.             ol = l;
  481.             l = l->next;
  482.             vlfree(ol);
  483.         }
  484.         else l = l->next;
  485.         }
  486.     }
  487.  
  488.     return(PSUCCESS);
  489.     }
  490.