1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 common.c
21
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif /* HAVE_CONFIG_H */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #if TIME_WITH_SYS_TIME
31 # include <sys/time.h>
32 # include <time.h>
33 #else
34 # if HAVE_SYS_TIME_H
35 # include <sys/time.h>
36 # else
37 # include <time.h>
38 # endif
39 #endif /* TIME_WITH_SYS_TIME */
40 #ifdef HAVE_SYS_TYPES_H
41 #include <sys/types.h>
42 #endif /* HAVE_SYS_TYPES_H */
43 #ifdef HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif /* HAVE_SYS_STAT_H */
46 #include <fcntl.h>
47
48 #ifndef NO_STRING_H
49 #include <string.h>
50 #else
51 #include <strings.h>
52 #endif
53 #include <ctype.h>
54 #ifndef __W32__
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif /* HAVE_UNISTD_H */
58 #else
59 #include <process.h>
60 #include <io.h>
61 #endif /* __W32__ */
62 #include "timidity.h"
63 #include "common.h"
64 #include "output.h"
65 #include "controls.h"
66 #include "arc.h"
67 #include "nkflib.h"
68 #include "wrd.h"
69 #include "strtab.h"
70 #include "support.h"
71
72 /* RAND_MAX must defined in stdlib.h
73 * Why RAND_MAX is not defined at SunOS?
74 */
75 #if defined(sun) && !defined(SOLARIS) && !defined(RAND_MAX)
76 #define RAND_MAX ((1<<15)-1)
77 #endif
78
79 #ifndef O_BINARY
80 #define O_BINARY 0
81 #endif
82
83 /* #define MIME_CONVERSION */
84
85 char *program_name, current_filename[1024];
86 MBlockList tmpbuffer;
87 char *output_text_code = NULL;
88 int open_file_noise_mode = OF_NORMAL;
89
90 #ifdef DEFAULT_PATH
91 /* The paths in this list will be tried whenever we're reading a file */
92 static PathList defaultpathlist={DEFAULT_PATH,0};
93 static PathList *pathlist=&defaultpathlist; /* This is a linked list */
94 #else
95 static PathList *pathlist=0;
96 #endif
97
98 const char *note_name[] =
99 {
100 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
101 };
102
103
104 #ifndef TMP_MAX
105 #define TMP_MAX 238328
106 #endif
107
108 int
tmdy_mkstemp(char * tmpl)109 tmdy_mkstemp(char *tmpl)
110 {
111 char *XXXXXX;
112 static uint32 value;
113 uint32 random_time_bits;
114 int count, fd = -1;
115 int save_errno = errno;
116
117 /* These are the characters used in temporary filenames. */
118 static const char letters[] =
119 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
120
121 /* This is where the Xs start. */
122 XXXXXX = strstr(tmpl, "XXXXXX");
123 if (XXXXXX == NULL) {
124 errno = EINVAL;
125 return -1;
126 }
127
128 /* Get some more or less random data. */
129 #if HAVE_GETTIMEOFDAY
130 {
131 struct timeval tv;
132 gettimeofday(&tv, NULL);
133 random_time_bits = (uint32)((tv.tv_usec << 16) ^ tv.tv_sec);
134 }
135 #else
136 random_time_bits = (uint32)time(NULL);
137 #endif
138
139 value += random_time_bits ^ getpid();
140
141 for (count = 0; count < TMP_MAX; value += 7777, ++count) {
142 uint32 v = value;
143
144 /* Fill in the random bits. */
145 XXXXXX[0] = letters[v % 62];
146 v /= 62;
147 XXXXXX[1] = letters[v % 62];
148 v /= 62;
149 XXXXXX[2] = letters[v % 62];
150
151 v = (v << 16) ^ value;
152 XXXXXX[3] = letters[v % 62];
153 v /= 62;
154 XXXXXX[4] = letters[v % 62];
155 v /= 62;
156 XXXXXX[5] = letters[v % 62];
157
158 #if defined(_MSC_VER) || defined(__DMC__)
159 #define S_IRUSR 0
160 #define S_IWUSR 0
161 #endif
162
163 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
164
165 if (fd >= 0) {
166 errno = save_errno;
167 return fd;
168 }
169 if (errno != EEXIST)
170 return -1;
171 }
172
173 /* We got out of the loop because we ran out of combinations to try. */
174 errno = EEXIST;
175 return -1;
176 }
177
178
179 static char *
url_dumpfile(URL url,const char * ext)180 url_dumpfile(URL url, const char *ext)
181 {
182 char filename[1024];
183 char *tmpdir;
184 int fd;
185 FILE *fp;
186 int n;
187 char buff[BUFSIZ];
188
189 #ifdef TMPDIR
190 tmpdir = TMPDIR;
191 #else
192 tmpdir = getenv("TMPDIR");
193 #endif
194 if(tmpdir == NULL || strlen(tmpdir) == 0)
195 tmpdir = PATH_STRING "tmp" PATH_STRING;
196 if(IS_PATH_SEP(tmpdir[strlen(tmpdir) - 1]))
197 snprintf(filename, sizeof(filename), "%sXXXXXX.%s", tmpdir, ext);
198 else
199 snprintf(filename, sizeof(filename), "%s" PATH_STRING "XXXXXX.%s",
200 tmpdir, ext);
201
202 fd = tmdy_mkstemp(filename);
203
204 if (fd == -1)
205 return NULL;
206
207 if ((fp = fdopen(fd, "w")) == NULL) {
208 close(fd);
209 unlink(filename);
210 return NULL;
211 }
212
213 while((n = url_read(url, buff, sizeof(buff))) > 0) {
214 size_t dummy = fwrite(buff, 1, n, fp); ++dummy;
215 }
216 fclose(fp);
217 return safe_strdup(filename);
218 }
219
220
221 /* Try to open a file for reading. If the filename ends in one of the
222 defined compressor extensions, pipe the file through the decompressor */
try_to_open(char * name,int decompress)223 struct timidity_file *try_to_open(char *name, int decompress)
224 {
225 struct timidity_file *tf;
226 URL url;
227 int len;
228
229 if((url = url_arc_open(name)) == NULL)
230 if((url = url_open(name)) == NULL)
231 return NULL;
232
233 tf = (struct timidity_file *)safe_malloc(sizeof(struct timidity_file));
234 tf->url = url;
235 tf->tmpname = NULL;
236
237 len = strlen(name);
238 if(decompress && len >= 3 && strcasecmp(name + len - 3, ".gz") == 0)
239 {
240 int method;
241
242 if(!IS_URL_SEEK_SAFE(tf->url))
243 {
244 if((tf->url = url_cache_open(tf->url, 1)) == NULL)
245 {
246 close_file(tf);
247 return NULL;
248 }
249 }
250
251 method = skip_gzip_header(tf->url);
252 if(method == ARCHIVEC_DEFLATED)
253 {
254 url_cache_disable(tf->url);
255 if((tf->url = url_inflate_open(tf->url, -1, 1)) == NULL)
256 {
257 close_file(tf);
258 return NULL;
259 }
260
261 /* success */
262 return tf;
263 }
264 /* fail */
265 url_rewind(tf->url);
266 url_cache_disable(tf->url);
267 }
268
269 #ifdef __W32__
270 /* Sorry, DECOMPRESSOR_LIST and PATCH_CONVERTERS are not worked yet. */
271 return tf;
272 #endif /* __W32__ */
273
274 #if defined(DECOMPRESSOR_LIST)
275 if(decompress)
276 {
277 static char *decompressor_list[] = DECOMPRESSOR_LIST, **dec;
278 char tmp[1024];
279
280 /* Check if it's a compressed file */
281 for(dec = decompressor_list; *dec; dec += 2)
282 {
283 if(!check_file_extension(name, *dec, 0))
284 continue;
285
286 tf->tmpname = url_dumpfile(tf->url, *dec);
287 if (tf->tmpname == NULL) {
288 close_file(tf);
289 return NULL;
290 }
291
292 url_close(tf->url);
293 snprintf(tmp, sizeof(tmp), *(dec+1), tf->tmpname);
294 if((tf->url = url_pipe_open(tmp)) == NULL)
295 {
296 close_file(tf);
297 return NULL;
298 }
299
300 break;
301 }
302 }
303 #endif /* DECOMPRESSOR_LIST */
304
305 #if defined(PATCH_CONVERTERS)
306 if(decompress == 2)
307 {
308 static char *decompressor_list[] = PATCH_CONVERTERS, **dec;
309 char tmp[1024];
310
311 /* Check if it's a compressed file */
312 for(dec = decompressor_list; *dec; dec += 2)
313 {
314 if(!check_file_extension(name, *dec, 0))
315 continue;
316
317 tf->tmpname = url_dumpfile(tf->url, *dec);
318 if (tf->tmpname == NULL) {
319 close_file(tf);
320 return NULL;
321 }
322
323 url_close(tf->url);
324 sprintf(tmp, *(dec+1), tf->tmpname);
325 if((tf->url = url_pipe_open(tmp)) == NULL)
326 {
327 close_file(tf);
328 return NULL;
329 }
330
331 break;
332 }
333 }
334 #endif /* PATCH_CONVERTERS */
335
336 return tf;
337 }
338
is_url_prefix(const char * name)339 int is_url_prefix(const char *name)
340 {
341 int i;
342
343 static char *url_proto_names[] =
344 {
345 "file:",
346 #ifdef SUPPORT_SOCKET
347 "http://",
348 "ftp://",
349 "news://",
350 #endif /* SUPPORT_SOCKET */
351 "mime:",
352 NULL
353 };
354 for(i = 0; url_proto_names[i]; i++)
355 if(strncmp(name, url_proto_names[i], strlen(url_proto_names[i])) == 0)
356 return 1;
357 return 0;
358 }
359
is_abs_path(const char * name)360 static int is_abs_path(const char *name)
361 {
362 #ifndef __MACOS__
363 if (IS_PATH_SEP(name[0]))
364 return 1;
365 #else
366 if (!IS_PATH_SEP(name[0]) && strchr(name, PATH_SEP) != NULL)
367 return 1;
368 #endif /* __MACOS__ */
369 #ifdef __W32__
370 /* [A-Za-z]: (for Windows) */
371 if (isalpha(name[0]) && name[1] == ':')
372 return 1;
373 #endif /* __W32__ */
374 if (is_url_prefix(name))
375 return 1; /* assuming relative notation is excluded */
376 return 0;
377 }
378
open_with_mem(char * mem,int32 memlen,int noise_mode)379 struct timidity_file *open_with_mem(char *mem, int32 memlen, int noise_mode)
380 {
381 URL url;
382 struct timidity_file *tf;
383
384 errno = 0;
385 if((url = url_mem_open(mem, memlen, 0)) == NULL)
386 {
387 if(noise_mode >= 2)
388 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't open.");
389 return NULL;
390 }
391 tf = (struct timidity_file *)safe_malloc(sizeof(struct timidity_file));
392 tf->url = url;
393 tf->tmpname = NULL;
394 return tf;
395 }
396
397 /*
398 * This is meant to find and open files for reading, possibly piping
399 * them through a decompressor.
400 */
open_file(char * name,int decompress,int noise_mode)401 struct timidity_file *open_file(char *name, int decompress, int noise_mode)
402 {
403 struct timidity_file *tf;
404 PathList *plp = pathlist;
405 int l;
406
407 open_file_noise_mode = noise_mode;
408 if (!name || !(*name)) {
409 if (noise_mode)
410 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
411 "Attempted to open nameless file.");
412 return 0;
413 }
414 /* First try the given name */
415 strncpy(current_filename, url_unexpand_home_dir(name), 1023);
416 current_filename[1023] = '\0';
417 if (noise_mode)
418 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s",
419 current_filename);
420 if ((tf = try_to_open(current_filename, decompress)))
421 return tf;
422 #ifdef __MACOS__
423 if (errno) {
424 #else
425 if (errno && errno != ENOENT) {
426 #endif
427 if (noise_mode)
428 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
429 current_filename, strerror(errno));
430 return 0;
431 }
432 if (!is_abs_path(name))
433 while (plp) { /* Try along the path then */
434 *current_filename = 0;
435 if((l = strlen(plp->path))) {
436 strncpy(current_filename, plp->path,
437 sizeof(current_filename));
438 if (!IS_PATH_SEP(current_filename[l - 1])
439 && current_filename[l - 1] != '#'
440 && name[0] != '#')
441 strncat(current_filename, PATH_STRING,
442 sizeof(current_filename)
443 - strlen(current_filename) - 1);
444 }
445 strncat(current_filename, name, sizeof(current_filename)
446 - strlen(current_filename) - 1);
447 if (noise_mode)
448 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
449 "Trying to open %s", current_filename);
450 if ((tf = try_to_open(current_filename, decompress)))
451 return tf;
452 #ifdef __MACOS__
453 if(errno) {
454 #else
455 if(errno && errno != ENOENT) {
456 #endif
457 if (noise_mode)
458 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
459 current_filename, strerror(errno));
460 return 0;
461 }
462 plp = plp->next;
463 }
464 /* Nothing could be opened. */
465 *current_filename = 0;
466 if (noise_mode >= 2)
467 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name,
468 (errno) ? strerror(errno) : "Can't open file");
469 return 0;
470 }
471
472 /*
473 * This is meant to find and open regular files for reading, possibly
474 * piping them through a decompressor.
475 */
476 struct timidity_file *open_file_r(char *name, int decompress, int noise_mode)
477 {
478 struct stat st;
479 struct timidity_file *tf;
480 PathList *plp = pathlist;
481 int l;
482
483 open_file_noise_mode = noise_mode;
484 if (!name || !(*name)) {
485 if (noise_mode)
486 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
487 "Attempted to open nameless file.");
488 return 0;
489 }
490 /* First try the given name */
491 strncpy(current_filename, url_unexpand_home_dir(name), 1023);
492 current_filename[1023] = '\0';
493 if (noise_mode)
494 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s",
495 current_filename);
496 stat(current_filename, &st);
497 if (!S_ISDIR(st.st_mode))
498 if ((tf = try_to_open(current_filename, decompress)))
499 return tf;
500 #ifdef __MACOS__
501 if (errno) {
502 #else
503 if (errno && errno != ENOENT) {
504 #endif
505 if (noise_mode)
506 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
507 current_filename, strerror(errno));
508 return 0;
509 }
510 if (!is_abs_path(name))
511 while (plp) { /* Try along the path then */
512 *current_filename = 0;
513 if((l = strlen(plp->path))) {
514 strncpy(current_filename, plp->path,
515 sizeof(current_filename));
516 if (!IS_PATH_SEP(current_filename[l - 1])
517 && current_filename[l - 1] != '#'
518 && name[0] != '#')
519 strncat(current_filename, PATH_STRING,
520 sizeof(current_filename)
521 - strlen(current_filename) - 1);
522 }
523 strncat(current_filename, name, sizeof(current_filename)
524 - strlen(current_filename) - 1);
525 if (noise_mode)
526 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
527 "Trying to open %s", current_filename);
528 stat(current_filename, &st);
529 if (!S_ISDIR(st.st_mode))
530 if ((tf = try_to_open(current_filename, decompress)))
531 return tf;
532 #ifdef __MACOS__
533 if(errno) {
534 #else
535 if(errno && errno != ENOENT) {
536 #endif
537 if (noise_mode)
538 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
539 current_filename, strerror(errno));
540 return 0;
541 }
542 plp = plp->next;
543 }
544 /* Nothing could be opened. */
545 *current_filename = 0;
546 if (noise_mode >= 2)
547 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name,
548 (errno) ? strerror(errno) : "Can't open file");
549 return 0;
550 }
551
552 /* This closes files opened with open_file */
553 void close_file(struct timidity_file *tf)
554 {
555 int save_errno = errno;
556 if(tf->url != NULL)
557 {
558 #ifndef __W32__
559 if(tf->tmpname != NULL)
560 {
561 int i;
562 /* dispose the pipe garbage */
563 for(i = 0; tf_getc(tf) != EOF && i < 0xFFFF; i++)
564 ;
565 }
566 #endif /* __W32__ */
567 url_close(tf->url);
568 }
569 if(tf->tmpname != NULL)
570 {
571 unlink(tf->tmpname); /* remove temporary file */
572 free(tf->tmpname);
573 }
574 free(tf);
575 errno = save_errno;
576 }
577
578 /* This is meant for skipping a few bytes. */
579 void skip(struct timidity_file *tf, size_t len)
580 {
581 url_skip(tf->url, (long)len);
582 }
583
584 char *tf_gets(char *buff, int n, struct timidity_file *tf)
585 {
586 return url_gets(tf->url, buff, n);
587 }
588
589 long tf_read(void *buff, int32 size, int32 nitems, struct timidity_file *tf)
590 {
591 return url_nread(tf->url, buff, size * nitems) / size;
592 }
593
594 long tf_seek(struct timidity_file *tf, long offset, int whence)
595 {
596 long prevpos;
597
598 prevpos = url_seek(tf->url, offset, whence);
599 if(prevpos == -1)
600 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
601 "Warning: Can't seek file position");
602 return prevpos;
603 }
604
605 long tf_tell(struct timidity_file *tf)
606 {
607 long pos;
608
609 pos = url_tell(tf->url);
610 if(pos == -1)
611 {
612 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
613 "Warning: Can't get current file position");
614 return (long)tf->url->nread;
615 }
616
617 return pos;
618 }
619
620 void safe_exit(int status)
621 {
622 if(play_mode->fd != -1)
623 {
624 play_mode->acntl(PM_REQ_DISCARD, NULL);
625 play_mode->close_output();
626 }
627 ctl->close();
628 wrdt->close();
629 exit(status);
630 /*NOTREACHED*/
631 }
632
633 /* This'll allocate memory or die. */
634 void *safe_malloc(size_t count)
635 {
636 void *p;
637 static int errflag = 0;
638
639 if(errflag)
640 safe_exit(10);
641 if(count > MAX_SAFE_MALLOC_SIZE)
642 {
643 errflag = 1;
644 ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
645 "Strange, I feel like allocating %d bytes. "
646 "This must be a bug.", count);
647 }
648 else {
649 if(count == 0)
650 /* Some malloc routine return NULL if count is zero, such as
651 * malloc routine from libmalloc.a of Solaris.
652 * But TiMidity doesn't want to return NULL even if count is zero.
653 */
654 count = 1;
655 if((p = (void *)malloc(count)) != NULL)
656 return p;
657 errflag = 1;
658 ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
659 "Sorry. Couldn't malloc %d bytes.", count);
660 }
661 #ifdef ABORT_AT_FATAL
662 abort();
663 #endif /* ABORT_AT_FATAL */
664 safe_exit(10);
665 /*NOTREACHED*/
666 return 0;
667 }
668
669 void *safe_large_malloc(size_t count)
670 {
671 void *p;
672 static int errflag = 0;
673
674 if(errflag)
675 safe_exit(10);
676 if(count == 0)
677 /* Some malloc routine return NULL if count is zero, such as
678 * malloc routine from libmalloc.a of Solaris.
679 * But TiMidity doesn't want to return NULL even if count is zero.
680 */
681 count = 1;
682 if((p = (void *)malloc(count)) != NULL)
683 return p;
684 errflag = 1;
685 ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
686 "Sorry. Couldn't malloc %d bytes.", count);
687
688 #ifdef ABORT_AT_FATAL
689 abort();
690 #endif /* ABORT_AT_FATAL */
691 safe_exit(10);
692 /*NOTREACHED*/
693 return 0;
694 }
695
696 void *safe_realloc(void *ptr, size_t count)
697 {
698 void *p;
699 static int errflag = 0;
700
701 if(errflag)
702 safe_exit(10);
703 if(count > MAX_SAFE_MALLOC_SIZE)
704 {
705 errflag = 1;
706 ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
707 "Strange, I feel like allocating %d bytes. "
708 "This must be a bug.", count);
709 }
710 else {
711 if (ptr == NULL)
712 return safe_malloc(count);
713 if(count == 0)
714 /* Some malloc routine return NULL if count is zero, such as
715 * malloc routine from libmalloc.a of Solaris.
716 * But TiMidity doesn't want to return NULL even if count is zero.
717 */
718 count = 1;
719 if((p = (void *)realloc(ptr, count)) != NULL)
720 return p;
721 errflag = 1;
722 ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
723 "Sorry. Couldn't malloc %d bytes.", count);
724 }
725 #ifdef ABORT_AT_FATAL
726 abort();
727 #endif /* ABORT_AT_FATAL */
728 safe_exit(10);
729 /*NOTREACHED*/
730 return 0;
731 }
732
733 /* This'll allocate memory or die. */
734 char *safe_strdup(const char *s)
735 {
736 char *p;
737 static int errflag = 0;
738
739 if(errflag)
740 safe_exit(10);
741
742 if(s == NULL)
743 p = strdup("");
744 else
745 p = strdup(s);
746 if(p != NULL)
747 return p;
748 errflag = 1;
749 ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't alloc memory.");
750 #ifdef ABORT_AT_FATAL
751 abort();
752 #endif /* ABORT_AT_FATAL */
753 safe_exit(10);
754 /*NOTREACHED*/
755 return 0;
756 }
757
758 /* free ((void **)ptr_list)[0..count-1] and ptr_list itself */
759 void free_ptr_list(void *ptr_list, int count)
760 {
761 int i;
762 for(i = 0; i < count; i++)
763 free(((void **)ptr_list)[i]);
764 free(ptr_list);
765 }
766
767 static int atoi_limited(const char *string, int v_min, int v_max)
768 {
769 int value = atoi(string);
770
771 if (value <= v_min)
772 value = v_min;
773 else if (value > v_max)
774 value = v_max;
775 return value;
776 }
777
778 int string_to_7bit_range(const char *string_, int *start, int *end)
779 {
780 const char *string = string_;
781
782 if(isdigit(*string)) {
783 *start = atoi_limited(string, 0, 127);
784 while(isdigit(*++string)) ;
785 } else
786 *start = 0;
787 if (*string == '-') {
788 string++;
789 *end = isdigit(*string) ? atoi_limited(string, 0, 127) : 127;
790 if(*start > *end)
791 *end = *start;
792 } else
793 *end = *start;
794 return string != string_;
795 }
796
797 /* This adds a directory to the path list */
798 void add_to_pathlist(char *s)
799 {
800 PathList *cur, *prev, *plp;
801
802 /* Check duplicated path in the pathlist. */
803 plp = prev = NULL;
804 for(cur = pathlist; cur; prev = cur, cur = cur->next)
805 if(pathcmp(s, cur->path, 0) == 0)
806 {
807 plp = cur;
808 break;
809 }
810
811 if(plp) /* found */
812 {
813 if(prev == NULL) /* first */
814 pathlist = pathlist->next;
815 else
816 prev->next = plp->next;
817 }
818 else
819 {
820 /* Allocate new path */
821 plp = safe_malloc(sizeof(PathList));
822 plp->path = safe_strdup(s);
823 }
824
825 plp->next = pathlist;
826 pathlist = plp;
827 }
828
829 void clean_up_pathlist(void)
830 {
831 PathList *cur, *next;
832
833 cur = pathlist;
834 while (cur) {
835 next = cur->next;
836 #ifdef DEFAULT_PATH
837 if (cur == &defaultpathlist) {
838 cur = next;
839 continue;
840 }
841 #endif
842 free(cur->path);
843 free(cur);
844 cur = next;
845 }
846
847 #ifdef DEFAULT_PATH
848 pathlist = &defaultpathlist;
849 #else
850 pathlist = NULL;
851 #endif
852 }
853
854 #ifndef HAVE_VOLATILE
855 /*ARGSUSED*/
856 int volatile_touch(void *dmy) {return 1;}
857 #endif /* HAVE_VOLATILE */
858
859 /* code converters */
860 static unsigned char
861 w2k[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
862 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
863 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
864 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
865 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240,
866 242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241,
867 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208,
868 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209};
869
870 static void code_convert_cp1251(char *in, char *out, int maxlen)
871 {
872 int i;
873 if(out == NULL)
874 out = in;
875 for(i = 0; i < maxlen && in[i]; i++)
876 {
877 if(in[i] & 0200)
878 out[i] = w2k[in[i] & 0177];
879 else
880 out[i] = in[i];
881 }
882 out[i]='\0';
883 }
884
885 static void code_convert_dump(char *in, char *out, int maxlen, char *ocode)
886 {
887 if(ocode == NULL)
888 ocode = output_text_code;
889
890 if(ocode != NULL && ocode != (char *)-1
891 && (strstr(ocode, "ASCII") || strstr(ocode, "ascii")))
892 {
893 int i;
894
895 if(out == NULL)
896 out = in;
897 for(i = 0; i < maxlen && in[i]; i++)
898 if(in[i] < ' ' || in[i] >= 127)
899 out[i] = '.';
900 else
901 out[i] = in[i];
902 out[i]='\0';
903 }
904 else /* "NOCNV" */
905 {
906 if(out == NULL)
907 return;
908 strncpy(out, in, maxlen);
909 out[maxlen] = '\0';
910 }
911 }
912
913 #ifdef JAPANESE
914 static void code_convert_japan(char *in, char *out, int maxlen,
915 char *icode, char *ocode)
916 {
917 static char *mode = NULL, *wrd_mode = NULL;
918
919 if(ocode != NULL && ocode != (char *)-1)
920 {
921 nkf_convert(in, out, maxlen, icode, ocode);
922 if(out != NULL)
923 out[maxlen] = '\0';
924 return;
925 }
926
927 if(mode == NULL || wrd_mode == NULL)
928 {
929 mode = output_text_code;
930 if(mode == NULL || strstr(mode, "AUTO"))
931 {
932 #ifndef __W32__
933 mode = getenv("LANG");
934 #else
935 mode = "SJIS";
936 wrd_mode = "SJISK";
937 #endif
938 if(mode == NULL || *mode == '\0')
939 {
940 mode = "ASCII";
941 wrd_mode = mode;
942 }
943 }
944
945 if(strstr(mode, "ASCII") ||
946 strstr(mode, "ascii"))
947 {
948 mode = "ASCII";
949 wrd_mode = mode;
950 }
951 else if(strstr(mode, "NOCNV") ||
952 strstr(mode, "nocnv"))
953 {
954 mode = "NOCNV";
955 wrd_mode = mode;
956 }
957 #ifndef HPUX
958 else if(strstr(mode, "EUC") ||
959 strstr(mode, "euc") ||
960 strstr(mode, "ujis") ||
961 strcmp(mode, "japanese") == 0)
962 {
963 mode = "EUC";
964 wrd_mode = "EUCK";
965 }
966 else if(strstr(mode, "SJIS") ||
967 strstr(mode, "sjis"))
968 {
969 mode = "SJIS";
970 wrd_mode = "SJISK";
971 }
972 #else
973 else if(strstr(mode, "EUC") ||
974 strstr(mode, "euc") ||
975 strstr(mode, "ujis"))
976 {
977 mode = "EUC";
978 wrd_mode = "EUCK";
979 }
980 else if(strstr(mode, "SJIS") ||
981 strstr(mode, "sjis") ||
982 strcmp(mode, "japanese") == 0)
983 {
984 mode = "SJIS";
985 wrd_mode = "SJISK";
986 }
987 #endif /* HPUX */
988 else if(strstr(mode,"JISk")||
989 strstr(mode,"jisk"))
990 {
991 mode = "JISK";
992 wrd_mode = mode;
993 }
994 else if(strstr(mode, "JIS") ||
995 strstr(mode, "jis"))
996 {
997 mode = "JIS";
998 wrd_mode = "JISK";
999 }
1000 else if(strcmp(mode, "ja") == 0)
1001 {
1002 mode = "EUC";
1003 wrd_mode = "EUCK";
1004 }
1005 else
1006 {
1007 mode = "NOCNV";
1008 wrd_mode = mode;
1009 }
1010 }
1011
1012 if(ocode == NULL)
1013 {
1014 if(strcmp(mode, "NOCNV") == 0)
1015 {
1016 if(out == NULL)
1017 return;
1018 strncpy(out, in, maxlen);
1019 out[maxlen] = '\0';
1020 }
1021 else if(strcmp(mode, "ASCII") == 0)
1022 code_convert_dump(in, out, maxlen, "ASCII");
1023 else
1024 {
1025 nkf_convert(in, out, maxlen, icode, mode);
1026 if(out != NULL)
1027 out[maxlen] = '\0';
1028 }
1029 }
1030 else if(ocode == (char *)-1)
1031 {
1032 if(strcmp(wrd_mode, "NOCNV") == 0)
1033 {
1034 if(out == NULL)
1035 return;
1036 strncpy(out, in, maxlen);
1037 out[maxlen] = '\0';
1038 }
1039 else if(strcmp(wrd_mode, "ASCII") == 0)
1040 code_convert_dump(in, out, maxlen, "ASCII");
1041 else
1042 {
1043 nkf_convert(in, out, maxlen, icode, wrd_mode);
1044 if(out != NULL)
1045 out[maxlen] = '\0';
1046 }
1047 }
1048 }
1049 #endif /* JAPANESE */
1050
1051 void code_convert(char *in, char *out, int outsiz, char *icode, char *ocode)
1052 {
1053 #if !defined(MIME_CONVERSION) && defined(JAPANESE)
1054 int i;
1055 /* check ASCII string */
1056 for(i = 0; in[i]; i++)
1057 if(in[i] < ' ' || in[i] >= 127)
1058 break;
1059 if(!in[i])
1060 {
1061 if(out == NULL)
1062 return;
1063 strncpy(out, in, outsiz - 1);
1064 out[outsiz - 1] = '\0';
1065 return; /* All ASCII string */
1066 }
1067 #endif /* MIME_CONVERSION */
1068
1069 if(ocode != NULL && ocode != (char *)-1)
1070 {
1071 if(strcasecmp(ocode, "nocnv") == 0)
1072 {
1073 if(out == NULL)
1074 return;
1075 outsiz--;
1076 strncpy(out, in, outsiz);
1077 out[outsiz] = '\0';
1078 return;
1079 }
1080
1081 if(strcasecmp(ocode, "ascii") == 0)
1082 {
1083 code_convert_dump(in, out, outsiz - 1, "ASCII");
1084 return;
1085 }
1086
1087 if(strcasecmp(ocode, "1251") == 0)
1088 {
1089 code_convert_cp1251(in, out, outsiz - 1);
1090 return;
1091 }
1092 }
1093
1094 #if defined(JAPANESE)
1095 code_convert_japan(in, out, outsiz - 1, icode, ocode);
1096 #else
1097 code_convert_dump(in, out, outsiz - 1, ocode);
1098 #endif
1099 }
1100
1101 /* EAW -- insert stuff from playlist files
1102 *
1103 * Tue Apr 6 1999: Modified by Masanao Izumo <mo@goice.co.jp>
1104 * One pass implemented.
1105 */
1106 static char **expand_file_lists(char **files, int *nfiles_in_out)
1107 {
1108 int nfiles;
1109 int i;
1110 char input_line[256];
1111 char *pfile;
1112 static const char *testext = ".m3u.pls.asx.M3U.PLS.ASX.tpl";
1113 struct timidity_file *list_file;
1114 char *one_file[1];
1115 int one;
1116
1117 /* Recusive global */
1118 static StringTable st;
1119 static int error_outflag = 0;
1120 static int depth = 0;
1121
1122 if(depth >= 16)
1123 {
1124 if(!error_outflag)
1125 {
1126 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1127 "Probable loop in playlist files");
1128 error_outflag = 1;
1129 }
1130 return NULL;
1131 }
1132
1133 if(depth == 0)
1134 {
1135 error_outflag = 0;
1136 init_string_table(&st);
1137 }
1138 nfiles = *nfiles_in_out;
1139
1140 /* Expand playlist recursively */
1141 for(i = 0; i < nfiles; i++)
1142 {
1143 /* extract the file extension */
1144 pfile = strrchr(files[i], '.');
1145
1146 if(*files[i] == '@' || (pfile != NULL && strstr(testext, pfile)))
1147 {
1148 /* Playlist file */
1149 if(*files[i] == '@')
1150 list_file = open_file(files[i] + 1, 1, 1);
1151 else
1152 list_file = open_file(files[i], 1, 1);
1153 if(list_file)
1154 {
1155 while(tf_gets(input_line, sizeof(input_line), list_file)
1156 != NULL) {
1157 if(*input_line == '\n' || *input_line == '\r')
1158 continue;
1159 if((pfile = strchr(input_line, '\r')))
1160 *pfile = '\0';
1161 if((pfile = strchr(input_line, '\n')))
1162 *pfile = '\0';
1163 one_file[0] = input_line;
1164 one = 1;
1165 depth++;
1166 expand_file_lists(one_file, &one);
1167 depth--;
1168 }
1169 close_file(list_file);
1170 }
1171 }
1172 else /* Other file */
1173 put_string_table(&st, files[i], strlen(files[i]));
1174 }
1175
1176 if(depth)
1177 return NULL;
1178 *nfiles_in_out = st.nstring;
1179 return make_string_array(&st);
1180 }
1181
1182 char **expand_file_archives(char **files, int *nfiles_in_out)
1183 {
1184 int nfiles;
1185 char **new_files;
1186 int new_nfiles;
1187
1188 /* First, expand playlist files */
1189 nfiles = *nfiles_in_out;
1190 files = expand_file_lists(files, &nfiles);
1191 if(files == NULL)
1192 {
1193 *nfiles_in_out = 0;
1194 return NULL;
1195 }
1196
1197 /* Second, expand archive files */
1198 new_nfiles = nfiles;
1199 open_file_noise_mode = OF_NORMAL;
1200 new_files = expand_archive_names(&new_nfiles, files);
1201 free(files[0]);
1202 free(files);
1203
1204 *nfiles_in_out = new_nfiles;
1205 return new_files;
1206 }
1207
1208 #ifdef RAND_MAX
1209 int int_rand(int n)
1210 {
1211 if(n < 0)
1212 {
1213 if(n == -1)
1214 srand(time(NULL));
1215 else
1216 srand(-n);
1217 return n;
1218 }
1219 return (int)(n * (double)rand() * (1.0 / (RAND_MAX + 1.0)));
1220 }
1221 #else
1222 int int_rand(int n)
1223 {
1224 static unsigned long rnd_seed = 0xabcd0123;
1225
1226 if(n < 0)
1227 {
1228 if(n == -1)
1229 rnd_seed = time(NULL);
1230 else
1231 rnd_seed = -n;
1232 return n;
1233 }
1234
1235 rnd_seed *= 69069UL;
1236 return (int)(n * (double)(rnd_seed & 0xffffffff) *
1237 (1.0 / (0xffffffff + 1.0)));
1238 }
1239 #endif /* RAND_MAX */
1240
1241 int check_file_extension(char *filename, char *ext, int decompress)
1242 {
1243 int len, elen, i;
1244 #if defined(DECOMPRESSOR_LIST)
1245 char *dlist[] = DECOMPRESSOR_LIST;
1246 #endif /* DECOMPRESSOR_LIST */
1247
1248 len = strlen(filename);
1249 elen = strlen(ext);
1250 if(len > elen && strncasecmp(filename + len - elen, ext, elen) == 0)
1251 return 1;
1252
1253 if(decompress)
1254 {
1255 /* Check gzip'ed file name */
1256
1257 if(len > 3 + elen &&
1258 strncasecmp(filename + len - elen - 3 , ext, elen) == 0 &&
1259 strncasecmp(filename + len - 3, ".gz", 3) == 0)
1260 return 1;
1261
1262 #if defined(DECOMPRESSOR_LIST)
1263 for(i = 0; dlist[i]; i += 2)
1264 {
1265 int dlen;
1266
1267 dlen = strlen(dlist[i]);
1268 if(len > dlen + elen &&
1269 strncasecmp(filename + len - elen - dlen , ext, elen) == 0 &&
1270 strncasecmp(filename + len - dlen, dlist[i], dlen) == 0)
1271 return 1;
1272 }
1273 #endif /* DECOMPRESSOR_LIST */
1274 }
1275 return 0;
1276 }
1277
1278 void randomize_string_list(char **strlist, int n)
1279 {
1280 int i, j;
1281 char *tmp;
1282 for(i = 0; i < n; i++)
1283 {
1284 j = int_rand(n - i);
1285 tmp = strlist[j];
1286 strlist[j] = strlist[n - i - 1];
1287 strlist[n - i - 1] = tmp;
1288 }
1289 }
1290
1291 int pathcmp(const char *p1, const char *p2, int ignore_case)
1292 {
1293 int c1, c2;
1294
1295 #ifdef __W32__
1296 ignore_case = 1; /* Always ignore the case */
1297 #endif
1298
1299 do {
1300 c1 = *p1++ & 0xff;
1301 c2 = *p2++ & 0xff;
1302 if(ignore_case)
1303 {
1304 c1 = tolower(c1);
1305 c2 = tolower(c2);
1306 }
1307 if(IS_PATH_SEP(c1)) c1 = *p1 ? 0x100 : 0;
1308 if(IS_PATH_SEP(c2)) c2 = *p2 ? 0x100 : 0;
1309 } while(c1 == c2 && c1 /* && c2 */);
1310
1311 return c1 - c2;
1312 }
1313
1314 static int pathcmp_qsort(const char **p1,
1315 const char **p2)
1316 {
1317 return pathcmp(*(const char **)p1, *(const char **)p2, 1);
1318 }
1319
1320 void sort_pathname(char **files, int nfiles)
1321 {
1322 qsort(files, nfiles, sizeof(char *),
1323 (int (*)(const void *, const void *))pathcmp_qsort);
1324 }
1325
1326 char *pathsep_strchr(const char *path)
1327 {
1328 #ifdef PATH_SEP2
1329 while(*path)
1330 {
1331 if(*path == PATH_SEP || *path == PATH_SEP2)
1332 return (char *)path;
1333 path++;
1334 }
1335 return NULL;
1336 #else
1337 return strchr(path, PATH_SEP);
1338 #endif
1339 }
1340
1341 char *pathsep_strrchr(const char *path)
1342 {
1343 #ifdef PATH_SEP2
1344 char *last_sep = NULL;
1345 while(*path)
1346 {
1347 if(*path == PATH_SEP || *path == PATH_SEP2)
1348 last_sep = (char *)path;
1349 path++;
1350 }
1351 return last_sep;
1352 #else
1353 return strrchr(path, PATH_SEP);
1354 #endif
1355 }
1356
1357 int str2mID(char *str)
1358 {
1359 int val;
1360
1361 if(strncasecmp(str, "gs", 2) == 0)
1362 val = 0x41;
1363 else if(strncasecmp(str, "xg", 2) == 0)
1364 val = 0x43;
1365 else if(strncasecmp(str, "gm", 2) == 0)
1366 val = 0x7e;
1367 else
1368 {
1369 int i, v;
1370 val = 0;
1371 for(i = 0; i < 2; i++)
1372 {
1373 v = str[i];
1374 if('0' <= v && v <= '9')
1375 v = v - '0';
1376 else if('A' <= v && v <= 'F')
1377 v = v - 'A' + 10;
1378 else if('a' <= v && v <= 'f')
1379 v = v - 'a' + 10;
1380 else
1381 return 0;
1382 val = (val << 4 | v);
1383 }
1384 }
1385 return val;
1386 }
1387