Example #1
0
bool mod_query_init()
{
    if(!mod_query_register_exports())
        goto err;
    
    mod_query_input_bindmap=ioncore_alloc_bindmap("WInput", NULL);
    mod_query_wedln_bindmap=ioncore_alloc_bindmap("WEdln", NULL);
    
    if(mod_query_wedln_bindmap==NULL ||
       mod_query_input_bindmap==NULL){
        goto err;
    }

    /*ioncore_read_config("cfg_query", NULL, TRUE);*/

    load_history();
    
    loaded_ok=TRUE;

    hook_add(ioncore_snapshot_hook, save_history);
    
    return TRUE;
    
err:
    mod_query_deinit();
    return FALSE;
}
Example #2
0
static int cmd_loop(int in_argc, const char *in_argv[])
{
	int argc;
	char *input, **argv;
	int quit = 0;
	char *history_path;

	history_path = load_history();

	while (!quit) {

		input = readline("> ");
		append_history(history_path, input);

		if ((tokenize_command_line(input, &argc, &argv) == -1) || argc < 1) {
			free(input);
			continue;
		}

		int cmd = str_to_cmd(argv[0]);
		if (cmd == CMD_UNKNOWN || CMD_INTERACTIVE) {
			warnx("'%s': unknown command", argv[0]);
			free(argv);
			free(input);
			continue;
		}

		do_cmd(cmd, --argc, (const char **) ++argv);

		free(--argv);
		free(input);
	}

	return AFC_E_SUCCESS;
}
Example #3
0
void history_add(history_t *ph, char *string)
{
	if (ph -> history_size > 0)
	{
		int loop;
		int found = -1;

		load_history(ph);

		/* bail out if this string is already in the history */
		for(loop=0; loop<ph -> history_size; loop++)
		{
			if ((ph -> history)[loop] != NULL && strcmp((ph -> history)[loop], string) == 0)
				return ;
		}

		/* find free spot */
		found = history_find_null_entry(ph);

		/* when no free spot was found, free-up an entry */
		if (found == -1)
		{
			myfree((ph -> history)[ph -> history_size - 1]);

			memmove(&(ph -> history)[1], &(ph -> history)[0], sizeof(char *) * (ph -> history_size - 1));

			found = 0;
		}

		(ph -> history)[found] = mystrdup(string);

		save_history(ph);
	}
}
Example #4
0
//------------------------------------------------------------------------------
static int startup_hook()
{
    static int initialised = 0;
    if (!initialised)
    {
        // This is a bit of a hack. Ideally we should take care of this in
        // the termcap functions.
        _rl_term_forward_char = "\013";
        _rl_term_clreol = "\001";

        rl_redisplay_function = display;
        rl_getc_function = getc_impl;

        rl_completer_quote_characters = "\"";
        rl_ignore_some_completions_function = postprocess_matches;
        rl_basic_word_break_characters = " <>|";
        rl_completer_word_break_characters = " <>|";
        rl_completion_display_matches_hook = display_matches;
        rl_attempted_completion_function = alternative_matches;

        rl_add_funmap_entry("clink-completion-shim", completion_shim);
        rl_add_funmap_entry("clear-line", clear_line);
        rl_add_funmap_entry("paste-from-clipboard", paste_from_clipboard);

        initialise_lua();
        load_history();
        rl_re_read_init_file(0, 0);
        rl_visible_stats = 0;               // serves no purpose under win32.

        initialised = 1;
    }
    
    return 0;
}
Example #5
0
static void load_new(void) {
	char hgz[256];

	sprintf(hgz, "%s.gz.new", history_fn);
	if (load_history(hgz) >= 0) save(0);
	unlink(hgz);
}
Example #6
0
/* Try loading from the backup versions.
 * We'll try from oldest to newest, then
 * retry the requested one again last.  In case the drive mounts while
 * we are trying to find a good version.
 */
