home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "bbc.h"
- #include "os.h"
- #include "swis.h"
-
- #include "pathent.h"
-
- #define PATH_OFF ((pathent_str *)0)
- #define PATH_DEF ((pathent_str *)1)
- #define PATH_TYPE ((pathent_str *)2)
-
- #define u_int unsigned int
-
- /* option priorities
- */
- #define cmd_DEFAULT 1
- #define cmd_END 2
-
- #define str_EXTS 0
- #define str_CURRENT 1
- #define str_DEFAULT 2
- #define str_ROOT 3
- #define str_END 4
-
- #define flg_NOCASE (1<<0)
- #define flg_TRUNCDIR (1<<1)
- #define flg_TRUNCATE (1<<2)
- #define flg_KEEPEXT (1<<3)
- #define flg_NOEXT (1<<4)
- #define flg_REVEXT (1<<5)
- #define flg_REV1EXT (1<<6)
- #define flg_NOPATH (1<<7)
- #define flg_UNIQUE (1<<8)
- #define flg_CONVNFS (1<<9)
- #define flg_TYPEEXT (1<<10)
- #define flg_NODIREXT (1<<11)
- #define flg_CONVDIREXT (1<<12)
- #define flg_OFF (1U<<31U) /* opt off */
-
- #define dir_ROOT 1
- #define dir_IN 2
- #define dir_TYPE 3
-
- #define ftpcliopt_truncdir (opts & flg_TRUNCDIR) /* Truncate dir elements */
- #define ftpcliopt_truncname (opts & flg_TRUNCATE) /* Truncate name element */
- #define ftpcliopt_revext (opts & flg_REVEXT) /* Reverse extensions */
- #define ftpcliopt_keepext (opts & flg_KEEPEXT) /* Keep extensions as "/" */
- #define ftpcliopt_noext (opts & flg_NOEXT) /* Ditch extensions */
- #define ftpcliopt_nopath (opts & flg_NOPATH) /* Ditch path */
- #define ftpcliopt_typeext (opts & flg_TYPEEXT) /* Loose last extension */
- #define ftpcliopt_convdirext (opts & flg_CONVDIREXT) /* Convert dir extentions */
- #define ftpcliopt_nodirext (opts & flg_NODIREXT) /* Loose dir extentions */
- #define ftpcliopt_convnfs (opts & flg_CONVNFS) /* Convert NFS extensions */
- #define ftpcliopt_rev1ext (opts & flg_REV1EXT) /* Reverse 1st extension */
- #define ftpcliopt_nocase (opts & flg_NOCASE) /* Reverse 1st extension */
-
- typedef struct optcmd_str
- {
- char *cmd;
- u_int opt;
- } optcmd_str;
-
- static optcmd_str flgopts[] =
- {
- "nocase", flg_NOCASE,
- "truncdir", flg_TRUNCDIR,
- "truncate", flg_TRUNCATE,
- "keepext", flg_KEEPEXT,
- "noext", flg_NOEXT,
- "revext", flg_REVEXT,
- "rev1ext", flg_REV1EXT,
- "nopath", flg_NOPATH,
- "unique", flg_UNIQUE,
- "nfsext", flg_CONVNFS,
- "nodirext", flg_NODIREXT,
- "convdirext", flg_CONVDIREXT,
- NULL, 0
- };
-
- static optcmd_str cmdopts[] =
- {
- "default", cmd_DEFAULT,
- "end", cmd_END,
- NULL, 0
- };
-
- static optcmd_str diropts[] =
- {
- "root", dir_ROOT,
- "in", dir_IN,
- "type", dir_TYPE,
- NULL, 0
- };
-
- static char *strdup(char *s);
- static int star(char *s, char *p, char **argv, int i);
- static int pe_wildmat(char *s, char *p, char **argv, int i);
- static u_int getoptcmd(optcmd_str *opts, char *s);
-
- static pathent_str *pathhead = NULL;
- static pathent_str *pathtail = NULL;
-
- /*
- * This array is designed for mapping upper and lower case letter
- * together for a case independent comparison. The mappings are
- * based upon ascii character sequences.
- */
- static char charmap[] =
- {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
- };
-
- #define fixc(a, b) ((b)?charmap[a]:a)
-
- static char *strdup(char *s)
- {
- char *p;
- if (s==NULL)
- return NULL;
-
- if (p=(char *)malloc(strlen(s)+1), p==NULL)
- return NULL;
-
- strcpy(p, s);
- return p;
- }
-
- static int star(char *s, char *p, char **argv, int i)
- {
- char *cp = s;
-
- while (pe_wildmat(cp, p, argv, i) == FALSE)
- {
- if (*++cp == '\0')
- return -1;
- }
- return ((int) (cp - s));
- }
-
- static int pe_wildmat(char *s, char *p, char **argv, int i)
- {
- int last;
- int matched;
- int reverse;
- int cnt;
-
- for (; *p; s++,p++)
- {
- switch(*p)
- {
- case '\\':
- /* Literal match with following character; fall through. */
- p++;
- default:
- if (fixc(*s,i) != fixc(*p,i))
- return FALSE;
- continue;
- case '?':
- /* Match anything. */
- if (*s == '\0')
- return FALSE;
- continue;
- case '*':
- /* Trailing star matches everything. */
- if (argv == NULL)
- return *++p ? 1 + star(s, p, NULL, i) : TRUE;
- if (*++p == '\0')
- {
- cnt = strlen(s);
- }
- else
- {
- if ((cnt = star(s, p, argv+1, i)) == -1)
- return FALSE;
- }
- *argv = malloc(cnt+1);
- strncpy(*argv,s,cnt);
- *(*argv + cnt) = '\0';
- return TRUE;
- case '[':
- /* [^....] means inverse character class. */
- reverse = (p[1] == '^') ? TRUE : FALSE;
- if (reverse)
- p++;
- for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
- {
- /* This next line requires a good C compiler. */
- if ( (*p=='-') ?
- fixc(*s, i) <= fixc(*++p, i) && fixc(*s, i) >= fixc(last, i) :
- fixc(*s, i) == fixc(*p, i))
- matched = TRUE;
- }
- if (matched == reverse)
- return FALSE;
- continue;
- }
- }
- /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
- return *s == '\0' || *s == '/';
- }
-
- /*
- * Scan command table, and return matching flag value
- * If an option if prefixed with '!', return flag value
- * with flg_OFF set.
- */
- static u_int getoptcmd(optcmd_str *opts, char *s)
- {
- u_int off;
- int i = 0;
-
- if (*s=='!')
- {
- s++;
- off = flg_OFF;
- }
- else
- off = 0;
-
- while (opts[i].cmd!=NULL && strcmp(opts[i].cmd, s))
- i++;
-
- return (opts[i].cmd==NULL) ? 0 : opts[i].opt | off;
- }
-
-
- pathent_str *getpathent(char *s)
- {
- char *p;
- char *list = NULL;
- u_int n;
- u_int on = 0;
- u_int off = 0;
- int type = -1;
- int str;
- char *path = NULL;
- char *exts[32];
- int nexts = 0;
- pathent_str *pathent = NULL;
-
- /* $ prefixes options line, so no extensions info present */
- if (*s!='$')
- {
- /* Get list of extentions */
- if (list = strtok(s, " \t\n"), list==NULL)
- return NULL;
-
- s = NULL;
-
- /* Get associated type */
- if (p = strtok(s, " \t\n"), p==NULL)
- return NULL;
-
- type = atoft(p);
- str = str_EXTS;
- }
- else
- {
- str = str_CURRENT;
- ++s;
- }
-
- /* Get options */
- while (p=strtok(s, " \t\n"), p!=NULL)
- {
- s = NULL;
- if (n = getoptcmd(flgopts, p), n!=0)
- {
- if (n & flg_OFF)
- off |= n;
- else
- on |= n;
- }
- else if (n = getoptcmd(cmdopts, p), n!=0)
- {
- switch (n)
- {
- case cmd_DEFAULT:
- str = str_DEFAULT;
- break;
- case cmd_END:
- str = str_END;
- break;
- }
- }
- else if (n = getoptcmd(diropts, p), n!=0)
- {
- if (n==dir_IN || n==dir_ROOT)
- {
- if (p = strtok(s, " \t\n"), p==NULL)
- return NULL;
- path = p;
- if (n==dir_ROOT)
- str = str_ROOT;
- }
- else if (n==dir_TYPE)
- {
- if (p = strtok(s, " \t\n"), p==NULL)
- return NULL;
- type = atoft(p);
- }
- }
- else
- return NULL;
- }
-
- if (list!=NULL)
- {
- if (p = strdup(list), p==NULL)
- return NULL;
- /* Split extensions list and count them */
- p = strtok(p, "|");
- while (p!=NULL && nexts<16)
- {
- exts[nexts++] = p;
- p = strtok(NULL, "|");
- }
- }
-
- /* Allocate memory for pathent struct */
- if (pathent = (pathent_str *)malloc(sizeof(pathent_str)), pathent==NULL)
- return NULL;
-
- if (list!=NULL)
- {
- /* and extensions list */
- if (pathent->exts = (char **)malloc(sizeof(char *)*nexts), pathent->exts==NULL)
- {
- free (pathent);
- return NULL;
- }
- }
- else
- pathent->exts = NULL;
-
- pathent->next = NULL;
- pathent->path = strdup(path);
- pathent->setopts = on;
- pathent->clropts = off;
- pathent->filetype = type;
- pathent->type = str;
- pathent->numexts = nexts;
-
- /* copy extensions into pathent struct */
- while (nexts--)
- pathent->exts[nexts] = exts[nexts];
-
- return pathent;
- }
-
- pathent_str *delpathent(pathent_str *p)
- {
- pathent_str *n=NULL;
-
- if (p!=(pathent_str *)0 && p!=(pathent_str *)1)
- {
- n = p->next;
- if (p->path)
- free(p->path);
- if (p->numexts)
- free(p->exts[0]);
- if (p->exts)
- free(p->exts);
- free(p);
- }
- return n;
- }
-
- void show_pathent(pathent_str *p)
- {
- int n;
- /*
- static char *types[] = { "match", "current", "default", "root", "end" };
- */
- if (p==NULL)
- return;
-
- printf("Path : %s\n", (p->path)?p->path:"<none>");
- printf("Extensions : ");
- for (n=0; n<p->numexts; n++)
- printf("%s ", p->exts[n]);
- printf("\n");
- printf("on opts : %.8x\n", p->setopts);
- printf("Off opts : %.8x\n", p->clropts);
- printf("Filetype : %s\n", fttoa(p->filetype));
- printf("\n");
- }
-
-
- int pathent_initialise(char *file)
- {
- char s[256];
- FILE *fp;
- pathent_str *p;
-
- if (pathhead)
- return 0;
-
- if (fp = fopen(file, "r"), fp==NULL)
- return -1;
-
- while (fgets(s, 256, fp)!=NULL)
- {
- if (*s!='\n' && *s!='#' && *s!=';')
- {
- if (p = getpathent(s), p!=NULL)
- {
- if (pathhead)
- {
- pathtail->next = p;
- pathtail = p;
- }
- else
- {
- pathhead = p;
- pathtail = p;
- }
- }
- }
- }
- fclose(fp);
- return 0;
- }
-
- int pathmap(char *unix, char *riscos, int *type, pathent_str *preset)
- {
- int n;
- char dir[256];
- char *extn = NULL;
- char *p = dir;
- char *sep = dir;
- char *extv[8];
-
- int i;
- char pat[16];
-
- char *path;
- u_int opts;
-
- /* for pe_wildmat() */
- char *tempv[8];
-
- pathent_str *pe;
- pathent_str *de = NULL;
- pathent_str *ce = NULL;
-
- pathent_str *placer = NULL;
- pathent_str *typer = NULL;
- pathent_str *namer = NULL;
-
- pathent_str *cplacer = NULL;
- pathent_str *ctyper = NULL;
- pathent_str *cnamer = NULL;
-
- char *rootpath = NULL;
-
- /*
- * Initialise pathent dbase
- */
- if (preset==PATH_DEF || preset==PATH_TYPE)
- {
- if (pathent_initialise("<TCPIP$Dir>.PathEnt")<0)
- return 0;
- /* printf("pathent initialised ok\n"); */
- }
- /*
- * Convert unix '/' to riscos '.', and unix '.' to '/'
- * Extract start of extensions
- */
- while (*unix>' ')
- {
- if (*unix=='/')
- {
- if (p!=dir)
- {
- *p++ = '.';
- sep = p;
- }
- }
- else if (*unix=='.')
- {
- *p++ = '/';
- if (!extn)
- extn = unix;
- }
- else
- *p++ = *unix;
- ++unix;
- }
- *p = '\0';
-
- /*
- * Now break down the name and extentions
- * leaving evtv[0] with the name and
- * extv[1]...extv[n-1] containing the extension parts
- */
- n = 0;
- p = sep;
- while (extv[n] = strtok(p, "/"), extv[n]!=NULL)
- {
- n++;
- p = NULL;
- }
- /*
- printf("dir: %s\n", dir);
- printf("nam: %s\n", extv[0]);
- printf("ext: %s ( ", extn);
- for (i=1; i<n; i++)
- printf("%s ", extv[i]);
- printf(")\n");
- */
- /*
- bbc_vdu(4);
- bbc_vdu(26);
- bbc_vdu(30);
- */
- /*
- * Now scan the path processing database
- * matching names, extension etc to types
- * and a destination path.
- */
- if (preset==PATH_DEF || preset==PATH_TYPE)
- {
- for (pe = pathhead; pe!=NULL; pe = pe->next)
- {
- if (pe->type == str_ROOT)
- rootpath = pe->path;
- else if (pe->type == str_DEFAULT)
- {
- de = pe;
- opts = de->setopts;
- }
- else if (pe->type == str_CURRENT)
- ce = pe;
- else if (pe->type == str_EXTS)
- {
- for (i=0; i<pe->numexts; i++)
- {
- /* name matcher */
- if (*pe->exts[i]!='.')
- {
- if (!namer && pe_wildmat(extv[0], pe->exts[0], tempv, ftpcliopt_nocase))
- {
- /*
- printf("Namer : %s %s\n", extv[0], pe->exts[0]);
- */
- namer = pe;
- cnamer = ce;
- }
- }
- else if (n>1)
- {
- /* try a full extension match for a type match */
- *pat = '*';
- strcpy(pat+1, pe->exts[i]);
- if (!typer && pe_wildmat(extn, pat, tempv, ftpcliopt_nocase))
- {
- /*
- printf("Typer : %s %s\n", extn, pat);
- */
- typer = pe;
- ctyper = ce;
- }
- /* try a place */
- if (!placer && pe_wildmat(extv[1], pat+2, tempv, ftpcliopt_nocase))
- {
- /*
- printf("Placer: %s %s\n", extv[1], pat+2);
- */
- placer = pe;
- cplacer = ce;
- }
- }
- }
- }
- }
- }
- else
- {
- de = preset;
- /* show_pathent(de); */
- }
- /*
- show_pathent(de);
- */
- /*
- printf("opts: %.8x\n", opts);
- */
- if (preset!=PATH_TYPE)
- {
- if (namer && namer->path)
- {
- path = namer->path;
- opts |= namer->setopts;
- opts &= ~namer->clropts;
- opts |= cnamer->setopts;
- opts &= ~cnamer->clropts;
- }
- else if (cnamer && cnamer->path)
- {
- path = cnamer->path;
- opts |= cnamer->setopts;
- opts &= ~cnamer->clropts;
- }
- else if (placer && placer->path)
- {
- path = placer->path;
- opts |= placer->setopts;
- opts &= ~placer->clropts;
- opts |= cplacer->setopts;
- opts &= ~cplacer->clropts;
- }
- else if (cplacer && cplacer->path)
- {
- path = cplacer->path;
- opts |= cplacer->setopts;
- opts &= ~cplacer->clropts;
- }
- else if (typer && typer->path)
- {
- path = typer->path;
- opts |= typer->setopts;
- opts &= ~typer->clropts;
- opts |= ctyper->setopts;
- opts &= ~ctyper->clropts;
- }
- else if (ctyper && ctyper->path)
- {
- path = ctyper->path;
- opts |= ctyper->setopts;
- opts &= ~ctyper->clropts;
- }
- else if (de && de->path)
- {
- path = de->path;
- }
- }
- /*
- printf("opts: %.8x\n", opts);
- */
- *type = -1;
- /*
- printf("root: %s\n",(rootpath)?rootpath:"<none>");
- printf("path: %s\n",(path)?path:"<none>");
- */
- /* Deal with NFS type extension (,xxx) */
- if (ftpcliopt_convnfs)
- {
- int t;
- char *q, *e;
-
- if (q = strrchr(extv[0], ','), q!=NULL)
- {
- t = (int)strtol(q+1, &e, 16);
- if (e>(q+1))
- {
- *type = t;
- *q = '\0';
- opts |= flg_TYPEEXT;
- }
- }
- }
-
- /* else extract type from other known information */
- if (*type<0)
- {
- if (typer && typer->filetype>=0)
- *type = typer->filetype;
- else if (ctyper && ctyper->filetype>=0)
- *type = ctyper->filetype;
- else if (placer && placer->filetype>=0)
- *type = placer->filetype;
- else if (cplacer && cplacer->filetype>=0)
- *type = cplacer->filetype;
- else if (namer && namer->filetype>=0)
- *type = namer->filetype;
- else if (cnamer && cnamer->filetype>=0)
- *type = cnamer->filetype;
- else if (de && de->filetype>=0)
- *type = de->filetype;
- if (*type>=0)
- opts |= flg_TYPEEXT;
- }
-
- if (preset!=PATH_TYPE)
- {
- if (rootpath && !strpbrk(path, "@%&$:<>"))
- {
- int j;
- j = sprintf(riscos, "%s.%s.",rootpath,path);
- riscos += j;
- }
- else
- {
- int j;
- j = sprintf(riscos, "%s.", path);
- riscos += j;
- }
-
- /* strip dirs completely */
- if (ftpcliopt_nopath)
- p = riscos;
- else
- {
- char *q;
- p = riscos;
- /* replace extension seps in dirs with '_' */
- if (ftpcliopt_convdirext)
- {
- for (q=dir; q<sep;)
- {
- *p++ = (*q=='/')?'_':*q;
- ++q;
- }
- }
- /* strip extension from dirs */
- else if (ftpcliopt_nodirext)
- {
- for (q=dir; q<sep;)
- {
- if (*q!='/')
- *p++ = *q++;
- else
- {
- while (*q!='.' && q<sep)
- q++;
- }
- }
- }
- /* copy path */
- else
- {
- for (q=dir; q<sep;)
- *p++ = *q++;
- }
- }
-
- /* loose an extension (relaced by type) */
- if (ftpcliopt_typeext && ((!ftpcliopt_rev1ext && n>1) || n>2))
- --n;
-
- /* reverse extensions */
- if (ftpcliopt_revext)
- {
- while (n>1)
- p += sprintf(p, "%s.", extv[--n] );
-
- if (n>0)
- p += sprintf(p, "%s", extv[--n] );
- }
- /* reverse 1st extension */
- else if (ftpcliopt_rev1ext)
- {
- if (n>1)
- p += sprintf(p, "%s.", extv[1] );
- if (n>0)
- p += sprintf(p, "%s", extv[0] );
- /* keep remaining extensions as /ext */
- if (ftpcliopt_keepext && !ftpcliopt_noext)
- {
- while (n>2)
- p += sprintf(p, "/%s", extv[--n] );
- }
- }
- else
- {
- int j;
- if (n>0)
- p += sprintf(p, "%s", extv[0] );
- /* keep all extensions as /ext */
- if (ftpcliopt_keepext && !ftpcliopt_noext)
- {
- for (j=1; j<n; j++)
- p += sprintf(p, "/%s", extv[j] );
- }
- }
- } /* !PATH_TYPE */
-
- return 1;
- }
-