示例#1
0
kdldap_servers *kdldap_servers_new(apr_pool_t *pool, int use_sasl) {
    apr_pool_t *obj_pool;
    kdldap_servers *self;
    const char *ldap_dom, *ldap_ad_site;

    apr_pool_create(&obj_pool, pool);

    self = apr_pcalloc(obj_pool, sizeof(kdldap_servers));
    self->use_sasl = use_sasl;

    /* Get the AD forest to query. */
    ldap_dom = options_get_str("ldap.domain");
    if (ldap_dom == NULL || strlen(ldap_dom) == 0) 
        self->ad_forest = NULL;
    else
        self->ad_forest = apr_pstrdup(obj_pool, ldap_dom);

    ldap_ad_site = options_get_str("ldap.ad_site");
    if (ldap_ad_site == NULL || strlen(ldap_ad_site) == 0)
        self->ad_site = NULL;
    else
        self->ad_site = apr_pstrdup(obj_pool, ldap_ad_site);

    /* Check if we were told to search in the DNS. */
    if (!self->ad_forest || options_get_bool("ldap.domain_search") <= 0) {
        WARN(_log_ldap_, "LDAP server search will use static server list.");
        self->use_dns = 0;
    } else
        self->use_dns = 1;

    if (self->use_dns) {
        if ((self->ad_forest && self->use_dns) && !self->ad_site)
            WARN(_log_ldap_, "No AD site defined.  LDAP server queries will be done forest-wide.");
        else
            INFO(_log_ldap_, "AD site: %s.", self->ad_site);
    }

    /* Parse the static server list. */
    if (!self->use_dns) {
        if (kdldap_servers_load_static_servers(self, obj_pool, &self->static_ldap_servers) < 0) {
            KERROR_PUSH(_ldap_, 0, "error loading static LDAP server list");
            apr_pool_destroy(obj_pool);
            return NULL;
        }
    }
    else {
        /* ADNS initialization. */
        if (adns_init(&self->adns_state, adns_if_noenv, 0)) {
            self->adns_init = 0;
            KERROR_SET(_ldap_, 0, "cannot initialize adns");
            apr_pool_destroy(obj_pool);
            return NULL;
        } else
            self->adns_init = 1;    
    }

    apr_pool_cleanup_register(obj_pool, self, kdldap_servers_cleanup, kdldap_servers_cleanup);

    return self;
}
示例#2
0
文件: server.c 项目: jonsafari/mocp
/* Handle running external command on Stop event. */
static void on_stop ()
{
	char *command;

	command = xstrdup (options_get_str("OnStop"));

	if (command) {
		char *args[2], *err;

		args[0] = xstrdup (command);
		args[1] = NULL;

		switch (fork()) {
			case 0:
				execve (command, args, environ);
				exit (EXIT_FAILURE);
			case -1:
				err = xstrerror (errno);
				logit ("Error when running OnStop command '%s': %s",
				        command, err);
				free (err);
				break;
		}

		free (command);
		free (args[0]);
	}
}
示例#3
0
文件: main.c 项目: fdgonthier/tbxsosd
/** Initialize the logging drivers and options. */
static void kd_init_logging() {
    int i;
    int is_filtered;    
    char buf[256];
    char *ce, *channel, *last;
    const char *log_chan_enabled;
    const char *log_driver;
    const char log_driver_fmt[] = "log_%s.driver";
    const char log_filtered_fmt[] = "log_%s.filter";
    /* Order matters here.  This is the order of the LOG_* constants
       found in /usr/include/sys/syslog.h. */
    const char *log_levels[] = {"emergency", 
                                "alert",
                                "critical", 
                                "error",
                                "warning",
                                "notice",
                                "info",
                                "debug", 
                                NULL};
    
    /* Configure the basic log levels. */
    for (i = 0; log_levels[i] != NULL; i++) {        
        /* Read the log driver.  If none was provided, we use the null
           driver. */
        sprintf(buf, log_driver_fmt, log_levels[i]);
        log_driver = options_get_str(buf);

        /* Check if the level needs to be filtered.  If the value was
           not provided we default to no. */        
        sprintf(buf, log_filtered_fmt, log_levels[i]);
        is_filtered = options_get_bool(buf);

        log_set_level(i, log_driver, is_filtered);
    }

    /* Configure the enabled channels. */
    log_chan_enabled = options_get_str("log_channel.enabled");
    if (strcmp(log_chan_enabled, "") == 0) return;
    ce = strdup(log_chan_enabled);
    
    for (channel = apr_strtok(ce, " ", &last); 
         channel != NULL;
         channel = apr_strtok(NULL, " ", &last)) 
        log_enable_channel(channel);
    free(ce);
}
示例#4
0
文件: db.c 项目: fdgonthier/tbxsosd
/** Connect a single database. */
static kdsql *kddb_connect_db(apr_pool_t *pool, enum kddb_auth_mode auth_mode) {
    kdsql *conn;

    /* Connect to the database. */
    conn = kdsql_new(pool);    
    conn->db_host = options_get_str("db.host");

    switch (auth_mode) {
    case DB_AUTH_CURRENT_CREDS_MODE: {
        apr_uid_t uid;
        apr_gid_t gid;
        char *username;

        DEBUG(_log_db_, "Connecting using current username.");

        apr_uid_current(&uid, &gid, pool);
        apr_uid_name_get(&username, uid, pool);

        conn->db_username = username;
        conn->db_password = "";
        break;
    }

    case DB_AUTH_ADMIN_MODE:
        DEBUG(_log_db_, "Connecting to %s using administrator username/password.", conn->db_host);
        conn->db_username = options_get_str("db.admin_username");
        conn->db_password = options_get_str("db.admin_password");
        break;

    case DB_AUTH_NORMAL_MODE:
        DEBUG(_log_db_, "Connecting to %s using normal username/password.", conn->db_host);
        conn->db_username = options_get_str("db.username");
        conn->db_password = options_get_str("db.password");
        break;
    }

    conn->db_name = "tbxsosd_db";
    conn->db_port = options_get_uint16("db.port");
    conn->db_timeout = options_get_uint32("db.timeout");
    
    if (kdsql_connect(conn) < 0) 
        return NULL;

    return conn;
}
示例#5
0
/** Load the statically defined list of servers in the LDAP config. */
static int kdldap_servers_load_static_servers(kdldap_servers *self,
                                              apr_pool_t *pool, 
                                              kdldap_servers_list **srv_lst) {
    size_t i, max;
    char *hosts, *host = NULL, *port_str = NULL;
    apr_pool_t *lst_pool;
    const char *cfg_hosts;

    apr_pool_create(&lst_pool, pool);

    self->static_ldap_servers = kdldap_servers_list_new(lst_pool); 
    cfg_hosts = options_get_str("ldap.host");
    hosts = apr_pstrdup(lst_pool, cfg_hosts);
    max = strlen(hosts);

    for (i = 0; i <= max; i++) {
        int is_whitespace = (hosts[i] == ' ' || hosts[i] == '\n' || hosts[i] == '\0');

        /* Start of new host. */
        if (host == NULL && port_str == NULL && !is_whitespace) 
            host = &hosts[i];

        /* Start of port. */
        else if (host != NULL && port_str == NULL && hosts[i - 1] == ':') {
            port_str = &hosts[i];
            hosts[i - 1] = '\0';
        }

        /* End of host:port. */
        if (host != NULL && port_str != NULL && is_whitespace) {
            int port;

            hosts[i] = '\0';
               
            port = strtoimax(port_str, NULL, 10);
            if (port == 0) {
                KERROR_SET(_ldap_, 0, "invalid port: %s", port_str);
                apr_pool_destroy(lst_pool);
                *srv_lst = NULL;
                return -1;
            }
            
            kdldap_servers_list_add(*srv_lst, host, port);
            host = NULL;
            port_str = NULL;
        }
    }             

    return 0;
}
示例#6
0
文件: main.c 项目: fdgonthier/tbxsosd
static void kd_spawn_save_pid_file(pid_t child_pid) {
    FILE *pidf;
    const char *config_pid_file;
   
    /* Get the run data path. */
    config_pid_file = options_get_str("server.pid_file");

    /* Create the PID if the option specifiying the path to the
       PID file was provided. */     
    if ((pidf = fopen(config_pid_file, "w")) != NULL) {
        fprintf(pidf, "%u", child_pid);
        fclose(pidf);
    }
    else ERROR(_log_server_, "Failed to open PID file.");
}
示例#7
0
文件: common.c 项目: gitkaste/moc
/* Return path to a file in MOC config directory. NOT THREAD SAFE */
char *create_file_name (const char *file)
{
	char *home_dir;
	static char fname[PATH_MAX];
	char *moc_dir = options_get_str ("MOCDir");
	
	if (moc_dir[0] == '~') {
		if (!(home_dir = getenv("HOME")))
			fatal ("No HOME environmential variable.");
		if (snprintf(fname, sizeof(fname), "%s/%s/%s", home_dir,
				(moc_dir[1] == '/') ? moc_dir + 2 : moc_dir + 1,
				file)
				>= (int)sizeof(fname))
			fatal ("Path too long.");
	}
	else if (snprintf(fname, sizeof(fname), "%s/%s", moc_dir, file)
			>= (int)sizeof(fname))
		fatal ("Path too long.");

	return fname;
}
示例#8
0
文件: themes.c 项目: Niarfe/mocp
void theme_init (bool has_xterm)
{
	reset_colors_table ();

	if (has_colors()) {
		if (options_get_str("ForceTheme"))
			load_color_theme (options_get_str("ForceTheme"), 1);
		else if (has_xterm && options_get_str("XTermTheme"))
			load_color_theme (options_get_str("XTermTheme"), 1);
		else if (options_get_str("Theme"))
			load_color_theme (options_get_str("Theme"), 1);

		set_default_colors ();
	}
	else
		set_bw_colors ();
}
示例#9
0
文件: main.c 项目: fdgonthier/tbxsosd
/** Displays command line options. */
static void kd_options_print() {
    int p, v;
    const char *d;

    p = options_get_uint16("server.port");
    v = options_get_uint32("server.log_verbosity");
    d = options_get_str("server.log_driver");

    printf("Usage: tbxsosd [OPTIONS] \n\n"                             \
           "Options: \n"                                              \
           "   -V                Print version information \n");
    
    printf("   -D                Debug mode, don't fork nor detach, and log to stderr.\n");
    printf("   -p                Listen on this port (defaults to: %d) \n", p);
    printf("   -v                Output verbosity level (defaults to: %d) \n", v);
    
    printf("   -d                Fork the server in the background.");

    if (strlen(d) != 0) 
        printf(" (enabled) \n");
    else   
        printf(" (disabled) \n");
}
示例#10
0
文件: keys.c 项目: fdgonthier/tbxsosd
/** Initialize common data for the kdkey object. */
int kdkey_static_init() {
    kbuffer buf, mk_buf, lk_buf;
    kstr str;
    int err;

    master_pkey_info.data = master_pkey_str;
    master_pkey_info.data_s = strlen(master_pkey_str);

    license_pkey_info.data = license_pkey_str;
    license_pkey_info.data_s = strlen(license_pkey_str);

    do {
        /* Load the master public key. */
        kstr_init_cstr(&str, master_pkey_str);
        kbuffer_init_b64(&mk_buf, &str);
        kstr_clean(&str);
        master_pkey_info.key = tagcrypt_pkey_new(&mk_buf, KEY_TYPE_MASTER);

        /* Load the license public key. */
        kstr_init_cstr(&str, license_pkey_str);
        kbuffer_init_b64(&lk_buf, &str);
        kstr_clean(&str);
        license_pkey_info.key = tagcrypt_pkey_new(&lk_buf, KEY_TYPE_MASTER);

        kbuffer_clean(&lk_buf);
        kbuffer_clean(&mk_buf);

#ifdef REQUEST_GETSIG
        tm_pkey_str = options_get_str("keysign.public");
        tm_skey_str = options_get_str("keysign.private");

        tm_pkey_info.data = tm_pkey_str;
        tm_pkey_info.data_s = strlen(tm_pkey_str);
        tm_skey_info.data = tm_skey_str;
        tm_skey_info.data_s = strlen(tm_skey_str);

        kstr_init_buf(&str, tm_skey_info.data, tm_skey_info.data_s);
        err = kbuffer_init_b64(&buf, &str);
        kstr_clean(&str);
        if (err) {
            KERROR_SET(_keys_, 0, "cannot convert the secret key from base64 to binary");
            break;
        }
        else
            /* FIXME: I believe this is actually a bug in libktools.
               Errors are pushed by libktools even where there is no
               returned errors. */
            kerror_reset();

        tm_skey_info.key = tagcrypt_skey_new(&buf);
        kbuffer_clean(&buf);

        if (tm_skey_info.key == NULL) {
            KERROR_SET(_keys_, 0, "cannot create internal timestamp key object");
            err = -1;
            break;
        }
#endif // REQUEST_GETSIG

        /* Cleans libktools error. */
        kerror_reset();
        err = 0;

    } while (0);

    return err ? -1 : 0;
}
示例#11
0
/* Fill caps with the device capabilities. Return 0 on error. */
static int fill_capabilities (struct output_driver_caps *caps)
{
	snd_pcm_hw_params_t *hw_params;
	snd_pcm_format_mask_t *format_mask;
	int err;
	unsigned val;

	if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"),
					SND_PCM_STREAM_PLAYBACK,
					SND_PCM_NONBLOCK)) < 0) {
		error ("Can't open audio: %s", snd_strerror(err));
		return 0;
	}

	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
		error ("Can't allocate alsa hardware parameters structure: %s",
				snd_strerror(err));
		snd_pcm_close (handle);
		return 0;
	}

	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
		error ("Can't initialize hardware parameters structure: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}

	if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &val)) < 0) {
		error ("Can't get the minimum number of channels: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	caps->min_channels = val;
	
	if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &val)) < 0) {
		error ("Can't get the maximum number of channels: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	caps->max_channels = val;

	if ((err = snd_pcm_format_mask_malloc(&format_mask)) < 0) {
		error ("Can't allocate format mask: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	snd_pcm_hw_params_get_format_mask (hw_params, format_mask);

	caps->formats = SFMT_NE;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S8))
		caps->formats |= SFMT_S8;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U8))
		caps->formats |= SFMT_U8;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S16))
		caps->formats |= SFMT_S16;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U16))
		caps->formats |= SFMT_U16;
