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