1 /* $OpenBSD: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ 2 3 /**************************************************************************** 4 * Copyright (c) 2006,2007 Free Software Foundation, Inc. * 5 * * 6 * Permission is hereby granted, free of charge, to any person obtaining a * 7 * copy of this software and associated documentation files (the * 8 * "Software"), to deal in the Software without restriction, including * 9 * without limitation the rights to use, copy, modify, merge, publish, * 10 * distribute, distribute with modifications, sublicense, and/or sell * 11 * copies of the Software, and to permit persons to whom the Software is * 12 * furnished to do so, subject to the following conditions: * 13 * * 14 * The above copyright notice and this permission notice shall be included * 15 * in all copies or substantial portions of the Software. * 16 * * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 24 * * 25 * Except as contained in this notice, the name(s) of the above copyright * 26 * holders shall not be used in advertising or otherwise to promote the * 27 * sale, use or other dealings in this Software without prior written * 28 * authorization. * 29 ****************************************************************************/ 30 31 /**************************************************************************** 32 * Author: Thomas E. Dickey * 33 ****************************************************************************/ 34 35 /* 36 * Iterators for terminal databases. 37 */ 38 39 #include <curses.priv.h> 40 41 #include <tic.h> 42 43 MODULE_ID("$Id: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") 44 45 #define HaveTicDirectory _nc_globals.have_tic_directory 46 #define KeepTicDirectory _nc_globals.keep_tic_directory 47 #define TicDirectory _nc_globals.tic_directory 48 49 /* 50 * Record the "official" location of the terminfo directory, according to 51 * the place where we're writing to, or the normal default, if not. 52 */ 53 NCURSES_EXPORT(const char *) 54 _nc_tic_dir(const char *path) 55 { 56 if (!KeepTicDirectory) { 57 if (path != 0) { 58 TicDirectory = path; 59 HaveTicDirectory = TRUE; 60 } else if (!HaveTicDirectory && use_terminfo_vars()) { 61 char *envp; 62 if ((envp = getenv("TERMINFO")) != 0) 63 return _nc_tic_dir(envp); 64 } 65 } 66 return TicDirectory; 67 } 68 69 /* 70 * Special fix to prevent the terminfo directory from being moved after tic 71 * has chdir'd to it. If we let it be changed, then if $TERMINFO has a 72 * relative path, we'll lose track of the actual directory. 73 */ 74 NCURSES_EXPORT(void) 75 _nc_keep_tic_dir(const char *path) 76 { 77 _nc_tic_dir(path); 78 KeepTicDirectory = TRUE; 79 } 80 81 /* 82 * Process the list of :-separated directories, looking for the terminal type. 83 * We don't use strtok because it does not show us empty tokens. 84 */ 85 #define ThisDbList _nc_globals.dbi_list 86 #define ThisDbSize _nc_globals.dbi_size 87 88 /* 89 * Cleanup. 90 */ 91 NCURSES_EXPORT(void) 92 _nc_last_db(void) 93 { 94 if (ThisDbList != 0) { 95 FreeAndNull(ThisDbList); 96 } 97 ThisDbSize = 0; 98 } 99 100 /* The TERMINFO_DIRS value, if defined by the configure script, begins with a 101 * ":", which will be interpreted as TERMINFO. 102 */ 103 static const char * 104 next_list_item(const char *source, int *offset) 105 { 106 if (source != 0) { 107 FreeIfNeeded(ThisDbList); 108 ThisDbList = strdup(source); 109 ThisDbSize = strlen(source); 110 } 111 112 if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) { 113 static char system_db[] = TERMINFO; 114 char *result = ThisDbList + *offset; 115 char *marker = strchr(result, NCURSES_PATHSEP); 116 117 /* 118 * Put a null on the marker if a separator was found. Set the offset 119 * to the next position after the marker so we can call this function 120 * again, using the data at the offset. 121 */ 122 if (marker == 0) { 123 *offset += strlen(result) + 1; 124 marker = result + *offset; 125 } else { 126 *marker++ = 0; 127 *offset = marker - ThisDbList; 128 } 129 if (*result == 0 && result != (ThisDbList + ThisDbSize)) 130 result = system_db; 131 return result; 132 } 133 return 0; 134 } 135 136 #define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset) 137 138 /* 139 * This is a simple iterator which allows the caller to step through the 140 * possible locations for a terminfo directory. ncurses uses this to find 141 * terminfo files to read. 142 */ 143 NCURSES_EXPORT(const char *) 144 _nc_next_db(DBDIRS * state, int *offset) 145 { 146 const char *result; 147 char *envp; 148 149 while (*state < dbdLAST) { 150 DBDIRS next = (DBDIRS) ((int) (*state) + 1); 151 152 result = 0; 153 154 switch (*state) { 155 case dbdTIC: 156 if (HaveTicDirectory) 157 result = _nc_tic_dir(0); 158 break; 159 #if USE_DATABASE 160 case dbdEnvOnce: 161 if (use_terminfo_vars()) { 162 if ((envp = getenv("TERMINFO")) != 0) 163 result = _nc_tic_dir(envp); 164 } 165 break; 166 case dbdHome: 167 if (use_terminfo_vars()) { 168 result = _nc_home_terminfo(); 169 } 170 break; 171 case dbdEnvList: 172 if (use_terminfo_vars()) { 173 if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0) 174 next = *state; 175 } 176 break; 177 case dbdCfgList: 178 #ifdef TERMINFO_DIRS 179 if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0) 180 next = *state; 181 #endif 182 break; 183 case dbdCfgOnce: 184 #ifndef TERMINFO_DIRS 185 result = TERMINFO; 186 #endif 187 break; 188 #endif /* USE_DATABASE */ 189 #if USE_TERMCAP 190 case dbdEnvOnce2: 191 if (use_terminfo_vars()) { 192 if ((envp = getenv("TERMCAP")) != 0) 193 result = _nc_tic_dir(envp); 194 } 195 break; 196 case dbdEnvList2: 197 if (use_terminfo_vars()) { 198 if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0) 199 next = *state; 200 } 201 break; 202 case dbdCfgList2: 203 if ((result = NEXT_DBD(TERMPATH, offset)) != 0) 204 next = *state; 205 break; 206 #endif /* USE_TERMCAP */ 207 case dbdLAST: 208 break; 209 } 210 if (*state != next) { 211 *state = next; 212 *offset = 0; 213 _nc_last_db(); 214 } 215 if (result != 0) { 216 return result; 217 } 218 } 219 return 0; 220 } 221 222 NCURSES_EXPORT(void) 223 _nc_first_db(DBDIRS * state, int *offset) 224 { 225 *state = dbdTIC; 226 *offset = 0; 227 } 228