static int try_hardway(const char *fname) {
	char fn[256];
	int n, b, found = 0;

	strcpy(fn, fname);
	n = strlen(fn);
	if ((n > 3) && (strcmp(fn + (n - 3), ".gz") == 0))
		n -= 3;
	for (b = HI_BACK; b > 0; --b) {
		sprintf(fn + n, "_%d.bak", b);
		found |= load_history(fn);
	}
	found |= load_history(fname);

	return found;
}
Example #7
0
int main(int argc, char *argv[])
{
	struct sysinfo si;
	long z;
	struct sigaction sa;

	printf("rstats\nCopyright (C) 2006 Jonathan Zarate\n\n");
	
	if (fork() != 0) return 0;

	openlog("rstats", LOG_PID, LOG_USER);
	
	sa.sa_handler = sig_handler;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	sigaction(SIGUSR1, &sa, NULL);
	sigaction(SIGUSR2, &sa, NULL);
	sigaction(SIGHUP, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);

	sysinfo(&si);
	z = si.uptime;

	load(si.uptime);
	
	while (1) {
		while (si.uptime < z) {
			sleep(z - si.uptime);
			if (gothup) {
				if (unlink("/var/tmp/rstats-reload") == 0) {
					load_history();
				}
				else {
					save(0);
				}
				gothup = 0;
			}
			if (gotterm) {
				save(1);
				exit(0);
			}
			if (gotuser == 1) {
				save_speedjs();
				gotuser = 0;
			}
			else if (gotuser == 2) {
				save_histjs();
				gotuser = 0;
			}
			sysinfo(&si);
		}
		calc(si.uptime);
		z += INTERVAL;
	}

	return 0;
}
Example #8
0
// line must be freed by caller
char *_readline (char prompt[]) {
    char *line;

    load_history();

    line = readline(prompt);
    if (!line) return NULL; // EOF
    add_history(line); // Add input to in-memory history

    append_to_history(); // Flush new line of history to disk

    return line;
}
Example #9
0
char * search_history(history_t *ph, char *search_string)
{
	if (ph -> history_size > 0)
	{
		int n_entries, free_entry;

		load_history(ph);

		free_entry = history_find_null_entry(ph);
		n_entries = free_entry == -1 ? ph -> history_size : free_entry;

		if (n_entries > 0)
		{
			int sel_index = selection_box((void **)ph -> history, NULL, n_entries, SEL_HISTORY, HELP_HISTORY, NULL);

			if (sel_index >= 0)
				return mystrdup((ph -> history)[sel_index]);
		}
		else
			error_popup("Search history", -1, "The history list is empty.");
	}

	return NULL;
}
Example #10
0
/* Returns:
 * -1 on read errors or EOF, or on bare Ctrl-D.
 * 0  on ctrl-C,
 * >0 length of input string, including terminating '\n'
 */
