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