summaryrefslogtreecommitdiff
path: root/plugins/uade2/uade-2.13/src/unixsupport.c
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2011-03-23 21:26:26 +0100
committerGravatar waker <wakeroid@gmail.com>2011-03-23 21:26:26 +0100
commitfd302d7abc36942e7ff14b22fae1e72b4495bef1 (patch)
tree2a36f8361c907a5bea91a9d905957a709f31ea64 /plugins/uade2/uade-2.13/src/unixsupport.c
parent11e63b53b8c91da89592c373bb32fc2b656c6024 (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.c350
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;
+}