int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st)
{
	int lastWasTab = FALSE;
	unsigned int ic;
	unsigned char c;
	smallint break_out = 0;
#if ENABLE_FEATURE_EDITING_VI
	smallint vi_cmdmode = 0;
	smalluint prevc;
#endif

	if (maxsize > MAX_LINELEN)
		maxsize = MAX_LINELEN;

	/* With null flags, no other fields are ever used */
	state = st ? st : (line_input_t*) &const_int_0;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
	if ((state->flags & SAVE_HISTORY) && state->hist_file)
		load_history(state->hist_file);
#endif

	/* prepare before init handlers */
	cmdedit_y = 0;  /* quasireal y, not true if line > xt*yt */
	command_len = 0;
	command_ps = command;
	command[0] = '\0';

	getTermSettings(0, (void *) &initial_settings);
	memcpy(&new_settings, &initial_settings, sizeof(new_settings));
	new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
	/* Turn off echoing and CTRL-C, so we can trap it */
	new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
	/* Hmm, in linux c_cc[] is not parsed if ICANON is off */
	new_settings.c_cc[VMIN] = 1;
	new_settings.c_cc[VTIME] = 0;
	/* Turn off CTRL-C, so we can trap it */
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE '\0'
#endif
	new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
	setTermSettings(0, (void *) &new_settings);

	/* Now initialize things */
	previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
	win_changed(0); /* do initial resizing */
#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
	{
		struct passwd *entry;

		entry = getpwuid(geteuid());
		if (entry) {
			/* If we enter read_line_input for the Nth time,
			 * they may be already allocated! Need to free. */
			free(user_buf);
			if (home_pwd_buf != null_str)
				free(home_pwd_buf);
			user_buf = xstrdup(entry->pw_name);
			home_pwd_buf = xstrdup(entry->pw_dir);
			/* They are not freed on exit (too small to bother) */
		}
	}
#endif
	/* Print out the command prompt */
	parse_prompt(prompt);

	while (1) {
		fflush(stdout);

		if (safe_read(0, &c, 1) < 1) {
			/* if we can't read input then exit */
			goto prepare_to_die;
		}

		ic = c;

#if ENABLE_FEATURE_EDITING_VI
		newdelflag = 1;
		if (vi_cmdmode)
			ic |= vbit;
#endif
		switch (ic) {
		case '\n':
		case '\r':
		vi_case('\n'|vbit:)
		vi_case('\r'|vbit:)
			/* Enter */
			goto_new_line();
			break_out = 1;
			break;
#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('A'):
		vi_case('0'|vbit:)
			/* Control-a -- Beginning of line */
			input_backward(cursor);
			break;
		case CTRL('B'):
		vi_case('h'|vbit:)
		vi_case('\b'|vbit:)
		vi_case('\x7f'|vbit:) /* DEL */
			/* Control-b -- Move back one character */
			input_backward(1);
			break;
#endif
		case CTRL('C'):
		vi_case(CTRL('C')|vbit:)
			/* Control-c -- stop gathering input */
			goto_new_line();
			command_len = 0;
			break_out = -1; /* "do not append '\n'" */
			break;
		case CTRL('D'):
			/* Control-d -- Delete one character, or exit
			 * if the len=0 and no chars to delete */
			if (command_len == 0) {
				errno = 0;
 prepare_to_die:
				/* to control stopped jobs */
				break_out = command_len = -1;
				break;
			}
			input_delete(0);
			break;

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('E'):
		vi_case('$'|vbit:)
			/* Control-e -- End of line */
			input_end();
			break;
		case CTRL('F'):
		vi_case('l'|vbit:)
		vi_case(' '|vbit:)
			/* Control-f -- Move forward one character */
			input_forward();
			break;
#endif

		case '\b':
		case '\x7f': /* DEL */
			/* Control-h and DEL */
			input_backspace();
			break;

		case '\t':
			input_tab(&lastWasTab);
			break;

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('K'):
			/* Control-k -- clear to end of line */
			command[cursor] = 0;
			command_len = cursor;
			printf("\033[J");
			break;
		case CTRL('L'):
		vi_case(CTRL('L')|vbit:)
			/* Control-l -- clear screen */
			printf("\033[H");
			redraw(0, command_len - cursor);
			break;
#endif

#if MAX_HISTORY > 0
		case CTRL('N'):
		vi_case(CTRL('N')|vbit:)
		vi_case('j'|vbit:)
			/* Control-n -- Get next command in history */
			if (get_next_history())
				goto rewrite_line;
			break;
		case CTRL('P'):
		vi_case(CTRL('P')|vbit:)
		vi_case('k'|vbit:)
			/* Control-p -- Get previous command from history */
			if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
				get_previous_history();
				goto rewrite_line;
			}
			beep();
			break;
#endif

#if ENABLE_FEATURE_EDITING_FANCY_KEYS
		case CTRL('U'):
		vi_case(CTRL('U')|vbit:)
			/* Control-U -- Clear line before cursor */
			if (cursor) {
				strcpy(command, command + cursor);
				command_len -= cursor;
				redraw(cmdedit_y, command_len);
			}
			break;
#endif
		case CTRL('W'):
		vi_case(CTRL('W')|vbit:)
			/* Control-W -- Remove the last word */
			while (cursor > 0 && isspace(command[cursor-1]))
				input_backspace();
			while (cursor > 0 && !isspace(command[cursor-1]))
				input_backspace();
			break;

#if ENABLE_FEATURE_EDITING_VI
		case 'i'|vbit:
			vi_cmdmode = 0;
			break;
		case 'I'|vbit:
			input_backward(cursor);
			vi_cmdmode = 0;
			break;
		case 'a'|vbit:
			input_forward();
			vi_cmdmode = 0;
			break;
		case 'A'|vbit:
			input_end();
			vi_cmdmode = 0;
			break;
		case 'x'|vbit:
			input_delete(1);
			break;
		case 'X'|vbit:
			if (cursor > 0) {
				input_backward(1);
				input_delete(1);
			}
			break;
		case 'W'|vbit:
			vi_Word_motion(command, 1);
			break;
		case 'w'|vbit:
			vi_word_motion(command, 1);
			break;
		case 'E'|vbit:
			vi_End_motion(command);
			break;
		case 'e'|vbit:
			vi_end_motion(command);
			break;
		case 'B'|vbit:
			vi_Back_motion(command);
			break;
		case 'b'|vbit:
			vi_back_motion(command);
			break;
		case 'C'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'D'|vbit:
			goto clear_to_eol;

		case 'c'|vbit:
			vi_cmdmode = 0;
			/* fall through */
		case 'd'|vbit: {
			int nc, sc;
			sc = cursor;
			prevc = ic;
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == (prevc & 0xff)) {
				/* "cc", "dd" */
				input_backward(cursor);
				goto clear_to_eol;
				break;
			}
			switch (c) {
			case 'w':
			case 'W':
			case 'e':
			case 'E':
				switch (c) {
				case 'w':   /* "dw", "cw" */
					vi_word_motion(command, vi_cmdmode);
					break;
				case 'W':   /* 'dW', 'cW' */
					vi_Word_motion(command, vi_cmdmode);
					break;
				case 'e':   /* 'de', 'ce' */
					vi_end_motion(command);
					input_forward();
					break;
				case 'E':   /* 'dE', 'cE' */
					vi_End_motion(command);
					input_forward();
					break;
				}
				nc = cursor;
				input_backward(cursor - sc);
				while (nc-- > cursor)
					input_delete(1);
				break;
			case 'b':  /* "db", "cb" */
			case 'B':  /* implemented as B */
				if (c == 'b')
					vi_back_motion(command);
				else
					vi_Back_motion(command);
				while (sc-- > cursor)
					input_delete(1);
				break;
			case ' ':  /* "d ", "c " */
				input_delete(1);
				break;
			case '$':  /* "d$", "c$" */
			clear_to_eol:
				while (cursor < command_len)
					input_delete(1);
				break;
			}
			break;
		}
		case 'p'|vbit:
			input_forward();
			/* fallthrough */
		case 'P'|vbit:
			put();
			break;
		case 'r'|vbit:
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			if (c == 0)
				beep();
			else {
				*(command + cursor) = c;
				putchar(c);
				putchar('\b');
			}
			break;
#endif /* FEATURE_COMMAND_EDITING_VI */

		case '\x1b': /* ESC */

#if ENABLE_FEATURE_EDITING_VI
			if (state->flags & VI_MODE) {
				/* ESC: insert mode --> command mode */
				vi_cmdmode = 1;
				input_backward(1);
				break;
			}
#endif
			/* escape sequence follows */
			if (safe_read(0, &c, 1) < 1)
				goto prepare_to_die;
			/* different vt100 emulations */
			if (c == '[' || c == 'O') {
		vi_case('['|vbit:)
		vi_case('O'|vbit:)
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
			}
			if (c >= '1' && c <= '9') {
				unsigned char dummy;

				if (safe_read(0, &dummy, 1) < 1)
					goto prepare_to_die;
				if (dummy != '~')
					c = '\0';
			}

			switch (c) {
#if ENABLE_FEATURE_TAB_COMPLETION
			case '\t':                      /* Alt-Tab */
				input_tab(&lastWasTab);
				break;
#endif
#if MAX_HISTORY > 0
			case 'A':
				/* Up Arrow -- Get previous command from history */
				if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
					get_previous_history();
					goto rewrite_line;
				}
				beep();
				break;
			case 'B':
				/* Down Arrow -- Get next command in history */
				if (!get_next_history())
					break;
 rewrite_line:
				/* Rewrite the line with the selected history item */
				/* change command */
				command_len = strlen(strcpy(command, state->history[state->cur_history]));
				/* redraw and go to eol (bol, in vi */
				redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
				break;
#endif
			case 'C':
				/* Right Arrow -- Move forward one character */
				input_forward();
				break;
			case 'D':
				/* Left Arrow -- Move back one character */
				input_backward(1);
				break;
			case '3':
				/* Delete */
				input_delete(0);
				break;
			case '1': // vt100? linux vt? or what?
			case '7': // vt100? linux vt? or what?
			case 'H': /* xterm's <Home> */
				input_backward(cursor);
				break;
			case '4': // vt100? linux vt? or what?
			case '8': // vt100? linux vt? or what?
			case 'F': /* xterm's <End> */
				input_end();
				break;
			default:
				c = '\0';
				beep();
			}
			break;

		default:        /* If it's regular input, do the normal thing */
