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