struct cpu_state* syscall(struct cpu_state* cpu) { save_cpu_state(cpu); cpu = get_current_task()->cpuState; switch (cpu->eax) { case 1: /* exit */ return terminate_current(cpu); case 3: /* exec */ { cpu->eax = vfs_exec((char*) cpu->ebx, (char**) cpu->ecx); } break; case 4: /* getargs */ { cpu->eax = (uint32_t) get_current_task()->args; } break; case 5: /* yield */ { cpu = schedule(cpu); } break; case 10: /* fopen */ { char* name = strclone((char*) cpu->ebx); uint32_t fmode = (uint32_t) cpu->ecx; struct res_handle* handle = vfs_open(name, fmode); if(handle) { register_handle(handle); cpu->eax = (uint32_t) handle; } else { cpu->eax = 0; } free(name); } break; case 11: /* fclose */ { struct res_handle* handle = (void*) cpu->ebx; if(!unregister_handle(handle)) { vfs_close(handle); cpu->eax = 0; } else { cpu->eax = (uint32_t) -1; } } break; case 12: /* fwrite */ { struct res_handle* handle = (void*) cpu->ebx; if(handle != 0) { cpu->eax = vfs_write(handle, (char*) cpu->ecx, cpu->edx, 1); } else { cpu->eax = RW_ERR_VFS; } } break; case 13: /* fread */ { struct res_handle* handle = (void*) cpu->ebx; if(handle != 0) { cpu->eax = vfs_read(handle, (char*) cpu->ecx, cpu->edx, 1); } else { cpu->eax = RW_ERR_VFS; } } break; case 14: /* fmkfifo */ { char* name = strclone((char*) cpu->ebx); vfs_create_kfile(name, ramfs_fifo_driver_struct(), &(uint32_t){4096}); //default to 4k Buffer-size struct res_handle* handle = vfs_open(name, FM_READ | FM_WRITE); if(handle) { register_handle(handle); cpu->eax = (uint32_t) handle; } else { cpu->eax = 0; } free(name); } break; case 20: /* getpmhandle */ { struct res_handle* handle = 0; switch(cpu->ebx) { case PMID_STDOUT: handle = get_current_task()->stdout; break; case PMID_STDIN: handle = get_current_task()->stdin; break; case PMID_STDERR: handle = get_current_task()->stderr; break; default: handle = get_current_task()->stdout; break; } cpu->eax = (uint32_t) handle; } break; case 21: /* fopenpmhandle */ { char* path = strclone((char*)cpu->ecx); struct res_handle* open; uint32_t fm = FM_WRITE; if(cpu->ebx == PMID_STDIN) { fm = FM_READ; } open = vfs_open(path, fm); free(path); if(!open) { cpu->eax = (uint32_t) -1; break; } struct res_handle* oldhandle = 0; switch(cpu->ebx) { case PMID_STDOUT: oldhandle = get_current_task()->stdout; get_current_task()->stdout = open; break; case PMID_STDIN: oldhandle = get_current_task()->stdin; get_current_task()->stdin = open; break; case PMID_STDERR: oldhandle = get_current_task()->stderr; get_current_task()->stderr = open; break; default: oldhandle = get_current_task()->stdout; get_current_task()->stdout = open; break; } if(oldhandle != 0) { vfs_close(oldhandle); } cpu->eax = 0; } break; case 201: /* kputc */ cpu->eax = kprintf("%c", cpu->ebx); break; case 202: /* kputs */ cpu->eax = kprintf("%s", cpu->ebx); break; case 203: /* vmm_alloc_ucont */ cpu->eax = (uint32_t) vmm_alloc_ucont(cpu->ebx); break; case 204: /* vmm_free */ cpu->eax = 0; if (cpu->ebx >= PROGRAM_BOTTOM) { //Only in PROGRAM AREA ;) vmm_free((void*) cpu->ebx); } break; case 205: /* pmm_print_stats */ pmm_print_stats(); break; default: kprintf("Invalid Syscall %d...", cpu->eax); break; } return cpu; }
static uae_u32 open_library (const char *name, uae_u32 min_version) { syncdivisor = (3580000.0 * CYCLE_UNIT) / (double) syncbase; for (const char *c = name; *c; c++) { if (*c == '/' || *c == '\\' || *c == ':') { return UNI_ERROR_ILLEGAL_LIBRARY_NAME; } } TCHAR *tname = au (name); write_log (_T("uni: open native library '%s'\n"), tname); TCHAR *path = get_native_library_path (tname); free (tname); if (path == NULL) { write_log(_T("uni: library not found\n")); return UNI_ERROR_LIBRARY_NOT_FOUND; } write_log (_T("uni: found library at %s - opening\n"), path); #ifdef _WIN32 void *dl = LoadLibrary (path); #else void *dl = dlopen (path, RTLD_NOW); #endif free(path); if (dl == NULL) { write_log (_T("uni: error opening library errno %d\n"), errno); return UNI_ERROR_COULD_NOT_OPEN_LIBRARY; } // FIXME: check min version set_library_globals(dl); void *function_address = dl_symbol(dl, "uni_init"); if (function_address) { int error = ((uni_init_function) function_address)(); if (error) { dl_close(dl); return error; } } struct library_data *library_data = (struct library_data *) malloc( sizeof(struct library_data)); memset(library_data, 0, sizeof(struct library_data)); library_data->dl_handle = dl; uae_u32 handle = register_handle (library_data, NULL); write_log(_T("uni: opened library %08x (%p)\n"), handle, dl); return handle; }
static uae_u32 get_function_handle (uae_u32 handle, const char *name) { struct library_data *library_data = get_library_data_from_handle (handle); if (library_data == NULL) { write_log(_T("uni: get_function - invalid library (%d)\n"), handle); return UNI_ERROR_INVALID_LIBRARY; } void *function_address = dl_symbol (library_data->dl_handle, name); if (!function_address) { write_log(_T("uni: get_function - function (%s) not found ") _T("in library %d (%p)\n"), name, handle, library_data->dl_handle); return UNI_ERROR_FUNCTION_NOT_FOUND; } return register_handle (library_data, function_address); }
static gboolean handle_save_file (XdpFileChooser *object, GDBusMethodInvocation *invocation, const gchar *arg_parent_window, const gchar *arg_title, GVariant *arg_options) { Request *request = request_from_invocation (invocation); const char *app_id = request->app_id; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); g_autoptr(GError) error = NULL; g_autofree char *impl_handle = NULL; GVariantBuilder options; g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT); copy_options (arg_options, &options, save_file_options, G_N_ELEMENTS (save_file_options)); if (!xdp_impl_file_chooser_call_save_file_sync (impl, sender, app_id, arg_parent_window, arg_title, g_variant_builder_end (&options), &impl_handle, NULL, &error)) { g_dbus_method_invocation_return_gerror (invocation, error); return TRUE; } g_object_set_data_full (G_OBJECT (request), "impl-handle", g_strdup (impl_handle), g_free); register_handle (impl_handle, request); g_signal_connect (request, "handle-close", (GCallback)handle_close, request); REQUEST_AUTOLOCK (request); request_export (request, g_dbus_method_invocation_get_connection (invocation)); xdp_file_chooser_complete_open_file (object, invocation, request->id); return TRUE; }
int main(int argc, char ** argv) { int option, nerror = 0, background = 0, quiet = 0, have_socket = 0; time_t pauselength = 0; char * proxy; opterr = 0; /* Create directories. */ makercd(); /* Load settings from ~/.shell-fm/shell-fm.rc. */ settings(rcpath("shell-fm.rc"), !0); /* Enable discovery by default if it is set in configuration. */ if(haskey(& rc, "discovery")) enable(DISCOVERY); /* Disable RTP if option "no-rtp" is set to something. */ if(haskey(& rc, "no-rtp")) disable(RTP); /* If "daemon" is set in the configuration, enable daemon mode by default. */ if(haskey(& rc, "daemon")) background = !0; /* If "quiet" is set in the configuration, enable quiet mode by default. */ if(haskey(& rc, "quiet")) quiet = !0; /* Get proxy environment variable. */ if((proxy = getenv("http_proxy")) != NULL) set(& rc, "proxy", proxy); /* Parse through command line options. */ while(-1 != (option = getopt(argc, argv, ":dbhqi:p:D:y:Y:"))) switch(option) { case 'd': /* Daemonize. */ background = !background; break; case 'i': /* IP to bind network interface to. */ set(& rc, "bind", optarg); break; case 'p': /* Port to listen on. */ if(atoi(optarg)) set(& rc, "port", optarg); else { fputs("Invalid port.\n", stderr); ++nerror; } break; case 'b': /* Batch mode */ batch = !0; break; case 'D': /* Path to audio device file. */ set(& rc, "device", optarg); break; case 'y': /* Proxy address. */ set(& rc, "proxy", optarg); break; case 'Y': /* SOCKS proxy address. */ set(& rc, "socks-proxy", optarg); break; case 'q': /* Quiet mode. */ quiet = !quiet; break; case 'h': /* Print help text and exit. */ help(argv[0], 0); break; case ':': fprintf(stderr, "Missing argument for option -%c.\n\n", optopt); ++nerror; break; case '?': default: fprintf(stderr, "Unknown option -%c.\n", optopt); ++nerror; break; } /* The next argument, if present, is the lastfm:// URL we want to play. */ if(optind > 0 && optind < argc && argv[optind]) { const char * station = argv[optind]; set(& rc, "default-radio", station); } if(nerror) help(argv[0], EXIT_FAILURE); #ifdef EXTERN_ONLY /* Abort if EXTERN_ONLY is defined and no extern command is present */ if(!haskey(& rc, "extern")) { fputs("Can't continue without extern command.\n", stderr); exit(EXIT_FAILURE); } #else #ifndef LIBAO if(!haskey(& rc, "device")) set(& rc, "device", "/dev/audio"); #endif #endif if(!background && !quiet) { puts("Shell.FM v" PACKAGE_VERSION ", (C) 2006-2012 by Jonas Kramer"); puts("Published under the terms of the GNU General Public License (GPL)."); #ifndef TUXBOX puts("\nPress ? for help.\n"); #else puts("Compiled for the use with Shell.FM Wrapper.\n"); #endif fflush(stdout); } /* Open a port so Shell.FM can be controlled over network. */ if(haskey(& rc, "bind")) { int port = 54311; if(haskey(& rc, "port")) port = atoi(value(& rc, "port")); if(tcpsock(value(& rc, "bind"), (unsigned short) port)) have_socket = !0; } /* Open a UNIX socket for local "remote" control. */ if(haskey(& rc, "unix") && unixsock(value(& rc, "unix"))) have_socket = !0; /* We can't daemonize if there's no possibility left to control Shell.FM. */ if(background && !have_socket) { fputs("Can't daemonize without control socket.\n", stderr); exit(EXIT_FAILURE); } memset(& data, 0, sizeof(struct hash)); memset(& track, 0, sizeof(struct hash)); memset(& playlist, 0, sizeof(struct playlist)); /* Fork to background. */ if(background) { int null; pid_t pid = fork(); if(pid == -1) { fputs("Failed to daemonize.\n", stderr); exit(EXIT_FAILURE); } else if(pid) { exit(EXIT_SUCCESS); } enable(QUIET); /* Detach from TTY */ setsid(); pid = fork(); if(pid > 0) exit(EXIT_SUCCESS); /* Close stdin out and err */ close(0); close(1); close(2); /* Redirect stdin and out to /dev/null */ null = open("/dev/null", O_RDWR); dup(null); dup(null); } ppid = getpid(); atexit(cleanup); load_queue(); /* Set up signal handlers for communication with the playback process. */ signal(SIGINT, forcequit); /* SIGUSR2 from playfork means it detected an error. */ signal(SIGUSR2, playsig); /* Catch SIGTSTP to set pausetime when user suspends us with ^Z. */ signal(SIGTSTP, stopsig); /* Authenticate to the Last.FM server. */ create_session(); if(!background) { struct input keyboard = { 0, KEYBOARD }; register_handle(keyboard); canon(0); atexit(cleanup_term); } /* Play default radio, if specified. */ if(haskey(& rc, "default-radio")) { if(!strcmp(value(& rc, "default-radio"), "last")) { char ** history = load_history(), * last = NULL, ** p; for(p = history; * p != NULL; ++p) { last = * p; } set(& rc, "default-radio", last); purge(history); } station(value(& rc, "default-radio")); } else if(!background) radioprompt("radio url> "); /* The main loop. */ while(!0) { pid_t child; int status, playnext = 0; /* Check if anything died (submissions fork or playback fork). */ while((child = waitpid(-1, & status, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { if(child == subfork) subdead(WEXITSTATUS(status)); else if(child == playfork) { if(WIFSTOPPED(status)) { /* time(& pausetime); */ } else { if(WIFCONTINUED(status)) { signal(SIGTSTP, stopsig); if(pausetime != 0) { pauselength += time(NULL) - pausetime; } } else { playnext = !0; unlinknp(); if(delayquit) { quit(); } } pausetime = 0; } } } /* Check if the playback process died. If so, submit the data of the last played track. Then check if there are tracks left in the playlist; if not, try to refresh the list and stop the stream if there are no new tracks to fetch. Also handle user stopping the stream here. We need to check for playnext != 0 before handling enabled(STOPPED) anyway, otherwise playfork would still be running. */ if(playnext) { playfork = 0; if(enabled(RTP)) { unsigned duration, played, minimum; duration = atoi(value(& track, "duration")); played = time(NULL) - change_time - pauselength; /* Allow user to specify minimum playback length (min. 50%). */ if(haskey(& rc, "minimum")) { unsigned percent = atoi(value(& rc, "minimum")); if(percent < 50) percent = 50; minimum = duration * percent / 100; } else { minimum = duration / 2; } if(duration >= 30 && (played >= 240 || played > minimum)) { debug("adding track to scrobble queue\n"); enqueue(& track); } else { debug("track too short (duration %d, played %d, minimum %d) - not scrobbling\n", duration, played, minimum); } } submit(); /* Check if the user stopped the stream. */ if(enabled(STOPPED) || error) { freelist(& playlist); empty(& track); if(error) { fputs("Playback stopped with an error.\n", stderr); error = 0; } disable(STOPPED); disable(CHANGED); continue; } shift(& playlist); } if(playnext || enabled(CHANGED)) { if(nextstation != NULL) { playnext = 0; disable(CHANGED); if(!station(nextstation)) enable(STOPPED); free(nextstation); nextstation = NULL; } if(!enabled(STOPPED) && !playlist.left) { expand(& playlist); if(!playlist.left) { puts("No tracks left."); playnext = 0; disable(CHANGED); continue; } } if(!playfork) { /* If there was a track played before, and there is a gap configured, wait that many seconds before playing the next track. */ if(playnext && !enabled(INTERRUPTED) && haskey(& rc, "gap")) { int gap = atoi(value(& rc, "gap")); if(gap > 0) sleep(gap); } disable(INTERRUPTED); if(play(& playlist)) { time(& change_time); pauselength = 0; set(& track, "stationURL", current_station); /* Print what's currently played. (Ondrej Novy) */ if(!background) { if(enabled(CHANGED) && playlist.left > 0) { puts(meta("Receiving %s.", M_COLORED, & track)); disable(CHANGED); } if(haskey(& rc, "title-format")) printf("%s\n", meta(value(& rc, "title-format"), M_COLORED, & track)); else printf("%s\n", meta("Now playing \"%t\" by %a.", M_COLORED, & track)); } if(enabled(RTP)) { notify_now_playing(& track); } /* Write track data into a file. */ if(haskey(& rc, "np-file") && haskey(& rc, "np-file-format")) { signed np; const char * file = value(& rc, "np-file"), * fmt = value(& rc, "np-file-format"); unlink(file); if(-1 != (np = open(file, O_WRONLY | O_CREAT, 0644))) { const char * output = meta(fmt, 0, & track); if(output) write(np, output, strlen(output)); close(np); } } if(haskey(& rc, "screen-format")) { const char * term = getenv("TERM"); if(term != NULL && !strncmp(term, "screen", 6)) { const char * output = meta(value(& rc, "screen-format"), 0, & track); printf("\x1Bk%s\x1B\\", output); } } if(haskey(& rc, "term-format")) { const char * output = meta(value(& rc, "term-format"), 0, & track); printf("\x1B]2;%s\a", output); } /* Run a command with our track data. */ if(haskey(& rc, "np-unescaped-cmd")) run(meta(value(& rc, "np-unescaped-cmd"), 0, & track)); if(haskey(& rc, "np-cmd")) run(meta(value(& rc, "np-cmd"), M_SHELLESC, & track)); } else change_time = 0; } if(banned(value(& track, "creator"))) { puts(meta("%a is banned.", M_COLORED, & track)); rate(RATING_BAN); fflush(stdout); } } playnext = 0; if(playfork && change_time && haskey(& track, "duration") && !pausetime) { unsigned duration; signed remain; char remstr[32]; duration = atoi(value(& track, "duration")); remain = (change_time + duration) - time(NULL) + pauselength; snprintf(remstr, sizeof(remstr), "%d", remain); set(& track, "remain", remstr); if(!background) { printf( "%s%c", meta("%r", M_COLORED, & track), // strdup(meta("%v", M_COLORED, & track)), batch ? '\n' : '\r' ); fflush(stdout); } } handle_input(1000000); } return 0; }