timidity/common.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 01 Jan 2012 01:00:51 -0500
changeset 530 a74d68325094
parent 525 88fafa3f3af2
child 755 7c9cfb3bf040
permissions -rw-r--r--
Added /usr/local/share/timidity to the default path. That's actually where local timidity files are supposed to be installed nowdays.
     1 /*
     2     TiMidity -- Experimental MIDI to WAVE converter
     3     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
     4 
     5     This program is free software; you can redistribute it and/or modify
     6     it under the terms of the Perl Artistic License, available in COPYING.
     7  */
     8 
     9 #include <stdio.h>
    10 #include <stdlib.h>
    11 #include <string.h>
    12 
    13 #include <errno.h>
    14 #include "config.h"
    15 #include "common.h"
    16 #include "output.h"
    17 #include "ctrlmode.h"
    18 
    19 /* I guess "rb" should be right for any libc */
    20 #define OPEN_MODE "rb"
    21 
    22 char current_filename[PATH_MAX];
    23 
    24 static PathList *pathlist=NULL;
    25 
    26 /* Try to open a file for reading. If the filename ends in one of the 
    27    defined compressor extensions, pipe the file through the decompressor */
    28 static FILE *try_to_open(const char *name, int decompress, int noise_mode)
    29 {
    30   FILE *fp;
    31 
    32   fp=fopen(name, OPEN_MODE); /* First just check that the file exists */
    33 
    34   if (!fp)
    35     return 0;
    36 
    37 #ifdef DECOMPRESSOR_LIST
    38   if (decompress)
    39     {
    40       int l,el;
    41       static char *decompressor_list[] = DECOMPRESSOR_LIST, **dec;
    42       const char *cp;
    43       char tmp[PATH_MAX], tmp2[PATH_MAX], *cp2;
    44       /* Check if it's a compressed file */ 
    45       l=strlen(name);
    46       for (dec=decompressor_list; *dec; dec+=2)
    47 	{
    48 	  el=strlen(*dec);
    49 	  if ((el>=l) || (strcmp(name+l-el, *dec)))
    50 	    continue;
    51 
    52 	  /* Yes. Close the file, open a pipe instead. */
    53 	  fclose(fp);
    54 
    55 	  /* Quote some special characters in the file name */
    56 	  cp=name;
    57 	  cp2=tmp2;
    58 	  while (*cp)
    59 	    {
    60 	      switch(*cp)
    61 		{
    62 		case '\'':
    63 		case '\\':
    64 		case ' ':
    65 		case '`':
    66 		case '!':
    67 		case '"':
    68 		case '&':
    69 		case ';':
    70 		  *cp2++='\\';
    71 		}
    72 	      *cp2++=*cp++;
    73 	    }
    74 	  *cp2=0;
    75 
    76 	  sprintf(tmp, *(dec+1), tmp2);
    77 	  fp=popen(tmp, "r");
    78 	  break;
    79 	}
    80     }
    81 #endif
    82   
    83   return fp;
    84 }
    85 
    86 /* This is meant to find and open files for reading, possibly piping
    87    them through a decompressor. */
    88 FILE *open_file(const char *name, int decompress, int noise_mode)
    89 {
    90   FILE *fp;
    91   PathList *plp;
    92   int l;
    93 
    94   if (!name || !(*name))
    95     {
    96       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Attempted to open nameless file.");
    97       return 0;
    98     }
    99 
   100   if (pathlist==NULL) {
   101     /* Generate path list */
   102 #ifdef DEFAULT_PATH
   103     add_to_pathlist(DEFAULT_PATH);
   104 #endif
   105 #ifdef DEFAULT_PATH1
   106     add_to_pathlist(DEFAULT_PATH1);
   107 #endif
   108 #ifdef DEFAULT_PATH2
   109     add_to_pathlist(DEFAULT_PATH2);
   110 #endif
   111 #ifdef DEFAULT_PATH3
   112     add_to_pathlist(DEFAULT_PATH3);
   113 #endif
   114   }
   115 
   116   /* First try the given name */
   117 
   118   strncpy(current_filename, name, PATH_MAX - 1);
   119   current_filename[PATH_MAX - 1]='\0';
   120 
   121   ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
   122   if ((fp=try_to_open(current_filename, decompress, noise_mode)))
   123     return fp;
   124 
   125 #ifdef ENOENT
   126   if (noise_mode && (errno != ENOENT))
   127     {
   128       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
   129 	   current_filename, strerror(errno));
   130       return 0;
   131     }
   132 #endif
   133 
   134   plp=pathlist;
   135   if (name[0] != PATH_SEP)
   136     while (plp)  /* Try along the path then */
   137       {
   138 	*current_filename=0;
   139 	l=strlen(plp->path);
   140 	if(l)
   141 	  {
   142 	    strcpy(current_filename, plp->path);
   143 	    if(current_filename[l-1]!=PATH_SEP)
   144 	      strcat(current_filename, PATH_STRING);
   145 	  }
   146 	strcat(current_filename, name);
   147 	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
   148 	if ((fp=try_to_open(current_filename, decompress, noise_mode)))
   149 	  return fp;
   150 #ifdef ENOENT
   151 	if (noise_mode && (errno != ENOENT))
   152 	  {
   153 	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
   154 		 current_filename, strerror(errno));
   155 	    return 0;
   156 	  }
   157 #endif
   158 	plp=plp->next;
   159       }
   160   
   161   /* Nothing could be opened. */
   162 
   163   *current_filename=0;
   164   
   165   if (noise_mode>=2)
   166     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name, strerror(errno));
   167   
   168   return 0;
   169 }
   170 
   171 /* This closes files opened with open_file */
   172 void close_file(FILE *fp)
   173 {
   174 #ifdef DECOMPRESSOR_LIST
   175   if (pclose(fp)) /* Any better ideas? */
   176 #endif
   177     fclose(fp);
   178 
   179   strncpy(current_filename, "MIDI file", PATH_MAX - 1);
   180 }
   181 
   182 /* This is meant for skipping a few bytes in a file or fifo. */
   183 void skip(FILE *fp, size_t len)
   184 {
   185   size_t c;
   186   char tmp[PATH_MAX];
   187   while (len>0)
   188     {
   189       c=len;
   190       if (c>PATH_MAX) c=PATH_MAX;
   191       len-=c;
   192       if (c!=fread(tmp, 1, c, fp))
   193 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: skip: %s",
   194 	     current_filename, strerror(errno));
   195     }
   196 }
   197 
   198 /* This'll allocate memory or die. */
   199 void *safe_malloc(size_t count)
   200 {
   201   void *p;
   202   if (count > (1<<21))
   203     {
   204       ctl->cmsg(CMSG_FATAL, VERB_NORMAL, 
   205 	   "Strange, I feel like allocating %d bytes. This must be a bug.",
   206 	   count);
   207     }
   208   else if ((p=malloc(count)))
   209     return p;
   210   else
   211     ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count);
   212 
   213   ctl->close();
   214   exit(10);
   215   return(NULL);
   216 }
   217 
   218 /* This adds a directory to the path list */
   219 void add_to_pathlist(const char *s)
   220 {
   221   PathList *plp=safe_malloc(sizeof(PathList));
   222   strcpy((plp->path=safe_malloc(strlen(s)+1)),s);
   223   plp->next=pathlist;
   224   pathlist=plp;
   225 }
   226 
   227 /* Free memory associated to path list */
   228 void free_pathlist(void)
   229 {
   230   PathList *plp, *next_plp;
   231 
   232   plp = pathlist;
   233   while (plp) {
   234     if (plp->path) {
   235       free(plp->path);
   236       plp->path=NULL;
   237     }
   238     next_plp = plp->next;
   239     free(plp);
   240     plp = next_plp;
   241   }
   242   pathlist = NULL;
   243 }