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