#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
			/* Control-V -- Add non-printable symbol */
			if (c == CTRL('V')) {
				if (safe_read(0, &c, 1) < 1)
					goto prepare_to_die;
				if (c == 0) {
					beep();
					break;
				}
			} else
#endif

#if ENABLE_FEATURE_EDITING_VI
			if (vi_cmdmode)  /* Don't self-insert */
				break;
#endif
			if (!Isprint(c)) /* Skip non-printable characters */
				break;

			if (command_len >= (maxsize - 2))        /* Need to leave space for enter */
				break;

			command_len++;
			if (cursor == (command_len - 1)) {      /* Append if at the end of the line */
				command[cursor] = c;
				command[cursor+1] = '\0';
				cmdedit_set_out_char(' ');
			} else {                        /* Insert otherwise */
				int sc = cursor;

				memmove(command + sc + 1, command + sc, command_len - sc);
				command[sc] = c;
				sc++;
				/* rewrite from cursor */
				input_end();
				/* to prev x pos + 1 */
				input_backward(cursor - sc);
			}
			break;
		}
		if (break_out)                  /* Enter is the command terminator, no more input. */
			break;

		if (c != '\t')
			lastWasTab = FALSE;
	}
Example #11
0
File: rl.c Project: HTshandou/clink
//------------------------------------------------------------------------------
static char* call_readline_impl(const char* prompt)
{
    static int initialised = 0;
    int expand_result;
    char* text;
    char* expanded;
    char* prepared_prompt;
    char cwd_cache[MAX_PATH];

    // Initialisation
    if (!initialised)
    {
        initialise_clink_settings();
        initialise_lua();
        load_history();

        rl_catch_signals = 0;
        rl_startup_hook = initialise_hook;
        initialised = 1;
    }

    // If no prompt was provided assume the line is prompted already and
    // extract it. If a prompt was provided filter it through Lua.
    prepared_prompt = NULL;
    if (prompt == NULL)
    {
        prepared_prompt = extract_prompt(1);

        // Even though we're not going to display filtered result the extracted
        // prompt is run through Lua. This is a little bit of a hack, but helps
        // to keep behaviour consistent.
        if (prepared_prompt != NULL)
        {
            char buffer[1024];

            str_cpy(buffer, prepared_prompt, sizeof(buffer));
            lua_filter_prompt(buffer, sizeof_array(buffer));
        }
    }
    else
    {
        prepared_prompt = filter_prompt(prompt);
    }

    GetCurrentDirectory(sizeof_array(cwd_cache), cwd_cache);

    // Call readline
    do
    {
        rl_already_prompted = (prompt == NULL);
        text = readline(prepared_prompt ? prepared_prompt : "");
        if (!text)
        {
            goto call_readline_epilogue;
        }

        // Expand history designators in returned buffer.
        expanded = NULL;
        expand_result = history_expand(text, &expanded);
        if (expand_result < 0)
        {
            free(expanded);
        }
        else
        {
            free(text);
            text = expanded;

            // If there was some expansion then display the expanded result.
            if (expand_result > 0)
            {
                hooked_fprintf(NULL, "History expansion: %s\n", text);
            }
        }

        add_to_history(text);
    }
    while (!text || expand_result == 2);

call_readline_epilogue:
    free_prompt(prepared_prompt);
    SetCurrentDirectory(cwd_cache);
    return text;
}
Example #12
0
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;
}
Example #13
0
File: rl.c Project: Tafhim/clink
//------------------------------------------------------------------------------
static char* call_readline_impl(const char* prompt)
{
    static int initialised = 0;
    int expand_result;
    char* text;
    char* expanded;
    char* prepared_prompt;
    char cwd_cache[MAX_PATH];

    // Turn off EOL wrapping as Readline will take care of it.
    {
        HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleMode(handle_stdout, ENABLE_PROCESSED_OUTPUT);
    }

    // Initialisation
    if (!initialised)
    {
        initialise_clink_settings();
        initialise_lua();
        initialise_fwrite();

        load_history();
        history_inhibit_expansion_function = history_expand_control;

        rl_catch_signals = 0;
        rl_startup_hook = initialise_hook;
        initialised = 1;
    }

    // If no prompt was provided assume the line is prompted already and
    // extract it. If a prompt was provided filter it through Lua.
    prepared_prompt = NULL;
    if (prompt == NULL)
    {
        prepared_prompt = extract_prompt(1);

        // Even though we're not going to display filtered result the extracted
        // prompt is run through Lua. This is a little bit of a hack, but helps
        // to keep behaviour consistent.
        if (prepared_prompt != NULL)
        {
            char buffer[1024];

            str_cpy(buffer, prepared_prompt, sizeof(buffer));
            lua_filter_prompt(buffer, sizeof_array(buffer));
        }
    }
    else
    {
        prepared_prompt = filter_prompt(prompt);
    }

    GetCurrentDirectory(sizeof_array(cwd_cache), cwd_cache);

    do
    {
        // Call readline
        rl_already_prompted = (prompt == NULL);
        text = readline(prepared_prompt ? prepared_prompt : "");
        if (!text)
        {
            goto call_readline_epilogue;
        }

        // Expand history designators in returned buffer.
        expanded = NULL;
        expand_result = expand_from_history(text, &expanded);
        if (expand_result > 0 && expanded != NULL)
        {
            free(text);
            text = expanded;

            // If there was some expansion then display the expanded result.
            if (expand_result > 0)
            {
                hooked_fprintf(NULL, "History expansion: %s\n", text);
            }
        }

        // Should we read the history from disk.
        if (get_clink_setting_int("history_io"))
        {
            load_history();
            add_to_history(text);
            save_history();
        }
        else
            add_to_history(text);
    }
    while (!text || expand_result == 2);

call_readline_epilogue:
    free_prompt(prepared_prompt);
    SetCurrentDirectory(cwd_cache);
    return text;
}
Example #14
0
static void load(long uptime)
{
	int i;
	long t;
	char *bi, *bo;
	int n;
	char hgz[256];
	unsigned char mac[6];

	strlcpy(save_path, nvram_safe_get("rstats_path"), sizeof(save_path) - 32);
	if (((n = strlen(save_path)) > 0) && (save_path[n - 1] == '/')) {
		ether_atoe(nvram_safe_get("et0macaddr"), mac);
		sprintf(save_path + n, "ddwrt_rstats_%02x%02x%02x%02x%02x%02x.gz",
			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	}

	if (f_read("/var/lib/misc/rstats-stime", &save_utime, sizeof(save_utime)) != sizeof(save_utime)) {
		save_utime = 0;
	}
	t = uptime + get_stime();
	if ((save_utime < uptime) || (save_utime > t)) save_utime = t;
	_dprintf("uptime = %dm, save_utime = %dm\n", uptime / 60, save_utime / 60);

	speed_count = decomp(speed_fn, speed, sizeof(speed[0]), MAX_SPEED_IF);
	_dprintf("load speed_count = %d\n", speed_count);
	
	if ((load_history()) || (save_path[0] == 0)) return;

	sprintf(hgz, "%s.gz", history_fn);

	if (strcmp(save_path, "*nvram") == 0) {
		if (!wait_action_idle(60)) exit(0);
		
		bi = nvram_safe_get("rstats_data");
		if ((n = strlen(bi)) > 0) {
			if ((bo = malloc(base64_decoded_len(n))) != NULL) {
				n = base64_decode(bi, bo, n);
				f_write(hgz, bo, n, 0, 0);
				free(bo);
				_dprintf("from nvram = %d\n", n);
			}
		}
	}
	else {
		for (i = 30; i > 0; --i) {
			if (!wait_action_idle(60)) exit(0);

			_dprintf("copy %s to %s\n", save_path, hgz);
			if (eval("cp", save_path, hgz) == 0) break;

			// not ready...
			sleep(3);
		}
		if (i == 0) {
			save_utime = uptime + 60;
			_dprintf("forcing early save on next\n");
		}
	}

	load_history();
}