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