1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29/*	  All Rights Reserved  	*/
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33/* system include files	*/
34
35#include <fcntl.h>
36#include <signal.h>
37#include <stdio.h>
38#include <unistd.h>
39#include <string.h>
40#include <errno.h>
41#include <sys/utsname.h>
42#include <sys/tiuser.h>
43#include <sys/param.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <sys/mkdev.h>
47#include <values.h>
48#include <ctype.h>
49#include <pwd.h>
50#include <grp.h>
51#include <sys/poll.h>
52#include <sys/stropts.h>
53#include <utmpx.h>
54#include <sac.h>
55
56
57/* listener include files */
58
59#include "lsparam.h"		/* listener parameters		*/
60#include "lsfiles.h"		/* listener files info		*/
61#include "lserror.h"		/* listener error codes		*/
62#include "lsnlsmsg.h"		/* NLPS listener protocol	*/
63#include "lssmbmsg.h"		/* MS_NET identifier		*/
64#include "lsdbf.h"		/* data base file stuff		*/
65#include "listen.h"
66
67/* global variables */
68
69FILE *Logfp;		/* file pointer for nlps_server's log file	*/
70#ifdef DEBUGMODE
71FILE *Debugfp;		/* debugging output				*/
72#endif
73
74int Dbf_entries;	/* number of private addresses in dbf file */
75dbf_t	*Dbfhead;
76dbf_t	*Newdbf;
77char	*New_cmd_lines;
78char	*Server_cmd_lines;
79
80extern int t_errno;
81
82/*
83 * These global symbols are used for logging.
84 * Pid, NLPS_proc, and Lastmsg are significant here; the others aren't used.
85 */
86int	NLPS_proc = 1;
87pid_t	Pid;
88char	Lastmsg[BUFSIZ];
89char	*Netspec = NULL;
90int	Splflag = 0;
91int	Logmax = 0;
92char	*Mytag = NULL;
93
94char	msgbuf[BUFSIZ];
95char	Altbasedir[BUFSIZ];
96char	Basedir[BUFSIZ];
97extern	char *getenv();
98
99static void nls_reply(int code, char *text);
100static void nullfix(void);
101
102int
103main(int argc, char **argv)
104{
105	extern int read_dbf();
106	char *provider;
107
108	provider = getenv("PMTAG");
109	sprintf(Altbasedir, "%s/%s/", ALTDIR, provider);
110	sprintf(Basedir, "%s/%s/", BASEDIR, provider);
111	sprintf(msgbuf, "%s/%s", Altbasedir, LOGNAME);
112	if (!(Logfp = fopen(msgbuf, "a+")))  {
113		(void)exit(1);
114	}
115
116#ifdef DEBUGMODE
117	sprintf(msgbuf, "%s/%s", Altbasedir, PDEBUGNAME);
118	if (!(Debugfp = fopen(msgbuf, "a")))  {
119		logmessage("NLPS: Unable to open DEBUG file");
120		(void)exit(1);
121	}
122#endif
123
124	/*
125	 * re-sync TLI structures after we were exec'ed from listener
126	 */
127
128	if (t_sync(0) == -1) {
129		DEBUG((9,"t_sync failed, t_errno %d", t_errno));
130		logmessage("NLPS: Resynchronization of TLI failed");
131		(void)exit(1);
132	}
133
134	nlps_server();
135	return(0);
136}
137
138/*
139 *  nlps_server:
140 */
141
142int
143nlps_server()
144{
145	int size;
146	char buf[RCVBUFSZ];
147	char **argv;
148	char *bp = buf;
149	dbf_t *dbp;
150	dbf_t *getdbfentry();
151	extern char **mkdbfargv();
152
153	Pid = getpid();
154	DEBUG((9,"in nlps_server (NLPS/SMB message), pid %ld", Pid));
155
156	if ((size = getrequest(bp)) <= 0)  {
157		logmessage("NLPS: No/bad service request received");
158		return(-1);
159	}
160
161	if (size < 0)  {
162		DEBUG((7,"nlps_server(): Error returned from getrequest()" ));
163		logmessage("NLPS: Error returned from getrequest()");
164		return(-1);
165	}
166
167	/*
168	 * if message is NLPS protocol...
169	 */
170
171	if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ))  && 	/* NLPS request	*/
172	    (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) {
173		nls_service(bp, size);
174		(void)sleep(10);	/* if returned to here, then
175				 * must sleep for a short period of time to
176				 * insure that the client received any possible
177				 * exit response message from the listener.
178					 */
179
180	/*
181	 * else if message is for the MS-NET file server...
182	 */
183
184	} else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) )  {
185		if (dbp = getdbfentry(DBF_SMB_CODE))
186		    if (dbp->dbf_flags & DBF_OFF)
187			logmessage("NLPS: SMB message, server disabled in data base");
188		    else    {
189			argv = mkdbfargv(dbp);
190			smbservice(bp, size, argv);
191		    }
192		else
193			logmessage("NLPS: SMB message, no data base entry");
194
195	/*
196	 * else, message type is unknown...
197	 */
198
199	} else  {
200		logmessage("NLPS: Unknown service request (ignored)");
201		DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x",
202			*bp, *(bp+1), *(bp+2), *(bp+3)));
203	}
204
205	/*
206	 * the routines that start servers return only if there was an error
207	 * and will have logged their own errors.
208	 */
209
210	return(-1);
211}
212
213
214/*
215 * getrequest:	read in a full message.  Timeout, in case the client died.
216 *		returns: -1 = timeout or other error.
217 *			 positive number = message size.
218 */
219
220int
221getrequest(bp)
222char *bp;
223{
224	int size;
225	char *tmp = bp;
226	int flags;
227	extern void timeout();
228	short cnt;
229	void (*oldhanp)();
230
231	DEBUG((9,"in getrequest"));
232
233	oldhanp = signal(SIGALRM, timeout);
234	(void)alarm(ALARMTIME);
235
236	/* read in MINMSGSZ to determine type of msg */
237	if ((size = l_rcv(bp, MINMSGSZ, &flags)) != MINMSGSZ) {
238		DEBUG((9, "getrequest: l_rcv returned %d", size));
239		tli_error(E_RCV_MSG, CONTINUE);
240		return(-1);
241	}
242	tmp += size;
243
244	/*
245	 * if message is NLPS protocol...
246	 */
247
248	if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ))  && 	/* NLPS request	*/
249	    (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) {
250
251		do {
252			if (++size > RCVBUFSZ) {
253				logmessage("NLPS: recieve buffer not large enough");
254				return(-1);
255			}
256
257			if (t_rcv(0, tmp, sizeof(char), &flags) != sizeof(char)) {
258				tli_error(E_RCV_MSG, CONTINUE);
259				return(-1);
260			}
261
262		} while (*tmp++ != '\0');
263
264
265
266	/*
267	 * else if message is for the MS-NET file server...
268	 */
269
270	} else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) )  {
271
272		/* read in 28 more bytes to get count of paramter words */
273		if (l_rcv(tmp, 28, &flags) != 28) {
274			tli_error(E_RCV_MSG, CONTINUE);
275			return(-1);
276		}
277		tmp += 28;
278		size += 28;
279
280		/*
281		 * read amount of paramater words plus word for
282                 * the number of data bytes to follow (2 bytes/word)
283                 */
284		cnt = (int)*(tmp - 1) * 2 + 2;
285
286		if ((size += cnt) > RCVBUFSZ) {
287			logmessage("NLPS: recieve buffer not large enough");
288			return(-1);
289		}
290
291		if (l_rcv(tmp, cnt, &flags) != cnt) {
292			tli_error(E_RCV_MSG, CONTINUE);
293			return(-1);
294		}
295		tmp += cnt;
296
297		getword(tmp - 2, &cnt);
298
299		if ((size += cnt) > RCVBUFSZ) {
300			logmessage("NLPS: recieve buffer not large enough");
301			return(-1);
302		}
303
304		if (l_rcv(tmp, cnt, &flags) != cnt) {
305			tli_error(E_RCV_MSG, CONTINUE);
306			return(-1);
307		}
308
309		nullfix();
310
311	/*
312	 * else, message type is unknown...
313	 */
314
315	} else  {
316		logmessage("NLPS: Unknown service request (ignored)");
317		DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x",
318			*bp, *(bp+1), *(bp+2), *(bp+3)));
319		return(-1);
320	}
321
322	(void)alarm(0);
323	signal(SIGALRM, oldhanp);
324
325	DEBUG((7,"t_rcv returned %d, flags: %x",size,flags));
326
327	return(size);
328}
329
330
331/*
332 * The following code is for patching a 6300 side bug.  The original
333 * message that comes over may contain 2 null bytes which aren't
334 * part of the message, and if left on the stream, will poison the
335 * server.  Peek into the stream and snarf up those bytes if they
336 * are there.  If anything goes wrong with the I_PEEK, just continue,
337 * if the nulls weren't there, it'll work, and if they were, all that
338 * will happen is that the server will fail.  Just note what happened
339 * in the log file.
340 */
341
342static void
343nullfix(void)
344{
345	struct strpeek peek;
346	register struct strpeek *peekp;
347	char scratch[BUFSIZ];
348	char junk[2];
349	int flags;
350	int ret;
351
352	peekp = &peek;
353	peekp->flags = 0;
354	/* need to ask for ctl info to avoid bug in I_PEEK code */
355	peekp->ctlbuf.maxlen = 1;
356	peekp->ctlbuf.buf = junk;
357	peekp->databuf.maxlen = 2;
358	peekp->databuf.buf = junk;
359	ret = ioctl(0, I_PEEK, &peek);
360	if (ret == -1) {
361		sprintf(scratch, "NLPS: nullfix(): unable to PEEK, errno is %d", errno);
362		DEBUG((9, "nullfix(): I_PEEK failed, errno is %d", errno));
363		logmessage(scratch);
364	}
365	else if (ret == 0) {
366		DEBUG((9, "nullfix(): no messages on stream to PEEK"));
367	}
368	else {
369		if (peekp->databuf.len == 2) {
370			/* Note: junk contains "peeked" data */
371			DEBUG((9, "peeked <%x> <%x>", junk[0], junk[1]));
372			if ((junk[0] == 0) && (junk[1] == 0)) {
373				/* pitch the nulls */
374				DEBUG((9, "pitching 2 nulls from first peek"));
375				l_rcv(junk, 2, &flags);
376			}
377		}
378
379		/*
380		 * this represents a somewhat pathological case where
381		 * the "2 nulls" are broken across message boundaries.
382		 * Pitch the first and hope the next one is there
383		 */
384
385		else if (peekp->databuf.len == 1) {
386			DEBUG((9, "peeked <%x>", junk[0]));
387			if (junk[0] == 0) {
388				/* pitch the first */
389				DEBUG((9, "split nulls, pitching first"));
390				l_rcv(junk, 1, &flags);
391				peekp->databuf.maxlen = 1;
392				ret = ioctl(0, I_PEEK, &peek);
393				if (ret == -1) {
394					sprintf(scratch, "NLPS: nullfix(): unable to PEEK second time, errno is %d", errno);
395					DEBUG((9, "second peek failed, errno %d", errno));
396					logmessage(scratch);
397				}
398				else if (ret == 0) {
399					DEBUG((9, "no messages for 2nd peek"));
400				}
401				else {
402					if (peekp->databuf.len == 1) {
403						DEBUG((9, "2nd peek <%x>", junk[0]));
404						if (junk[0] == 0) {
405							/* pitch the second */
406							DEBUG((9, "pitching 2nd single null"));
407							l_rcv(junk, 1, &flags);
408						}
409						else {
410							/* uh oh, server will most likely fail */
411							DEBUG((9, "2nd null not found"));
412							logmessage("NLPS: nullfix(): threw away a valid null byte");
413						}
414					}
415				}
416			}
417		}
418	}
419}
420
421
422/*
423 * timeout:	SIGALRM signal handler.  Invoked if t_rcv timed out.
424 *		See comments about 'exit' in nlps_server().
425 */
426
427
428void
429timeout()
430{
431	DEBUG((9, "TIMEOUT"));
432	error(E_RCV_TMO, EXIT | NOCORE);
433}
434
435
436
437/*
438 * nls_service:	Validate and start a server requested via the NLPS protocol
439 *
440 *		version 0:1 -- expect "NLPS:000:001:service_code".
441 *
442 *	returns only if there was an error (either msg format, or couldn't exec)
443 */
444
445static char *badversion =
446	"NLPS: Unknown version of an NLPS service request: %d:%d";
447static char *disabledmsg =
448	"NLPS: Request for service code <%s> denied, service is disabled";
449static char *nlsunknown =
450	"NLPS: Request for service code <%s> denied, unknown service code";
451
452
453/*
454 * Nlsversion can be used as a NLPS flag (< 0 == not nls service)
455 * and when >= 0, indicates the version of the NLPS protocol used
456 */
457
458static int Nlsversion = -1;	/* protocol version	*/
459
460int
461nls_service(bp, size)
462int  size;
463char *bp;
464{
465	int low, high;
466	char svc_buf[64];
467	register char *svc_code_p = svc_buf;
468	char scratch[256];
469	register dbf_t *dbp;
470	dbf_t *getdbfentry();
471	extern char **mkdbfargv();
472	int passfd;
473	int i;
474
475	if (nls_chkmsg(bp, size, &low, &high, svc_code_p))  {
476		if ((low == 0) || (low == 2))
477			Nlsversion = low;
478		else  {
479			sprintf(scratch, badversion, low, high);
480			logmessage(scratch);
481			error(E_BAD_VERSION, CONTINUE);
482			return(-1);
483		}
484
485		DEBUG((9,"nls_service: protocol version %d", Nlsversion));
486
487		/*
488		 * common code for protocol version 0 or 2
489		 * version 0 allows no answerback message
490		 * version 2 allows exactly 1 answerback message
491		 */
492
493		if (dbp = getdbfentry(svc_code_p)) {
494			if (dbp->dbf_flags & DBF_OFF)  {
495				sprintf(scratch, disabledmsg, svc_code_p);
496				logmessage(scratch);
497				nls_reply(NLSDISABLED, scratch);
498			}
499			else {
500				if (dbp->dbf_sflags & CFLAG) {
501					exec_cmd(dbp, (char **)0);
502					/* return is an error	*/
503				}
504				else {
505					sprintf(msgbuf,"NLPS (%s) passfd: %s",
506						dbp->dbf_svc_code,
507						dbp->dbf_cmd_line);
508					nls_reply(NLSSTART, msgbuf);
509					logmessage(msgbuf);
510					/* open pipe to pass fd through */
511					if ((passfd = open(dbp->dbf_cmd_line,
512							O_WRONLY)) < 0) {
513						sprintf(scratch,"NLPS open failed: %s", dbp->dbf_cmd_line);
514						logmessage(scratch);
515					}
516					DEBUG((9, "pushmod string: %s", dbp->dbf_modules));
517					if (pushmod(0, dbp->dbf_modules)) {
518						logmessage("NLPS: Can't push server's modules: exit");
519						(void)exit(2); /* server, don't log */
520					}
521
522					DEBUG((9, "Running doconfig on %s", dbp->dbf_svc_code));
523
524					sprintf(msgbuf,"%s/%s",Basedir,dbp->dbf_svc_code);
525
526					if ((i = doconfig(0, msgbuf, NOASSIGN)) != 0) {
527						DEBUG((9, "doconfig exited with code %d", i));
528						sprintf(scratch, "doconfig failed on line %d of script %s",
529								i, msgbuf);
530						logmessage(scratch);
531						(void)exit(2);
532					}
533					if (ioctl(passfd, I_SENDFD, 0) < 0) {
534						sprintf(scratch,"NLPS passfd failed: %s", dbp->dbf_cmd_line);
535						logmessage(scratch);
536					}
537				}
538			}
539		}
540		else  {
541			sprintf(scratch, nlsunknown, svc_code_p);
542			logmessage(scratch);
543			nls_reply(NLSUNKNOWN, scratch);
544		}
545		exit(2);
546
547	}  else
548		error(E_BAD_FORMAT, CONTINUE);
549
550	/* if we're still here, server didn't get exec'ed	*/
551
552	return(-1);
553}
554
555
556
557/*
558 * nls_chkmsg:	validate message and return fields to caller.
559 *		returns: TRUE == good format
560 *			 FALSE== bad format
561 */
562
563int
564nls_chkmsg(bp, size, lowp, highp, svc_code_p)
565char *bp, *svc_code_p;
566int size, *lowp, *highp;
567{
568
569	/* first, make sure bp is null terminated */
570
571	if ((*(bp + size - 1)) != (char)0)
572		return(0);
573
574	/* scanf returns number of "matched and assigned items"	*/
575
576	return(sscanf(bp, "%*4c:%3d:%3d:%s", lowp, highp, svc_code_p) == 3);
577
578}
579
580
581/*
582 * nls_reply:	send the "service request response message"
583 *		when appropriate.  (Valid if running version 2 or greater).
584 *		Must use write(2) since unknown modules may be pushed.
585 *
586 *		Message format:
587 *		protocol_verion_# : message_code_# : message_text
588 */
589
590static char *srrpprot = "%d:%d:%s";
591
592static void
593nls_reply(int code, char *text)
594{
595	char scratch[256];
596
597	/* Nlsversion = -1 for login service */
598
599	if (Nlsversion >= 2)  {
600		DEBUG((7, "nls_reply: sending response message"));
601		sprintf(scratch, srrpprot, Nlsversion, code, text);
602		t_snd(0, scratch, strlen(scratch)+1, 0);
603	}
604}
605
606
607/*
608 * common code to  start a server process (for any service)
609 * if optional argv is given, info comes from o_argv, else pointer
610 * to dbf struct is used.  In either case, first argument in argv is
611 * full pathname of server. Before exec-ing the server, the caller's
612 * logical address, opt and udata are added to the environment.
613 */
614
615static char homeenv[BUFSIZ];
616#define NETFD	0
617
618
619int
620exec_cmd(dbf_t *dbp, char **o_argv)
621{
622	char *path;
623	char **argvp;
624	extern char **environ;
625	dbf_t *getdbfentry();
626	extern char **mkdbfargv();
627	struct passwd *pwdp;
628	struct group *grpp;
629	dbf_t *wdbp = dbp;
630	int	i;
631
632	/*
633	 * o_argv is set during SMB service setup only, in
634	 * which case dbp is NULL.
635	 */
636
637	if (o_argv) {
638		argvp = o_argv;
639		if ((wdbp = getdbfentry(DBF_SMB_CODE)) == NULL) {
640			/* this shouldn't happen because at this point we've
641			   already found it once */
642			logmessage("NLPS: SMB message, missing data base entry");
643			(void)exit(2); /* server, don't log */
644		}
645	}
646	else
647		argvp = mkdbfargv(dbp);
648	path = *argvp;
649
650	sprintf(msgbuf,"NLPS (%s) exec: %s",
651			(dbp)?dbp->dbf_svc_code:DBF_SMB_CODE, path);
652	nls_reply(NLSSTART, msgbuf);
653	logmessage(msgbuf);
654
655	if (wdbp->dbf_flags & DBF_UTMP) {
656		pid_t	tmp;
657		struct	stat	sbuf;
658		char	*prefix;
659		char	device[20];
660		struct	utmpx utline;
661
662		/*
663		 * create a utmpx entry.  extra fork makes parent init,
664		 * which will clean up the entry.
665		 */
666
667		DEBUG((9, "Creating a utmpx entry for this service "));
668		if ((tmp = fork()) < 0) {
669			logmessage("NLPS: Can't fork to create utmpx entry");
670			exit(2);
671		}
672		if (tmp)
673			exit(0);	/* kill parent */
674
675		/*
676		 * child continues processing, creating utmpx and exec'ing
677		 * the service
678		 */
679
680		setpgrp();
681		if (fstat(0, &sbuf) < 0) {
682			logmessage("NLPS: Stat failed on fd 0: no line "
683			    "field available for utmpx entry");
684			*device = '\0';
685		}
686		else {
687			/*
688			 * MPREFIX is added to the environment by the parent
689			 * listener process.
690			 */
691			prefix = getenv("MPREFIX");
692			if (minor(sbuf.st_rdev) < 100)
693				sprintf(device, "%.9s%02.02d", prefix, minor(sbuf.st_rdev));
694			else
695				sprintf(device, "%.8s%03.03d", prefix, minor(sbuf.st_rdev));
696			DEBUG((9, "Device: %s", device));
697		}
698		strncpy(utline.ut_user, wdbp->dbf_id,
699		    sizeof (utline.ut_user) - 1);
700		sprintf(utline.ut_id, "ps%c%c", SC_WILDC, SC_WILDC);
701		strncpy(utline.ut_line, device, sizeof (utline.ut_line) - 1);
702		utline.ut_pid = getpid();
703                utline.ut_type = USER_PROCESS;
704		utline.ut_exit.e_termination = 0;
705		utline.ut_exit.e_exit = 0;
706		utline.ut_xtime = (time_t) time((time_t *)0);
707		makeutx(&utline);
708	}
709
710	/* after pushmod, tli calls are questionable?		*/
711
712	DEBUG((9, "pushmod string: %s", wdbp->dbf_modules));
713	if (dbp && pushmod(NETFD, dbp->dbf_modules)) {
714		logmessage("NLPS: Can't push server's modules: exit");
715		exit(2); /* server, don't log */
716	}
717
718	DEBUG((9, "Running doconfig on %s", wdbp->dbf_svc_code));
719	if ((i = doconfig(NETFD, wdbp->dbf_svc_code, 0)) != 0) {
720		DEBUG((9, "doconfig exited with code %d", i));
721		sprintf(msgbuf, "doconfig failed on line %d of script %s",
722				i, wdbp->dbf_svc_code);
723		logmessage(msgbuf);
724	}
725
726	if (wdbp == NULL) {
727		logmessage("NLPS: No database entry");
728		exit(2); /* server, don't log */
729	}
730
731	if ((pwdp = getpwnam(wdbp->dbf_id)) == NULL)  {
732		sprintf(msgbuf, "NLPS: Missing or bad passwd entry for <%s>",wdbp->dbf_id);
733		logmessage(msgbuf);
734		exit(2); /* server, don't log */
735	}
736
737
738	if (setgid(pwdp->pw_gid)) {
739		if ((grpp = getgrgid(pwdp->pw_gid)) == NULL) {
740			sprintf(msgbuf, "NLPS: No group entry for %ld", pwdp->pw_gid);
741			logmessage(msgbuf);
742			exit(2); /* server, don't log */
743		}
744		sprintf(msgbuf, "NLPS: Cannot set group id to %s", grpp->gr_name);
745		logmessage(msgbuf);
746		(void)exit(2); /* server, don't log */
747	}
748
749	if (setuid(pwdp->pw_uid)) {
750		sprintf(msgbuf, "NLPS: Cannot set user id to %s", wdbp->dbf_id);
751		logmessage(msgbuf);
752		(void)exit(2); /* server, don't log */
753	}
754
755	if (chdir(pwdp->pw_dir)) {
756		sprintf(msgbuf, "NLPS: Cannot chdir to %s", pwdp->pw_dir);
757		logmessage(msgbuf);
758		(void)exit(2); /* server, don't log */
759	}
760
761	DEBUG((9, "New uid %ld New gid %ld", getuid(), getgid()));
762
763	sprintf(homeenv, "HOME=%s", pwdp->pw_dir);
764	DEBUG((9,"HOME=%s", pwdp->pw_dir));
765	putenv(homeenv);
766	endpwent();
767
768	fclose(Logfp);
769#ifdef DEBUGMODE
770	fclose(Debugfp);
771#endif
772	execve(path, argvp, environ);
773
774	/* exec returns only on failure!		*/
775
776	logmessage("NLPS server: could not exec service");
777	sys_error(E_SYS_ERROR, CONTINUE);
778	return(-1);
779}
780
781
782
783
784
785/*
786 * isdigits:	string version of isdigit.  (See ctype(3))
787 */
788
789/* This routine is public here and used in lsdbf.c as an external */
790int
791isdigits(p)
792register char *p;
793{
794	register int flag = 1;
795
796	if (!strlen(p))
797		return(0);
798
799	while (*p)
800		if (!isdigit(*p++))
801			flag = 0;
802	return(flag);
803}
804
805
806int
807l_rcv(bufp, bytes, flagp)
808char *bufp;
809int bytes;
810int *flagp;
811{
812	register int n;
813	register int count = bytes;
814	register char *bp = bufp;
815
816	DEBUG((9, "in l_rcv"));
817
818	do {
819		*flagp = 0;
820		n = t_rcv(0, bp, count, flagp);
821		DEBUG((9, "l_rcv, after t_rcv call, n =  %d",n));
822
823		if (n < 0) {
824			DEBUG((9, "l_rcv, t_errno is %d", t_errno));
825#ifdef DEBUGMODE
826			if (t_errno == TLOOK) {
827				DEBUG((9, "l_rcv, t_look returns %d", t_look(0)));
828			}
829#endif
830			return(n);
831		}
832		count -= n;
833		bp += n;
834	} while (count > 0);
835
836	return(bp - bufp);
837}
838
839
840/*
841 * getdbfentry:	Given a service code, return a pointer to the dbf_t
842 *		entry.  Return NULL if the entry doesn't exist.
843 *		Reads the data base, one line at a time, into
844 *		Dbf_line_buf.
845 */
846
847static	char	Dbf_line_buf[DBFLINESZ];
848static	dbf_t	Dbf_entry;
849
850dbf_t *
851getdbfentry(svc_code_p)
852register char *svc_code_p;
853{
854	FILE	*dbfp;
855	char	dbfname[BUFSIZ];
856
857	sprintf(dbfname, "%s/%s", Basedir, DBFNAME);
858	if ((dbfp = fopen(dbfname, "r")) == NULL) {
859		DEBUG((9, "open of database file %s failed", DBFNAME));
860		logmessage("NLPS: Unable to open database file");
861		return((dbf_t *)NULL);
862	}
863
864	DEBUG((9, "database file opened, looking for %s", svc_code_p));
865	while (rd_dbf_line(dbfp, Dbf_line_buf, &Dbf_entry.dbf_svc_code,
866		&Dbf_entry.dbf_flags, &Dbf_entry.dbf_id, &Dbf_entry.dbf_res1,
867		&Dbf_entry.dbf_res2, &Dbf_entry.dbf_res3,&Dbf_entry.dbf_prv_adr,
868		&Dbf_entry.dbf_prognum, &Dbf_entry.dbf_version,
869		&Dbf_entry.dbf_modules, &Dbf_entry.dbf_sflags,
870		&Dbf_entry.dbf_cmd_line) > 0) {
871
872		/* see if this line is the one we want (svc_code match) */
873		if (!strcmp(Dbf_entry.dbf_svc_code, svc_code_p)) {
874			fclose(dbfp);
875			return(&Dbf_entry);
876		}
877	}
878
879	DEBUG((9, "No svc code match"));
880	fclose(dbfp);
881	return((dbf_t *)0);	/* svc code not in database	*/
882}
883