home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / open.c < prev    next >
Text File  |  1994-12-07  |  8KB  |  407 lines

  1. /* open.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* Magic open file: path lookup and transparent decompression */
  6.  
  7. /* $Id: open.c,v 4.4 1994/11/15 16:11:01 espie Exp espie $ 
  8.  * $Log: open.c,v $
  9.  * Revision 4.4  1994/11/15  16:11:01  espie
  10.  * *** empty log message ***
  11.  *
  12.  *
  13.  * Revision 4.2  1994/07/04  14:00:06  espie
  14.  * External compression methods.
  15.  * A little more abstract, should work better
  16.  * Better amiga patterns.
  17.  * Amiga support.
  18.  * Added gzip/shorten.
  19.  * restore stty.
  20.  *
  21.  * Revision 1.5  1992/11/01  13:10:06  espie
  22.  * Cleaned up path handler, and some more bugs.
  23.  * Check for size now.
  24.  * Added path support. Transparent interface. We look up through the file
  25.  * list, which is small anyway.
  26.  */
  27.  
  28. #include "defs.h"
  29.  
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #ifdef MALLOC_NOT_IN_STDLIB
  34. #include <malloc.h>
  35. #endif
  36. #include <stdlib.h>
  37.  
  38. #include "extern.h"
  39.  
  40. ID("$Id: open.c,v 4.4 1994/11/15 16:11:01 espie Exp espie $")
  41.  
  42.  
  43.  
  44. /* Max buffer length for reading compression methods */
  45. #define MAX_LENGTH 90
  46.  
  47.  
  48. /* automaton */
  49. #define END_OF_LINE 0
  50. #define BEGIN_OF_LINE 1
  51. #define IN_SPEC 2
  52. #define BEGIN_OF_COMMAND 3
  53. #define IN_COMMAND 4
  54.  
  55.  
  56. LOCAL void init_compression P((void));
  57. LOCAL void (*INIT)P((void)) = init_compression;
  58. extern int error;
  59.  
  60. struct exfile
  61.    {
  62.    FILE *handle;
  63.    void (*close)P((struct exfile *f));
  64.    void (*rewind)P((struct exfile *f));
  65.    int (*getcar)P((struct exfile *f));
  66.    int (*tell)P((struct exfile *f));
  67.    int pos;
  68.    };
  69.  
  70. LOCAL int do_getchar(f)
  71. struct exfile *f;
  72.    {
  73.    int c;
  74.  
  75.    if ((c = fgetc(f->handle)) == EOF)
  76.       error = FILE_TOO_SHORT;
  77.    else
  78.       f->pos++;
  79.    return c;
  80.    }
  81.  
  82. LOCAL int do_tell(f)
  83. struct exfile *f;
  84.    {
  85.    return f->pos;
  86.    }
  87.  
  88. LOCAL void do_pclose(f)
  89. struct exfile *f;
  90.    {
  91.    pclose(f->handle);
  92.    }
  93.  
  94. LOCAL void do_fclose(f)
  95. struct exfile *f;
  96.    {
  97.    fclose(f->handle);
  98.    }
  99.  
  100.    
  101. /* compression methods we do know about.
  102.  * Important restriction: for the time being, the output
  103.  * must be a single module.
  104.  */
  105.  
  106. struct compression_method
  107.    {
  108.    struct compression_method *next;
  109.    char *extension;
  110.    char *command;
  111.    };
  112.  
  113. struct compression_method *read_method(f)
  114. FILE *f;
  115.    {
  116.    static char buffer[MAX_LENGTH + 1];
  117.    
  118.    while (fgets(buffer, MAX_LENGTH, f))
  119.       {
  120.       int state = BEGIN_OF_LINE;
  121.       int start, i;
  122.       char *spec, *command = NULL;
  123.       
  124.       for (i = 0; state != END_OF_LINE; i++)
  125.          {
  126.          switch(state)
  127.             {
  128.          case BEGIN_OF_LINE:
  129.             switch(buffer[i])
  130.                {
  131.             case ' ':
  132.             case '\t':
  133.                break;
  134.             case 0:
  135.             case '\n':
  136.             case '#':
  137.                state = END_OF_LINE;
  138.                break;
  139.             default:
  140.                start = i;
  141.                state = IN_SPEC;
  142.                }
  143.             break;
  144.          case IN_SPEC:
  145.             switch(buffer[i])
  146.                {
  147.             case ' ':
  148.             case '\t':
  149.                spec = malloc(i - start + 1);
  150.                strncpy(spec, buffer + start, i - start);
  151.                spec[i - start] = 0;
  152.                state = BEGIN_OF_COMMAND;
  153.                break;
  154.             case 0:
  155.             case '\n':
  156.                state = END_OF_LINE;
  157.                break;
  158.             default:
  159.                break;
  160.                }
  161.             break;
  162.          case BEGIN_OF_COMMAND:
  163.             switch (buffer[i])
  164.                {
  165.             case ' ':
  166.             case '\t':
  167.                break;
  168.             case 0:
  169.             case '\n':
  170.                state = END_OF_LINE;
  171.                free(spec);
  172.                break;
  173.             default:
  174.                state = IN_COMMAND;
  175.                start = i;
  176.                }
  177.             break;
  178.          case IN_COMMAND:
  179.             switch (buffer[i])
  180.                {
  181.             case 0:
  182.             case '\n':
  183.                command = malloc(i - start + 1);
  184.                strncpy(command, buffer + start, i - start);
  185.                command[i-start] = 0;
  186.                state = END_OF_LINE;
  187.             default:
  188.                break;
  189.                }
  190.             }
  191.          }      
  192.       if (command)
  193.          {
  194.          struct compression_method *new;
  195.          
  196.          new = malloc(sizeof(struct compression_method));
  197.          new->next = 0;
  198.          new->extension = spec;
  199.          new->command = command;
  200.          return new;
  201.          }
  202.       }
  203.    return 0;
  204.    }
  205.       
  206.  
  207. LOCAL struct compression_method **read_methods(previous, f)
  208. struct compression_method **previous;
  209. FILE *f;
  210.    {
  211.    struct compression_method *method;
  212.    
  213.    if (f)
  214.       {
  215.       while (method = read_method(f))
  216.          {
  217.          *previous = method;
  218.          previous = &(method->next);
  219.          }
  220.       fclose(f);
  221.       }
  222.    return previous;
  223.    }
  224.       
  225.  
  226. LOCAL struct compression_method *comp_list;
  227.  
  228. LOCAL void init_compression()
  229.    {
  230.    char *fname;
  231.    FILE *f;
  232.    struct compression_method **previous;
  233.  
  234.    f = 0;
  235.    fname = getenv("TRACKER_COMPRESSION");
  236.    if (fname)
  237.       f = fopen(fname, "r");
  238.    if (!f)
  239.       {
  240.       fname = COMPRESSION_FILE;
  241.       f = fopen(fname, "r");
  242.       }
  243.    previous = read_methods(&comp_list, f);
  244.    }
  245.       
  246. /***
  247.  *
  248.  *  Handling extensions.
  249.  *
  250.  ***/
  251.  
  252. LOCAL int check_ext(s, ext)
  253. char *s, *ext;
  254.    {
  255.    int ext_len, s_len;
  256.    char *c;
  257.  
  258.    ext_len = strlen(ext);
  259.    s_len = strlen(s);
  260.    if (s_len < ext_len)
  261.       return FALSE;
  262.    for (c = s + s_len - ext_len; *c; c++, ext++)
  263.       if (tolower(*c) != tolower(*ext))
  264.          return FALSE;
  265.    return TRUE;
  266.    }
  267.  
  268. LOCAL int exist_file(fname)
  269. char *fname;
  270.    {
  271.    FILE *temp;
  272.  
  273.    temp = fopen(fname, READ_ONLY);
  274.    if (temp)
  275.       {
  276.       fclose(temp);
  277.       return TRUE;
  278.       }
  279.    else
  280.       return FALSE;
  281.    }
  282.  
  283. #ifndef MAXPATHLEN
  284. #define MAXPATHLEN 350
  285. #endif
  286.  
  287. /* note that find_file returns a STATIC value */
  288.  
  289. LOCAL char *find_file(fname, path)
  290. char *fname;
  291. char *path;
  292.    {
  293.    char *sep;
  294.    static char buffer[MAXPATHLEN];
  295.    int len;
  296.  
  297.       /* first, check the current directory */
  298.    if (exist_file(fname))
  299.       return fname;
  300.    while(path)
  301.       {
  302. #ifndef OSK
  303.       sep = strchr(path, ':');
  304. #else
  305.       sep = index(path, ':');
  306. #endif
  307.       if (sep)
  308.          len = sep - path;
  309.       else
  310.          len = strlen(path);
  311.       if (len < MAXPATHLEN)
  312.          {
  313.          strncpy(buffer, path, len);
  314.          buffer[len] = '/';
  315.          if (len + strlen(fname) < MAXPATHLEN - 5)
  316.             {
  317.             strcpy(buffer + len + 1, fname);
  318.             puts(buffer);
  319.             if (exist_file(buffer))
  320.                return buffer;
  321.             }
  322.          }
  323.       if (sep)
  324.          path = sep + 1;
  325.       else
  326.             return NULL;
  327.       }
  328.     return NULL;
  329.    }
  330.  
  331. FILE *file_handle(f)
  332. struct exfile *f;
  333.    {
  334.    return f->handle;
  335.    }
  336.  
  337. int getc_file(f)
  338. struct exfile *f;
  339.    {
  340.    return (*f->getcar)(f);
  341.    }
  342.  
  343. int tell_file(f)
  344. struct exfile *f;
  345.    {
  346.    return (*f->tell)(f);
  347.    }
  348.  
  349. struct exfile *open_file(fname, mode, path)
  350. char *fname;
  351. char *mode; /* right now, only mode "r" is supported */
  352. char *path; 
  353.    {
  354.    struct exfile *new;
  355.    struct compression_method *comp;
  356.  
  357.    INIT_ONCE;
  358.    if (mode[0] != 'r' || mode[1] != 0)
  359.       return NULL;
  360.     
  361.    new = (struct exfile *)malloc(sizeof(struct exfile));
  362.    if (!new)
  363.       return NULL;
  364.  
  365.    new->getcar = do_getchar;
  366.    new->tell = do_tell;
  367.    new->pos = 0;
  368.    fname = find_file(fname, path);
  369.    if (!fname)
  370.       goto not_opened;
  371.          /* check for extension */
  372.    for (comp = comp_list; comp; comp = comp->next)
  373.       if (check_ext(fname, comp->extension))
  374.          {
  375.          char *pipe;
  376.          
  377.          pipe = malloc(strlen(comp->command) + strlen(fname) + 25);
  378.          if (!pipe)
  379.             goto not_opened;
  380.  
  381.          sprintf(pipe, comp->command, fname);
  382.          new->close = do_pclose;
  383.          new->handle = popen(pipe, READ_ONLY);
  384.          free(pipe);
  385.          if (new->handle)
  386.             return new;
  387.          else
  388.             goto not_opened;
  389.          }
  390.    new->close = do_fclose;
  391.    if (new->handle = fopen(fname, READ_ONLY))
  392.       return new;
  393.  
  394. not_opened:
  395.    free(new);
  396.    return NULL;
  397.    }
  398.  
  399.  
  400. void close_file(file)
  401. struct exfile *file;
  402.    {
  403.    (*file->close)(file);
  404.    free(file);
  405.    }
  406.  
  407.