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 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 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 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 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 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 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 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 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 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 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 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 * 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