xref: /openbsd-src/lib/libcurses/tinfo/db_iterator.c (revision de8cc8edbc71bd3e3bc7fbffa27ba0e564c37d8b)
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