#if 0
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S24))
		caps->formats |= SFMT_S32; /* conversion needed */
#endif
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S32))
		caps->formats |= SFMT_S32;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U32))
		caps->formats |= SFMT_U32;

	snd_pcm_format_mask_free (format_mask);
	snd_pcm_hw_params_free (hw_params);
	snd_pcm_close (handle);
	handle = NULL;

	return 1;
}
示例#12
0
static char *alsa_get_mixer_channel_name ()
{
	if (mixer_elem_curr == mixer_elem1)
		return xstrdup (options_get_str("AlsaMixer"));
	return xstrdup (options_get_str("AlsaMixer2"));
}
示例#13
0
static int alsa_open (struct sound_params *sound_params)
{
	snd_pcm_hw_params_t *hw_params;
	int err;
	unsigned int period_time;
	unsigned int buffer_time;
	snd_pcm_uframes_t chunk_frames;
	snd_pcm_uframes_t buffer_frames;
	char fmt_name[128];

	switch (sound_params->fmt & SFMT_MASK_FORMAT) {
		case SFMT_S8:
			params.format = SND_PCM_FORMAT_S8;
			break;
		case SFMT_U8:
			params.format = SND_PCM_FORMAT_U8;
			break;
		case SFMT_S16:
			params.format = SND_PCM_FORMAT_S16;
			break;
		case SFMT_U16:
			params.format = SND_PCM_FORMAT_U16;
			break;
		case SFMT_S32:
			params.format = SND_PCM_FORMAT_S32;
			break;
		case SFMT_U32:
			params.format = SND_PCM_FORMAT_U32;
			break;
		default:
			error ("Unknown sample format: %s",
					sfmt_str(sound_params->fmt, fmt_name,
						sizeof(fmt_name)));
			params.format = SND_PCM_FORMAT_UNKNOWN;
			return 0;
	}

	if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"),
					SND_PCM_STREAM_PLAYBACK,
					SND_PCM_NONBLOCK)) < 0) {
		error ("Can't open audio: %s", snd_strerror(err));
		return 0;
	}

	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
		error ("Can't allocate alsa hardware parameters structure: %s",
				snd_strerror(err));
		return 0;
	}

	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
		error ("Can't initialize hardware parameters structure: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
		error ("Can't set alsa access type: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if ((err = snd_pcm_hw_params_set_format (handle, hw_params,
					params.format)) < 0) {
		error ("Can't set sample format: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	params.rate = sound_params->rate;
	if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params,
					&params.rate, 0)) < 0) {
		error ("Can't set sample rate: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	logit ("Set rate to %d", params.rate);
	
	if ((err = snd_pcm_hw_params_set_channels (handle, hw_params,
					sound_params->channels)) < 0) {
		error ("Can't set number of channels: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if ((err = snd_pcm_hw_params_get_buffer_time_max(hw_params,
					&buffer_time, 0)) < 0) {
		error ("Can't get maximum buffer time: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if (buffer_time > BUFFER_MAX_USEC)
		buffer_time = BUFFER_MAX_USEC;
	period_time = buffer_time / 4;

	if ((err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, 
					&period_time, 0)) < 0) {
		error ("Can't set period time: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if ((err = snd_pcm_hw_params_set_buffer_time_near(handle, hw_params, 
					&buffer_time, 0)) < 0) {
		error ("Can't set buffer time: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
		error ("Can't set audio parameters: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	snd_pcm_hw_params_get_period_size (hw_params, &chunk_frames, 0);
	snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_frames);

	bytes_per_frame = sound_params->channels
		* sfmt_Bps(sound_params->fmt);

	logit ("Buffer time: %ldus", buffer_frames * bytes_per_frame);

	if (chunk_frames == buffer_frames) {
		error ("Can't use period equal to buffer size (%lu == %lu)",
				chunk_frames, buffer_frames);
		snd_pcm_hw_params_free (hw_params);
		return 0;
	}

	chunk_size = chunk_frames * bytes_per_frame;

	debug ("Chunk size: %d", chunk_size);
	
	snd_pcm_hw_params_free (hw_params);
	
	if ((err = snd_pcm_prepare(handle)) < 0) {
		error ("Can't prepare audio interface for use: %s",
				snd_strerror(err));
		return 0;
	}

	debug ("ALSA device initialized");
	
	params.channels = sound_params->channels;
	alsa_buf_fill = 0;
	return 1;
}
示例#14
0
static int alsa_init (struct output_driver_caps *caps)
{
	int err;

	if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
		error ("Can't open ALSA mixer: %s", snd_strerror(err));
		mixer_handle = NULL;
	}
	else if ((err = snd_mixer_attach(mixer_handle,
					options_get_str("AlsaDevice"))) < 0) {
		snd_mixer_close (mixer_handle);
		mixer_handle = NULL;
		error ("Can't attach mixer: %s", snd_strerror(err));
	}
	else if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL))
			< 0) {
		snd_mixer_close (mixer_handle);
		mixer_handle = NULL;
		error ("Can't register mixer: %s", snd_strerror(err));
	}
	else if ((err = snd_mixer_load(mixer_handle)) < 0) {
		snd_mixer_close (mixer_handle);
		mixer_handle = NULL;
		error ("Can't load mixer: %s", snd_strerror(err));
	}

	if (mixer_handle) {
		mixer_elem1 = alsa_init_mixer_channel (
				options_get_str("AlsaMixer"),
				&mixer1_min, &mixer1_max);
		mixer_elem2 = alsa_init_mixer_channel (
				options_get_str("AlsaMixer2"),
				&mixer2_min, &mixer2_max);
	}

	mixer_elem_curr = mixer_elem1 ? mixer_elem1 : mixer_elem2;

	if (mixer_elem_curr) {
		if (mixer_elem1 && (real_volume1
					= alsa_read_mixer_raw(mixer_elem1))
				!= -1)
			volume1 = scale_volume1 (real_volume1);
		else {
			mixer_elem1 = NULL;
			mixer_elem_curr = mixer_elem2;
		}
		
		if (mixer_elem2 && (real_volume2
					= alsa_read_mixer_raw(mixer_elem2))
				!= -1)
			volume2 = scale_volume2 (real_volume2);
		else {
			mixer_elem2 = NULL;
			mixer_elem_curr = mixer_elem1;
		}

		if (!mixer_elem_curr) {
			snd_mixer_close (mixer_handle);
			mixer_handle = NULL;
		}
	}
	else if (mixer_handle) {
		snd_mixer_close (mixer_handle);
		mixer_handle = NULL;
	}

	return fill_capabilities (caps);
}
示例#15
0
文件: server.c 项目: jonsafari/mocp
static void on_song_change ()
{
	static char *last_file = NULL;
	static lists_t_strs *on_song_change = NULL;

	int ix;
	bool same_file, unpaused;
	char *curr_file, **args;
	struct file_tags *curr_tags;
	lists_t_strs *arg_list;

	/* We only need to do OnSongChange tokenisation once. */
	if (on_song_change == NULL) {
		char *command;

		on_song_change = lists_strs_new (4);
		command = options_get_str ("OnSongChange");

		if (command)
			lists_strs_tokenise (on_song_change, command);
	}

	if (lists_strs_empty (on_song_change))
		return;

	curr_file = audio_get_sname ();

	if (curr_file == NULL)
		return;

	same_file = (last_file && !strcmp (last_file, curr_file));
	unpaused = (audio_get_prev_state () == STATE_PAUSE);
	if (same_file && (unpaused || !options_get_bool ("RepeatSongChange"))) {
		free (curr_file);
		return;
	}

	curr_tags = tags_cache_get_immediate (tags_cache, curr_file,
	                                      TAGS_COMMENTS | TAGS_TIME);
	arg_list = lists_strs_new (lists_strs_size (on_song_change));
	for (ix = 0; ix < lists_strs_size (on_song_change); ix += 1) {
		char *arg, *str;

		arg = lists_strs_at (on_song_change, ix);
		if (arg[0] != '%')
			lists_strs_append (arg_list, arg);
		else if (!curr_tags)
			lists_strs_append (arg_list, "");
		else {
			switch (arg[1]) {
			case 'a':
				str = curr_tags->artist ? curr_tags->artist : "";
				lists_strs_append (arg_list, str);
				break;
			case 'r':
				str = curr_tags->album ? curr_tags->album : "";
				lists_strs_append (arg_list, str);
				break;
			case 't':
				str = curr_tags->title ? curr_tags->title : "";
				lists_strs_append (arg_list, str);
				break;
			case 'n':
				if (curr_tags->track >= 0) {
					str = (char *) xmalloc (sizeof (char) * 4);
					snprintf (str, 4, "%d", curr_tags->track);
					lists_strs_push (arg_list, str);
				}
				else
					lists_strs_append (arg_list, "");
				break;
			case 'f':
				lists_strs_append (arg_list, curr_file);
				break;
			case 'D':
				if (curr_tags->time >= 0) {
					str = (char *) xmalloc (sizeof (char) * 10);
					snprintf (str, 10, "%d", curr_tags->time);
					lists_strs_push (arg_list, str);
				}
				else
					lists_strs_append (arg_list, "");
				break;
			case 'd':
				if (curr_tags->time >= 0) {
					str = (char *) xmalloc (sizeof (char) * 12);
					sec_to_min (str, curr_tags->time);
					lists_strs_push (arg_list, str);
				}
				else
					lists_strs_append (arg_list, "");
				break;
			default:
				lists_strs_append (arg_list, arg);
			}
		}
	}
	tags_free (curr_tags);

#ifndef NDEBUG
	{
		char *cmd;

		cmd = lists_strs_fmt (arg_list, " %s");
		debug ("Running command: %s", cmd);
		free (cmd);
	}
#endif

	switch (fork ()) {
	case 0:
		args = lists_strs_save (arg_list);
		execve (args[0], args, environ);
		exit (EXIT_FAILURE);
	case -1:
		log_errno ("Failed to fork()", errno);
	}

	lists_strs_free (arg_list);
	free (last_file);
	last_file = curr_file;
}
示例#16
0
文件: playlist.c 项目: jonsafari/mocp
/* Build file title from struct file_tags. Returned memory is malloc()ed. */
char *build_title (const struct file_tags *tags)
{
	return build_title_with_format (tags, options_get_str ("FormatString"));
}