1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17/***************************************************************************
18 * LPRng - An Extended Print Spooler System
19 *
20 * Copyright 1988-2003, Patrick Powell, San Diego, CA
21 *     papowell@lprng.com
22 * See LICENSE for conditions of use.
23 *
24 ***************************************************************************/
25
26 static char *const _id =
27"$Id: initialize.c,v 1.1.1.1 2008/10/15 03:28:26 james26_jang Exp $";
28
29#include "lp.h"
30#include "defs.h"
31#include "initialize.h"
32#include "getopt.h"
33#include "child.h"
34#include "gethostinfo.h"
35#include "proctitle.h"
36#include "getqueue.h"
37#include "errorcodes.h"
38/**** ENDINCLUDE ****/
39
40#ifdef IS_AUX
41# include <compat.h>
42#endif
43#if defined (HAVE_LOCALE_H)
44# include <locale.h>
45#endif
46
47#ifdef HAVE_ARPA_NAMESER_H
48#include <arpa/nameser.h>
49#endif
50
51#ifdef HAVE_RESOLV_H
52#include <resolv.h>
53#endif
54
55
56/***************************************************************************
57 * general initialization.
58 * This should NOT do any network operations
59 ***************************************************************************/
60
61void Initialize(int argc,  char *argv[], char *envp[], int debugchar )
62{
63	char *s;
64	int fd;
65
66
67	/* the gettext facility has been shown to be able to be used to
68	 * compromize setuid programs.
69	 * remove the slightest possibility of NLSPATH being used in a root
70	 * environment
71	 */
72	if( getuid() == ROOTUID || geteuid() == ROOTUID ){
73#if defined(HAVE_UNSETENV)
74		unsetenv("NLSPATH");
75#elif defined(HAVE_SETENV)
76		setenv("NLSPATH","",1);
77#elif defined(HAVE_PUTENV)
78		putenv("NLSPATH=");
79#else
80# error require one of unsetenv(), setenv(), or putenv()
81#endif
82	}
83
84	DEBUG1("Initialize: starting");
85
86	if( argc > 1 ){
87		s = argv[1];
88		if( s[0] == '-' && s[1] == debugchar ){
89			if( s[2] ){
90				Parse_debug(s+2,1);
91			} else {
92				Parse_debug(argv[2],1);
93			}
94		}
95	}
96
97    if(DEBUGL3){
98		struct stat statb;
99		int i;
100        LOGDEBUG("Initialize: starting with open fd's");
101        for( i = 0; i < 20; ++i ){
102            if( fstat(i,&statb) == 0 ){
103                LOGDEBUG("  fd %d (0%o)", i, statb.st_mode&S_IFMT);
104            }
105        }
106    }
107	/*
108		open /dev/null on fd 0, 1, 2, 3, 4, if neccessary
109		This must be done before using any other database access
110		functions,  as they may open a socket and leave it open.
111	*/
112	if( (fd = open( "/dev/null", O_RDWR, 0600 )) < 0 ){
113		LOGERR_DIE(LOG_CRIT) "Initialize: cannot open '/dev/null'" );
114	}
115	Max_open(fd);
116	DEBUG1("Initialize: /dev/null fd %d", fd );
117	if( Is_server ) while( fd < 5 ){
118		if( (fd = dup(fd)) < 0 ){
119			LOGERR_DIE(LOG_CRIT) "Initialize: main cannot dup '/dev/null'" );
120		}
121		Max_open(fd);
122	}
123	close(fd);
124
125	initsetproctitle( argc, argv, envp );
126	Name = "UNKNOWN";
127	if( argv && argv[0] ){
128		Name = argv[0];
129		if( (s = strrchr(Name,'/')) ) Name = s+1;
130	}
131	/* set the umask so that you create safe files */
132	umask( 0077 );
133
134#ifdef IS_AUX
135	/********************************************
136	 * Apparently this needs to be done for AUX
137	 *******************************************/
138	/* A/UX needs this to be more BSD-compatible. */
139	setcompat (COMPAT_BSDPROT);
140	set42sig();
141#endif
142
143	/* set suid information */
144	Setup_uid();
145
146    if(DEBUGL3){
147		struct stat statb;
148		int i;
149        LOGDEBUG("Initialize: before setlocale");
150        for( i = 0; i < 20; ++i ){
151            if( fstat(i,&statb) == 0 ){
152                LOGDEBUG("  fd %d (0%o)", i, statb.st_mode&S_IFMT);
153            }
154        }
155    }
156#if defined (HAVE_LOCALE_H)
157	setlocale(LC_ALL, "");
158#endif
159	/* FPRINTF(STDERR,"LOCALEDIR '" LOCALEDIR "'\n"); FPRINTF(STDERR,"PACKAGE '" PACKAGE "'\n"); */
160	bindtextdomain (PACKAGE, LOCALEDIR);
161	textdomain (PACKAGE);
162
163    if(DEBUGL3){
164		struct stat statb;
165		int i;
166        LOGDEBUG("Initialize: ending with open fd's");
167        for( i = 0; i < 20; ++i ){
168            if( fstat(i,&statb) == 0 ){
169                LOGDEBUG("  fd %d (0%o)", i, statb.st_mode&S_IFMT);
170            }
171        }
172    }
173
174}
175
176void Setup_configuration()
177{
178	char *s;
179	struct line_list raw;
180	struct line_list order;
181
182	/* Get default configuration file information */
183#ifdef DMALLOC
184	extern int _dmalloc_outfile_fd;
185	extern char *_dmalloc_logpath;
186	char buffer[SMALLBUFFER];
187
188	safestrdup("DMALLOC",__FILE__,__LINE__);
189	if( _dmalloc_logpath && _dmalloc_outfile_fd < 0 ){
190		_dmalloc_outfile_fd = open( _dmalloc_logpath,  O_WRONLY | O_CREAT | O_TRUNC, 0666);
191		Max_open(_dmalloc_outfile_fd);
192	}
193	SNPRINTF(buffer,sizeof(buffer))"*** Setup_configuration: pid %d\n", getpid() );
194	Write_fd_str(_dmalloc_outfile_fd,buffer);
195	DEBUG1("Setup_configuration: _dmalloc_outfile fd %d", _dmalloc_outfile_fd);
196#endif
197
198	Init_line_list(&raw);
199	Init_line_list(&order);
200	Clear_config();
201
202
203	DEBUG1("Setup_configuration: starting, Allow_getenv %d",
204		Allow_getenv_DYN );
205
206    /* get the configuration file information if there is any */
207    if( Allow_getenv_DYN ){
208		if( getuid() == ROOTUID || geteuid() == ROOTUID ){
209			FPRINTF( STDERR,
210			"%s: WARNING- LPD_CONF environment variable option enabled\n"
211			"  and running as root!  You have an exposed security breach!\n"
212			"  Recompile without -DGETENV or do not run clients as ROOT\n",
213			Name );
214			exit(1);
215		}
216		if( (s = getenv( LPD_CONF )) ){
217			Set_DYN(&Config_file_DYN, s);
218		}
219    }
220
221    DEBUG1("Setup_configuration: Configuration file '%s'", Config_file_DYN );
222    DEBUG1("Setup_configuration: Require_configfiles_DYN '%d'",
223		Require_configfiles_DYN );
224
225	Get_config( Is_server || Require_configfiles_DYN, Config_file_DYN );
226
227	Reset_daemonuid();
228	if( Is_server ){
229		Setdaemon_group();
230		To_daemon();
231	} else {
232		s = Get_user_information();
233		Set_DYN( &Logname_DYN, s );
234		if(s) free(s); s = 0;
235	}
236	DEBUG1( "Is_server %d, DaemonUID %d, DaemonGID %d, UID %d, EUID %d, GID %d, EGID %d",
237		Is_server, DaemonUID, DaemonGID,
238		getuid(), geteuid(), getgid(), getegid() );
239
240	DEBUG1("Setup_configuration: Host '%s', ShortHost '%s', user '%s'",
241		FQDNHost_FQDN, ShortHost_FQDN, Logname_DYN );
242
243#ifdef ORIGINAL_DEBUG//JY@1020
244	if(DEBUGL2) Dump_parms( "Setup_configuration - final values", Pc_var_list );
245#endif
246
247	if( Is_server ){
248		DEBUG2("Setup_configuration: Printcap_path '%s'", Printcap_path_DYN );
249		Getprintcap_pathlist( 1, &raw, &PC_filters_line_list,
250			Printcap_path_DYN );
251		DEBUG2("Setup_configuration: Lpd_printcap_path '%s'", Lpd_printcap_path_DYN );
252		Getprintcap_pathlist( 0, &raw, &PC_filters_line_list,
253			Lpd_printcap_path_DYN );
254		DEBUG2("Setup_configuration: Printer_perms_path '%s'", Printer_perms_path_DYN );
255		Getprintcap_pathlist( 1, &RawPerm_line_list, &Perm_filters_line_list,
256			Printer_perms_path_DYN );
257		Free_line_list(&Perm_line_list);
258		Merge_line_list(&Perm_line_list,&RawPerm_line_list,0,0,0);
259	} else {
260		DEBUG2("Setup_configuration: Printcap_path '%s'", Printcap_path_DYN );
261		Getprintcap_pathlist( Require_configfiles_DYN,
262			&raw, &PC_filters_line_list,
263			Printcap_path_DYN );
264	}
265	Build_printcap_info( &PC_names_line_list, &PC_order_line_list,
266		&PC_info_line_list, &raw, &Host_IP );
267	/* now we can free up the raw list */
268	Free_line_list( &raw );
269
270	/* now we get the user level information */
271	DEBUG2("Setup_configuration: User_printcap '%s'", User_printcap_DYN );
272	if( !Is_server && User_printcap_DYN && (s = getenv("HOME")) ){
273		s = Make_pathname( s, User_printcap_DYN );
274		DEBUG2("Setup_configuration: User_printcap '%s'", s );
275		Getprintcap_pathlist( 0, &raw, 0, s );
276		Build_printcap_info( &PC_names_line_list, &order,
277			&PC_info_line_list, &raw, &Host_IP );
278		Free_line_list( &raw );
279		if( s ) free(s); s = 0;
280		/* now we append the names from the order list */
281		if( order.count > 0 ){
282			int i;
283			/* append the found ones, remove duplicates */
284			for( i = 0; i < PC_order_line_list.count; ++i ){
285				int j;
286				int found = 0;
287				s = PC_order_line_list.list[i];
288				for( j = 0; !found && j < order.count; ++j ){
289					found = !strcmp(s, order.list[j]);
290				}
291				if( !found ){
292					Add_line_list(&order,s,0,0,0);
293				}
294			}
295			Free_line_list( &PC_order_line_list );
296			for( i = 0; i < order.count; ++i ){
297				s = order.list[i];
298				Add_line_list(&PC_order_line_list,s,0,0,0);
299			}
300		}
301		Free_line_list( &order );
302	}
303#ifdef ORIGINAL_DEBUG//JY@1020
304	if(DEBUGL3){
305		Dump_line_list("Setup_configuration: PC names", &PC_names_line_list );
306		Dump_line_list("Setup_configuration: PC order", &PC_order_line_list );
307		Dump_line_list("Setup_configuration: PC info", &PC_info_line_list );
308	/*
309		Dump_line_list("Setup_configuration: User_PC names", &User_PC_names_line_list );
310		Dump_line_list("Setup_configuration: User_PC order", &User_PC_order_line_list );
311		Dump_line_list("Setup_configuration: User_PC info", &User_PC_info_line_list );
312	*/
313		Dump_line_list("Setup_configuration: Raw Perms", &RawPerm_line_list );
314		Dump_line_list("Setup_configuration: Perms", &Perm_line_list );
315	}
316#endif
317}
318
319/*
320 * char *Get_user_information(void)
321 * OUTPUT: dynamic alloc string
322 *  - returns user name
323 */
324char *Get_user_information( void )
325{
326	char *name = 0;
327	char uid_msg[32];
328	uid_t uid = OriginalRUID;
329
330	struct passwd *pw_ent;
331
332	/* get the password file entry */
333    if( (pw_ent = getpwuid( uid )) ){
334		name =  pw_ent->pw_name;
335	}
336	if( name == 0 ) name = getenv( "LOGNAME" );
337	if( name == 0 ) name = getenv( "USER" );
338	if( name == 0 ){
339		SNPRINTF( uid_msg, sizeof(uid_msg)) "UID_%d", uid );
340		name = uid_msg;
341	}
342	name = safestrdup(name,__FILE__,__LINE__);
343    return( name );
344}
345