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
69 FILE *Logfp; /* file pointer for nlps_server's log file */
70 #ifdef DEBUGMODE
71 FILE *Debugfp; /* debugging output */
72 #endif
73
74 int Dbf_entries; /* number of private addresses in dbf file */
75 dbf_t *Dbfhead;
76 dbf_t *Newdbf;
77 char *New_cmd_lines;
78 char *Server_cmd_lines;
79
80 extern 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 */
86 int NLPS_proc = 1;
87 pid_t Pid;
88 char Lastmsg[BUFSIZ];
89 char *Netspec = NULL;
90 int Splflag = 0;
91 int Logmax = 0;
92 char *Mytag = NULL;
93
94 char msgbuf[BUFSIZ];
95 char Altbasedir[BUFSIZ];
96 char Basedir[BUFSIZ];
97 extern char *getenv();
98
99 static void nls_reply(int code, char *text);
100 static void nullfix(void);
101
102 int
main(int argc,char ** argv)103 main(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
142 int
nlps_server()143 nlps_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
220 int
getrequest(bp)221 getrequest(bp)
222 char *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
342 static void
nullfix(void)343 nullfix(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
428 void
timeout()429 timeout()
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
445 static char *badversion =
446 "NLPS: Unknown version of an NLPS service request: %d:%d";
447 static char *disabledmsg =
448 "NLPS: Request for service code <%s> denied, service is disabled";
449 static 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
458 static int Nlsversion = -1; /* protocol version */
459
460 int
nls_service(bp,size)461 nls_service(bp, size)
462 int size;
463 char *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
563 int
nls_chkmsg(bp,size,lowp,highp,svc_code_p)564 nls_chkmsg(bp, size, lowp, highp, svc_code_p)
565 char *bp, *svc_code_p;
566 int 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
590 static char *srrpprot = "%d:%d:%s";
591
592 static void
nls_reply(int code,char * text)593 nls_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
615 static char homeenv[BUFSIZ];
616 #define NETFD 0
617
618
619 int
exec_cmd(dbf_t * dbp,char ** o_argv)620 exec_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 */
790 int
isdigits(p)791 isdigits(p)
792 register 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
806 int
l_rcv(bufp,bytes,flagp)807 l_rcv(bufp, bytes, flagp)
808 char *bufp;
809 int bytes;
810 int *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
847 static char Dbf_line_buf[DBFLINESZ];
848 static dbf_t Dbf_entry;
849
850 dbf_t *
getdbfentry(svc_code_p)851 getdbfentry(svc_code_p)
852 register 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