diff options
author | 2011-03-23 21:26:26 +0100 | |
---|---|---|
committer | 2011-03-23 21:26:26 +0100 | |
commit | fd302d7abc36942e7ff14b22fae1e72b4495bef1 (patch) | |
tree | 2a36f8361c907a5bea91a9d905957a709f31ea64 /plugins/uade2/uade-2.13/src/unixsupport.c | |
parent | 11e63b53b8c91da89592c373bb32fc2b656c6024 (diff) |
renamed soundtouch and uade2 plugin folders and output .so
Diffstat (limited to 'plugins/uade2/uade-2.13/src/unixsupport.c')
-rw-r--r-- | plugins/uade2/uade-2.13/src/unixsupport.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/plugins/uade2/uade-2.13/src/unixsupport.c b/plugins/uade2/uade-2.13/src/unixsupport.c new file mode 100644 index 00000000..d6131bc2 --- /dev/null +++ b/plugins/uade2/uade-2.13/src/unixsupport.c @@ -0,0 +1,350 @@ +/* UNIX support tools for uadecore. + + Copyright 2000 - 2005 (C) Heikki Orsila <heikki.orsila@iki.fi> + + This module is licensed under the GNU GPL. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <libgen.h> +#include <sys/socket.h> +#include <unistd.h> +#include <limits.h> +#include <ctype.h> + +#include "uade.h" +#include "unixatomic.h" + + +static int url_to_fd(const char *url, int flags, mode_t mode) +{ + int fd; + if (strncmp(url, "fd://", 5) == 0) { + char *endptr; + if (url[5] == 0) + return -1; + fd = strtol(&url[5], &endptr, 10); + if (*endptr != 0) + return -1; + } else { + if (flags & O_WRONLY) { + fd = open(url, flags, mode); + } else { + fd = open(url, flags); + } + } + if (fd < 0) + fd = -1; + return fd; +} + + +/* This must read the full size_t count if it can, and therefore we use + atomic_read() */ +ssize_t uade_ipc_read(void *f, const void *buf, size_t count) +{ + int fd = (intptr_t) f; + return atomic_read(fd, buf, count); +} + + +/* This must write the full size_t count if it can, and therefore we use + atomic_write() */ +ssize_t uade_ipc_write(void *f, const void *buf, size_t count) +{ + int fd = (intptr_t) f; + return atomic_write(fd, buf, count); +} + + +void *uade_ipc_set_input(const char *input) +{ + int fd; + if ((fd = url_to_fd(input, O_RDONLY, 0)) < 0) { + fprintf(stderr, "can not open input file %s: %s\n", input, strerror(errno)); + exit(-1); + } + return (void *) ((intptr_t) fd); +} + + +void *uade_ipc_set_output(const char *output) +{ + int fd; + if ((fd = url_to_fd(output, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { + fprintf(stderr, "can not open output file %s: %s\n", output, strerror(errno)); + exit(-1); + } + return (void *) ((intptr_t) fd); +} + + +static int uade_amiga_scandir(char *real, char *dirname, char *fake, int ml) +{ + DIR *dir; + struct dirent *direntry; + if (!(dir = opendir(dirname))) { + fprintf(stderr, "uade: can't open dir (%s) (amiga scandir)\n", dirname); + return 0; + } + while ((direntry = readdir(dir))) { + if (!strcmp(fake, direntry->d_name)) { + if (((int) strlcpy(real, direntry->d_name, ml)) >= ml) { + fprintf(stderr, "uade: %s does not fit real", direntry->d_name); + closedir(dir); + return 0; + } + break; + } + } + if (direntry) { + closedir(dir); + return 1; + } + rewinddir(dir); + while ((direntry = readdir(dir))) { + if (!strcasecmp(fake, direntry->d_name)) { + if (((int) strlcpy(real, direntry->d_name, ml)) >= ml) { + fprintf(stderr, "uade: %s does not fit real", direntry->d_name); + closedir(dir); + return 0; + } + break; + } + } + closedir(dir); + return direntry ? 1 : 0; +} + + +char *uade_dirname(char *dst, char *src, size_t maxlen) +{ + char *srctemp = strdup(src); + if (srctemp == NULL) + return NULL; + strlcpy(dst, dirname(srctemp), maxlen); + free(srctemp); + return dst; +} + + +/* opens file in amiga namespace */ +FILE *uade_open_amiga_file(char *aname, const char *playerdir) +{ + char *separator; + char *ptr; + char copy[PATH_MAX]; + char dirname[PATH_MAX]; + char fake[PATH_MAX]; + char real[PATH_MAX]; + int len; + DIR *dir; + FILE *file; + + if (strlcpy(copy, aname, sizeof(copy)) >= sizeof(copy)) { + fprintf(stderr, "uade: error: amiga tried to open a very long filename\nplease REPORT THIS!\n"); + return NULL; + } + ptr = copy; + /* fprintf(stderr, "uade: opening %s\n", ptr); */ + if ((separator = strchr(ptr, (int) ':'))) { + len = (int) (separator - ptr); + memcpy(dirname, ptr, len); + dirname[len] = 0; + if (!strcasecmp(dirname, "ENV")) { + snprintf(dirname, sizeof(dirname), "%s/ENV/", playerdir); + } else if (!strcasecmp(dirname, "S")) { + snprintf(dirname, sizeof(dirname), "%s/S/", playerdir); + } else { + fprintf(stderr, "uade: open_amiga_file: unknown amiga volume (%s)\n", aname); + return NULL; + } + if (!(dir = opendir(dirname))) { + fprintf(stderr, "uade: can't open dir (%s) (volume parsing)\n", dirname); + return NULL; + } + closedir(dir); + /* fprintf(stderr, "uade: opening from dir %s\n", dirname); */ + ptr = separator + 1; + } else { + if (*ptr == '/') { + /* absolute path */ + strlcpy(dirname, "/", sizeof(dirname)); + ptr++; + } else { + /* relative path */ + strlcpy(dirname, "./", sizeof(dirname)); + } + } + + while ((separator = strchr(ptr, (int) '/'))) { + len = (int) (separator - ptr); + if (!len) { + ptr++; + continue; + } + memcpy(fake, ptr, len); + fake[len] = 0; + if (uade_amiga_scandir(real, dirname, fake, sizeof(real))) { + /* found matching entry */ + if (strlcat(dirname, real, sizeof(dirname)) >= sizeof(dirname)) { + fprintf(stderr, "uade: too long dir path (%s + %s)\n", dirname, real); + return NULL; + } + if (strlcat(dirname, "/", sizeof(dirname)) >= sizeof(dirname)) { + fprintf(stderr, "uade: too long dir path (%s + %s)\n", dirname, "/"); + return NULL; + } + } else { + /* didn't find entry */ + /* fprintf (stderr, "uade: %s not found from (%s) (dir scanning)\n", fake, dirname); */ + return NULL; + } + ptr = separator + 1; + } + /* fprintf(stderr, "uade: pass 3: (%s) (%s)\n", dirname, ptr); */ + + if (!(dir = opendir(dirname))) { + fprintf(stderr, "can't open dir (%s) (after dir scanning)\n", dirname); + return NULL; + } + closedir(dir); + + if (uade_amiga_scandir(real, dirname, ptr, sizeof(real))) { + /* found matching entry */ + if (strlcat(dirname, real, sizeof(dirname)) >= sizeof(dirname)) { + fprintf(stderr, "uade: too long dir path (%s + %s)\n", dirname, real); + return NULL; + } + } else { + /* didn't find entry */ + /* fprintf (stderr, "uade: %s not found from %s\n", ptr, dirname); */ + return NULL; + } + if (!(file = fopen(dirname, "r"))) { + fprintf (stderr, "uade: couldn't open file (%s) induced by (%s)\n", dirname, aname); + } + return file; +} + + +void uade_portable_initializations(void) +{ + int signals[] = {SIGINT, -1}; + int *signum = signals; + struct sigaction act; + memset(&act, 0, sizeof act); + act.sa_handler = SIG_IGN; + + while (*signum != -1) { + while (1) { + if ((sigaction(*signum, &act, NULL)) < 0) { + if (errno == EINTR) + continue; + fprintf(stderr, "can not ignore signal %d: %s\n", *signum, strerror(errno)); + exit(-1); + } + break; + } + signum++; + } +} + + +void uade_arch_spawn(struct uade_ipc *ipc, pid_t *uadepid, + const char *uadename) +{ + int fds[2]; + char input[32], output[32]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { + fprintf(stderr, "Can not create socketpair: %s\n", strerror(errno)); + abort(); + } + + *uadepid = fork(); + if (*uadepid < 0) { + fprintf(stderr, "Fork failed: %s\n", strerror(errno)); + abort(); + } + + /* The child (*uadepid == 0) will execute uadecore */ + if (*uadepid == 0) { + int fd; + int maxfds; + + if ((maxfds = sysconf(_SC_OPEN_MAX)) < 0) { + maxfds = 1024; + fprintf(stderr, "Getting max fds failed. Using %d.\n", maxfds); + } + + /* close everything else but stdin, stdout, stderr, and in/out fds */ + for (fd = 3; fd < maxfds; fd++) { + if (fd != fds[1]) + atomic_close(fd); + } + + /* give in/out fds as command line parameters to the uade process */ + snprintf(input, sizeof(input), "fd://%d", fds[1]); + snprintf(output, sizeof(output), "fd://%d", fds[1]); + + execlp(uadename, uadename, "-i", input, "-o", output, (char *) NULL); + fprintf(stderr, "uade execlp failed: %s\n", strerror(errno)); + abort(); + } + + /* Close fds that the uadecore uses */ + if (atomic_close(fds[1]) < 0) { + fprintf(stderr, "Could not close uadecore fds: %s\n", strerror(errno)); + kill (*uadepid, SIGTERM); + abort(); + } + + do { + snprintf(output, sizeof output, "fd://%d", fds[0]); + snprintf(input, sizeof input, "fd://%d", fds[0]); + uade_set_peer(ipc, 1, input, output); + } while (0); +} + +/* + * A hack that converts X:\something style windows names into cygwin style name + * /cygdrive/X/something. All '\\' characters are converted into '/' + * characters. + */ +char *windows_to_cygwin_path(const char *path) +{ + size_t i; + char *s; + size_t len = strlen(path); + + if (len == 0) + return calloc(1, 1); + + if (len >= 2 && isalpha(path[0]) && path[1] == ':') { + /* uses windows drive names */ + size_t newlen = len + 32; + s = malloc(newlen); + if (s != NULL) + snprintf(s, newlen, "/cygdrive/%c/%s", path[0], &path[2]); + } else { + s = strdup(path); + } + if (s == NULL) + return NULL; + + for (i = 0; s[i] != 0; i++) { + if (s[i] == '\\') + s[i] = '/'; + } + + return s; +} |