profile.c revision 8f234d9650eb6f6a897148d5136cb27f373de4a7
13f00e317064560ad11168d22030416d853829f6eJim Grosbach/* 23f00e317064560ad11168d22030416d853829f6eJim Grosbach * profile.c -- A simple configuration file parsing "library in a file" 33f00e317064560ad11168d22030416d853829f6eJim Grosbach * 4e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * The profile library was originally written by Theodore Ts'o in 1995 5e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * for use in the MIT Kerberos v5 library. It has been 6e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * modified/enhanced/bug-fixed over time by other members of the MIT 7e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * Kerberos team. This version was originally taken from the Kerberos 8e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * v5 distribution, version 1.4.2, and radically simplified for use in 9e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * e2fsprogs. (Support for locking for multi-threaded operations, 10e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * being able to modify and update the configuration file 113f00e317064560ad11168d22030416d853829f6eJim Grosbach * programmatically, and Mac/Windows portability have been removed. 123f00e317064560ad11168d22030416d853829f6eJim Grosbach * It has been folded into a single C source file to make it easier to 133f00e317064560ad11168d22030416d853829f6eJim Grosbach * fold into an application program.) 14da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach * 153f00e317064560ad11168d22030416d853829f6eJim Grosbach * Copyright (C) 2005, 2006 by Theodore Ts'o. 16da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach * 173f00e317064560ad11168d22030416d853829f6eJim Grosbach * %Begin-Header% 183f00e317064560ad11168d22030416d853829f6eJim Grosbach * This file may be redistributed under the terms of the GNU Public 193f00e317064560ad11168d22030416d853829f6eJim Grosbach * License. 203f00e317064560ad11168d22030416d853829f6eJim Grosbach * %End-Header% 213f00e317064560ad11168d22030416d853829f6eJim Grosbach * 223f00e317064560ad11168d22030416d853829f6eJim Grosbach * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology. 233f00e317064560ad11168d22030416d853829f6eJim Grosbach * 243f00e317064560ad11168d22030416d853829f6eJim Grosbach * All rights reserved. 253f00e317064560ad11168d22030416d853829f6eJim Grosbach * 263f00e317064560ad11168d22030416d853829f6eJim Grosbach * Export of this software from the United States of America may require 273f00e317064560ad11168d22030416d853829f6eJim Grosbach * a specific license from the United States Government. It is the 28dc89561fecf100d6c32d73c7b009fd73e51be688Jim Grosbach * responsibility of any person or organization contemplating export to 293f00e317064560ad11168d22030416d853829f6eJim Grosbach * obtain such a license before exporting. 303f00e317064560ad11168d22030416d853829f6eJim Grosbach * 313f00e317064560ad11168d22030416d853829f6eJim Grosbach * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 323f00e317064560ad11168d22030416d853829f6eJim Grosbach * distribute this software and its documentation for any purpose and 333f00e317064560ad11168d22030416d853829f6eJim Grosbach * without fee is hereby granted, provided that the above copyright 343f00e317064560ad11168d22030416d853829f6eJim Grosbach * notice appear in all copies and that both that copyright notice and 353f00e317064560ad11168d22030416d853829f6eJim Grosbach * this permission notice appear in supporting documentation, and that 363f00e317064560ad11168d22030416d853829f6eJim Grosbach * the name of M.I.T. not be used in advertising or publicity pertaining 373f00e317064560ad11168d22030416d853829f6eJim Grosbach * to distribution of the software without specific, written prior 383f00e317064560ad11168d22030416d853829f6eJim Grosbach * permission. Furthermore if you modify this software you must label 393f00e317064560ad11168d22030416d853829f6eJim Grosbach * your software as modified software and not distribute it in such a 403f00e317064560ad11168d22030416d853829f6eJim Grosbach * fashion that it might be confused with the original MIT software. 413f00e317064560ad11168d22030416d853829f6eJim Grosbach * M.I.T. makes no representations about the suitability of this software 42dc89561fecf100d6c32d73c7b009fd73e51be688Jim Grosbach * for any purpose. It is provided "as is" without express or implied 43e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * warranty. 44da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach * 45e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 46da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 47da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 48e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * 49e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach */ 50e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach 51e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#ifdef HAVE_UNISTD_H 52e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <unistd.h> 53e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#endif 54e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <stdio.h> 55e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#ifdef HAVE_STDLIB_H 56e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <stdlib.h> 57e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#endif 58e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <time.h> 59e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <string.h> 60e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <errno.h> 61e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <ctype.h> 62e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <limits.h> 63e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <stddef.h> 64e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <sys/types.h> 65e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <sys/stat.h> 66e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#include <dirent.h> 67e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#ifdef HAVE_PWD_H 6837ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#include <pwd.h> 6937ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#endif 7037ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 7137ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#include <et/com_err.h> 7237ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#include "profile.h" 7337ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#include "prof_err.h" 7437ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 7537ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#undef STAT_ONCE_PER_SECOND 7637ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#undef HAVE_STAT 7737ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 7837ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach/* 7937ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * prof_int.h 8037ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach */ 8137ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 8237ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbachtypedef long prf_magic_t; 8337ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 8437ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach/* 8537ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * This is the structure which stores the profile information for a 8637ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * particular configuration file. 87e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach */ 88e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbachstruct _prf_file_t { 89e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach prf_magic_t magic; 90e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach char *filespec; 91e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#ifdef STAT_ONCE_PER_SECOND 92e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach time_t last_stat; 93e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach#endif 94e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach time_t timestamp; /* time tree was last updated from file */ 95e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach int flags; /* r/w, dirty */ 96e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach int upd_serial; /* incremented when data changes */ 97e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach struct profile_node *root; 98e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach struct _prf_file_t *next; 99e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach}; 100e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach 101e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbachtypedef struct _prf_file_t *prf_file_t; 102e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach 103e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach/* 104e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach * The profile flags 105e8606dc7c878d4562da5e3e5609b9d7d734d498cJim Grosbach */ 10637ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#define PROFILE_FILE_RW 0x0001 10737ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#define PROFILE_FILE_DIRTY 0x0002 10837ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 10937ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach/* 11037ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * This structure defines the high-level, user visible profile_t 11137ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * object, which is used as a handle by users who need to query some 11237ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * configuration file(s) 11337ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach */ 11437ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbachstruct _profile_t { 11537ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach prf_magic_t magic; 11637ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach prf_file_t first_file; 11737ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach}; 11837ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach 11937ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach/* 12037ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach * Used by the profile iterator in prof_get.c 12137ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach */ 12237ee464ea98544d3ed84cec6dde5f769ce003d5fJim Grosbach#define PROFILE_ITER_LIST_SECTION 0x0001 123da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#define PROFILE_ITER_SECTIONS_ONLY 0x0002 124da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#define PROFILE_ITER_RELATIONS_ONLY 0x0004 125da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 1267ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach#define PROFILE_ITER_FINAL_SEEN 0x0100 1277ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach 1287ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach/* 1297ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS 130da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach */ 131da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 132da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#define PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0')) 133da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 134da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstruct profile_node { 135da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach errcode_t magic; 136da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach char *name; 137da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach char *value; 138da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach int group_level; 139da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach unsigned int final:1; /* Indicate don't search next file */ 140da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach unsigned int deleted:1; 141da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node *first_child; 142da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node *parent; 143da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node *next, *prev; 144da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach}; 145da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 146da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#define CHECK_MAGIC(node) \ 147da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach if ((node)->magic != PROF_MAGIC_NODE) \ 148da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach return PROF_MAGIC_NODE; 149da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 150da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach/* profile parser declarations */ 151da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstruct parse_state { 152da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach int state; 153da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach int group_level; 154da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach int line_num; 155da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node *root_section; 156da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node *current_section; 157da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach}; 158da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 159da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic profile_syntax_err_cb_t syntax_err_cb; 160da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 161da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t parse_line(char *line, struct parse_state *state); 162da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 163da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#ifdef DEBUG_PROGRAM 164da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t profile_write_tree_file 165da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach (struct profile_node *root, FILE *dstfile); 166da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 167da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t profile_write_tree_to_buffer 168da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach (struct profile_node *root, char **buf); 169da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#endif 170da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 171da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 172da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic void profile_free_node 173da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach (struct profile_node *relation); 174da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 175da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t profile_create_node 176da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach (const char *name, const char *value, 177da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach struct profile_node **ret_node); 178da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 179da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#ifdef DEBUG_PROGRAM 180da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t profile_verify_node 181da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach (struct profile_node *node); 182da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach#endif 183da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbach 184da9f278c741e8ced7c1652720270918eb04ed348Jim Grosbachstatic errcode_t profile_add_node 18559642c260064a0c9140e048d702a21830020487fJim Grosbach (struct profile_node *section, 18659642c260064a0c9140e048d702a21830020487fJim Grosbach const char *name, const char *value, 18759642c260064a0c9140e048d702a21830020487fJim Grosbach struct profile_node **ret_node); 18859642c260064a0c9140e048d702a21830020487fJim Grosbach 18959642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t profile_find_node 19059642c260064a0c9140e048d702a21830020487fJim Grosbach (struct profile_node *section, 19159642c260064a0c9140e048d702a21830020487fJim Grosbach const char *name, const char *value, 19259642c260064a0c9140e048d702a21830020487fJim Grosbach int section_flag, void **state, 19359642c260064a0c9140e048d702a21830020487fJim Grosbach struct profile_node **node); 19459642c260064a0c9140e048d702a21830020487fJim Grosbach 19559642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t profile_node_iterator 19659642c260064a0c9140e048d702a21830020487fJim Grosbach (void **iter_p, struct profile_node **ret_node, 19759642c260064a0c9140e048d702a21830020487fJim Grosbach char **ret_name, char **ret_value); 19859642c260064a0c9140e048d702a21830020487fJim Grosbach 19959642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t profile_open_file 20059642c260064a0c9140e048d702a21830020487fJim Grosbach (const char * file, prf_file_t *ret_prof); 20159642c260064a0c9140e048d702a21830020487fJim Grosbach 20259642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t profile_update_file 20359642c260064a0c9140e048d702a21830020487fJim Grosbach (prf_file_t prf); 20459642c260064a0c9140e048d702a21830020487fJim Grosbach 20559642c260064a0c9140e048d702a21830020487fJim Grosbachstatic void profile_free_file 20659642c260064a0c9140e048d702a21830020487fJim Grosbach (prf_file_t profile); 20759642c260064a0c9140e048d702a21830020487fJim Grosbach 20859642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t profile_get_value(profile_t profile, const char *name, 20959642c260064a0c9140e048d702a21830020487fJim Grosbach const char *subname, const char *subsubname, 21059642c260064a0c9140e048d702a21830020487fJim Grosbach const char **ret_value); 21159642c260064a0c9140e048d702a21830020487fJim Grosbach 21259642c260064a0c9140e048d702a21830020487fJim Grosbach 21359642c260064a0c9140e048d702a21830020487fJim Grosbach/* 21459642c260064a0c9140e048d702a21830020487fJim Grosbach * prof_init.c --- routines that manipulate the user-visible profile_t 21559642c260064a0c9140e048d702a21830020487fJim Grosbach * object. 21659642c260064a0c9140e048d702a21830020487fJim Grosbach */ 21759642c260064a0c9140e048d702a21830020487fJim Grosbach 21859642c260064a0c9140e048d702a21830020487fJim Grosbachstatic int compstr(const void *m1, const void *m2) 21959642c260064a0c9140e048d702a21830020487fJim Grosbach{ 22059642c260064a0c9140e048d702a21830020487fJim Grosbach const char *s1 = *((const char * const *) m1); 22159642c260064a0c9140e048d702a21830020487fJim Grosbach const char *s2 = *((const char * const *) m2); 22259642c260064a0c9140e048d702a21830020487fJim Grosbach 22359642c260064a0c9140e048d702a21830020487fJim Grosbach return strcmp(s1, s2); 22459642c260064a0c9140e048d702a21830020487fJim Grosbach} 22559642c260064a0c9140e048d702a21830020487fJim Grosbach 22659642c260064a0c9140e048d702a21830020487fJim Grosbachstatic void free_list(char **list) 22759642c260064a0c9140e048d702a21830020487fJim Grosbach{ 22859642c260064a0c9140e048d702a21830020487fJim Grosbach char **cp; 22959642c260064a0c9140e048d702a21830020487fJim Grosbach 23059642c260064a0c9140e048d702a21830020487fJim Grosbach if (list == 0) 23159642c260064a0c9140e048d702a21830020487fJim Grosbach return; 23259642c260064a0c9140e048d702a21830020487fJim Grosbach 23359642c260064a0c9140e048d702a21830020487fJim Grosbach for (cp = list; *cp; cp++) 23459642c260064a0c9140e048d702a21830020487fJim Grosbach free(*cp); 23559642c260064a0c9140e048d702a21830020487fJim Grosbach free(list); 23659642c260064a0c9140e048d702a21830020487fJim Grosbach} 23759642c260064a0c9140e048d702a21830020487fJim Grosbach 23859642c260064a0c9140e048d702a21830020487fJim Grosbachstatic errcode_t get_dirlist(const char *dirname, char***ret_array) 23959642c260064a0c9140e048d702a21830020487fJim Grosbach{ 24059642c260064a0c9140e048d702a21830020487fJim Grosbach DIR *dir; 24159642c260064a0c9140e048d702a21830020487fJim Grosbach struct dirent *de; 24259642c260064a0c9140e048d702a21830020487fJim Grosbach struct stat st; 2437ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach errcode_t retval; 2447ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach char *fn, *cp; 2457ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach char **array = 0, **new_array; 2467ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach int max = 0, num = 0; 2477ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach 2487ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach dir = opendir(dirname); 2497ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach if (!dir) 2507ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach return errno; 2517ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach 2527ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach while ((de = readdir(dir)) != NULL) { 2537ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach for (cp = de->d_name; *cp; cp++) { 2547ed6d22e9637c52b3511ac6907830251d1124e60Jim Grosbach if (!isalnum(*cp) && 255e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach (*cp != '-') && 256e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach (*cp != '_')) 25776cbe02cdd57a297d9c6f1e5106e4718abd7ff9fJim Grosbach break; 258e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 259e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (*cp) 260e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach continue; 261e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach fn = malloc(strlen(dirname) + strlen(de->d_name) + 2); 262e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (!fn) { 263e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach retval = ENOMEM; 264e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach goto errout; 265e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 266e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach sprintf(fn, "%s/%s", dirname, de->d_name); 267e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if ((stat(fn, &st) < 0) || !S_ISREG(st.st_mode)) { 268e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach free(fn); 269e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach continue; 270e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 271e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (num >= max) { 272e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach max += 10; 273e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach new_array = realloc(array, sizeof(char *) * (max+1)); 274e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (!new_array) { 275e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach retval = ENOMEM; 276e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach goto errout; 277e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 278e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach array = new_array; 279e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 280e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach array[num++] = fn; 281e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 282e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (array) { 283e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach qsort(array, num, sizeof(char *), compstr); 284e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach array[num++] = 0; 285e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach } 286e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach *ret_array = array; 287e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach closedir(dir); 288e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach return 0; 289e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbacherrout: 290e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach closedir(dir); 291e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach free_list(array); 292e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach return retval; 293e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach} 294e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach 295e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbacherrcode_t 296e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbachprofile_init(const char **files, profile_t *ret_profile) 297e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach{ 298e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach const char **fs; 299e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach profile_t profile; 300e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach prf_file_t new_file, *last; 301e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach errcode_t retval = 0; 302e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach char **cpp, *cp, **array = 0; 303e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach 304e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach profile = malloc(sizeof(struct _profile_t)); 305e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if (!profile) 306e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach return ENOMEM; 307e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach memset(profile, 0, sizeof(struct _profile_t)); 308e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach profile->magic = PROF_MAGIC_PROFILE; 309e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach last = &profile->first_file; 310e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach 311e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach /* if the filenames list is not specified return an empty profile */ 312e52240c3705f3133eb8c4ebb4220054c68de2651Jim Grosbach if ( files ) { 31321101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) { 31421101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach retval = get_dirlist(*fs, &array); 31521101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach if (retval == 0) { 31621101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach if (!array) 31721101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach continue; 31821101d60ce94f51651f71eeb61ceb8264eccac83Jim Grosbach for (cpp = array; (cp = *cpp); cpp++) { 319fff76ee7ef007b2bb74804f165fee475e30ead0dJim Grosbach retval = profile_open_file(cp, &new_file); 320fff76ee7ef007b2bb74804f165fee475e30ead0dJim Grosbach if (retval == EACCES) 32137023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach continue; 32237023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach if (retval) 32337023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach goto errout; 32437023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach *last = new_file; 32537023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach last = &new_file->next; 32637023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach } 32737023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach } else if (retval != ENOTDIR) 32837023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach goto errout; 329f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach 330f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach retval = profile_open_file(*fs, &new_file); 331f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach /* if this file is missing, skip to the next */ 332f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach if (retval == ENOENT || retval == EACCES) { 333f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach continue; 334f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach } 33537023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach if (retval) 33637023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach goto errout; 33737023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach *last = new_file; 33837023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach last = &new_file->next; 33937023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach } 34037023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach /* 341f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach * If all the files were not found, return the appropriate error. 342f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach */ 343f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach if (!profile->first_file) { 344f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach profile_release(profile); 345f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach return ENOENT; 346f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach } 347f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach } 348f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach 349f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach free_list(array); 350f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach *ret_profile = profile; 351f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach return 0; 352f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbacherrout: 353f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach free_list(array); 354f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach profile_release(profile); 355f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach return retval; 356f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbach} 35737023b05c84000373fcfc0871edad3c2b995be33Jim Grosbach 358f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbachvoid 359f333d471d2cdd47d830dfe3a3e40efbb106c100dJim Grosbachprofile_release(profile_t profile) 36083ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach{ 36183ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach prf_file_t p, next; 36283ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach 36383ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach if (!profile || profile->magic != PROF_MAGIC_PROFILE) 36483ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach return; 36583ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach 36683ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach for (p = profile->first_file; p; p = next) { 36783ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach next = p->next; 36883ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach profile_free_file(p); 369d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach } 370d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach profile->magic = 0; 37183ab070fc1fbb02ca77b0a37e6ae0eacf58001e1Jim Grosbach free(profile); 372d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach} 373d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach 374d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach 375d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach/* 376d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach * prof_file.c ---- routines that manipulate an individual profile file. 377d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach */ 378d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach 379d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbacherrcode_t profile_open_file(const char * filespec, 380d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach prf_file_t *ret_prof) 381d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach{ 382d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach prf_file_t prf; 383d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach errcode_t retval; 384d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach char *home_env = 0; 385d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach unsigned int len; 386d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach char *expanded_filename; 387d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach 388d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach prf = malloc(sizeof(struct _prf_file_t)); 389d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach if (!prf) 390d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach return ENOMEM; 391d986bc66bc56251c2b7d5b9a89df14c4760568fcJim Grosbach memset(prf, 0, sizeof(struct _prf_file_t)); 39214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach prf->magic = PROF_MAGIC_FILE; 39314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 39414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach len = strlen(filespec)+1; 39514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (filespec[0] == '~' && filespec[1] == '/') { 39614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach home_env = getenv("HOME"); 39714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#ifdef HAVE_PWD_H 39814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (home_env == NULL) { 39914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#ifdef HAVE_GETWUID_R 40014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach struct passwd *pw, pwx; 40114ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach uid_t uid; 40214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach char pwbuf[BUFSIZ]; 40314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 40414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach uid = getuid(); 40514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (!getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) 40614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach && pw != NULL && pw->pw_dir[0] != 0) 40714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach home_env = pw->pw_dir; 40814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#else 40914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach struct passwd *pw; 41014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 41114ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach pw = getpwuid(getuid()); 41214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach home_env = pw->pw_dir; 41314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#endif 41414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach } 41514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#endif 41614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (home_env) 41714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach len += strlen(home_env); 41814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach } 41914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach expanded_filename = malloc(len); 42014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (expanded_filename == 0) { 42114ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach profile_free_file(prf); 42214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach return errno; 42314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach } 42414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (home_env) { 42514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach strcpy(expanded_filename, home_env); 42614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach strcat(expanded_filename, filespec+1); 42714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach } else 42814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach memcpy(expanded_filename, filespec, len); 42914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 43014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach prf->filespec = expanded_filename; 43114ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 43214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach retval = profile_update_file(prf); 43314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach if (retval) { 43414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach profile_free_file(prf); 43514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach return retval; 43614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach } 43714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 43814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach *ret_prof = prf; 43914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach return 0; 44014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach} 44114ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach 44214ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbacherrcode_t profile_update_file(prf_file_t prf) 44314ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach{ 44414ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach errcode_t retval; 44514ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#ifdef HAVE_STAT 44614ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach struct stat st; 44714ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#ifdef STAT_ONCE_PER_SECOND 44814ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach time_t now; 44914ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#endif 45014ab1c3387a240a914cf8b1907bb3609bae72269Jim Grosbach#endif 4516f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach FILE *f; 4526f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach char buf[2048]; 4536f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach struct parse_state state; 4546f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach 4556f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach#ifdef HAVE_STAT 4566f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach#ifdef STAT_ONCE_PER_SECOND 4576f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach now = time(0); 4586f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach if (now == prf->last_stat && prf->root != NULL) { 4596f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach return 0; 4606f9f8845028d4d3b96c33417398034a71137d867Jim Grosbach } 461032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach#endif 462032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (stat(prf->filespec, &st)) { 463032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach retval = errno; 464032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach return retval; 465032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach } 466032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach#ifdef STAT_ONCE_PER_SECOND 467032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach prf->last_stat = now; 468032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach#endif 469032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (st.st_mtime == prf->timestamp && prf->root != NULL) { 470032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach return 0; 471032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach } 472032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (prf->root) { 473032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach profile_free_node(prf->root); 474032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach prf->root = 0; 475032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach } 476032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach#else 477032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach /* 478032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach * If we don't have the stat() call, assume that our in-core 479032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach * memory image is correct. That is, we won't reread the 480032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach * profile file if it changes. 481032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach */ 482032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (prf->root) { 483032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach return 0; 484032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach } 485032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach#endif 486032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach memset(&state, 0, sizeof(struct parse_state)); 487032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach retval = profile_create_node("(root)", 0, &state.root_section); 488032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (retval) 489032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach return retval; 490032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach errno = 0; 491032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach f = fopen(prf->filespec, "r"); 492032434d622b6cd030a60bb9045a520c93b0d7d68Jim Grosbach if (f == NULL) { 493e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach retval = errno; 494e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach if (retval == 0) 495e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach retval = ENOENT; 496e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach return retval; 497e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach } 498e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach prf->upd_serial++; 499e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach while (!feof(f)) { 500e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach if (fgets(buf, sizeof(buf), f) == NULL) 501e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach break; 502e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach retval = parse_line(buf, &state); 503e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach if (retval) { 504e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach if (syntax_err_cb) 505e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach (syntax_err_cb)(prf->filespec, retval, 506e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach state.line_num); 507e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach fclose(f); 508e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach return retval; 509e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach } 510e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach } 511e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach prf->root = state.root_section; 512e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach 513e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach fclose(f); 514e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach 515e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach#ifdef HAVE_STAT 516e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach prf->timestamp = st.st_mtime; 517e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach#endif 518e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach return 0; 519e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach} 520e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach 521e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbachvoid profile_free_file(prf_file_t prf) 522e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach{ 523e77494e3e3da59afaa51d1bbcf732fa2851d865dJim Grosbach if (prf->root) 52400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach profile_free_node(prf->root); 52500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach if (prf->filespec) 52600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach free(prf->filespec); 52700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach free(prf); 52800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 52900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 53000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach/* Begin the profile parser */ 53100a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 53200a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachprofile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook) 53300a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 53400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach profile_syntax_err_cb_t old; 53500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 53600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach old = syntax_err_cb; 53700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach syntax_err_cb = hook; 53800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach return(old); 53900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 54000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 54100a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach#define STATE_INIT_COMMENT 0 54200a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach#define STATE_STD_LINE 1 54300a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach#define STATE_GET_OBRACE 2 54400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 54500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachstatic char *skip_over_blanks(char *cp) 54600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 54700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach while (*cp && isspace((int) (*cp))) 54800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach cp++; 54900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach return cp; 55000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 55100a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 55200a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachstatic int end_or_comment(char ch) 55300a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 55400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach return (ch == 0 || ch == '#' || ch == ';'); 55500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 55600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 55700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachstatic char *skip_over_nonblanks(char *cp) 55800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 55900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach while (!end_or_comment(*cp) && !isspace(*cp)) 56000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach cp++; 56100a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach return cp; 56200a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 56300a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 56400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachstatic void strip_line(char *line) 56500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 56600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach char *p = line + strlen(line); 56700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach while (p > line && (p[-1] == '\n' || p[-1] == '\r')) 56800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach *p-- = 0; 56900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach} 57000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 57100a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbachstatic void parse_quoted_string(char *str) 57200a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach{ 57300a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach char *to, *from; 57400a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 57500a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach to = from = str; 57600a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach 57700a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach for (to = from = str; *from && *from != '"'; to++, from++) { 57800a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach if (*from == '\\') { 57900a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach from++; 58000a66653cbe56dfbdb831172b54097bf8256a191Jim Grosbach switch (*from) { 581791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach case 'n': 582791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach *to = '\n'; 583791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach break; 584791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach case 't': 585791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach *to = '\t'; 586791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach break; 587791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach case 'b': 588791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach *to = '\b'; 589791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach break; 590791feea10071223886e2fe2bfa0e1f4cb2c0ce74Jim Grosbach default: 5913b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach *to = *from; 5923b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } 5933b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach continue; 5943b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } 5953b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach *to = *from; 5963b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } 5973b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach *to = '\0'; 5983b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach} 5993b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach 6003b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbachstatic errcode_t parse_line(char *line, struct parse_state *state) 6013b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach{ 6023b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach char *cp, ch, *tag, *value; 6033b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach char *p; 6043b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach errcode_t retval; 6053b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach struct profile_node *node; 6063b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach int do_subsection = 0; 6073b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach void *iter = 0; 6083b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach 6093b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach state->line_num++; 6103b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach if (state->state == STATE_GET_OBRACE) { 6113b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach cp = skip_over_blanks(line); 6123b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach if (*cp != '{') 6133b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach return PROF_MISSING_OBRACE; 6143b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach state->state = STATE_STD_LINE; 6153b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach return 0; 6163b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } 6173b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach if (state->state == STATE_INIT_COMMENT) { 6183b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach if (line[0] != '[') 6193b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach return 0; 6203b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach state->state = STATE_STD_LINE; 6213b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } 622e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach 623e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach if (*line == 0) 624e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach return 0; 62536711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach strip_line(line); 62636711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach cp = skip_over_blanks(line); 62736711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach ch = *cp; 62836711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (end_or_comment(ch)) 62936711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach return 0; 63036711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (ch == '[') { 63136711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (state->group_level > 0) 63236711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach return PROF_SECTION_NOTOP; 63336711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach cp++; 63436711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach cp = skip_over_blanks(cp); 63536711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach p = strchr(cp, ']'); 63636711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (p == NULL) 63736711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach return PROF_SECTION_SYNTAX; 63836711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (*cp == '"') { 63936711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach cp++; 640e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach parse_quoted_string(cp); 641e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach } else { 642e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach *p-- = '\0'; 643e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach while (isspace(*p) && (p > cp)) 644e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach *p-- = '\0'; 645e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach if (*cp == 0) 646e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach return PROF_SECTION_SYNTAX; 647e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach } 648e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach retval = profile_find_node(state->root_section, cp, 0, 1, 649e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach &iter, &state->current_section); 650e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach if (retval == PROF_NO_SECTION) { 651e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach retval = profile_add_node(state->root_section, 652e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach cp, 0, 653e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach &state->current_section); 654e540c7422ca13c950f0e8f6f93af7225bb7742a9Jim Grosbach if (retval) 6553b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach return retval; 6563b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } else if (retval) 657c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach return retval; 658c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach 659c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach /* 660c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach * Finish off the rest of the line. 661c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach */ 662c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach cp = p+1; 663c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach if (*cp == '*') { 664c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach state->current_section->final = 1; 66570d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach cp++; 66670d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach } 66770d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach /* 66870d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach * Spaces or comments after ']' should not be fatal 66970d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach */ 67070d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach cp = skip_over_blanks(cp); 67170d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach if (!end_or_comment(*cp)) 67270d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach return PROF_SECTION_SYNTAX; 67370d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach return 0; 67470d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach } 67570d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach if (ch == '}') { 67670d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach if (state->group_level == 0) 67770d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach return PROF_EXTRA_CBRACE; 67870d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach if (*(cp+1) == '*') 67970d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach state->current_section->final = 1; 68070d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach state->current_section = state->current_section->parent; 68170d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach state->group_level--; 68270d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach return 0; 68370d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach } 68470d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach /* 68570d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach * Parse the relations 68670d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach */ 68770d8fcfaa04eb20541b006a8fb97cbc1d3033cc4Jim Grosbach tag = cp; 688c8ae39e746a20dc326def0ccfc052df3e21f16d3Jim Grosbach cp = strchr(cp, '='); 689ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach if (!cp) 690ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach return PROF_RELATION_SYNTAX; 691ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach if (cp == tag) 692ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach return PROF_RELATION_SYNTAX; 693ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach *cp = '\0'; 694ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach if (*tag == '"') { 695ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach tag++; 6965f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach parse_quoted_string(tag); 6975f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach } else { 6985f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach /* Look for whitespace on left-hand side. */ 699ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach p = skip_over_nonblanks(tag); 700ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach if (*p) 701ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach *p++ = 0; 702ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach p = skip_over_blanks(p); 703ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach /* If we have more non-whitespace, it's an error. */ 704ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach if (*p) 7055f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach return PROF_RELATION_SYNTAX; 7065f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach } 7075f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach 7085f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach cp = skip_over_blanks(cp+1); 7095f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach value = cp; 7105f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach ch = value[0]; 7115f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach if (ch == '"') { 7125f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach value++; 7135f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach parse_quoted_string(value); 7145f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach } else if (end_or_comment(ch)) { 7155f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach do_subsection++; 7165f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach state->state = STATE_GET_OBRACE; 7175f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach } else if (value[0] == '{') { 7185f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach cp = skip_over_blanks(value+1); 7195f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach ch = *cp; 7205f16057d1e4b711d492091bc555693a03d4a1b6eJim Grosbach if (end_or_comment(ch)) 721ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach do_subsection++; 722ffa3225e26cc1977d20f0d9649fcd6f38a3c4815Jim Grosbach else 7231a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach return PROF_RELATION_SYNTAX; 7241a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach } else { 7251a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach cp = skip_over_nonblanks(value); 7261a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach p = skip_over_blanks(cp); 7271a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach ch = *p; 7281a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach *cp = 0; 7291a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach if (!end_or_comment(ch)) 7301a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach return PROF_RELATION_SYNTAX; 7311a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach } 7321a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach if (do_subsection) { 7332317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach p = strchr(tag, '*'); 7342317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach if (p) 7352317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach *p = '\0'; 7362317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach retval = profile_add_node(state->current_section, 7372317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach tag, 0, &state->current_section); 7382317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach if (retval) 7392317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach return retval; 7402317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach if (p) 7412317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach state->current_section->final = 1; 7422317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach state->group_level++; 7432317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach return 0; 7442317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach } 7452317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach p = strchr(tag, '*'); 7462317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach if (p) 7472317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach *p = '\0'; 7482317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach profile_add_node(state->current_section, tag, value, &node); 7492317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach if (p) 7502317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach node->final = 1; 7512317fe1584e02582c616c1c4d15954999ff5525aJim Grosbach return 0; 75280d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach} 75380d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach 75480d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach#ifdef DEBUG_PROGRAM 75580d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach/* 75680d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach * Return TRUE if the string begins or ends with whitespace 75780d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach */ 75880d01dd3d19a84621324ac444c6749602df7a513Jim Grosbachstatic int need_double_quotes(char *str) 75980d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach{ 76080d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach if (!str || !*str) 76180d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach return 0; 76280d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1)))) 76380d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach return 1; 76480d01dd3d19a84621324ac444c6749602df7a513Jim Grosbach if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b') || 7651a2be4db5b12cb7bfa351bcebd5e94b0decb021fJim Grosbach strchr(str, ' ') || strchr(str, '#') || strchr(str, ';')) 766b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach return 1; 767b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach return 0; 768b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach} 769b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach 770b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach/* 771b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach * Output a string with double quotes, doing appropriate backquoting 772b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach * of characters as necessary. 773b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach */ 774b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbachstatic void output_quoted_string(char *str, void (*cb)(const char *,void *), 775b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach void *data) 776b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach{ 777b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach char ch; 778b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach char buf[2]; 779b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach 780b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\"", data); 781b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach if (!str) { 782b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\"", data); 783b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach return; 784b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach } 785b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach buf[1] = 0; 786b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach while ((ch = *str++)) { 787b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach switch (ch) { 788b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach case '\\': 789b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\\\\", data); 790b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 791b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach case '\n': 792b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\\n", data); 793b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 794b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach case '\t': 795b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\\t", data); 796b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 797b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach case '\b': 798b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\\b", data); 799b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 800b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach default: 801b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach /* This would be a lot faster if we scanned 802b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach forward for the next "interesting" 803b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach character. */ 804b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach buf[0] = ch; 805b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb(buf, data); 806b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 807b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach } 808b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach } 809b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach cb("\"", data); 810b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach} 811b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach 812b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach#ifndef EOL 813b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach#define EOL "\n" 814b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach#endif 815b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach 816b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach/* Errors should be returned, not ignored! */ 817b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbachstatic void dump_profile(struct profile_node *root, int level, 818b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach void (*cb)(const char *, void *), void *data) 819b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach{ 820b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach int i; 821b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach struct profile_node *p; 822b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach void *iter; 823b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach long retval; 824b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach 825b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach iter = 0; 826b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach do { 827b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach retval = profile_find_node(root, 0, 0, 0, &iter, &p); 828b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach if (retval) 829b29b4dd988c50d5c4a15cd196e7910bf46f30b83Jim Grosbach break; 830ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach for (i=0; i < level; i++) 831ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach cb("\t", data); 832ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach if (need_double_quotes(p->name)) 833ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach output_quoted_string(p->name, cb, data); 834ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach else 835ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach cb(p->name, data); 836ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach cb(" = ", data); 837ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach if (need_double_quotes(p->value)) 838ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach output_quoted_string(p->value, cb, data); 839ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach else 840ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach cb(p->value, data); 841ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach cb(EOL, data); 842ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach } while (iter != 0); 843c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach 844c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach iter = 0; 845c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach do { 846c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach retval = profile_find_node(root, 0, 0, 1, &iter, &p); 847c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach if (retval) 848c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach break; 849c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach if (level == 0) { /* [xxx] */ 850c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb("[", data); 851c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach if (need_double_quotes(p->name)) 852c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach output_quoted_string(p->name, cb, data); 853c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach else 854c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(p->name, data); 855c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb("]", data); 856c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(p->final ? "*" : "", data); 857c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(EOL, data); 858c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach dump_profile(p, level+1, cb, data); 859c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(EOL, data); 860c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach } else { /* xxx = { ... } */ 861c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach for (i=0; i < level; i++) 862c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb("\t", data); 863c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach if (need_double_quotes(p->name)) 864c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach output_quoted_string(p->name, cb, data); 865c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach else 866c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(p->name, data); 867c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(" = {", data); 868c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(EOL, data); 869c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach dump_profile(p, level+1, cb, data); 870c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach for (i=0; i < level; i++) 871c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb("\t", data); 872c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb("}", data); 873c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(p->final ? "*" : "", data); 874c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach cb(EOL, data); 875c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach } 876c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach } while (iter != 0); 877c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach} 878c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach 879c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbachstatic void dump_profile_to_file_cb(const char *str, void *data) 880c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach{ 881c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach fputs(str, data); 882c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach} 883c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach 884c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbacherrcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile) 885c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach{ 886c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach dump_profile(root, 0, dump_profile_to_file_cb, dstfile); 887c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach return 0; 888c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach} 889c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach 890c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbachstruct prof_buf { 891c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach char *base; 892c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach size_t cur, max; 893c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach int err; 894c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach}; 895c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach 896c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbachstatic void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len) 897c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach{ 898c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach if (b->err) 899a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach return; 900a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach if (b->max - b->cur < len) { 901a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach size_t newsize; 902a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach char *newptr; 903a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach 904a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach newsize = b->max + (b->max >> 1) + len + 1024; 905a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach newptr = realloc(b->base, newsize); 906a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach if (newptr == NULL) { 907a67851445902d1fc01fa2a37a3dfc347af949f84Jim Grosbach b->err = 1; 908c3635c2e928a7ecde11398ff272411f6dea2dcd2Jim Grosbach return; 909ab40f4b737b0a87c4048a9ad2f0c02be735e3770Jim Grosbach } 91088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach b->base = newptr; 91188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach b->max = newsize; 91288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach } 91388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach memcpy(b->base + b->cur, d, len); 91488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach b->cur += len; /* ignore overflow */ 91588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach} 91688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 91788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbachstatic void dump_profile_to_buffer_cb(const char *str, void *data) 91888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach{ 91988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach add_data_to_buffer((struct prof_buf *)data, str, strlen(str)); 92088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach} 92188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 92288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbacherrcode_t profile_write_tree_to_buffer(struct profile_node *root, 92388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach char **buf) 92488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach{ 92588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach struct prof_buf prof_buf = { 0, 0, 0, 0 }; 92688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 92788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf); 92888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (prof_buf.err) { 92988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach *buf = NULL; 93088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach return ENOMEM; 93188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach } 93288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach add_data_to_buffer(&prof_buf, "", 1); /* append nul */ 93388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) { 93488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach char *newptr = realloc(prof_buf.base, prof_buf.cur); 93588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (newptr) 93688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach prof_buf.base = newptr; 93788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach } 93888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach *buf = prof_buf.base; 93988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach return 0; 94088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach} 94188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach#endif 94288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 94388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach/* 94488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * prof_tree.c --- these routines maintain the parse tree of the 94588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * config file. 94688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * 94788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * All of the details of how the tree is stored is abstracted away in 94888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * this file; all of the other profile routines build, access, and 94988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * modify the tree via the accessor functions found in this file. 95088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * 95188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * Each node may represent either a relation or a section header. 95288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * 95388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * A section header must have its value field set to 0, and may a one 95488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * or more child nodes, pointed to by first_child. 95588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * 95688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * A relation has as its value a pointer to allocated memory 95788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * containing a string. Its first_child pointer must be null. 95888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * 95988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach */ 96088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 96188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach/* 96288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach * Free a node, and any children 96388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach */ 96488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbachvoid profile_free_node(struct profile_node *node) 96588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach{ 96688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach struct profile_node *child, *next; 96788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 96888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (node->magic != PROF_MAGIC_NODE) 96988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach return; 97088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 97188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (node->name) 97288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach free(node->name); 97388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach if (node->value) 97488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach free(node->value); 97588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 97688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach for (child=node->first_child; child; child = next) { 97788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach next = child->next; 97888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach profile_free_node(child); 97988d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach } 98088d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach node->magic = 0; 98188d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 98288d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach free(node); 98388d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach} 98488d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 98588d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach#ifndef HAVE_STRDUP 98688d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach#undef strdup 98761b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach#define strdup MYstrdup 98861b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbachstatic char *MYstrdup (const char *s) 98961b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach{ 99061b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach size_t sz = strlen(s) + 1; 99161b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach char *p = malloc(sz); 99261b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach if (p != 0) 99361b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach memcpy(p, s, sz); 99461b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach return p; 99561b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach} 99661b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach#endif 99761b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach 99861b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach/* 99961b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach * Create a node 100061b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach */ 100161b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbacherrcode_t profile_create_node(const char *name, const char *value, 100261b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach struct profile_node **ret_node) 100361b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach{ 100461b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach struct profile_node *new; 100561b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach 100661b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach new = malloc(sizeof(struct profile_node)); 100761b1b21e9ad2b8af163a352766eeb159979f4ff2Jim Grosbach if (!new) 100810c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach return ENOMEM; 100910c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach memset(new, 0, sizeof(struct profile_node)); 101010c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach new->name = strdup(name); 101110c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach if (new->name == 0) { 101210c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach profile_free_node(new); 101310c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach return ENOMEM; 101410c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach } 101510c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach if (value) { 101610c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach new->value = strdup(value); 101710c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach if (new->value == 0) { 101810c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach profile_free_node(new); 101910c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach return ENOMEM; 102010c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach } 102110c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach } 102210c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach new->magic = PROF_MAGIC_NODE; 102310c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach 102410c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach *ret_node = new; 102510c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach return 0; 102610c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach} 102710c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach 102810c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach/* 102910c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach * This function verifies that all of the representation invarients of 103010c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach * the profile are true. If not, we have a programming bug somewhere, 103110c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach * probably in this file. 103210c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach */ 103310c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach#ifdef DEBUG_PROGRAM 103410c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbacherrcode_t profile_verify_node(struct profile_node *node) 103510c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach{ 103610c7d70a4e843b3006db9f5f583d6f6f56cc245eJim Grosbach struct profile_node *p, *last; 103788d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach errcode_t retval; 103888d1bc832ca5b458c8460929227be8eae6c6bdc3Jim Grosbach 1039a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach CHECK_MAGIC(node); 1040a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1041a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (node->value && node->first_child) 1042a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_SECTION_WITH_VALUE; 1043a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1044a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach last = 0; 1045a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach for (p = node->first_child; p; last = p, p = p->next) { 1046a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (p->prev != last) 1047a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_BAD_LINK_LIST; 1048a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (last && (last->next != p)) 1049a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_BAD_LINK_LIST; 1050a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (node->group_level+1 != p->group_level) 1051a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_BAD_GROUP_LVL; 1052a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (p->parent != node) 1053a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_BAD_PARENT_PTR; 1054a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach retval = profile_verify_node(p); 1055a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (retval) 1056a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return retval; 1057a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach } 1058a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return 0; 1059a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach} 1060a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach#endif 1061a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1062a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach/* 1063a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach * Add a node to a particular section 1064a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach */ 1065a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbacherrcode_t profile_add_node(struct profile_node *section, const char *name, 1066a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach const char *value, struct profile_node **ret_node) 1067a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach{ 1068a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach errcode_t retval; 1069a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach struct profile_node *p, *last, *new; 1070a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1071a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach CHECK_MAGIC(section); 1072a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1073a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (section->value) 1074a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return PROF_ADD_NOT_SECTION; 1075a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach 1076a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach /* 1077a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach * Find the place to insert the new node. We look for the 1078a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach * place *after* the last match of the node name, since 1079a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach * order matters. 1080a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach */ 108141438398c13be01ec53c3ad6b08a6cab47e96735Jim Grosbach for (p=section->first_child, last = 0; p; last = p, p = p->next) { 1082a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach int cmp; 1083a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach cmp = strcmp(p->name, name); 1084a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (cmp > 0) 1085a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach break; 1086a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach } 1087a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach retval = profile_create_node(name, value, &new); 1088a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (retval) 1089a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach return retval; 1090a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach new->group_level = section->group_level+1; 1091a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach new->deleted = 0; 1092a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach new->parent = section; 1093a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach new->prev = last; 1094a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach new->next = p; 1095a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (p) 1096a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach p->prev = new; 1097a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach if (last) 1098a4c34ab54485f64d3b962a499526825a7a0d4bbcJim Grosbach last->next = new; 1099616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach else 1100616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach section->first_child = new; 1101616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach if (ret_node) 1102616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach *ret_node = new; 1103616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach return 0; 1104616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach} 1105616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach 1106616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach/* 1107616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * Iterate through the section, returning the nodes which match 1108616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * the given name. If name is NULL, then interate through all the 1109616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * nodes in the section. If section_flag is non-zero, only return the 1110616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * section which matches the name; don't return relations. If value 1111616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * is non-NULL, then only return relations which match the requested 1112616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * value. (The value argument is ignored if section_flag is non-zero.) 1113616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * 1114616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * The first time this routine is called, the state pointer must be 1115616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * null. When this profile_find_node_relation() returns, if the state 1116616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * pointer is non-NULL, then this routine should be called again. 1117616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * (This won't happen if section_flag is non-zero, obviously.) 1118616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach * 1119616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach */ 1120616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbacherrcode_t profile_find_node(struct profile_node *section, const char *name, 1121616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach const char *value, int section_flag, void **state, 1122616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach struct profile_node **node) 1123616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach{ 1124616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach struct profile_node *p; 1125616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach 1126616fbdf987170addd0d8f75f4fd677589d54cd75Jim Grosbach CHECK_MAGIC(section); 112786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach p = *state; 112886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (p) { 112986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach CHECK_MAGIC(p); 113086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } else 113186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach p = section->first_child; 113286fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach 113386fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach for (; p; p = p->next) { 113486fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (name && (strcmp(p->name, name))) 113586fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 113686fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (section_flag) { 113786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (p->value) 113886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 113986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } else { 114086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (!p->value) 114186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 114286fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (value && (strcmp(p->value, value))) 114386fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 114486fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } 114586fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (p->deleted) 114686fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 114786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach /* A match! */ 114886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (node) 114986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach *node = p; 115086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach break; 115186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } 115286fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (p == 0) { 115386fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach *state = 0; 115486fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION; 115586fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } 115686fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach /* 115786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach * OK, we've found one match; now let's try to find another 115886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach * one. This way, if we return a non-zero state pointer, 115986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach * there's guaranteed to be another match that's returned. 116086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach */ 116186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach for (p = p->next; p; p = p->next) { 116286fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (name && (strcmp(p->name, name))) 116386fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 116486fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (section_flag) { 116586fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (p->value) 116686fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 116786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } else { 116886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (!p->value) 116986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 117086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach if (value && (strcmp(p->value, value))) 117186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach continue; 117286fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } 117386fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach /* A match! */ 117486fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach break; 117586fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach } 117686fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach *state = p; 117786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach return 0; 117886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach} 117986fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach 118086fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach/* 118186fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach * This is a general-purpose iterator for returning all nodes that 1182f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach * match the specified name array. 1183f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach */ 1184f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbachstruct profile_iterator { 1185f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach prf_magic_t magic; 1186f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach profile_t profile; 1187f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach int flags; 1188f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach const char *const *names; 1189f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach const char *name; 1190f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach prf_file_t file; 1191f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach int file_serial; 1192f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach int done_idx; 1193f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach struct profile_node *node; 1194f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach int num; 1195f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach}; 1196f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach 1197f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbacherrcode_t 1198f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbachprofile_iterator_create(profile_t profile, const char *const *names, int flags, 1199f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach void **ret_iter) 1200f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach{ 1201f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach struct profile_iterator *iter; 1202f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach int done_idx = 0; 1203f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach 1204f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if (profile == 0) 1205f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return PROF_NO_PROFILE; 1206f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if (profile->magic != PROF_MAGIC_PROFILE) 1207f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return PROF_MAGIC_PROFILE; 1208f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if (!names) 1209f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return PROF_BAD_NAMESET; 1210f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if (!(flags & PROFILE_ITER_LIST_SECTION)) { 1211f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if (!names[0]) 1212f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return PROF_BAD_NAMESET; 1213f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach done_idx = 1; 1214f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach } 1215f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach 1216f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach if ((iter = malloc(sizeof(struct profile_iterator))) == NULL) 1217f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return ENOMEM; 1218f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach 1219f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->magic = PROF_MAGIC_ITERATOR; 1220f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->profile = profile; 1221f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->names = names; 1222f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->flags = flags; 1223f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->file = profile->first_file; 1224f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->done_idx = done_idx; 1225f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->node = 0; 1226f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach iter->num = 0; 1227f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach *ret_iter = iter; 1228f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach return 0; 1229f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach} 1230f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach 1231f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbachvoid profile_iterator_free(void **iter_p) 1232f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach{ 1233f790193aec11747bb35206d2c79e0c5ffbc6dc7fJim Grosbach struct profile_iterator *iter; 12348ae45af7941dc3e78859ba3624676081590c435dJim Grosbach 12358ae45af7941dc3e78859ba3624676081590c435dJim Grosbach if (!iter_p) 12368ae45af7941dc3e78859ba3624676081590c435dJim Grosbach return; 12378ae45af7941dc3e78859ba3624676081590c435dJim Grosbach iter = *iter_p; 12388ae45af7941dc3e78859ba3624676081590c435dJim Grosbach if (!iter || iter->magic != PROF_MAGIC_ITERATOR) 12398ae45af7941dc3e78859ba3624676081590c435dJim Grosbach return; 12408ae45af7941dc3e78859ba3624676081590c435dJim Grosbach free(iter); 12418ae45af7941dc3e78859ba3624676081590c435dJim Grosbach *iter_p = 0; 12428ae45af7941dc3e78859ba3624676081590c435dJim Grosbach} 12438ae45af7941dc3e78859ba3624676081590c435dJim Grosbach 12448ae45af7941dc3e78859ba3624676081590c435dJim Grosbach/* 12458ae45af7941dc3e78859ba3624676081590c435dJim Grosbach * Note: the returned character strings in ret_name and ret_value 12468ae45af7941dc3e78859ba3624676081590c435dJim Grosbach * points to the stored character string in the parse string. Before 12478ae45af7941dc3e78859ba3624676081590c435dJim Grosbach * this string value is returned to a calling application 12488ae45af7941dc3e78859ba3624676081590c435dJim Grosbach * (profile_node_iterator is not an exported interface), it should be 12498ae45af7941dc3e78859ba3624676081590c435dJim Grosbach * strdup()'ed. 12508ae45af7941dc3e78859ba3624676081590c435dJim Grosbach */ 12518ae45af7941dc3e78859ba3624676081590c435dJim Grosbacherrcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node, 12528ae45af7941dc3e78859ba3624676081590c435dJim Grosbach char **ret_name, char **ret_value) 12538ae45af7941dc3e78859ba3624676081590c435dJim Grosbach{ 12548ae45af7941dc3e78859ba3624676081590c435dJim Grosbach struct profile_iterator *iter = *iter_p; 12558ae45af7941dc3e78859ba3624676081590c435dJim Grosbach struct profile_node *section, *p; 12568ae45af7941dc3e78859ba3624676081590c435dJim Grosbach const char *const *cpp; 125786fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach errcode_t retval; 125886fdff0fa79b2c00cb68a2961cca0466eb50d666Jim Grosbach int skip_num = 0; 12598409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach 12608409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (!iter || iter->magic != PROF_MAGIC_ITERATOR) 12618409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach return PROF_MAGIC_ITERATOR; 12628409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (iter->file && iter->file->magic != PROF_MAGIC_FILE) 12638409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach return PROF_MAGIC_FILE; 12648409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach /* 12658409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach * If the file has changed, then the node pointer is invalid, 12668409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach * so we'll have search the file again looking for it. 12678409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach */ 12688409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (iter->node && (iter->file && 12698409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach iter->file->upd_serial != iter->file_serial)) { 12708409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach iter->flags &= ~PROFILE_ITER_FINAL_SEEN; 12718409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach skip_num = iter->num; 12728409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach iter->node = 0; 12738409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } 12748409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (iter->node && iter->node->magic != PROF_MAGIC_NODE) { 12758409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach return PROF_MAGIC_NODE; 12768409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } 12778409f047312da0318af2a2fce162810ca3a95da3Jim Grosbachget_new_file: 12788409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (iter->node == 0) { 12798409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (iter->file == 0 || 12808409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach (iter->flags & PROFILE_ITER_FINAL_SEEN)) { 12818409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach profile_iterator_free(iter_p); 12828409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (ret_node) 12838409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach *ret_node = 0; 12848409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (ret_name) 12858409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach *ret_name = 0; 12868409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (ret_value) 12878409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach *ret_value =0; 12888409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach return 0; 12898409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } 12908409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if ((retval = profile_update_file(iter->file))) { 12918409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (retval == ENOENT || retval == EACCES) { 12928409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach /* XXX memory leak? */ 12938409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach iter->file = iter->file->next; 12948409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach skip_num = 0; 12958409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach retval = 0; 12968409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach goto get_new_file; 12978409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } else { 12988409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach profile_iterator_free(iter_p); 12998409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach return retval; 13008409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } 13018409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach } 13028409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach iter->file_serial = iter->file->upd_serial; 13038409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach /* 13048409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach * Find the section to list if we are a LIST_SECTION, 13058409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach * or find the containing section if not. 13068409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach */ 13078409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach section = iter->file->root; 13088409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach for (cpp = iter->names; cpp[iter->done_idx]; cpp++) { 13098409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach for (p=section->first_child; p; p = p->next) { 13108409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach if (!strcmp(p->name, *cpp) && !p->value) 13118409f047312da0318af2a2fce162810ca3a95da3Jim Grosbach break; 1312fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach } 1313fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach if (!p) { 1314fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach section = 0; 1315fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach break; 1316fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach } 1317fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach section = p; 1318fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach if (p->final) 1319fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach iter->flags |= PROFILE_ITER_FINAL_SEEN; 1320fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach } 1321fb8989e64024547e4ad5ab6fe4d94fe146a7899fJim Grosbach if (!section) { 13229076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach iter->file = iter->file->next; 13239076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach skip_num = 0; 13249076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach goto get_new_file; 13259076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach } 13269076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach iter->name = *cpp; 13279076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach iter->node = section->first_child; 13289076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach } 13299076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach /* 13309076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach * OK, now we know iter->node is set up correctly. Let's do 13319076b6e8f43c7eade7e0b667081f94df097e85c3Jim Grosbach * the search. 1332c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach */ 1333c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach for (p = iter->node; p; p = p->next) { 1334c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach if (iter->name && strcmp(p->name, iter->name)) 1335c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach continue; 1336c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach if ((iter->flags & PROFILE_ITER_SECTIONS_ONLY) && 1337fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach p->value) 1338fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach continue; 1339c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach if ((iter->flags & PROFILE_ITER_RELATIONS_ONLY) && 1340c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach !p->value) 1341c27d4f9ea0cb9064d3e2cadb384d73e95e9de449Jim Grosbach continue; 1342248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (skip_num > 0) { 1343248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach skip_num--; 1344248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach continue; 1345248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach } 1346248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (p->deleted) 1347248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach continue; 1348248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach break; 1349248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach } 1350248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach iter->num++; 1351248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (!p) { 1352248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach iter->file = iter->file->next; 1353248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach iter->node = 0; 1354248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach skip_num = 0; 1355248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach goto get_new_file; 1356248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach } 1357248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if ((iter->node = p->next) == NULL) 1358248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach iter->file = iter->file->next; 1359248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (ret_node) 1360248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach *ret_node = p; 1361248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (ret_name) 1362248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach *ret_name = p->name; 1363248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (ret_value) 1364248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach *ret_value = p->value; 1365248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach return 0; 1366248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach} 1367248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach 1368248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach 1369248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach/* 1370248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach * prof_get.c --- routines that expose the public interfaces for 1371248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach * querying items from the profile. 1372248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach * 1373248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach */ 1374248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach 1375248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach/* 1376248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach * This function only gets the first value from the file; it is a 1377248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach * helper function for profile_get_string, profile_get_integer, etc. 1378248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach */ 1379248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbacherrcode_t profile_get_value(profile_t profile, const char *name, 1380248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach const char *subname, const char *subsubname, 1381248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach const char **ret_value) 1382248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach{ 1383248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach errcode_t retval; 1384248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach void *state; 1385248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach char *value; 1386248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach const char *names[4]; 13877c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach 13887c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach names[0] = name; 13897c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach names[1] = subname; 13907c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach names[2] = subsubname; 13917c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach names[3] = 0; 13927c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach 13937c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach if ((retval = profile_iterator_create(profile, names, 13947c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach PROFILE_ITER_RELATIONS_ONLY, 13957c9fbc0340aff9e20fd9009be23ffd279c1c0a7dJim Grosbach &state))) 13960ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach return retval; 13970ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach 13980ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach if ((retval = profile_node_iterator(&state, 0, 0, &value))) 13990ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach goto cleanup; 14000ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach 14010ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach if (value) 14020ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach *ret_value = value; 14030ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach else 14040ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach retval = PROF_NO_RELATION; 14050ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach 14060ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbachcleanup: 14070ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach profile_iterator_free(&state); 14080ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach return retval; 14090ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach} 14100ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach 14110ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbacherrcode_t 14120ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbachprofile_get_string(profile_t profile, const char *name, const char *subname, 14130ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach const char *subsubname, const char *def_val, 14140ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach char **ret_string) 14150ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach{ 14160ffd4a09dfb1ee56ec335fed0d15954f92cfa5b3Jim Grosbach const char *value; 1417b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach errcode_t retval; 1418b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach 1419b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach if (profile) { 1420b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach retval = profile_get_value(profile, name, subname, 1421b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach subsubname, &value); 1422b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) 1423b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach value = def_val; 1424b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach else if (retval) 1425b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach return retval; 1426b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach } else 1427b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach value = def_val; 1428b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach 1429b206daaec1a2ec25e99fbdc413cd0866cec160b2Jim Grosbach if (value) { 1430248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach *ret_string = malloc(strlen(value)+1); 1431248e6c328c06afc2a6af6b95a1a8a41c1b53055cJim Grosbach if (*ret_string == 0) 1432ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return ENOMEM; 1433b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach strcpy(*ret_string, value); 1434b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach } else 1435b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach *ret_string = 0; 1436b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach return 0; 1437b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach} 1438b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach 1439b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbacherrcode_t 1440b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbachprofile_get_integer(profile_t profile, const char *name, const char *subname, 1441b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach const char *subsubname, int def_val, int *ret_int) 1442b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach{ 1443b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach const char *value; 1444b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach errcode_t retval; 1445b544f68b70475f06a8ec39c874297549edc0f695Jim Grosbach char *end_value; 1446ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach long ret_long; 1447ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1448ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach *ret_int = def_val; 1449ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if (profile == 0) 1450ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return 0; 1451ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1452ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach retval = profile_get_value(profile, name, subname, subsubname, &value); 1453ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 1454ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach *ret_int = def_val; 1455ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return 0; 1456ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach } else if (retval) 1457ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return retval; 1458ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1459ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if (value[0] == 0) 1460ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach /* Empty string is no good. */ 1461ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return PROF_BAD_INTEGER; 1462ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach errno = 0; 1463ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach ret_long = strtol (value, &end_value, 10); 1464ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1465ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach /* Overflow or underflow. */ 1466ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0) 1467ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return PROF_BAD_INTEGER; 1468ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach /* Value outside "int" range. */ 1469ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if ((long) (int) ret_long != ret_long) 1470ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return PROF_BAD_INTEGER; 1471ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach /* Garbage in string. */ 1472ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach if (end_value != value + strlen (value)) 1473ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return PROF_BAD_INTEGER; 1474ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1475ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1476ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach *ret_int = ret_long; 1477ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach return 0; 1478ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach} 1479ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbach 1480ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbacherrcode_t 1481ce501030d9b0213d951fbf05f928ac75b06b5a3aJim Grosbachprofile_get_uint(profile_t profile, const char *name, const char *subname, 148244a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach const char *subsubname, unsigned int def_val, 148344a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach unsigned int *ret_int) 148444a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach{ 148544a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach const char *value; 148644a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach errcode_t retval; 148744a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach char *end_value; 148844a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach unsigned long ret_long; 148944a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach 149044a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach *ret_int = def_val; 149144a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach if (profile == 0) 149244a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach return 0; 149344a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach 149444a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach retval = profile_get_value(profile, name, subname, subsubname, &value); 149544a456332f1f41d1e0b2815d93e47a88d501ee6eJim Grosbach if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 14966808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_int = def_val; 14976808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 14986808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } else if (retval) 14996808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return retval; 15006808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15016808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (value[0] == 0) 15026808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach /* Empty string is no good. */ 15036808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_BAD_INTEGER; 15046808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach errno = 0; 15056808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach ret_long = strtoul (value, &end_value, 10); 15066808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15076808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach /* Overflow or underflow. */ 15086808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if ((ret_long == ULONG_MAX) && errno != 0) 15096808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_BAD_INTEGER; 15106808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach /* Value outside "int" range. */ 15116808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if ((unsigned long) (unsigned int) ret_long != ret_long) 15126808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_BAD_INTEGER; 15136808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach /* Garbage in string. */ 15146808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (end_value != value + strlen (value)) 15156808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_BAD_INTEGER; 15166808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15176808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_int = ret_long; 15186808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 15196808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach} 15206808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15216808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbachstatic const char *const conf_yes[] = { 15226808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach "y", "yes", "true", "t", "1", "on", 15236808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 0, 15246808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach}; 15256808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15266808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbachstatic const char *const conf_no[] = { 15276808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach "n", "no", "false", "nil", "0", "off", 15286808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 0, 15296808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach}; 15306808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15316808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbachstatic errcode_t 15326808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbachprofile_parse_boolean(const char *s, int *ret_boolean) 15336808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach{ 15346808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach const char *const *p; 15356808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15366808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (ret_boolean == NULL) 15376808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_EINVAL; 15386808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15396808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach for(p=conf_yes; *p; p++) { 15406808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (!strcasecmp(*p,s)) { 15416808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_boolean = 1; 15426808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 15436808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } 15446808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } 15456808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15466808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach for(p=conf_no; *p; p++) { 15476808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (!strcasecmp(*p,s)) { 15486808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_boolean = 0; 15496808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 15506808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } 15516808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } 15526808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15536808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return PROF_BAD_BOOLEAN; 15546808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach} 15556808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15566808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbacherrcode_t 15576808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbachprofile_get_boolean(profile_t profile, const char *name, const char *subname, 15586808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach const char *subsubname, int def_val, int *ret_boolean) 15596808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach{ 15606808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach const char *value; 15616808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach errcode_t retval; 15626808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15636808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (profile == 0) { 15646808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_boolean = def_val; 15656808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 15666808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } 15676808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15686808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach retval = profile_get_value(profile, name, subname, subsubname, &value); 15696808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 15706808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach *ret_boolean = def_val; 15716808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return 0; 15726808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach } else if (retval) 15736808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return retval; 15746808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 15756808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach return profile_parse_boolean (value, ret_boolean); 15766808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach} 15776808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach 1578bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbacherrcode_t 1579bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbachprofile_iterator(void **iter_p, char **ret_name, char **ret_value) 1580bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach{ 1581bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach char *name, *value; 1582bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach errcode_t retval; 1583bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach 1584bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach retval = profile_node_iterator(iter_p, 0, &name, &value); 1585bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (retval) 1586bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach return retval; 1587bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach 1588bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (ret_name) { 1589bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (name) { 1590bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach *ret_name = malloc(strlen(name)+1); 1591bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (!*ret_name) 1592bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach return ENOMEM; 1593bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach strcpy(*ret_name, name); 1594bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach } else 1595bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach *ret_name = 0; 1596bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach } 1597bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (ret_value) { 1598bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (value) { 1599bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach *ret_value = malloc(strlen(value)+1); 16000e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach if (!*ret_value) { 1601bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach if (ret_name) { 1602bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach free(*ret_name); 1603bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach *ret_name = 0; 1604bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach } 1605bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach return ENOMEM; 1606bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach } 1607bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach strcpy(*ret_value, value); 1608bf2845c0d8a77d24e9971871badeba8cee7b2648Jim Grosbach } else 16090e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach *ret_value = 0; 16100e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach } 16110e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach return 0; 16120e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach} 16130e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16140e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach#ifdef DEBUG_PROGRAM 16150e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16160e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach/* 16170e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach * test_profile.c --- testing program for the profile routine 16180e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach */ 16190e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16200e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach#include "argv_parse.h" 16210e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach#include "profile_helpers.h" 16220e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16230e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbachconst char *program_name = "test_profile"; 16240e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16250e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach#define PRINT_VALUE 1 16260e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach#define PRINT_VALUES 2 16270e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16280e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbachstatic void do_cmd(profile_t profile, char **argv) 16290e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach{ 16300e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach errcode_t retval; 16310e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach const char **names, *value; 16320e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach char **values, **cpp; 16330e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach char *cmd; 16340e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach int print_status; 16350e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach 16360e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach cmd = *(argv); 16370e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach names = (const char **) argv + 1; 16380e76edf8c05c5107acb687b898fea686ae756c38Jim Grosbach print_status = 0; 16396808f21757f4f2be05a3b12a67d9360b4f9f62e2Jim Grosbach retval = 0; 16406ab4e3dd2375c3dcee06dde37437dc0c5a99aa24Jim Grosbach if (cmd == 0) 16416ab4e3dd2375c3dcee06dde37437dc0c5a99aa24Jim Grosbach return; 1642580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach if (!strcmp(cmd, "query")) { 1643580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach retval = profile_get_values(profile, names, &values); 1644580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach print_status = PRINT_VALUES; 1645580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach } else if (!strcmp(cmd, "query1")) { 1646580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach const char *name = 0; 1647fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach const char *subname = 0; 1648fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach const char *subsubname = 0; 1649fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach 1650fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach name = names[0]; 1651fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach if (name) 1652580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach subname = names[1]; 1653580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach if (subname) 1654580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach subsubname = names[2]; 1655580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach if (subsubname && names[3]) { 1656580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach fprintf(stderr, 1657580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach "Only 3 levels are allowed with query1\n"); 1658580f4a9c1c2fcbb8877463f873c6e9ca2a5ccf9fJim Grosbach retval = EINVAL; 1659f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach } else 1660f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach retval = profile_get_value(profile, name, subname, 1661f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach subsubname, &value); 1662f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach print_status = PRINT_VALUE; 1663fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach } else if (!strcmp(cmd, "list_sections")) { 1664fc2eb31a3c054f9611a2e88238fbb5a8842064a6Jim Grosbach retval = profile_get_subsection_names(profile, names, 1665f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach &values); 1666f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach print_status = PRINT_VALUES; 1667f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach } else if (!strcmp(cmd, "list_relations")) { 1668f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach retval = profile_get_relation_names(profile, names, 1669f49433523e8a39db6d83503e312ae55160eed90aJim Grosbach &values); 16706ab4e3dd2375c3dcee06dde37437dc0c5a99aa24Jim Grosbach print_status = PRINT_VALUES; 1671185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "dump")) { 1672185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_write_tree_file 1673185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach (profile->first_file->root, stdout); 1674185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach#if 0 1675185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "clear")) { 1676185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_clear_relation(profile, names); 1677185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "update")) { 1678185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_update_relation(profile, names+2, 1679185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach *names, *(names+1)); 1680185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach#endif 1681185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "verify")) { 1682185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_verify_node 1683185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach (profile->first_file->root); 1684185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach#if 0 1685185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "rename_section")) { 1686185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_rename_section(profile, names+1, *names); 1687185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "add")) { 1688185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach value = *names; 1689185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach if (strcmp(value, "NULL") == 0) 1690185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach value = NULL; 1691185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_add_relation(profile, names+1, value); 1692185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach } else if (!strcmp(cmd, "flush")) { 1693185f92e7d019bc52413a2b082d61e35c80f8b597Jim Grosbach retval = profile_flush(profile); 16943b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach#endif 16953b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach } else { 16963b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach printf("Invalid command.\n"); 1697a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach } 1698a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach if (retval) { 1699a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach com_err(cmd, retval, ""); 1700a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach print_status = 0; 1701a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach } 17023b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach switch (print_status) { 17033b14a5c5469176effb921d91d4494f0aa2919fd0Jim Grosbach case PRINT_VALUE: 1704a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach printf("%s\n", value); 1705a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach break; 1706a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach case PRINT_VALUES: 1707a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach for (cpp = values; *cpp; cpp++) 1708a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach printf("%s\n", *cpp); 1709a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach profile_free_list(values); 1710a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach break; 1711a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach } 1712a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach} 1713a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach 1714a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbachstatic void do_batchmode(profile_t profile) 1715a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach{ 1716a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach int argc, ret; 1717a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach char **argv; 1718a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach char buf[256]; 1719a46c658c6619e979a54ec1e4dc919b3a0319129aJim Grosbach 1720873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach while (!feof(stdin)) { 1721873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach if (fgets(buf, sizeof(buf), stdin) == NULL) 1722873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach break; 1723873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach printf(">%s", buf); 1724873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach ret = argv_parse(buf, &argc, &argv); 172536711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach if (ret != 0) { 172636711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach printf("Argv_parse returned %d!\n", ret); 172736711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach continue; 172836711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach } 172936711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach do_cmd(profile, argv); 173036711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach printf("\n"); 173136711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach argv_free(argv); 173236711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach } 173336711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach profile_release(profile); 173436711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach exit(0); 173536711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach 173636711e4a3c0b53000ea594233bd619dbf252558cJim Grosbach} 1737873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1738873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbachvoid syntax_err_report(const char *filename, long err, int line_num) 1739873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach{ 1740873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach fprintf(stderr, "Syntax error in %s, line number %d: %s\n", 1741873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach filename, line_num, error_message(err)); 1742873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach exit(1); 1743873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach} 1744873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1745873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbachint main(int argc, char **argv) 1746873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach{ 1747873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach profile_t profile; 1748873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach long retval; 1749873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach char *cmd; 1750873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1751873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach if (argc < 2) { 1752873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name); 1753873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach exit(1); 1754873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach } 1755873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1756873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach initialize_prof_error_table(); 1757873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1758873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach profile_set_syntax_err_cb(syntax_err_report); 1759873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1760873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach retval = profile_init_path(argv[1], &profile); 1761873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach if (retval) { 1762873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach com_err(program_name, retval, "while initializing profile"); 1763873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach exit(1); 1764873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach } 1765873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach cmd = *(argv+2); 1766873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach if (!cmd || !strcmp(cmd, "batch")) 1767873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach do_batchmode(profile); 1768873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach else 1769873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach do_cmd(profile, argv+2); 1770873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach profile_release(profile); 1771873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1772873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach return 0; 1773873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach} 1774873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach 1775873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach#endif 1776873db3eebae3cf1e0931149896f262d17a4dc79dJim Grosbach