示例#1
1
文件: kernel.c 项目: LolHens/mikrOS
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;
}
示例#2
0
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;
}
示例#3
0
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);
}
示例#4
0
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;
}
示例#5
0
文件: main.c 项目: jiaju707/shell-fm
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;
}