home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
MM1
/
SOUNDUTILS
/
tracker.4.6.lzh
/
TRACKER4.6
/
open.c
< prev
next >
Wrap
Text File
|
1994-12-07
|
8KB
|
407 lines
/* open.c
vi:ts=3 sw=3:
*/
/* Magic open file: path lookup and transparent decompression */
/* $Id: open.c,v 4.4 1994/11/15 16:11:01 espie Exp espie $
* $Log: open.c,v $
* Revision 4.4 1994/11/15 16:11:01 espie
* *** empty log message ***
*
*
* Revision 4.2 1994/07/04 14:00:06 espie
* External compression methods.
* A little more abstract, should work better
* Better amiga patterns.
* Amiga support.
* Added gzip/shorten.
* restore stty.
*
* Revision 1.5 1992/11/01 13:10:06 espie
* Cleaned up path handler, and some more bugs.
* Check for size now.
* Added path support. Transparent interface. We look up through the file
* list, which is small anyway.
*/
#include "defs.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef MALLOC_NOT_IN_STDLIB
#include <malloc.h>
#endif
#include <stdlib.h>
#include "extern.h"
ID("$Id: open.c,v 4.4 1994/11/15 16:11:01 espie Exp espie $")
/* Max buffer length for reading compression methods */
#define MAX_LENGTH 90
/* automaton */
#define END_OF_LINE 0
#define BEGIN_OF_LINE 1
#define IN_SPEC 2
#define BEGIN_OF_COMMAND 3
#define IN_COMMAND 4
LOCAL void init_compression P((void));
LOCAL void (*INIT)P((void)) = init_compression;
extern int error;
struct exfile
{
FILE *handle;
void (*close)P((struct exfile *f));
void (*rewind)P((struct exfile *f));
int (*getcar)P((struct exfile *f));
int (*tell)P((struct exfile *f));
int pos;
};
LOCAL int do_getchar(f)
struct exfile *f;
{
int c;
if ((c = fgetc(f->handle)) == EOF)
error = FILE_TOO_SHORT;
else
f->pos++;
return c;
}
LOCAL int do_tell(f)
struct exfile *f;
{
return f->pos;
}
LOCAL void do_pclose(f)
struct exfile *f;
{
pclose(f->handle);
}
LOCAL void do_fclose(f)
struct exfile *f;
{
fclose(f->handle);
}
/* compression methods we do know about.
* Important restriction: for the time being, the output
* must be a single module.
*/
struct compression_method
{
struct compression_method *next;
char *extension;
char *command;
};
struct compression_method *read_method(f)
FILE *f;
{
static char buffer[MAX_LENGTH + 1];
while (fgets(buffer, MAX_LENGTH, f))
{
int state = BEGIN_OF_LINE;
int start, i;
char *spec, *command = NULL;
for (i = 0; state != END_OF_LINE; i++)
{
switch(state)
{
case BEGIN_OF_LINE:
switch(buffer[i])
{
case ' ':
case '\t':
break;
case 0:
case '\n':
case '#':
state = END_OF_LINE;
break;
default:
start = i;
state = IN_SPEC;
}
break;
case IN_SPEC:
switch(buffer[i])
{
case ' ':
case '\t':
spec = malloc(i - start + 1);
strncpy(spec, buffer + start, i - start);
spec[i - start] = 0;
state = BEGIN_OF_COMMAND;
break;
case 0:
case '\n':
state = END_OF_LINE;
break;
default:
break;
}
break;
case BEGIN_OF_COMMAND:
switch (buffer[i])
{
case ' ':
case '\t':
break;
case 0:
case '\n':
state = END_OF_LINE;
free(spec);
break;
default:
state = IN_COMMAND;
start = i;
}
break;
case IN_COMMAND:
switch (buffer[i])
{
case 0:
case '\n':
command = malloc(i - start + 1);
strncpy(command, buffer + start, i - start);
command[i-start] = 0;
state = END_OF_LINE;
default:
break;
}
}
}
if (command)
{
struct compression_method *new;
new = malloc(sizeof(struct compression_method));
new->next = 0;
new->extension = spec;
new->command = command;
return new;
}
}
return 0;
}
LOCAL struct compression_method **read_methods(previous, f)
struct compression_method **previous;
FILE *f;
{
struct compression_method *method;
if (f)
{
while (method = read_method(f))
{
*previous = method;
previous = &(method->next);
}
fclose(f);
}
return previous;
}
LOCAL struct compression_method *comp_list;
LOCAL void init_compression()
{
char *fname;
FILE *f;
struct compression_method **previous;
f = 0;
fname = getenv("TRACKER_COMPRESSION");
if (fname)
f = fopen(fname, "r");
if (!f)
{
fname = COMPRESSION_FILE;
f = fopen(fname, "r");
}
previous = read_methods(&comp_list, f);
}
/***
*
* Handling extensions.
*
***/
LOCAL int check_ext(s, ext)
char *s, *ext;
{
int ext_len, s_len;
char *c;
ext_len = strlen(ext);
s_len = strlen(s);
if (s_len < ext_len)
return FALSE;
for (c = s + s_len - ext_len; *c; c++, ext++)
if (tolower(*c) != tolower(*ext))
return FALSE;
return TRUE;
}
LOCAL int exist_file(fname)
char *fname;
{
FILE *temp;
temp = fopen(fname, READ_ONLY);
if (temp)
{
fclose(temp);
return TRUE;
}
else
return FALSE;
}
#ifndef MAXPATHLEN
#define MAXPATHLEN 350
#endif
/* note that find_file returns a STATIC value */
LOCAL char *find_file(fname, path)
char *fname;
char *path;
{
char *sep;
static char buffer[MAXPATHLEN];
int len;
/* first, check the current directory */
if (exist_file(fname))
return fname;
while(path)
{
#ifndef OSK
sep = strchr(path, ':');
#else
sep = index(path, ':');
#endif
if (sep)
len = sep - path;
else
len = strlen(path);
if (len < MAXPATHLEN)
{
strncpy(buffer, path, len);
buffer[len] = '/';
if (len + strlen(fname) < MAXPATHLEN - 5)
{
strcpy(buffer + len + 1, fname);
puts(buffer);
if (exist_file(buffer))
return buffer;
}
}
if (sep)
path = sep + 1;
else
return NULL;
}
return NULL;
}
FILE *file_handle(f)
struct exfile *f;
{
return f->handle;
}
int getc_file(f)
struct exfile *f;
{
return (*f->getcar)(f);
}
int tell_file(f)
struct exfile *f;
{
return (*f->tell)(f);
}
struct exfile *open_file(fname, mode, path)
char *fname;
char *mode; /* right now, only mode "r" is supported */
char *path;
{
struct exfile *new;
struct compression_method *comp;
INIT_ONCE;
if (mode[0] != 'r' || mode[1] != 0)
return NULL;
new = (struct exfile *)malloc(sizeof(struct exfile));
if (!new)
return NULL;
new->getcar = do_getchar;
new->tell = do_tell;
new->pos = 0;
fname = find_file(fname, path);
if (!fname)
goto not_opened;
/* check for extension */
for (comp = comp_list; comp; comp = comp->next)
if (check_ext(fname, comp->extension))
{
char *pipe;
pipe = malloc(strlen(comp->command) + strlen(fname) + 25);
if (!pipe)
goto not_opened;
sprintf(pipe, comp->command, fname);
new->close = do_pclose;
new->handle = popen(pipe, READ_ONLY);
free(pipe);
if (new->handle)
return new;
else
goto not_opened;
}
new->close = do_fclose;
if (new->handle = fopen(fname, READ_ONLY))
return new;
not_opened:
free(new);
return NULL;
}
void close_file(file)
struct exfile *file;
{
(*file->close)(file);
free(file);
}