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