home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / internet / tcpip / src205 / TCPIP_Src / FTP / c / pathent < prev   
Encoding:
Text File  |  1995-04-17  |  20.6 KB  |  934 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #include "bbc.h"
  7. #include "os.h"
  8. #include "swis.h"
  9.  
  10.  
  11. #include "pathent.h"
  12.  
  13.  
  14. #define u_int unsigned int
  15.  
  16. /* option priorities 
  17.  */
  18. #define cmd_DEFAULT  1
  19. #define cmd_END      2
  20.  
  21. #define str_EXTS     0
  22. #define str_CURRENT  1
  23. #define str_DEFAULT  2
  24. #define str_ROOT     3
  25. #define str_END      4
  26.  
  27. #define flg_NOCASE     (1<<0)
  28. #define flg_TRUNCDIR   (1<<1)
  29. #define flg_TRUNCATE   (1<<2)
  30. #define flg_KEEPEXT    (1<<3)
  31. #define flg_NOEXT      (1<<4)
  32. #define flg_REVEXT     (1<<5)
  33. #define flg_REV1EXT    (1<<6)
  34. #define flg_NOPATH     (1<<7)
  35. #define flg_UNIQUE     (1<<8)
  36. #define flg_CONVNFS    (1<<9)
  37. #define flg_TYPEEXT    (1<<10)
  38. #define flg_NODIREXT   (1<<11)
  39. #define flg_CONVDIREXT (1<<12)
  40. #define flg_OFF        (1U<<31U)  /* opt off */
  41.  
  42. #define dir_ROOT   1
  43. #define dir_IN     2
  44. #define dir_TYPE   3
  45.  
  46. #define ftpcliopt_truncdir   (opts & flg_TRUNCDIR)    /* Truncate dir elements */
  47. #define ftpcliopt_truncname  (opts & flg_TRUNCATE)    /* Truncate name element */
  48. #define ftpcliopt_revext     (opts & flg_REVEXT)      /* Reverse extensions */
  49. #define ftpcliopt_keepext    (opts & flg_KEEPEXT)     /* Keep extensions as "/" */
  50. #define ftpcliopt_noext      (opts & flg_NOEXT)       /* Ditch extensions */
  51. #define ftpcliopt_nopath     (opts & flg_NOPATH)      /* Ditch path */
  52. #define ftpcliopt_typeext    (opts & flg_TYPEEXT)     /* Loose last extension */
  53. #define ftpcliopt_convdirext (opts & flg_CONVDIREXT)  /* Convert dir extentions */
  54. #define ftpcliopt_nodirext   (opts & flg_NODIREXT)    /* Loose dir extentions */
  55. #define ftpcliopt_convnfs    (opts & flg_CONVNFS)     /* Convert NFS extensions */
  56. #define ftpcliopt_rev1ext    (opts & flg_REV1EXT)     /* Reverse 1st extension */
  57. #define ftpcliopt_nocase     (opts & flg_NOCASE)      /* Reverse 1st extension */
  58.  
  59. typedef struct optcmd_str
  60. {
  61.   char *cmd;
  62.   u_int opt;
  63. } optcmd_str;
  64.  
  65. static optcmd_str flgopts[] = 
  66. {
  67.   "nocase",     flg_NOCASE,
  68.   "truncdir",   flg_TRUNCDIR,
  69.   "truncate",   flg_TRUNCATE,
  70.   "keepext",    flg_KEEPEXT,
  71.   "noext",      flg_NOEXT,
  72.   "revext",     flg_REVEXT,
  73.   "rev1ext",    flg_REV1EXT,
  74.   "nopath",     flg_NOPATH,
  75.   "unique",     flg_UNIQUE,
  76.   "nfsext",     flg_CONVNFS,
  77.   "nodirext",   flg_NODIREXT,
  78.   "convdirext", flg_CONVDIREXT,
  79.   NULL, 0   
  80. };
  81.  
  82. static optcmd_str cmdopts[] = 
  83. {
  84.   "default",  cmd_DEFAULT,
  85.   "end",      cmd_END,
  86.   NULL, 0
  87. };
  88.  
  89. static optcmd_str diropts[] = 
  90. {
  91.   "root",     dir_ROOT,
  92.   "in",       dir_IN,
  93.   "type",     dir_TYPE,
  94.   NULL, 0
  95. };
  96.  
  97. static char *strdup(char *s);
  98. static int star(char *s, char *p, char **argv, int i);
  99. static int pe_wildmat(char *s, char *p, char **argv, int i);
  100. static u_int getoptcmd(optcmd_str *opts, char *s);
  101. static char *optflgtoa(u_int opt);
  102.  
  103. static pathent_str *pathhead = NULL;
  104. static pathent_str *pathtail = NULL;
  105.  
  106. /*
  107.  * This array is designed for mapping upper and lower case letter
  108.  * together for a case independent comparison.  The mappings are
  109.  * based upon ascii character sequences.
  110.  */
  111. static char charmap[] =
  112. {
  113.   '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  114.   '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  115.   '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  116.   '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  117.   '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  118.   '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  119.   '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  120.   '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  121.   '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  122.   '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  123.   '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  124.   '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  125.   '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  126.   '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  127.   '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  128.   '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  129.   '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  130.   '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  131.   '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  132.   '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  133.   '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  134.   '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  135.   '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  136.   '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  137.   '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  138.   '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  139.   '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  140.   '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  141.   '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  142.   '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  143.   '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  144.   '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  145. };
  146.  
  147. #define fixc(a, b) ((b)?charmap[a]:a)
  148.  
  149. static char *strdup(char *s)
  150. {
  151.   char *p;
  152.   if (s==NULL)
  153.     return NULL;
  154.  
  155.   if (p=(char *)malloc(strlen(s)+1), p==NULL)
  156.     return NULL;
  157.  
  158.   strcpy(p, s);
  159.   return p;
  160. }
  161.  
  162. static int star(char *s, char *p, char **argv, int i)
  163. {
  164.   char *cp = s;
  165.  
  166.   while (pe_wildmat(cp, p, argv, i) == FALSE)
  167.   {
  168.     if (*++cp == '\0')
  169.       return -1;
  170.   }
  171.   return ((int) (cp - s));
  172. }
  173.  
  174. static int pe_wildmat(char *s, char *p, char **argv, int i)
  175. {
  176.   int last;
  177.   int matched;
  178.   int reverse;
  179.   int cnt;
  180.  
  181.   for (; *p; s++,p++)
  182.   {
  183.     switch(*p)
  184.     {
  185.       case '\\':
  186.         /* Literal match with following character; fall through. */
  187.         p++;
  188.       default:
  189.         if (fixc(*s,i) != fixc(*p,i))
  190.           return FALSE;
  191.         continue;
  192.       case '?':
  193.         /* Match anything. */
  194.         if (*s == '\0')
  195.           return FALSE;
  196.         continue;
  197.       case '*':
  198.         /* Trailing star matches everything. */
  199.         if (argv == NULL)
  200.           return *++p ? 1 + star(s, p, NULL, i) : TRUE;
  201.         if (*++p == '\0')
  202.         {
  203.           cnt = strlen(s);
  204.         }
  205.         else
  206.         {
  207.           if ((cnt = star(s, p, argv+1, i)) == -1)
  208.             return FALSE;
  209.         }
  210.         *argv = malloc(cnt+1);
  211.         strncpy(*argv,s,cnt);
  212.         *(*argv + cnt) = '\0';
  213.         return TRUE;
  214.       case '[':
  215.         /* [^....] means inverse character class. */
  216.         reverse = (p[1] == '^') ? TRUE : FALSE;
  217.         if (reverse)
  218.           p++;
  219.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  220.         {
  221.           /* This next line requires a good C compiler. */
  222.           if ( (*p=='-') ? 
  223.                fixc(*s, i) <= fixc(*++p, i) && fixc(*s, i) >= fixc(last, i) : 
  224.                fixc(*s, i) == fixc(*p, i))
  225.             matched = TRUE;
  226.         }
  227.         if (matched == reverse)
  228.           return FALSE;
  229.         continue;
  230.     }
  231.   }
  232.   /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  233.   return *s == '\0' || *s == '/';
  234. }
  235.  
  236.  
  237. /*
  238.  * Scan options table for string entry with matching flag
  239.  */
  240. static char *optflgtoa(u_int opt)
  241. {
  242.   int i;
  243.   for (i=0; flgopts[i].cmd!=NULL && flgopts[i].opt!=opt; i++);
  244.   return (flgopts[i].opt==opt)?flgopts[i].cmd:NULL;
  245. }
  246.  
  247. /*
  248.  * Create a string representing option flags
  249.  */
  250. char *pe_optflagstostr(int opts, char *buffer)
  251. {
  252.   int i;
  253.   char *s;
  254.   char *p = buffer;
  255.  
  256.   *p = '\0';
  257.  
  258.   for (i=0; i<30; i++)
  259.   {
  260.     if (s = optflgtoa(opts & (1<<i)))
  261.       p += sprintf(p, "%s%s%s", (p==buffer)?"":" ", (opts & (1<<31))?"!":"", s);
  262.   }
  263.   return buffer;
  264. }
  265.  
  266. /*
  267.  * Scan command table, and return matching flag value
  268.  * If an option if prefixed with '!', return flag value
  269.  * with flg_OFF set.
  270.  */
  271. static u_int getoptcmd(optcmd_str *opts, char *s)
  272. {
  273.   u_int off;
  274.   int i = 0;
  275.  
  276.   if (*s=='!')
  277.   {
  278.     s++;
  279.     off = flg_OFF;
  280.   }
  281.   else
  282.     off = 0;
  283.     
  284.   while (opts[i].cmd!=NULL && strcmp(opts[i].cmd, s))
  285.     i++;
  286.  
  287.   return (opts[i].cmd==NULL) ? 0 : opts[i].opt | off;
  288. }
  289.  
  290.  
  291. pathent_str *getpathent(char *s)
  292. {
  293.   char *p;
  294.   char *list = NULL;
  295.   u_int n;
  296.   u_int on = 0;
  297.   u_int off = 0;
  298.   int type = -1;
  299.   int str;
  300.   char *path = NULL;
  301.   char *exts[32];
  302.   int nexts = 0;
  303.   pathent_str *pathent = NULL;
  304.  
  305.   /* $ prefixes options line, so no extensions info present */
  306.   if (*s!='$')
  307.   {
  308.     /* Get list of extentions */
  309.     if (list = strtok(s, " \t\n"), list==NULL)
  310.       return NULL;
  311.     
  312.     s = NULL;
  313.  
  314.     /* Get associated type */
  315.     if (p = strtok(s, " \t\n"), p==NULL)
  316.       return NULL;
  317.  
  318.     type = atoft(p);
  319.     str = str_EXTS;
  320.   }
  321.   else
  322.   {
  323.     str = str_CURRENT;
  324.     ++s;
  325.   }
  326.   
  327.   /* Get options */
  328.   while (p=strtok(s, " \t\n"), p!=NULL)
  329.   {
  330.     s = NULL;
  331.     if (n = getoptcmd(flgopts, p), n!=0)
  332.     {
  333.       if (n & flg_OFF)
  334.         off |= n;
  335.       else
  336.         on |= n;
  337.     }
  338.     else if (n = getoptcmd(cmdopts, p), n!=0)
  339.     {
  340.       switch (n)
  341.       {
  342.         case cmd_DEFAULT:
  343.           str = str_DEFAULT;
  344.           break;
  345.         case cmd_END:
  346.           str = str_END;
  347.           break;
  348.       }
  349.     }
  350.     else if (n = getoptcmd(diropts, p), n!=0)
  351.     {
  352.       if (n==dir_IN || n==dir_ROOT)
  353.       {
  354.         if (p = strtok(s, " \t\n"), p==NULL)
  355.           return NULL;
  356.         path = p;
  357.         if (n==dir_ROOT)
  358.           str = str_ROOT;
  359.       }
  360.       else if (n==dir_TYPE)
  361.       {
  362.         if (p = strtok(s, " \t\n"), p==NULL)
  363.           return NULL;
  364.         type = atoft(p);
  365.       }
  366.     }
  367.     else
  368.       return NULL;
  369.   }
  370.  
  371.   if (list!=NULL)
  372.   {
  373.     if (p = strdup(list), p==NULL)
  374.       return NULL;
  375.     /* Split extensions list and count them */
  376.     p = strtok(p, "|");
  377.     while (p!=NULL && nexts<16)
  378.     {
  379.       exts[nexts++] = p;
  380.       p = strtok(NULL, "|");
  381.     }
  382.   }
  383.  
  384.   /* Allocate memory for pathent struct */
  385.   if (pathent = (pathent_str *)malloc(sizeof(pathent_str)), pathent==NULL)
  386.     return NULL;
  387.  
  388.   if (list!=NULL)
  389.   {
  390.     /* and extensions list */
  391.     if (pathent->exts = (char **)malloc(sizeof(char *)*nexts), pathent->exts==NULL)
  392.     {
  393.       free (pathent);
  394.       return NULL;
  395.     }
  396.   }
  397.   else
  398.     pathent->exts = NULL;
  399.     
  400.   pathent->next = NULL;
  401.   pathent->path = strdup(path);
  402.   pathent->setopts = on;
  403.   pathent->clropts = off;
  404.   pathent->filetype = type;
  405.   pathent->type = str;
  406.   pathent->numexts = nexts;
  407.  
  408.   /* copy extensions into pathent struct */
  409.   while (nexts--)
  410.     pathent->exts[nexts] = exts[nexts];
  411.  
  412.   return pathent;
  413. }
  414.  
  415. /*
  416.  * Delete a pathent structure
  417.  */
  418. pathent_str *delpathent(pathent_str *p)
  419. {
  420.   pathent_str *n=NULL;
  421.  
  422.   if (p!=PATH_OFF && p!=PATH_DEF && p!=PATH_TYPE && p!=PATH_RISCOS)
  423.   {
  424.     n = p->next;
  425.     if (p->path)
  426.       free(p->path);
  427.     if (p->numexts)
  428.       free(p->exts[0]);
  429.     if (p->exts)
  430.       free(p->exts);
  431.     free(p);
  432.   }
  433.   return n;
  434. }
  435.  
  436. /*
  437.  * Creates a duplicate copy of a pathent structure.
  438.  */
  439. pathent_str *duppathent(pathent_str *p)
  440. {
  441.   int i, n;
  442.   pathent_str *pe;
  443.  
  444.   if (p==PATH_OFF || p==PATH_DEF || p==PATH_TYPE || p==PATH_RISCOS)
  445.     return p;
  446.  
  447.   /* Allocate memory for pathent struct */
  448.   if (pe = (pathent_str *)malloc(sizeof(pathent_str)), pe==NULL)
  449.     return PATH_OFF;
  450.  
  451.   pe->next = NULL;
  452.   pe->exts = NULL;
  453.   pe->path = NULL;
  454.   pe->numexts = 0;
  455.  
  456.   if (p->exts!=NULL)
  457.   {
  458.     /* and extensions list */
  459.     if (pe->exts = (char **)malloc(sizeof(char *)*p->numexts), pe->exts==NULL)
  460.     {
  461.       delpathent(pe);
  462.       return PATH_OFF;
  463.     }
  464.  
  465.     for (n=0, i=0; i<p->numexts; i++)
  466.       n += (strlen(p->exts[n])+1);
  467.       
  468.     if (pe->exts[0] = (char *)malloc(n), pe->exts[0]==NULL)
  469.     {
  470.       delpathent(pe);
  471.       return PATH_OFF;
  472.     }
  473.     pe->numexts = p->numexts;
  474.     
  475.     memcpy(pe->exts[0], p->exts[0], n);
  476.     for (i=1; i<<p->numexts; i++)
  477.       pe->exts[i] = pe->exts[0] + (p->exts[i]-p->exts[0]);
  478.   }
  479.  
  480.   if (p->path!=NULL)
  481.   {
  482.     if (pe->path = (char *)malloc(strlen(p->path)+1), pe->path==NULL)
  483.     {
  484.       delpathent(pe);
  485.       return PATH_OFF;
  486.     }
  487.     strcpy(pe->path, p->path);
  488.   }
  489.  
  490.   pe->type = p->type;
  491.   pe->filetype = p->filetype;
  492.   pe->setopts = p->setopts;
  493.   pe->clropts = p->clropts;
  494.  
  495.   return pe;
  496. }
  497.  
  498.  
  499. void show_pathent(pathent_str *p)
  500. {
  501.   int n;
  502. /*
  503.   static char *types[] = { "match", "current", "default", "root", "end" };
  504. */
  505.   if (p==PATH_OFF || p==PATH_DEF || p==PATH_TYPE || p==PATH_RISCOS)
  506.     return;
  507.   
  508.   printf("Path       : %s\n", (p->path)?p->path:"<none>");
  509.   printf("Extensions : ");
  510.   for (n=0; n<p->numexts; n++)
  511.     printf("%s ", p->exts[n]);
  512.   printf("\n");
  513.   printf("On opts    : %.8x\n", p->setopts);
  514.   printf("Off opts   : %.8x\n", p->clropts);
  515.   printf("Filetype   : %s\n", fttoa(p->filetype));
  516.   printf("\n");
  517. }
  518.  
  519.  
  520. int pathent_initialise(char *file)
  521. {
  522.   char s[256];
  523.   FILE *fp;
  524.   pathent_str *p;
  525.  
  526.   if (pathhead)
  527.     return 0;
  528.  
  529.   if (fp = fopen(file, "r"), fp==NULL)
  530.     return -1;
  531.     
  532.   while (fgets(s, 256, fp)!=NULL)
  533.   {
  534.     if (*s!='\n' && *s!='#' && *s!=';')
  535.     {
  536.       if (p = getpathent(s), p!=NULL)
  537.       {
  538.         if (pathhead)
  539.         {
  540.           pathtail->next = p;
  541.           pathtail = p;
  542.         }
  543.         else
  544.         {
  545.           pathhead = p;
  546.           pathtail = p;
  547.         }
  548.       }
  549.     }
  550.   }
  551.   fclose(fp);
  552.   return 0;
  553. }
  554.  
  555.  
  556. /*
  557.  * The unix -> risc os path name mapper.
  558.  */
  559. int pathmap(char *unix, char *riscos, int *type, pathent_str *preset)
  560. {
  561.   int n;
  562.   char dir[256];
  563.   char *extn = NULL;
  564.   char *p = dir;
  565.   char *sep = dir;
  566.   char *extv[8];
  567.  
  568.   int i;
  569.   char pat[16];
  570.         
  571.   char *path;
  572.   u_int opts;
  573.  
  574. /* for pe_wildmat() */
  575.   char *tempv[8];
  576.  
  577.   pathent_str *pe = NULL;  /* previous group preset */
  578.   pathent_str *de = NULL;  /* default entry */
  579.   pathent_str *ce = NULL;  /* current */
  580.  
  581.   pathent_str *placer = NULL;
  582.   pathent_str *typer  = NULL;
  583.   pathent_str *namer  = NULL;
  584.  
  585.   pathent_str *cplacer = NULL;
  586.   pathent_str *ctyper  = NULL;
  587.   pathent_str *cnamer  = NULL;
  588.  
  589.   char *rootpath = NULL;
  590.  
  591.   /* in files.c */
  592.   extern char ftppathfile[];
  593.  
  594.   /*
  595.    * Initialise pathent dbase
  596.    */
  597.   if (preset!=PATH_OFF)
  598.   {
  599.     if (pathent_initialise(ftppathfile)<0)
  600.       return 0;
  601.   }
  602.   /*
  603.    * Convert unix '/' to riscos '.', and unix '.' to '/'
  604.    * Extract start of extensions
  605.    */
  606.   while (*unix>' ')
  607.   {
  608.     if (*unix=='/')
  609.     {
  610.       if (p!=dir)
  611.       {
  612.         *p++ = '.';
  613.         sep = p;
  614.       }
  615.     }
  616.     else if (*unix=='.')
  617.     {
  618.       *p++ = '/';
  619.       if (!extn)
  620.         extn = unix;
  621.     }
  622.     else
  623.       *p++ = *unix;
  624.     ++unix;
  625.   }
  626.   *p = '\0';
  627.  
  628.   /*
  629.    * Now break down the name and extentions
  630.    * leaving evtv[0] with the name and
  631.    * extv[1]...extv[n-1] containing the extension parts
  632.    */
  633.   n = 0;
  634.   p = sep;
  635.   while (extv[n] = strtok(p, "/"), extv[n]!=NULL)
  636.   {
  637.     n++;
  638.     p = NULL;
  639.   }
  640. /*
  641.   printf("dir: %s\n", dir);
  642.   printf("nam: %s\n", extv[0]);
  643.   printf("ext: %s ( ", extn);
  644.   for (i=1; i<n; i++)
  645.     printf("%s ", extv[i]);
  646.   printf(")\n");
  647. */
  648. /*
  649.   bbc_vdu(4);
  650.   bbc_vdu(26);
  651.   bbc_vdu(30);
  652. */
  653.   /*
  654.    * Now scan the path processing database
  655.    * matching names, extension etc to types
  656.    * and a destination path.
  657.    */
  658.  
  659.   /* XXX Can this be delyed until type determined? */
  660.   if (preset>=PATH_PRESET)
  661.   {
  662.     de = preset;
  663.   }
  664.  
  665.   if (preset==PATH_DEF || preset==PATH_TYPE || (preset>=PATH_PRESET && preset->filetype<0))
  666.   {
  667.     for (pe = pathhead; pe!=NULL; pe = pe->next)
  668.     {
  669.       if (pe->type == str_ROOT)
  670.         rootpath = pe->path;
  671.       else if (pe->type == str_DEFAULT)
  672.       {
  673.         de = pe;
  674.         opts = de->setopts;
  675.       }
  676.       else if (pe->type == str_CURRENT)
  677.         ce = pe;
  678.       else if (pe->type == str_EXTS)
  679.       {
  680.         for (i=0; i<pe->numexts; i++)
  681.         {
  682.           /* name matcher */
  683.           if (*pe->exts[i]!='.')
  684.           {
  685.             if (!namer && pe_wildmat(extv[0], pe->exts[0], tempv, ftpcliopt_nocase))
  686.             {
  687. /*
  688. printf("Namer : %s %s\n", extv[0], pe->exts[0]);
  689. */
  690.               namer = pe;
  691.               cnamer = ce;
  692.             }
  693.           }
  694.           else if (n>1)
  695.           {
  696.            /* try a full extension match for a type match */
  697.             *pat = '*';
  698.             strcpy(pat+1, pe->exts[i]);
  699.             if (!typer && pe_wildmat(extn, pat, tempv, ftpcliopt_nocase))
  700.             {
  701. /*
  702. printf("Typer : %s %s\n", extn, pat);
  703. */
  704.               typer = pe;
  705.               ctyper = ce;
  706.             }
  707.             /* try a place */
  708.             if (!placer && pe_wildmat(extv[1], pat+2, tempv, ftpcliopt_nocase))
  709.             {
  710. /*
  711. printf("Placer: %s %s\n", extv[1], pat+2);
  712. */
  713.               placer = pe;
  714.               cplacer = ce;
  715.             }
  716.           }
  717.         }
  718.       }
  719.     }
  720.   }
  721.  
  722. /*
  723.   printf("opts: %.8x\n", opts);
  724. */
  725.   if (preset!=PATH_TYPE)
  726.   {
  727.     if (namer && namer->path)
  728.     {
  729.       path = namer->path;
  730.       opts |= namer->setopts;
  731.       opts &= ~namer->clropts;
  732.       opts |= cnamer->setopts;
  733.       opts &= ~cnamer->clropts;
  734.     }
  735.     else if (cnamer && cnamer->path)
  736.     {
  737.       path = cnamer->path;
  738.       opts |= cnamer->setopts;
  739.       opts &= ~cnamer->clropts;
  740.     }
  741.     else if (placer && placer->path)
  742.     {
  743.       path = placer->path;
  744.       opts |= placer->setopts;
  745.       opts &= ~placer->clropts;
  746.       opts |= cplacer->setopts;
  747.       opts &= ~cplacer->clropts;
  748.     }
  749.     else if (cplacer && cplacer->path)
  750.     {
  751.       path = cplacer->path;
  752.       opts |= cplacer->setopts;
  753.       opts &= ~cplacer->clropts;
  754.     }
  755.     else if (typer && typer->path)
  756.     {
  757.       path = typer->path;
  758.       opts |= typer->setopts;
  759.       opts &= ~typer->clropts;
  760.       opts |= ctyper->setopts;
  761.       opts &= ~ctyper->clropts;
  762.     }
  763.     else if (ctyper && ctyper->path)
  764.     {
  765.       path = ctyper->path;
  766.       opts |= ctyper->setopts;
  767.       opts &= ~ctyper->clropts;
  768.     }
  769.     else if (de && de->path)
  770.     {
  771.       path = de->path;
  772.     }
  773.   }
  774.  
  775.   if (preset>=PATH_PRESET)
  776.   {
  777.     /*
  778.      * Preset path, so cancel placers and namers
  779.      * leaving only the typer intact.
  780.      */
  781.     path = preset->path;
  782.     opts = preset->setopts;
  783.     namer = NULL;
  784.     cnamer = NULL;
  785.     placer = NULL;
  786.     cplacer = NULL;
  787.     de = preset;
  788.     *type = preset->filetype; /* If unknown, then will be over-ridden later */
  789.   }
  790.  
  791. /*
  792.   printf("opts: %.8x\n", opts);
  793. */
  794.   *type = -1;
  795. /*
  796.   printf("root: %s\n",(rootpath)?rootpath:"<none>");
  797.   printf("path: %s\n",(path)?path:"<none>");
  798. */
  799.   /* Deal with NFS type extension (,xxx) */
  800.   if (ftpcliopt_convnfs)
  801.   {
  802.     int t;
  803.     char *q, *e;
  804.  
  805.     if (q = strrchr(extv[0], ','), q!=NULL)
  806.     {
  807.       t = (int)strtol(q+1, &e, 16);
  808.       if (e>(q+1))
  809.       {
  810.         *type = t;
  811.         *q = '\0';
  812.         opts |= flg_TYPEEXT;
  813.       }
  814.     }
  815.   }
  816.  
  817.   /* else extract type from other known information */
  818.   if (*type<0)
  819.   {
  820.     if (typer && typer->filetype>=0)
  821.       *type = typer->filetype;
  822.     else if (ctyper && ctyper->filetype>=0)
  823.       *type = ctyper->filetype;
  824.     else if (placer && placer->filetype>=0)
  825.       *type = placer->filetype;
  826.     else if (cplacer && cplacer->filetype>=0)
  827.       *type = cplacer->filetype;
  828.     else if (namer && namer->filetype>=0)
  829.       *type = namer->filetype;
  830.     else if (cnamer && cnamer->filetype>=0)
  831.       *type = cnamer->filetype;
  832.     else if (de && de->filetype>=0)
  833.       *type = de->filetype;
  834.     if (*type>=0)
  835.       opts |= flg_TYPEEXT;
  836.   }
  837.   
  838.   if (preset!=PATH_TYPE)
  839.   {
  840.     if (rootpath && !strpbrk(path, "@%&$:<>"))
  841.     {
  842.       int j;
  843.       j = sprintf(riscos, "%s.%s.",rootpath,path);
  844.       riscos += j;
  845.     }
  846.     else
  847.     {
  848.       int j;
  849.       j = sprintf(riscos, "%s.", path);
  850.       riscos += j;
  851.     }
  852.  
  853.     /* strip dirs completely */
  854.     if (ftpcliopt_nopath)
  855.       p = riscos;
  856.     else
  857.     {
  858.       char *q;
  859.       p = riscos;
  860.       /* replace extension seps in dirs with '_' */
  861.       if (ftpcliopt_convdirext)
  862.       {
  863.         for (q=dir; q<sep;)
  864.         {
  865.           *p++ = (*q=='/')?'_':*q;
  866.           ++q;
  867.         }
  868.       }
  869.       /* strip extension from dirs */
  870.       else if (ftpcliopt_nodirext)
  871.       {
  872.         for (q=dir; q<sep;)
  873.         {
  874.           if (*q!='/')
  875.             *p++ = *q++;
  876.           else  
  877.           {
  878.             while (*q!='.' && q<sep)
  879.               q++;
  880.           }
  881.         }
  882.       }
  883.       /* copy path */
  884.       else
  885.       {
  886.         for (q=dir; q<sep;)
  887.           *p++ = *q++;
  888.       }
  889.     }
  890.  
  891.     /* loose an extension (relaced by type) */
  892.     if (ftpcliopt_typeext && ((!ftpcliopt_rev1ext && n>1) || n>2))
  893.       --n;
  894.   
  895.     /* reverse extensions */
  896.     if (ftpcliopt_revext)
  897.     {
  898.       while (n>1)
  899.         p += sprintf(p, "%s.", extv[--n] );
  900.   
  901.       if (n>0)
  902.         p += sprintf(p, "%s", extv[--n] );
  903.     }
  904.     /* reverse 1st extension */
  905.     else if (ftpcliopt_rev1ext) 
  906.     {
  907.       if (n>1)
  908.         p += sprintf(p, "%s.", extv[1] );
  909.       if (n>0)
  910.         p += sprintf(p, "%s", extv[0] );
  911.       /* keep remaining extensions as /ext */
  912.       if (ftpcliopt_keepext && !ftpcliopt_noext)  
  913.       {
  914.         while (n>2)
  915.           p += sprintf(p, "/%s", extv[--n] );
  916.       }
  917.     }
  918.     else
  919.     {
  920.       int j;
  921.       if (n>0)
  922.         p += sprintf(p, "%s", extv[0] );
  923.       /* keep all extensions as /ext */
  924.       if (ftpcliopt_keepext && !ftpcliopt_noext)  
  925.       {
  926.         for (j=1; j<n; j++)
  927.           p += sprintf(p, "/%s", extv[j] );
  928.       }
  929.     }
  930.   } /* !PATH_TYPE */
  931.  
  932.   return 1;
  933. }
  934.