1 /*
2 * sqsh_init.c - Initialize/cleanup global variable
3 *
4 * Copyright (C) 1995, 1996 by Scott C. Gray
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, write to the Free Software
18 * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * You may contact the author :
21 * e-mail: gray@voicenet.com
22 * grays@xtend-tech.com
23 * gray@xenotropic.com
24 */
25 #include <stdio.h>
26 #include "sqsh_config.h"
27 #include "sqsh_error.h"
28 #include "sqsh_global.h"
29 #include "sqsh_expand.h"
30 #include "sqsh_cmd.h"
31 #include "sqsh_env.h"
32 #include "sqsh_readline.h"
33 #include "sqsh_stdin.h"
34 #include "sqsh_init.h"
35 #include "config.h"
36 #if defined(HAVE_LOCALE_H)
37 #include <locale.h>
38 #endif
39 /*
40 * The following defines the tables which are used to inialize the
41 * variable global variables.
42 */
43 #define SQSH_INIT
44 #include "cmd.h"
45 #include "var.h"
46 #include "alias.h"
47 #undef SQSH_INIT
48
49 /*-- Current Version --*/
50 #if !defined(lint) && !defined(__LINT__)
51 static char RCS_Id[] = "$Id: sqsh_init.c,v 1.9 2013/12/03 09:22:23 mwesdorp Exp $" ;
USE(RCS_Id)52 USE(RCS_Id)
53 #endif /* !defined(lint) */
54
55 /*
56 * sqsh_init():
57 *
58 * Initializes all global variables for the first time. This function
59 * should be pretty much the first thing called. True is returned
60 * upon success, False is returned otherwise.
61 *
62 * Note: Careful attention should be payed to sqsh_fork.c and how it
63 * interacts with these variables.
64 */
65 int sqsh_init()
66 {
67 int i ;
68 char *histsize ;
69 varbuf_t *expand_buf ;
70
71
72 /*
73 * sqsh-2.3 : Initialize locale to the default of C.
74 */
75 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
76 setlocale ( LC_ALL, "C" );
77 #endif
78
79 /*
80 * g_connection: This variable is initiazed to NULL. It is the responsibility
81 * of a user function to actually perform the connection to
82 * set it. This allows sqsh to be started without actually
83 * connecting to the database.
84 */
85 g_context = NULL ;
86 g_connection = NULL ;
87
88 /*
89 * g_sqlbuf: This variable contains the working SQL buffer being typed
90 * into by the user. It is initialized to an empty buffer.
91 */
92 if( (g_sqlbuf = varbuf_create( 1024 )) == NULL ) {
93 sqsh_set_error( sqsh_get_error(), "varbuf_create: %s", sqsh_get_errstr());
94 return False ;
95 }
96
97 /*
98 * g_cmdset: The set of commands that may be executed by a user or
99 * internally.
100 */
101 if( (g_cmdset = cmdset_create()) == NULL ) {
102 sqsh_set_error( sqsh_get_error(), "cmdset_create: %s", sqsh_get_errstr());
103 return False ;
104 }
105
106 /*
107 * g_funcset: The set of commands that may be executed by a user or
108 * internally.
109 */
110 if ((g_funcset = funcset_create()) == NULL)
111 {
112 sqsh_set_error( sqsh_get_error(),
113 "cmdset_create: %s", sqsh_get_errstr());
114 return False;
115 }
116
117 /*
118 * Now, populate the g_cmdset with the set of commands defined in
119 * cmd.h.
120 */
121 for( i = 0; i < (sizeof(sg_cmd_entry) / sizeof(cmd_entry_t)); i++ ) {
122
123 if( cmdset_add( g_cmdset,
124 sg_cmd_entry[i].ce_name,
125 sg_cmd_entry[i].ce_func ) == False ) {
126 sqsh_set_error( sqsh_get_error(), "cmdset_add: %s",
127 sqsh_get_errstr() ) ;
128 return False ;
129 }
130
131 }
132
133 /*
134 * Initialize our table of aliases
135 */
136 if( (g_alias = alias_create()) == NULL ) {
137 sqsh_set_error(sqsh_get_error(), "alias_create: %s", sqsh_get_errstr()) ;
138 return False ;
139 }
140
141 for( i = 0; i < (sizeof(sg_alias_entry) / sizeof(alias_entry_t)); i++ ) {
142 if( alias_add( g_alias,
143 sg_alias_entry[i].ae_name,
144 sg_alias_entry[i].ae_body ) == False ) {
145 sqsh_set_error( sqsh_get_error(), "alias_add: %s: %s",
146 sg_alias_entry[i].ae_name,
147 sqsh_get_errstr() ) ;
148 return False ;
149 }
150 }
151
152 /*
153 * g_buf: Where named buffers are stored.
154 */
155 if( (g_buf = env_create( 47 )) == NULL ) {
156 sqsh_set_error( sqsh_get_error(), "env_create: %s", sqsh_get_errstr() ) ;
157 return False ;
158 }
159
160 /*
161 * g_internal_env: This is the internal environment information that
162 * is not settable by a user, but is queryable.
163 *
164 */
165 if( (g_internal_env = env_create(47)) == NULL ) {
166 sqsh_set_error( sqsh_get_error(), "env_create: %s", sqsh_get_errstr() ) ;
167 return False ;
168 }
169
170 /*
171 * g_env: This is the environment for the process. Here we simply
172 * create the environment and initialize it with the default
173 * values, these may then be overridden by the users .sqshrc
174 */
175 if( (g_env = env_create( 47 )) == NULL ) {
176 sqsh_set_error( sqsh_get_error(), "env_create: %s", sqsh_get_errstr() ) ;
177 return False ;
178 }
179
180 /*
181 * The following buffer is used to expand the values of the variables
182 * prior to setting them within the environment. It is destroyed when
183 * we are done with this process.
184 */
185 if( (expand_buf = varbuf_create( 64 )) == NULL ) {
186 sqsh_set_error(sqsh_get_error(), "varbuf_create: %s", sqsh_get_errstr());
187 return False ;
188 }
189
190 /*
191 * Now, using the array defined in var.h, populate the global
192 * environment.
193 */
194 for( i = 0; i < (sizeof(sg_var_entry) / sizeof(var_entry_t)); i++ ) {
195
196 if( sg_var_entry[i].ve_value != NULL ) {
197 /*
198 * Expand the value of the variable prior to sticking it in the
199 * environment. This, more-or-less, emulates the behaviour as
200 * if you had typed it in from the command line.
201 */
202 if( sqsh_expand( sg_var_entry[i].ve_value, expand_buf,
203 EXP_STRIPESC ) == False ){
204 sqsh_set_error( sqsh_get_error(), "%s: %s",
205 sg_var_entry[i].ve_value, sqsh_get_errstr());
206 return False ;
207 }
208
209 if( env_set_valid(
210 g_env, /* Global environment */
211 sg_var_entry[i].ve_name, /* Name of variable */
212 varbuf_getstr(expand_buf), /* Default value */
213 sg_var_entry[i].ve_set, /* Settor function */
214 sg_var_entry[i].ve_get ) == False ) {
215 sqsh_set_error( sqsh_get_error(), "env_set_valid: %s",
216 sqsh_get_errstr() ) ;
217 return False ;
218 }
219 } else { /* NULL value */
220 if( env_set_valid(
221 g_env, /* Global environment */
222 sg_var_entry[i].ve_name, /* Name of variable */
223 NULL, /* NULL value */
224 sg_var_entry[i].ve_set, /* Settor function */
225 sg_var_entry[i].ve_get ) == False ) {
226 sqsh_set_error( sqsh_get_error(), "env_set_valid: %s",
227 sqsh_get_errstr() ) ;
228 return False ;
229 }
230 }
231 }
232
233 /*-- Don't need it any more --*/
234 varbuf_destroy( expand_buf ) ;
235
236 /*
237 * sqsh-2.2.0 - Initialize variable keyword_refresh in the
238 * g_internal_env to prevent misses in subsequent variable lookups.
239 */
240 env_set( g_internal_env, "keyword_refresh", "0" );
241
242 /*
243 * Allocate our global set of sub-processes.
244 */
245 if( (g_jobset = jobset_create( 47 )) == NULL ) {
246 sqsh_set_error( sqsh_get_error(), "jobset_create: %s",
247 sqsh_get_errstr() ) ;
248 return False ;
249 }
250
251 /*
252 * Since the global environment set has been created and initialized
253 * we can retrieve any variables that may affect the size of other
254 * data structures...such as the history.
255 */
256 env_get( g_env, "histsize", &histsize ) ;
257 if( histsize == NULL || (i = atoi( histsize )) == 0 )
258 i = 10 ;
259
260 if( (g_history = history_create( i )) == NULL ) {
261 sqsh_set_error( sqsh_get_error(), "history_create: %s",
262 sqsh_get_errstr() ) ;
263 return False ;
264 }
265
266 sqsh_set_error( SQSH_E_NONE, NULL ) ;
267 return True ;
268 }
269
sqsh_exit(exit_status)270 void sqsh_exit( exit_status )
271 int exit_status ;
272 {
273 char *history;
274 char *histsave;
275 char *term_title;
276 varbuf_t *exp_buf;
277
278 /*
279 * If the history has been created, and it contains items, and $history
280 * has been defined, then we write the history out to a file.
281 */
282 if (g_history != NULL)
283 {
284 if (g_env != NULL)
285 {
286 env_get( g_env, "history", &history );
287 env_get( g_env, "histsave", &histsave );
288 }
289 else
290 {
291 history = NULL;
292 histsave = NULL;
293 }
294
295 if (g_interactive && (histsave == NULL || *histsave == '1') &&
296 history != NULL && history_get_nitems( g_history ) > 0)
297 {
298 exp_buf = varbuf_create( 512 );
299
300 if (exp_buf == NULL)
301 {
302 fprintf( stderr, "sqsh_exit: %s\n", sqsh_get_errstr() );
303 }
304 else
305 {
306 if (sqsh_expand( history, exp_buf, 0 ) == False)
307 {
308 fprintf( stderr, "sqsh_exit: Error expanding $history: %s\n",
309 sqsh_get_errstr() );
310 }
311 else
312 {
313 history_save( g_history, varbuf_getstr(exp_buf) );
314 }
315
316 varbuf_destroy( exp_buf );
317 }
318 }
319
320 history_destroy( g_history );
321 g_history = NULL;
322 }
323
324 /*
325 * Clean up readline.
326 */
327 if ( g_interactive )
328 sqsh_readline_exit();
329
330 if( g_connection != NULL )
331 {
332 if (ct_close( g_connection, CS_UNUSED) != CS_SUCCEED)
333 ct_close( g_connection, CS_FORCE_CLOSE );
334 ct_con_drop( g_connection );
335 g_connection = NULL;
336 }
337
338 if (g_context != NULL)
339 {
340 if (ct_exit( g_context, CS_UNUSED ) != CS_SUCCEED)
341 ct_exit( g_context, CS_FORCE_EXIT );
342
343 /*
344 * If sqsh is aborting, maybe because of losing a database connection
345 * and the callback handler requests sqsh_exit(254), then do not drop
346 * the g_context structure, as it will generate an error:
347 * CS-Library error:
348 * severity(1) layer(2) origin(1) number(31)
349 * cs_ctx_drop: cslib user api layer: external error:
350 * The context structure cannot be dropped because the application
351 * has not exited from ct.
352 * This is due to the fact that the callback handler did not return
353 * to CS/CT-Library.
354 */
355 if (exit_status != 254)
356 cs_ctx_drop( g_context );
357 g_context = NULL;
358 }
359
360 if( g_buf != NULL ) {
361 env_destroy( g_buf ) ;
362 g_buf = NULL;
363 }
364
365 if ( g_internal_env != NULL ) {
366 env_destroy( g_internal_env ) ;
367 g_internal_env = NULL;
368 }
369
370 /*
371 * sqsh-2.1.7 - Reset term_title.
372 */
373 if (g_env != NULL && g_interactive)
374 {
375 env_get( g_env, "term_title", &term_title );
376 if (term_title != NULL && *term_title != '\0')
377 fprintf (stdout, "%c]0;%c", '\033', '\007' );
378 }
379
380 /*
381 * sqsh-2.5 - Close file $p2fname
382 */
383 if (g_p2f_fp != NULL) {
384 fclose (g_p2f_fp);
385 g_p2f_fp = NULL;
386 }
387
388 if( g_env != NULL ) {
389 env_destroy( g_env ) ;
390 g_env = NULL;
391 }
392
393 if( g_sqlbuf != NULL ) {
394 varbuf_destroy( g_sqlbuf ) ;
395 g_sqlbuf = NULL;
396 }
397
398 if( g_cmdset != NULL ) {
399 cmdset_destroy( g_cmdset ) ;
400 g_cmdset = NULL;
401 }
402
403 if( g_funcset != NULL ) {
404 funcset_destroy( g_funcset ) ;
405 g_funcset = NULL;
406 }
407
408 if( g_jobset != NULL ) {
409 jobset_destroy( g_jobset ) ;
410 g_jobset = NULL;
411 }
412
413 exit (exit_status) ;
414 }
415
416
417