static void default_values(starter_config_t *cfg) { if (cfg == NULL) return; memset(cfg, 0, sizeof(struct starter_config)); /* is there enough space for all seen flags? */ assert(KW_SETUP_LAST - KW_SETUP_FIRST < sizeof(cfg->setup.seen) * BITS_PER_BYTE); assert(KW_CONN_LAST - KW_CONN_FIRST < sizeof(cfg->conn_default.seen) * BITS_PER_BYTE); assert(KW_END_LAST - KW_END_FIRST < sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE); assert(KW_CA_LAST - KW_CA_FIRST < sizeof(cfg->ca_default.seen) * BITS_PER_BYTE); cfg->setup.seen = SEEN_NONE; cfg->setup.uniqueids = TRUE; #ifdef START_CHARON cfg->setup.charonstart = TRUE; #endif cfg->conn_default.seen = SEEN_NONE; cfg->conn_default.startup = STARTUP_NO; cfg->conn_default.state = STATE_IGNORE; cfg->conn_default.mode = MODE_TUNNEL; cfg->conn_default.options = SA_OPTION_MOBIKE; cfg->conn_default.ike = strdupnull(ike_defaults); cfg->conn_default.esp = strdupnull(esp_defaults); cfg->conn_default.sa_ike_life_seconds = IKE_LIFETIME_DEFAULT; cfg->conn_default.sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT; cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT; cfg->conn_default.install_policy = TRUE; cfg->conn_default.dpd_delay = 30; /* seconds */ cfg->conn_default.dpd_timeout = 150; /* seconds */ cfg->conn_default.left.seen = SEEN_NONE; cfg->conn_default.right.seen = SEEN_NONE; cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED; cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED; cfg->conn_default.left.ikeport = 500; cfg->conn_default.right.ikeport = 500; cfg->conn_default.left.to_port = 0xffff; cfg->conn_default.right.to_port = 0xffff; cfg->ca_default.seen = SEEN_NONE; }
/***************************************************************************** * config_GetPsz: get the string value of a string variable ***************************************************************************** * This function is used to get the value of variables which are internally * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_*FILE, * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE). * * Important note: remember to free() the returned char* because it's a * duplicate of the actual value. It isn't safe to return a pointer to the * actual value as it can be modified at any time. *****************************************************************************/ char * config_GetPsz( vlc_object_t *p_this, const char *psz_name ) { module_config_t *p_config; p_config = config_FindConfig( p_this, psz_name ); /* sanity checks */ if( !p_config ) { msg_Err( p_this, "option %s does not exist", psz_name ); return NULL; } if (!IsConfigStringType (p_config->i_type)) { msg_Err( p_this, "option %s does not refer to a string", psz_name ); return NULL; } /* return a copy of the string */ vlc_rwlock_rdlock (&config_lock); char *psz_value = strdupnull (p_config->value.psz); vlc_rwlock_unlock (&config_lock); return psz_value; }
/* * initialize a ca object with the default ca */ static void ca_default(char *name, starter_ca_t *ca, starter_ca_t *def) { memcpy(ca, def, sizeof(starter_ca_t)); ca->name = strdupnull(name); clone_args(KW_CA_FIRST, KW_CA_LAST, (char *)ca, (char *)def); }
/***************************************************************************** * config_ResetAll: reset the configuration data for all the modules. *****************************************************************************/ void config_ResetAll( vlc_object_t *p_this ) { VLC_UNUSED(p_this); module_t *p_module; module_t **list = module_list_get (NULL); vlc_rwlock_wrlock (&config_lock); for (size_t j = 0; (p_module = list[j]) != NULL; j++) { if( p_module->b_submodule ) continue; for (size_t i = 0; i < p_module->confsize; i++ ) { module_config_t *p_config = p_module->p_config + i; if (IsConfigIntegerType (p_config->i_type)) p_config->value.i = p_config->orig.i; else if (IsConfigFloatType (p_config->i_type)) p_config->value.f = p_config->orig.f; else if (IsConfigStringType (p_config->i_type)) { free ((char *)p_config->value.psz); p_config->value.psz = strdupnull (p_config->orig.psz); } } } vlc_rwlock_unlock (&config_lock); module_list_free (list); }
/* TODO : documenation */ void emphasis_cover_change(Emphasis_Gui *gui, char *artist, char *album) { Cover_Info *ci; Cover_Info *old; ci = malloc(sizeof(Cover_Info)); if(ci == NULL) { return; } ci->artist = strdupnull(artist); ci->album = strdupnull(album); old = gui->cover_queue; gui->cover_queue = ci; emphasis_cover_clear_queue(old); }
/* * initialize a conn object with the default conn */ static void conn_default(char *name, starter_conn_t *conn, starter_conn_t *def) { memcpy(conn, def, sizeof(starter_conn_t)); conn->name = strdupnull(name); clone_args(KW_CONN_FIRST, KW_CONN_LAST, (char *)conn, (char *)def); clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left, (char *)&def->left); clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right, (char *)&def->right); }
/* * parse a ca section */ static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg) { char *ca_name = (ca->name == NULL)? "%default":ca->name; for ( ; kw; kw = kw->next) { bool assigned = FALSE; kw_token_t token = kw->entry->token; if (token == KW_AUTO) { token = KW_CA_SETUP; } else if (token == KW_ALSO) { if (cfg->parse_also) { also_t *also = malloc_thing(also_t); also->name = strdupnull(kw->value); also->next = ca->also; ca->also = also; DBG2(DBG_APP, " also=%s", kw->value); } continue; } if (token < KW_CA_FIRST || token > KW_CA_LAST) { DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'", kw->entry->name, ca_name); cfg->err++; continue; } if (is_deprecated(token, kw, ca_name)) { cfg->non_fatal_err++; continue; } if (!assign_arg(token, KW_CA_FIRST, kw, (char *)ca, &assigned)) { DBG1(DBG_APP, " bad argument value in ca '%s'", ca_name); cfg->err++; } } /* treat 'route' and 'start' as 'add' */ if (ca->startup != STARTUP_NO) ca->startup = STARTUP_ADD; }
/* * handles left|rightfirewall and left|rightupdown parameters */ static void handle_firewall(const char *label, starter_end_t *end, starter_config_t *cfg) { if (end->firewall) { if (end->updown != NULL) { DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label, label); cfg->err++; } else { end->updown = strdupnull(firewall_defaults); end->firewall = FALSE; } } }
/***************************************************************************** * config_SaveConfigFile: Save a module's config options. ***************************************************************************** * This will save the specified module's config options to the config file. * If psz_module_name is NULL then we save all the modules config options. * It's no use to save the config options that kept their default values, so * we'll try to be a bit clever here. * * When we save we mustn't delete the config options of the modules that * haven't been loaded. So we cannot just create a new config file with the * config structures we've got in memory. * I don't really know how to deal with this nicely, so I will use a completly * dumb method ;-) * I will load the config file in memory, but skipping all the sections of the * modules we want to save. Then I will create a brand new file, dump the file * loaded in memory and then append the sections of the modules we want to * save. * Really stupid no ? *****************************************************************************/ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, bool b_autosave ) { module_t *p_parser; char *permanent = NULL, *temporary = NULL; if( config_PrepareDir( p_this ) ) { msg_Err( p_this, "no configuration directory" ); return -1; } /* List all available modules */ module_t **list = module_list_get (NULL); char *bigbuf = NULL; size_t bigsize = 0; FILE *file = config_OpenConfigFile (p_this); if (file != NULL) { struct stat st; /* Some users make vlcrc read-only to prevent changes. * The atomic replacement scheme breaks this "feature", * so we check for read-only by hand. */ if (fstat (fileno (file), &st) || !(st.st_mode & S_IWUSR)) { msg_Err (p_this, "configuration file is read-only"); goto error; } bigsize = (st.st_size < LONG_MAX) ? st.st_size : 0; bigbuf = malloc (bigsize + 1); if (bigbuf == NULL) goto error; /* backup file into memory, we only need to backup the sections we * won't save later on */ char *p_index = bigbuf; char *line = NULL; size_t bufsize; ssize_t linelen; bool backup = false; while ((linelen = getline (&line, &bufsize, file)) != -1) { char *p_index2; if ((line[0] == '[') && (p_index2 = strchr(line,']'))) { /* we found a new section, check if we need to do a backup */ backup = true; for (int i = 0; (p_parser = list[i]) != NULL; i++) { if (!strncmp (line + 1, p_parser->psz_object_name, strlen (p_parser->psz_object_name)) && ((psz_module_name == NULL) || !strcmp (psz_module_name, p_parser->psz_object_name))) { backup = false; /* no, we will rewrite it! */ break; } } } /* save line if requested and line is valid (doesn't begin with a * space, tab, or eol) */ if (backup && !memchr ("\n\t ", line[0], 3)) { memcpy (p_index, line, linelen); p_index += linelen; } } fclose (file); file = NULL; free (line); *p_index = '\0'; bigsize = p_index - bigbuf; } /* * Save module config in file */ permanent = config_GetConfigFile (p_this); if (!permanent) { module_list_free (list); goto error; } if (asprintf (&temporary, "%s.%u", permanent, getpid ()) == -1) { temporary = NULL; module_list_free (list); goto error; } /* Configuration lock must be taken before vlcrc serializer below. */ vlc_rwlock_rdlock (&config_lock); /* The temporary configuration file is per-PID. Therefore SaveConfigFile() * should be serialized against itself within a given process. */ static vlc_mutex_t lock = VLC_STATIC_MUTEX; vlc_mutex_lock (&lock); int fd = vlc_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR); if (fd == -1) { vlc_rwlock_unlock (&config_lock); vlc_mutex_unlock (&lock); module_list_free (list); goto error; } file = fdopen (fd, "wt"); if (file == NULL) { msg_Err (p_this, "cannot create configuration file: %m"); vlc_rwlock_unlock (&config_lock); close (fd); vlc_mutex_unlock (&lock); module_list_free (list); goto error; } fprintf( file, "\xEF\xBB\xBF###\n" "### "PACKAGE_NAME" "PACKAGE_VERSION"\n" "###\n" "\n" "###\n" "### lines beginning with a '#' character are comments\n" "###\n" "\n" ); /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); /* We would take the config lock here. But this would cause a lock * inversion with the serializer above and config_AutoSaveConfigFile(). vlc_rwlock_rdlock (&config_lock);*/ /* Look for the selected module, if NULL then save everything */ for (int i = 0; (p_parser = list[i]) != NULL; i++) { module_config_t *p_item, *p_end; if( psz_module_name && strcmp( psz_module_name, p_parser->psz_object_name ) ) continue; if( !p_parser->i_config_items ) continue; if( psz_module_name ) msg_Dbg( p_this, "saving config for module \"%s\"", p_parser->psz_object_name ); fprintf( file, "[%s]", p_parser->psz_object_name ); if( p_parser->psz_longname ) fprintf( file, " # %s\n\n", p_parser->psz_longname ); else fprintf( file, "\n\n" ); for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize; p_item < p_end; p_item++ ) { if ((p_item->i_type & CONFIG_HINT) /* ignore hint */ || p_item->b_removed /* ignore deprecated option */ || p_item->b_unsaveable) /* ignore volatile option */ continue; /* Do not save the new value in the configuration file * if doing an autosave, and the item is not an "autosaved" one. */ bool b_retain = b_autosave && !p_item->b_autosave; if (IsConfigIntegerType (p_item->i_type)) { int64_t val = b_retain ? p_item->saved.i : p_item->value.i; config_Write (file, p_item->psz_text, (p_item->i_type == CONFIG_ITEM_BOOL) ? N_("boolean") : N_("integer"), val == p_item->orig.i, p_item->psz_name, "%"PRId64, val); p_item->saved.i = val; } else if (IsConfigFloatType (p_item->i_type)) { float val = b_retain ? p_item->saved.f : p_item->value.f; config_Write (file, p_item->psz_text, N_("float"), val == p_item->orig.f, p_item->psz_name, "%f", val); p_item->saved.f = val; } else { const char *psz_value = b_retain ? p_item->saved.psz : p_item->value.psz; bool modified; assert (IsConfigStringType (p_item->i_type)); if (b_retain && (psz_value == NULL)) /* FIXME: hack */ psz_value = p_item->orig.psz; modified = (psz_value != NULL) ? ((p_item->orig.psz != NULL) ? (strcmp (psz_value, p_item->orig.psz) != 0) : true) : (p_item->orig.psz != NULL); config_Write (file, p_item->psz_text, N_("string"), !modified, p_item->psz_name, "%s", psz_value ? psz_value : ""); if ( !b_retain ) { free ((char *)p_item->saved.psz); if( (psz_value && p_item->orig.psz && strcmp( psz_value, p_item->orig.psz )) || !psz_value || !p_item->orig.psz) p_item->saved.psz = strdupnull (psz_value); else p_item->saved.psz = NULL; } } if (!b_retain) p_item->b_dirty = false; } } vlc_rwlock_unlock (&config_lock); module_list_free (list); if (loc != (locale_t)0) { uselocale (baseloc); freelocale (loc); } /* * Restore old settings from the config in file */ if (bigsize) fwrite (bigbuf, 1, bigsize, file); /* * Flush to disk and replace atomically */ fflush (file); /* Flush from run-time */ if (ferror (file)) { vlc_unlink (temporary); vlc_mutex_unlock (&lock); msg_Err (p_this, "cannot write configuration file"); clearerr (file); goto error; } #ifndef WIN32 #ifdef __APPLE__ fsync (fd); /* Flush from OS */ #else fdatasync (fd); /* Flush from OS */ #endif /* Atomically replace the file... */ if (vlc_rename (temporary, permanent)) vlc_unlink (temporary); /* (...then synchronize the directory, err, TODO...) */ /* ...and finally close the file */ vlc_mutex_unlock (&lock); #endif fclose (file); #ifdef WIN32 /* Windows cannot remove open files nor overwrite existing ones */ vlc_unlink (permanent); if (vlc_rename (temporary, permanent)) vlc_unlink (temporary); vlc_mutex_unlock (&lock); #endif free (temporary); free (permanent); free (bigbuf); return 0; error: if( file ) fclose( file ); free (temporary); free (permanent); free (bigbuf); return -1; }
/***************************************************************************** * config_LoadConfigFile: loads the configuration file. ***************************************************************************** * This function is called to load the config options stored in the config * file. *****************************************************************************/ int config_LoadConfigFile( vlc_object_t *p_this ) { FILE *file; file = config_OpenConfigFile (p_this); if (file == NULL) return VLC_EGENERIC; /* Look for UTF-8 Byte Order Mark */ char * (*convert) (const char *) = strdupnull; char bom[3]; if ((fread (bom, 1, 3, file) != 3) || memcmp (bom, "\xEF\xBB\xBF", 3)) { convert = FromLocaleDup; rewind (file); /* no BOM, rewind */ } char *line = NULL; size_t bufsize; ssize_t linelen; /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); vlc_rwlock_wrlock (&config_lock); while ((linelen = getline (&line, &bufsize, file)) != -1) { line[linelen - 1] = '\0'; /* trim newline */ /* Ignore comments, section and empty lines */ if (memchr ("#[", line[0], 3) != NULL) continue; /* look for option name */ const char *psz_option_name = line; char *ptr = strchr (line, '='); if (ptr == NULL) continue; /* syntax error */ *ptr = '\0'; module_config_t *item = config_FindConfig (p_this, psz_option_name); if (item == NULL) continue; const char *psz_option_value = ptr + 1; switch (item->i_type) { case CONFIG_ITEM_BOOL: case CONFIG_ITEM_INTEGER: { int64_t l; errno = 0; l = strtoi (psz_option_value); if ((l > item->max.i) || (l < item->min.i)) errno = ERANGE; if (errno) msg_Warn (p_this, "Integer value (%s) for %s: %m", psz_option_value, psz_option_name); else item->saved.i = item->value.i = l; break; } case CONFIG_ITEM_FLOAT: if (!*psz_option_value) break; /* ignore empty option */ item->value.f = (float)atof (psz_option_value); item->saved.f = item->value.f; break; default: free ((char *)item->value.psz); free ((char *)item->saved.psz); item->value.psz = convert (psz_option_value); item->saved.psz = strdupnull (item->value.psz); break; } } vlc_rwlock_unlock (&config_lock); free (line); if (ferror (file)) { msg_Err (p_this, "error reading configuration: %m"); clearerr (file); } fclose (file); if (loc != (locale_t)0) { uselocale (baseloc); freelocale (loc); } return 0; }
/* * parse left|right specific options */ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, char *key, char *value, starter_config_t *cfg) { bool assigned = FALSE; if (is_deprecated(token, key, conn->name)) { cfg->non_fatal_err++; return; } if (!assign_arg(token, KW_END_FIRST, key, value, end, &assigned)) { goto err; } /* post processing of some keywords that were assigned automatically */ switch (token) { case KW_HOST: if (value && strlen(value) > 0 && value[0] == '%') { if (streq(value, "%defaultroute")) { value = "%any"; } if (!streq(value, "%any") && !streq(value, "%any4") && !streq(value, "%any6")) { /* allow_any prefix */ end->allow_any = TRUE; value++; } } free(end->host); end->host = strdupnull(value); break; case KW_SOURCEIP: conn->mode = MODE_TUNNEL; conn->proxy_mode = FALSE; break; case KW_SENDCERT: if (end->sendcert == CERT_YES_SEND) { end->sendcert = CERT_ALWAYS_SEND; } else if (end->sendcert == CERT_NO_SEND) { end->sendcert = CERT_NEVER_SEND; } break; default: break; } if (assigned) { return; } /* individual processing of keywords that were not assigned automatically */ switch (token) { case KW_PROTOPORT: { struct protoent *proto; struct servent *svc; char *sep, *port = "", *endptr; long int p; sep = strchr(value, '/'); if (sep) { /* protocol/port */ *sep = '\0'; port = sep + 1; } if (streq(value, "%any")) { end->protocol = 0; } else { proto = getprotobyname(value); if (proto) { end->protocol = proto->p_proto; } else { p = strtol(value, &endptr, 0); if ((*value && *endptr) || p < 0 || p > 0xff) { DBG1(DBG_APP, "# bad protocol: %s=%s", key, value); goto err; } end->protocol = (uint8_t)p; } } if (streq(port, "%any")) { end->from_port = 0; end->to_port = 0xffff; } else if (streq(port, "%opaque")) { end->from_port = 0xffff; end->to_port = 0; } else if (*port) { svc = getservbyname(port, NULL); if (svc) { end->from_port = end->to_port = ntohs(svc->s_port); } else { p = strtol(port, &endptr, 0); if (p < 0 || p > 0xffff) { DBG1(DBG_APP, "# bad port: %s=%s", key, port); goto err; } end->from_port = p; if (*endptr == '-') { port = endptr + 1; p = strtol(port, &endptr, 0); if (p < 0 || p > 0xffff) { DBG1(DBG_APP, "# bad port: %s=%s", key, port); goto err; } } end->to_port = p; if (*endptr) { DBG1(DBG_APP, "# bad port: %s=%s", key, port); goto err; } } } if (sep) { /* restore the original text in case also= is used */ *sep = '/'; } break; } default: break; } return; err: DBG1(DBG_APP, " bad argument value in conn '%s'", conn->name); cfg->err++; }
/***************************************************************************** * config_SaveConfigFile: Save a module's config options. ***************************************************************************** * This will save the specified module's config options to the config file. * If psz_module_name is NULL then we save all the modules config options. * It's no use to save the config options that kept their default values, so * we'll try to be a bit clever here. * * When we save we mustn't delete the config options of the modules that * haven't been loaded. So we cannot just create a new config file with the * config structures we've got in memory. * I don't really know how to deal with this nicely, so I will use a completly * dumb method ;-) * I will load the config file in memory, but skipping all the sections of the * modules we want to save. Then I will create a brand new file, dump the file * loaded in memory and then append the sections of the modules we want to * save. * Really stupid no ? *****************************************************************************/ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, bool b_autosave ) { module_t *p_parser; FILE *file = NULL; char *permanent = NULL, *temporary = NULL; char p_line[1024], *p_index2; unsigned long i_sizebuf = 0; char *p_bigbuffer = NULL, *p_index; bool b_backup; int i_index; if( config_PrepareDir( p_this ) ) { msg_Err( p_this, "no configuration directory" ); goto error; } file = config_OpenConfigFile( p_this ); if( file != NULL ) { struct stat st; /* Some users make vlcrc read-only to prevent changes. * The atomic replacement scheme breaks this "feature", * so we check for read-only by hand. */ if (fstat (fileno (file), &st) || !(st.st_mode & S_IWUSR)) { msg_Err (p_this, "configuration file is read-only"); goto error; } i_sizebuf = ( st.st_size < LONG_MAX ) ? st.st_size : 0; } p_bigbuffer = p_index = malloc( i_sizebuf+1 ); if( !p_bigbuffer ) goto error; p_bigbuffer[0] = 0; /* List all available modules */ module_t **list = module_list_get (NULL); /* backup file into memory, we only need to backup the sections we won't * save later on */ b_backup = false; while( file && fgets( p_line, 1024, file ) ) { if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']'))) { /* we found a section, check if we need to do a backup */ for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ ) { if( ((p_index2 - &p_line[1]) == (int)strlen(p_parser->psz_object_name) ) && !memcmp( &p_line[1], p_parser->psz_object_name, strlen(p_parser->psz_object_name) ) ) { if( !psz_module_name ) break; else if( !strcmp( psz_module_name, p_parser->psz_object_name ) ) break; } } if( list[i_index] == NULL ) { /* we don't have this section in our list so we need to back * it up */ *p_index2 = 0; #if 0 msg_Dbg( p_this, "backing up config for unknown module \"%s\"", &p_line[1] ); #endif *p_index2 = ']'; b_backup = true; } else { b_backup = false; } } /* save line if requested and line is valid (doesn't begin with a * space, tab, or eol) */ if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ') && (p_line[0] != '\t') ) { strcpy( p_index, p_line ); p_index += strlen( p_line ); } } if( file ) fclose( file ); file = NULL; /* * Save module config in file */ permanent = config_GetConfigFile (p_this); if (!permanent) { module_list_free (list); goto error; } if (asprintf (&temporary, "%s.%u", permanent, getpid ()) == -1) { temporary = NULL; module_list_free (list); goto error; } /* The temporary configuration file is per-PID. Therefore SaveConfigFile() * should be serialized against itself within a given process. */ static vlc_mutex_t lock = VLC_STATIC_MUTEX; vlc_mutex_lock (&lock); int fd = utf8_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR); if (fd == -1) { vlc_mutex_unlock (&lock); module_list_free (list); goto error; } file = fdopen (fd, "wt"); if (file == NULL) { close (fd); vlc_mutex_unlock (&lock); module_list_free (list); goto error; } fprintf( file, "\xEF\xBB\xBF###\n### " COPYRIGHT_MESSAGE "\n###\n\n" "###\n### lines beginning with a '#' character are comments\n###\n\n" ); /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); /* Look for the selected module, if NULL then save everything */ for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ ) { module_config_t *p_item, *p_end; if( psz_module_name && strcmp( psz_module_name, p_parser->psz_object_name ) ) continue; if( !p_parser->i_config_items ) continue; if( psz_module_name ) msg_Dbg( p_this, "saving config for module \"%s\"", p_parser->psz_object_name ); fprintf( file, "[%s]", p_parser->psz_object_name ); if( p_parser->psz_longname ) fprintf( file, " # %s\n\n", p_parser->psz_longname ); else fprintf( file, "\n\n" ); for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize; p_item < p_end; p_item++ ) { if ((p_item->i_type & CONFIG_HINT) /* ignore hint */ || p_item->b_removed /* ignore deprecated option */ || p_item->b_unsaveable) /* ignore volatile option */ continue; vlc_mutex_lock (p_item->p_lock); /* Do not save the new value in the configuration file * if doing an autosave, and the item is not an "autosaved" one. */ bool b_retain = b_autosave && !p_item->b_autosave; if (IsConfigIntegerType (p_item->i_type)) { int val = b_retain ? p_item->saved.i : p_item->value.i; if (p_item->i_type == CONFIG_ITEM_KEY) { char *psz_key = ConfigKeyToString (val); config_Write (file, p_item->psz_text, N_("key"), val == p_item->orig.i, p_item->psz_name, "%s", psz_key ? psz_key : ""); free (psz_key); } else config_Write (file, p_item->psz_text, (p_item->i_type == CONFIG_ITEM_BOOL) ? N_("boolean") : N_("integer"), val == p_item->orig.i, p_item->psz_name, "%d", val); p_item->saved.i = val; } else if (IsConfigFloatType (p_item->i_type)) { float val = b_retain ? p_item->saved.f : p_item->value.f; config_Write (file, p_item->psz_text, N_("float"), val == p_item->orig.f, p_item->psz_name, "%f", val); p_item->saved.f = val; } else { const char *psz_value = b_retain ? p_item->saved.psz : p_item->value.psz; bool modified; assert (IsConfigStringType (p_item->i_type)); if (b_retain && (psz_value == NULL)) /* FIXME: hack */ psz_value = p_item->orig.psz; modified = (psz_value != NULL) ? ((p_item->orig.psz != NULL) ? (strcmp (psz_value, p_item->orig.psz) != 0) : true) : (p_item->orig.psz != NULL); config_Write (file, p_item->psz_text, N_("string"), !modified, p_item->psz_name, "%s", psz_value ? psz_value : ""); if ( !b_retain ) { free ((char *)p_item->saved.psz); if( (psz_value && p_item->orig.psz && strcmp( psz_value, p_item->orig.psz )) || !psz_value || !p_item->orig.psz) p_item->saved.psz = strdupnull (psz_value); else p_item->saved.psz = NULL; } } if (!b_retain) p_item->b_dirty = false; vlc_mutex_unlock (p_item->p_lock); } } module_list_free (list); if (loc != (locale_t)0) { uselocale (baseloc); freelocale (loc); } /* * Restore old settings from the config in file */ fputs( p_bigbuffer, file ); free( p_bigbuffer ); /* * Flush to disk and replace atomically */ fflush (file); /* Flush from run-time */ #ifndef WIN32 fdatasync (fd); /* Flush from OS */ /* Atomically replace the file... */ if (utf8_rename (temporary, permanent)) utf8_unlink (temporary); /* (...then synchronize the directory, err, TODO...) */ /* ...and finally close the file */ vlc_mutex_unlock (&lock); #endif fclose (file); #ifdef WIN32 /* Windows cannot remove open files nor overwrite existing ones */ utf8_unlink (permanent); if (utf8_rename (temporary, permanent)) utf8_unlink (temporary); vlc_mutex_unlock (&lock); #endif free (temporary); free (permanent); return 0; error: if( file ) fclose( file ); free (temporary); free (permanent); free( p_bigbuffer ); return -1; }
/***************************************************************************** * config_LoadConfigFile: loads the configuration file. ***************************************************************************** * This function is called to load the config options stored in the config * file. *****************************************************************************/ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) { FILE *file; file = config_OpenConfigFile (p_this); if (file == NULL) return VLC_EGENERIC; /* Look for the selected module, if NULL then save everything */ module_t **list = module_list_get (NULL); /* Look for UTF-8 Byte Order Mark */ char * (*convert) (const char *) = strdupnull; char bom[3]; if ((fread (bom, 1, 3, file) != 3) || memcmp (bom, "\xEF\xBB\xBF", 3)) { convert = FromLocaleDup; rewind (file); /* no BOM, rewind */ } module_t *module = NULL; char line[1024], section[1022]; section[0] = '\0'; /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); while (fgets (line, 1024, file) != NULL) { /* Ignore comments and empty lines */ switch (line[0]) { case '#': case '\n': case '\0': continue; } if (line[0] == '[') { char *ptr = strchr (line, ']'); if (ptr == NULL) continue; /* syntax error; */ *ptr = '\0'; /* New section ( = a given module) */ strcpy (section, line + 1); module = NULL; if ((psz_module_name == NULL) || (strcmp (psz_module_name, section) == 0)) { for (int i = 0; list[i]; i++) { module_t *m = list[i]; if ((strcmp (section, m->psz_object_name) == 0) && (m->i_config_items > 0)) /* ignore config-less modules */ { module = m; if (psz_module_name != NULL) msg_Dbg (p_this, "loading config for module \"%s\"", section); break; } } } continue; } if (module == NULL) continue; /* no need to parse if there is no matching module */ char *ptr = strchr (line, '\n'); if (ptr != NULL) *ptr = '\0'; /* look for option name */ const char *psz_option_name = line; ptr = strchr (line, '='); if (ptr == NULL) continue; /* syntax error */ *ptr = '\0'; const char *psz_option_value = ptr + 1; /* try to match this option with one of the module's options */ for (size_t i = 0; i < module->confsize; i++) { module_config_t *p_item = module->p_config + i; if ((p_item->i_type & CONFIG_HINT) || strcmp (p_item->psz_name, psz_option_name)) continue; /* We found it */ errno = 0; vlc_mutex_lock( p_item->p_lock ); switch( p_item->i_type ) { case CONFIG_ITEM_BOOL: case CONFIG_ITEM_INTEGER: { long l = strtoi (psz_option_value); if (errno) msg_Warn (p_this, "Integer value (%s) for %s: %m", psz_option_value, psz_option_name); else p_item->saved.i = p_item->value.i = (int)l; break; } case CONFIG_ITEM_FLOAT: if( !*psz_option_value ) break; /* ignore empty option */ p_item->value.f = (float)atof (psz_option_value); p_item->saved.f = p_item->value.f; break; case CONFIG_ITEM_KEY: if( !*psz_option_value ) break; /* ignore empty option */ p_item->value.i = ConfigStringToKey(psz_option_value); p_item->saved.i = p_item->value.i; break; default: /* free old string */ free( (char*) p_item->value.psz ); free( (char*) p_item->saved.psz ); p_item->value.psz = convert (psz_option_value); p_item->saved.psz = strdupnull (p_item->value.psz); break; } vlc_mutex_unlock( p_item->p_lock ); break; } } if (ferror (file)) { msg_Err (p_this, "error reading configuration: %m"); clearerr (file); } fclose (file); module_list_free (list); if (loc != (locale_t)0) { uselocale (baseloc); freelocale (loc); } return 0; }
/* * parse a conn section */ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) { char *conn_name = (conn->name == NULL)? "%default":conn->name; for ( ; kw; kw = kw->next) { bool assigned = FALSE; kw_token_t token = kw->entry->token; if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST) { kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST) { kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } if (token == KW_AUTO) { token = KW_CONN_SETUP; } else if (token == KW_ALSO) { if (cfg->parse_also) { also_t *also = malloc_thing(also_t); also->name = strdupnull(kw->value); also->next = conn->also; conn->also = also; DBG2(DBG_APP, " also=%s", kw->value); } continue; } if (token < KW_CONN_FIRST || token > KW_CONN_LAST) { DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'", kw->entry->name, conn_name); cfg->err++; continue; } if (is_deprecated(token, kw, conn_name)) { cfg->non_fatal_err++; continue; } if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned)) { DBG1(DBG_APP, " bad argument value in conn '%s'", conn_name); cfg->err++; continue; } if (assigned) continue; switch (token) { case KW_TYPE: conn->mode = MODE_TRANSPORT; conn->proxy_mode = FALSE; if (streq(kw->value, "tunnel")) { conn->mode = MODE_TUNNEL; } else if (streq(kw->value, "beet")) { conn->mode = MODE_BEET; } else if (streq(kw->value, "transport_proxy")) { conn->mode = MODE_TRANSPORT; conn->proxy_mode = TRUE; } else if (streq(kw->value, "passthrough") || streq(kw->value, "pass")) { conn->mode = MODE_PASS; } else if (streq(kw->value, "drop") || streq(kw->value, "reject")) { conn->mode = MODE_DROP; } else if (!streq(kw->value, "transport")) { DBG1(DBG_APP, "# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; } break; case KW_COMPRESS: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS) break; case KW_AUTH: KW_SA_OPTION_FLAG("ah", "esp", SA_OPTION_AUTHENTICATE) break; case KW_MARK: if (!handle_mark(kw->value, &conn->mark_in)) { cfg->err++; break; } conn->mark_out = conn->mark_in; break; case KW_MARK_IN: if (!handle_mark(kw->value, &conn->mark_in)) { cfg->err++; } break; case KW_MARK_OUT: if (!handle_mark(kw->value, &conn->mark_out)) { cfg->err++; } break; case KW_TFC: if (streq(kw->value, "%mtu")) { conn->tfc = -1; } else { char *endptr; conn->tfc = strtoul(kw->value, &endptr, 10); if (*endptr != '\0') { DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; case KW_KEYINGTRIES: if (streq(kw->value, "%forever")) { conn->sa_keying_tries = 0; } else { char *endptr; conn->sa_keying_tries = strtoul(kw->value, &endptr, 10); if (*endptr != '\0') { DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; case KW_REKEY: KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REKEY) break; case KW_REAUTH: KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REAUTH) break; case KW_MOBIKE: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_MOBIKE) break; case KW_FORCEENCAPS: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP) break; case KW_MODECONFIG: KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH) break; case KW_XAUTH: KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER) break; default: break; } } handle_firewall("left", &conn->left, cfg); handle_firewall("right", &conn->right, cfg); }