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 * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * nlsadmin.c -- control program for the network listener service 35 * 36 * This program replaces a previous version of nlsadmin. 37 * 38 * This version of nlsadmin works with the service access facility to 39 * control the network listener. The functionality of the SVR3.2 nlsadmin 40 * command is supported through calls to the more general sacadm and pmadm 41 * commands available through SAF. Users should migrate away from nlsadmin 42 * to sacadm and pmadm for these functions. 43 * 44 * The -m option of the SVR3.2 nlsadmin command is now ignored. 45 * 46 * The -t option associates an address with service code 1 (same as in SVR3.2). 47 * The -l option associates an address with service code 0. 48 * 49 * nlsadmin also contains new functionality -- the ability to format a 50 * "listener-specific" string to put in the _pmtab database. This 51 * functionality is required by SAF. 52 */ 53 54 #include <sys/types.h> 55 #include <sys/stat.h> 56 #include <stdio.h> 57 #include <ctype.h> 58 #include <errno.h> 59 #include <string.h> 60 #include <sac.h> 61 #include "nlsadmin.h" 62 63 #define OPTIONS "a:c:d:e:ikl:mo:p:qr:st:vw:xy:z:A:N:VDR:" 64 #ifndef FALSE 65 #define TRUE 1 66 #define FALSE 0 67 #endif 68 /* 69 * defines for -q exit codes: QZERO is used for conditions that the 70 * man page documents as returning 0, QONE for those that return 1 71 */ 72 #define QZERO 0 73 #define QONE 1 74 75 /* 76 * defines for simulated standard error format code 77 */ 78 #define MM_NOSEV 0 79 #define MM_HALT 1 80 #define MM_ERROR 2 81 #define MM_WARNING 3 82 #define MM_INFO 4 83 84 char *Nlsname; /* set to argv[0] */ 85 char Label[25]; /* label component for fmtmsg */ 86 int Quietflag = FALSE; /* set to TRUE when -q used */ 87 88 extern int errno; 89 void nlsmesg(); 90 uid_t geteuid(); 91 char *nexttok(); 92 char *pflags(); 93 char *gencmdstr(); 94 95 struct svcfields { 96 char *pmtag; 97 char *pmtype; 98 char *svc_code; 99 char *flags; 100 char *id; 101 char *res1; 102 char *res2; 103 char *res3; 104 char *addr; 105 char *rpc; 106 char *lflags; 107 char *modules; 108 char *command; 109 char *comment; 110 }; 111 112 113 main(argc, argv) 114 int argc; 115 char **argv; 116 { 117 extern char *optarg; 118 extern int optind; 119 int c; /* used for return from getopt */ 120 char *addrptr = NULL; /* set when -A address is used */ 121 char *rpcptr = NULL; /* set when -R rpcinfo is used */ 122 char *cmdptr = NULL; /* set with -c command */ 123 char *comptr = NULL; /* set with -y comment (old) */ 124 char *idptr = NULL; /* set with -w id (old) */ 125 char *lptr = NULL; /* set with -l addr (old) */ 126 char *moduleptr = NULL; /* set with -m modules */ 127 char *pipeptr = NULL; /* set with -o pipe */ 128 char *svcptr = NULL; /* set when service code used (old) */ 129 char *tptr = NULL; /* set when -t addr used (old) */ 130 char *netspec = NULL; /* set to the network specification */ 131 int flag = 0; /* bit flag of type of command */ 132 int exitcode = 0; /* exit status of this command */ 133 int lflags = 0; /* listener flags */ 134 char buf[BUFSIZ]; /* temp buffer #1 */ 135 char mesg[BUFSIZ]; /* temp buffer #2 */ 136 FILE *fp; /* used for checking netspec */ 137 char *ptr; /* temp pointer */ 138 char *ptr2; /* temp pointer */ 139 int sawsep = 0; /* flag for RPC separator */ 140 141 Nlsname = argv[0]; 142 sprintf(Label, "UX:%.14s", argv[0]); /* for standard message fmt */ 143 144 while ((c = getopt(argc, argv, OPTIONS)) != -1) { 145 switch (c) { 146 case 'a': 147 if ( (flag && (flag != CMDFLAG)) || svcptr || Quietflag 148 || addrptr || rpcptr || lflags) 149 usage(INCONSISTENT); 150 svcptr = optarg; 151 break; 152 case 'c': 153 if ( (flag && (flag != CMDFLAG)) || cmdptr || Quietflag ) 154 usage(INCONSISTENT); 155 cmdptr = optarg; 156 flag |= CMDFLAG; 157 break; 158 case 'd': 159 if ( flag || svcptr || Quietflag || comptr || addrptr 160 || rpcptr || cmdptr || idptr || lflags ) 161 usage(INCONSISTENT); 162 svcptr = optarg; 163 flag |= DISFLAG; 164 break; 165 case 'e': 166 if ( flag || svcptr || Quietflag || comptr || addrptr 167 || rpcptr || cmdptr || idptr || lflags ) 168 usage(INCONSISTENT); 169 svcptr = optarg; 170 flag |= ENAFLAG; 171 break; 172 case 'i': 173 if ( flag || svcptr || Quietflag || comptr || addrptr 174 || rpcptr || cmdptr || idptr || lflags ) 175 usage(INCONSISTENT); 176 flag |= INIFLAG; 177 break; 178 case 'k': 179 if ( flag || svcptr || Quietflag || comptr || addrptr 180 || rpcptr || cmdptr || idptr || lflags ) 181 usage(INCONSISTENT); 182 flag |= KILFLAG; 183 break; 184 case 'l': 185 if ( ( flag && (flag != ADRFLAG)) || svcptr || lptr 186 || Quietflag || comptr || addrptr || rpcptr 187 || cmdptr || idptr || lflags ) 188 usage(INCONSISTENT); 189 lptr = optarg; 190 flag |= ADRFLAG; 191 break; 192 case 'm': 193 if ( (flag && (flag != CMDFLAG)) || Quietflag || rpcptr || lflags ) 194 usage(INCONSISTENT); 195 flag |= CMDFLAG; 196 break; 197 case 'o': 198 if ( flag || svcptr || Quietflag || comptr || idptr || netspec ) 199 usage(INCONSISTENT); 200 pipeptr = optarg; 201 flag |= PIPFLAG; 202 break; 203 case 'p': 204 if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) || Quietflag ) 205 usage(INCONSISTENT); 206 moduleptr = optarg; 207 break; 208 case 'q': 209 if ( (flag && (flag != ZZZFLAG)) || Quietflag || comptr 210 || rpcptr || lflags || idptr ) 211 usage(INCONSISTENT); 212 Quietflag = TRUE; 213 break; 214 case 'r': 215 if ( flag || svcptr || Quietflag || comptr || addrptr 216 || rpcptr || cmdptr || idptr || lflags ) 217 usage(INCONSISTENT); 218 flag |= REMFLAG; 219 svcptr = optarg; 220 break; 221 case 's': 222 if ( flag || svcptr || Quietflag || comptr || addrptr 223 || rpcptr || cmdptr || idptr || lflags ) 224 usage(INCONSISTENT); 225 flag |= STAFLAG; 226 break; 227 case 't': 228 if ( (flag && (flag != ADRFLAG)) || svcptr || tptr 229 || Quietflag || comptr || addrptr || rpcptr 230 || cmdptr || idptr || lflags ) 231 usage(INCONSISTENT); 232 tptr = optarg; 233 flag |= ADRFLAG; 234 break; 235 case 'v': 236 if ( flag || svcptr || Quietflag || comptr || rpcptr 237 || addrptr || idptr || lflags ) 238 usage(INCONSISTENT); 239 flag |= VBSFLAG; 240 break; 241 case 'w': 242 if ( (flag && (flag != CMDFLAG)) || Quietflag || idptr 243 || rpcptr || addrptr || lflags ) 244 usage(INCONSISTENT); 245 idptr = optarg; 246 break; 247 case 'x': 248 if ( flag || svcptr || Quietflag || netspec || comptr 249 || rpcptr || addrptr || lflags || idptr ) 250 usage(INCONSISTENT); 251 flag |= NETFLAG; 252 break; 253 case 'y': 254 if ( (flag && (flag != CMDFLAG)) || Quietflag || comptr 255 || rpcptr || addrptr || lflags ) 256 usage(INCONSISTENT); 257 comptr = optarg; 258 break; 259 case 'z': 260 if ( flag || svcptr || comptr || addrptr || rpcptr 261 || idptr || lflags ) 262 usage(INCONSISTENT); 263 flag |= ZZZFLAG; 264 svcptr = optarg; 265 break; 266 case 'A': 267 if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) 268 || netspec || svcptr || idptr || comptr ) 269 usage(INCONSISTENT); 270 addrptr = optarg; 271 break; 272 case 'D': 273 if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) 274 || netspec || svcptr || idptr || comptr || addrptr 275 || lflags ) 276 usage(INCONSISTENT); 277 lflags |= DFLAG; 278 break; 279 case 'N': 280 if ( netspec ) 281 usage(INCONSISTENT); 282 netspec = optarg; 283 break; 284 case 'R': 285 if ( (flag && (flag != CMDFLAG) && (flag != PIPFLAG)) 286 || netspec || svcptr || idptr || comptr ) 287 usage(INCONSISTENT); 288 for (ptr = optarg; *ptr; ++ptr) { 289 if ((*ptr == ':') && !sawsep) { 290 /* 291 * skip separator - note that if 292 * separator has been seen, it's not 293 * a digit so it will generate a usage 294 * message below like we want 295 */ 296 sawsep++; 297 continue; 298 } 299 if (!isdigit(*ptr)) 300 usage(USAGE); 301 } 302 ptr = strchr(optarg, ':'); 303 if (ptr) 304 /* change the ':' to a ',' */ 305 *ptr = ','; 306 else 307 usage(USAGE); 308 rpcptr = optarg; 309 break; 310 case 'V': 311 if ( flag || svcptr || Quietflag || comptr || netspec 312 || rpcptr || addrptr || idptr || lflags ) 313 usage(INCONSISTENT); 314 flag |= VERFLAG; 315 break; 316 case '?': 317 usage(USAGE); 318 } 319 } 320 321 if ((optind < argc) && ! netspec) 322 netspec = argv[optind++]; 323 if (optind < argc) 324 usage(USAGE); 325 326 327 /* determine if this command requires a netspec */ 328 if (flag != CMDFLAG) { 329 /* if flag is CMDFLAG, more complicated checking of netspec 330 * is done below in switch 331 */ 332 if ((flag == PIPFLAG || flag == VERFLAG || flag == NETFLAG)) { 333 if (netspec) 334 usage(USAGE); 335 } 336 else if (!netspec) 337 usage(USAGE); 338 } 339 340 if (netspec && (flag != INIFLAG)) { 341 sprintf(buf, SAC_LSPM, netspec); 342 343 if ((fp = popen(buf, "r")) == NULL) { 344 nlsmesg(MM_ERROR, "System error"); 345 exit(NLS_SYSERR); 346 } 347 348 if (fgets(buf, BUFSIZ, fp) == NULL) { 349 nlsmesg(MM_ERROR, "Invalid network specification"); 350 exit(NLS_BADPM); 351 } 352 else { 353 ptr = strchr(buf, ':'); 354 ptr++; 355 ptr2 = strchr(ptr, ':'); 356 *ptr2 = NULL; 357 if (strcmp(ptr, LISTENTYPE) != 0) { 358 sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE); 359 nlsmesg(MM_ERROR, mesg); 360 exit(NLS_BADPM); 361 } 362 } 363 364 pclose(fp); 365 } 366 367 if (svcptr) { 368 /* check to see if service code is "correct" -- right range 369 * and format. The -m flag is ignored, so no check for 370 * "administrative" service codes (0-100) is done. 371 */ 372 c = strlen(svcptr); 373 if ((c == 0) || (c >= SVC_CODE_SZ)) { 374 sprintf(mesg, "Service code contains more than %d characters", SVC_CODE_SZ); 375 nlsmesg(MM_ERROR, mesg); 376 exit(NLS_SERV); 377 } 378 } 379 380 switch (flag) { 381 default: 382 usage(USAGE); 383 break; 384 case NONE: 385 if ( svcptr || comptr || rpcptr || lflags || idptr ) 386 usage(INCONSISTENT); 387 exitcode = prt_nets(netspec); 388 break; 389 case INIFLAG: 390 if (geteuid() != ROOT) 391 no_permission(); 392 exitcode = add_pm(netspec); 393 break; 394 case CMDFLAG: 395 if ( svcptr || comptr || idptr || netspec ) { 396 if (geteuid() != ROOT) 397 no_permission(); 398 if ((exitcode = old_addsvc(svcptr, "", cmdptr, comptr, moduleptr, idptr, NULL, netspec)) != NLS_OK) 399 switch (exitcode) { 400 case NLS_SERV: 401 nlsmesg(MM_ERROR, "Service code already exists"); 402 break; 403 default: 404 nlsmesg(MM_ERROR, "Could not add service"); 405 break; 406 } 407 } 408 else { 409 if (netspec) 410 usage(INCONSISTENT); 411 exitcode = prt_cmd(cmdptr, CFLAG | lflags, moduleptr, addrptr, rpcptr); 412 } 413 break; 414 case PIPFLAG: 415 if (geteuid() != ROOT) 416 no_permission(); 417 exitcode = prt_cmd(pipeptr, PFLAG | lflags, moduleptr, addrptr, rpcptr); 418 break; 419 case VERFLAG: 420 printf("%d\n", VERSION); 421 exit(NLS_OK); 422 break; 423 case DISFLAG: 424 if (geteuid() != ROOT) 425 no_permission(); 426 exitcode = disable_svc(svcptr, netspec); 427 break; 428 case ENAFLAG: 429 if (geteuid() != ROOT) 430 no_permission(); 431 exitcode = enable_svc(svcptr, netspec); 432 break; 433 case KILFLAG: 434 if (geteuid() != ROOT) 435 no_permission(); 436 exitcode = kill_listener(netspec); 437 break; 438 case ADRFLAG: 439 /* check for root permissions in setup_addr */ 440 exitcode = setup_addr(lptr, tptr, netspec); 441 break; 442 case REMFLAG: 443 if (geteuid() != ROOT) 444 no_permission(); 445 exitcode = remove_svc(svcptr, netspec, TRUE); 446 break; 447 case STAFLAG: 448 if (geteuid() != ROOT) 449 no_permission(); 450 exitcode = start_listener(netspec); 451 break; 452 case VBSFLAG: 453 exitcode = prt_svcs(NULL, netspec); 454 break; 455 case NETFLAG: 456 exitcode = prt_nets(NULL); 457 break; 458 case ZZZFLAG: 459 exitcode = prt_svcs(svcptr, netspec); 460 break; 461 } 462 if (exitcode == NLS_SYSERR) 463 nlsmesg(MM_ERROR, "System error in SAC command"); 464 exit(exitcode); 465 } 466 467 468 static char umsg[] = "usage: %s -x\n\ 469 %s [ options ] netspec\n\ 470 %s [ options ] -N port_monitor_tag\n\ 471 %s -V\n\ 472 %s -c cmd | -o pipename [ -p modules ] [ -A addr | -D ] \\\n\ 473 [ -R prognum:versnum ]\n\ 474 \n\ 475 [ options ] are:\n\ 476 [ -a svc_code -c \"cmd\" -y \"cmt\" [-p modules] [-w id] ]\n\ 477 [-q] | [-v] | [-s] | [-k] | [-i] |\n\ 478 [-e svc_code] | [-d svc_code] | [-r svc_code] | [[-q] -z svc_code]\n\ 479 [[-l addr | -] [-t addr | -]] |\n\ 480 "; 481 482 usage(flag) 483 int flag; 484 { 485 switch (flag) { 486 case INCONSISTENT: 487 nlsmesg(MM_ERROR, "Inconsistent options"); 488 break; 489 case MISSINGARG: 490 nlsmesg(MM_ERROR, "Missing argument"); 491 break; 492 case USAGE: 493 break; 494 } 495 fprintf(stderr, umsg, Nlsname, Nlsname, Nlsname, Nlsname, Nlsname); 496 exit(NLS_CMD); 497 } 498 499 500 /* 501 * no_permission: print out error message and exit when the user needs to 502 * needs to be root and isn't. 503 */ 504 505 no_permission() 506 { 507 nlsmesg(MM_ERROR, "Must be super user"); 508 exit(NLS_PERM); 509 } 510 511 /* 512 * nlsmesg: print out either an error or a warning message. severity must 513 * be either MM_ERROR or MM_WARNING. this routine will be converted 514 * to use the standard message format later. 515 */ 516 517 void 518 nlsmesg(severity, text) 519 int severity; 520 char *text; 521 { 522 int class; 523 524 if (severity == MM_ERROR) 525 fprintf(stderr, "%s: error: %s\n", Nlsname, text); 526 else 527 fprintf(stderr, "%s: warning: %s\n", Nlsname, text); 528 return; 529 } 530 531 /* 532 * prt_cmd: print out the listener-dependent string for sacadm. 533 */ 534 535 prt_cmd(path, flags, modules, addr, rpcp) 536 char *path; /* full path of command or pipe */ 537 long flags; /* listener flags */ 538 /* PFLAG for pipe */ 539 /* CFLAG for command */ 540 /* DFLAG for dynamic addr */ 541 char *modules; /* STREAMS modules to push */ 542 char *addr; /* private address */ 543 char *rpcp; /* RPC prog and ver # */ 544 { 545 struct stat sbuf; 546 char mesgbuf[BUFSIZ]; 547 char *tmp; 548 549 if (*path != '/') { 550 nlsmesg(MM_ERROR, "Must specify full path name"); 551 return(NLS_CMD); 552 } 553 554 if ((tmp = strchr(path, ' ')) != NULL) 555 *tmp = NULL; 556 557 if (stat(path, &sbuf) < 0) { 558 if (errno != EFAULT) { 559 sprintf(mesgbuf, "%s does not exist", path); 560 nlsmesg(MM_WARNING, mesgbuf); 561 } 562 else 563 return(NLS_SYSERR); 564 } 565 566 if (tmp) 567 *tmp = ' '; 568 569 printf("%s:%s:%s:%s:%s\n", (addr ? addr : ""), (rpcp ? rpcp : ""), 570 pflags(flags), (modules ? modules : ""), path); 571 return(NLS_OK); 572 } 573 574 /* 575 * old_addsvc: use pmadm to add a service code to the listener. this will 576 * not allow specification of a private address -- use pmadm! 577 */ 578 579 old_addsvc(svc, addr, cmd, com, module, id, flags, netspec) 580 char *svc; 581 char *addr; 582 char *cmd; 583 char *com; 584 char *module; 585 char *id; 586 char *flags; 587 char *netspec; 588 { 589 char buf[BUFSIZ]; 590 char mesgbuf[BUFSIZ]; 591 int rtn; 592 struct stat sbuf; 593 char *tmp; 594 595 if (!svc || !cmd || !com || !netspec) 596 usage(MISSINGARG); 597 598 /* create "port-monitor specific" info in the same way as prt_cmd */ 599 600 if (*cmd != '/') { 601 nlsmesg(MM_ERROR, "Must specify full path name"); 602 return(NLS_CMD); 603 } 604 605 if ((tmp = strchr(cmd, ' ')) != NULL) 606 *tmp = NULL; 607 608 if (stat(cmd, &sbuf) < 0) { 609 if (errno != EFAULT) { 610 sprintf(mesgbuf, "%s does not exist", cmd); 611 nlsmesg(MM_WARNING, mesgbuf); 612 } 613 else 614 return(NLS_SYSERR); 615 } 616 617 if (tmp) 618 *tmp = ' '; 619 620 if (addr) 621 sprintf(mesgbuf, "'%s::c:%s:%s'", addr, module ? module : "" , cmd); 622 else 623 sprintf(mesgbuf, "'::c:%s:%s'", module ? module : "" , cmd); 624 625 if (flags && *flags) 626 sprintf(buf, PM_ADDSVCF, netspec, svc, (id)?id:DEFAULTID, flags, mesgbuf, VERSION, com ? com : ""); 627 else 628 sprintf(buf, PM_ADDSVC, netspec, svc, (id)?id:DEFAULTID, mesgbuf, VERSION, com ? com : ""); 629 630 if ((rtn = system(buf)) < 0) { 631 return(NLS_SYSERR); 632 } 633 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 634 635 switch (rtn) { 636 case 0: 637 return(NLS_OK); 638 break; 639 case E_BADARGS: 640 case E_SAFERR: 641 case E_SYSERR: 642 case E_NOEXIST: 643 case E_PMRUN: 644 case E_PMNOTRUN: 645 case E_RECOVER: 646 case E_SACNOTRUN: 647 default: 648 return(NLS_SYSERR); 649 break; 650 case E_DUP: 651 return(NLS_SERV); 652 break; 653 case E_NOPRIV: 654 no_permission(); 655 break; 656 } 657 } 658 659 /* 660 * prt_nets: print the status of one network, or all nets if netspec 661 * is NULL 662 */ 663 prt_nets(netspec) 664 char *netspec; 665 { 666 char buf[BUFSIZ]; 667 FILE *fp; 668 char *name; 669 char *state; 670 char *type; 671 int found = FALSE; 672 int rtn = NLS_OK; 673 674 if (netspec == NULL) 675 sprintf(buf, SAC_LSTY, LISTENTYPE); 676 else 677 sprintf(buf, SAC_LSPM, netspec); 678 679 if ((fp = popen(buf, "r")) == NULL) 680 return(NLS_SYSERR); 681 682 while (fgets(buf, BUFSIZ, fp) != NULL) { 683 if ((name = nexttok(buf, ":")) == NULL) 684 return(NLS_SYSERR); 685 if ((type = nexttok(NULL, ":")) == NULL) 686 return(NLS_SYSERR); 687 688 if (strcmp(type, LISTENTYPE) != 0) 689 continue; /* ignore other types of port monitors */ 690 691 found = TRUE; 692 if (nexttok(NULL, ":") == NULL) 693 return(NLS_SYSERR); 694 if (nexttok(NULL, ":") == NULL) 695 return(NLS_SYSERR); 696 if ((state = nexttok(NULL, ":")) == NULL) 697 return(NLS_SYSERR); 698 if (strcmp(state, "ENABLED") == NULL || 699 strcmp(state, "STARTING") == NULL) { 700 rtn = QZERO; 701 if (!Quietflag) 702 printf("%s\t%s\n", name, "ACTIVE"); 703 } 704 else { 705 rtn = QONE; 706 if (!Quietflag) 707 printf("%s\t%s\n", name, "INACTIVE"); 708 } 709 } 710 pclose(fp); 711 712 if (netspec && !found) { 713 nlsmesg(MM_ERROR, "Invalid network specification"); 714 return(NLS_BADPM); 715 } 716 717 if (netspec) 718 return(rtn); 719 else 720 return(NLS_OK); 721 722 } 723 724 725 /* 726 * print info about service on netspec, or all services on netspec 727 * if svc is NULL 728 */ 729 730 prt_svcs(svc, netspec) 731 char *svc; 732 char *netspec; 733 { 734 char buf[BUFSIZ]; 735 char mesg[BUFSIZ]; 736 FILE *fp; 737 struct svcfields entry; 738 int rtn; 739 int found = FALSE; 740 char *p; 741 742 if (svc == NULL) 743 sprintf(buf, PM_LSALL, netspec); 744 else 745 sprintf(buf, PM_LSONE, netspec, svc); 746 747 if ((fp = popen(buf, "r")) == NULL) 748 return(NLS_SYSERR); 749 750 while (fgets(buf, BUFSIZ, fp) != NULL) { 751 if ((rtn = svc_format(buf, &entry)) != 0) { 752 switch (rtn) { 753 case NOTLISTEN: 754 continue; 755 break; 756 case BADPMFMT: 757 return(NLS_SYSERR); 758 break; 759 case BADLISFMT: 760 sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); 761 nlsmesg(MM_WARNING, mesg); 762 continue; 763 break; 764 } 765 } 766 found = TRUE; 767 768 if (!Quietflag) { 769 printf("%s\t", entry.svc_code); 770 if (*entry.addr) 771 printf("%s\t", entry.addr); 772 else if (strchr(entry.lflags, 'd')) 773 printf("DYNAMIC\t"); 774 else 775 printf("NOADDR\t"); 776 777 if (strchr(entry.flags, 'x') == NULL) 778 printf("ENABLED \t"); 779 else 780 printf("DISABLED\t"); 781 782 783 printf("%s\t%s\t%s\t%s\t# %s", 784 (*entry.rpc)?entry.rpc:"NORPC", entry.id, 785 (*entry.modules)?entry.modules:"NOMODULES", 786 entry.command, (*entry.comment)?entry.comment:""); 787 } 788 else { 789 if (strchr(entry.flags, 'x') == NULL) 790 return(QZERO); 791 else 792 return(QONE); 793 } 794 } 795 796 pclose(fp); 797 798 if (rtn == NOTLISTEN) { /* check last return to see if error */ 799 sprintf(mesg, "Network specification \"%s\" is not of type %s", netspec, LISTENTYPE); 800 nlsmesg(MM_ERROR, mesg); 801 return(NLS_BADPM); 802 } 803 if (svc && !found) { 804 if (!Quietflag) { 805 sprintf(mesg, "Service \"%s\" unknown", svc); 806 nlsmesg(MM_ERROR, mesg); 807 } 808 return(NLS_SERV); 809 } 810 811 return(NLS_OK); 812 } 813 814 /* 815 * disable_svc: use pmadm to disable a service 816 */ 817 818 disable_svc(svc, netspec) 819 char *svc; 820 char *netspec; 821 { 822 char buf[BUFSIZ]; 823 int rtn; 824 825 sprintf(buf, PM_DISABLE, netspec, svc); 826 827 if ((rtn = system(buf)) < 0) { 828 return(NLS_SYSERR); 829 } 830 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 831 832 switch (rtn) { 833 case 0: 834 return(NLS_OK); 835 break; 836 case E_BADARGS: 837 case E_SAFERR: 838 case E_SYSERR: 839 case E_PMRUN: 840 case E_PMNOTRUN: 841 case E_RECOVER: 842 case E_SACNOTRUN: 843 default: 844 return(NLS_SYSERR); 845 break; 846 case E_NOEXIST: 847 case E_DUP: 848 nlsmesg(MM_ERROR, "Non-existent service."); 849 return(NLS_SERV); 850 break; 851 case E_NOPRIV: 852 no_permission(); 853 break; 854 } 855 } 856 857 858 enable_svc(svc, netspec) 859 char *svc; 860 char *netspec; 861 { 862 char buf[BUFSIZ]; 863 int rtn; 864 865 sprintf(buf, PM_ENABLE, netspec, svc); 866 867 if ((rtn = system(buf)) < 0) { 868 return(NLS_SYSERR); 869 } 870 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 871 872 switch (rtn) { 873 case 0: 874 return(NLS_OK); 875 break; 876 case E_BADARGS: 877 case E_SAFERR: 878 case E_SYSERR: 879 case E_PMRUN: 880 case E_PMNOTRUN: 881 case E_RECOVER: 882 case E_SACNOTRUN: 883 default: 884 return(NLS_SYSERR); 885 break; 886 case E_NOEXIST: 887 case E_DUP: 888 nlsmesg(MM_ERROR, "Non-existent service."); 889 return(NLS_SERV); 890 break; 891 case E_NOPRIV: 892 no_permission(); 893 break; 894 } 895 } 896 897 898 remove_svc(svc, netspec, printerrors) 899 char *svc; 900 char *netspec; 901 int printerrors; 902 { 903 char buf[BUFSIZ]; 904 int rtn; 905 906 sprintf(buf, PM_REMSVC, netspec, svc); 907 908 if ((rtn = system(buf)) < 0) { 909 return(NLS_SYSERR); 910 } 911 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 912 913 switch (rtn) { 914 case 0: 915 return(NLS_OK); 916 break; 917 case E_BADARGS: 918 case E_SAFERR: 919 case E_SYSERR: 920 case E_PMRUN: 921 case E_PMNOTRUN: 922 case E_RECOVER: 923 case E_SACNOTRUN: 924 default: 925 return(NLS_SYSERR); 926 break; 927 case E_NOEXIST: 928 case E_DUP: 929 if (printerrors) 930 nlsmesg(MM_ERROR, "Non-existent service."); 931 return(NLS_SERV); 932 break; 933 case E_NOPRIV: 934 no_permission(); 935 break; 936 } 937 } 938 939 940 kill_listener(netspec) 941 char *netspec; 942 { 943 char buf[BUFSIZ]; 944 char mesg[BUFSIZ]; 945 int rtn; 946 947 sprintf(buf, SAC_KILLPM, netspec); 948 949 if ((rtn = system(buf)) < 0) { 950 return(NLS_SYSERR); 951 } 952 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 953 954 switch (rtn) { 955 case 0: 956 return(NLS_OK); 957 break; 958 case E_BADARGS: 959 case E_DUP: 960 case E_SAFERR: 961 case E_SYSERR: 962 case E_PMRUN: 963 case E_RECOVER: 964 case E_SACNOTRUN: 965 default: 966 return(NLS_SYSERR); 967 break; 968 case E_PMNOTRUN: 969 sprintf(mesg, "No listener active on network \"%s\"", netspec); 970 nlsmesg(MM_ERROR, mesg); 971 return(NLS_FAILED); 972 case E_NOEXIST: 973 nlsmesg(MM_ERROR, "Non-existent port monitor."); 974 return(NLS_SERV); 975 break; 976 case E_NOPRIV: 977 no_permission(); 978 break; 979 } 980 } 981 982 983 /* 984 * add_pm: add a port monitor (initialize directories) using sacadm 985 */ 986 987 add_pm(netspec) 988 char *netspec; 989 { 990 char buf[BUFSIZ]; 991 char mesg[BUFSIZ]; 992 int rtn; 993 994 sprintf(buf, SAC_ADDPM, netspec, LISTENTYPE, gencmdstr(netspec), VERSION); 995 996 if ((rtn = system(buf)) < 0) { 997 return(NLS_SYSERR); 998 } 999 rtn = (rtn>>8) & 0xff; /* get child return value out of exit word */ 1000 1001 switch (rtn) { 1002 case 0: 1003 old_addsvc(NLPSSVCCODE, NULL, NLPSSRV, "NLPS server", "", "root", NULL, netspec); 1004 return(NLS_OK); 1005 break; 1006 case E_BADARGS: 1007 case E_SAFERR: 1008 case E_SYSERR: 1009 case E_RECOVER: 1010 case E_NOEXIST: 1011 case E_PMNOTRUN: 1012 case E_SACNOTRUN: 1013 default: 1014 return(NLS_SYSERR); 1015 break; 1016 case E_DUP: 1017 case E_PMRUN: 1018 nlsmesg(MM_ERROR, "Listener already initialized"); 1019 return(NLS_FAILED); 1020 break; 1021 case E_NOPRIV: 1022 no_permission(); 1023 break; 1024 } 1025 } 1026 1027 1028 /* 1029 * gencmdstr: generate the correct string to invoke the listener (starlan 1030 * requires special handling) 1031 */ 1032 1033 char * 1034 gencmdstr(netspec) 1035 char *netspec; 1036 { 1037 static char buf[BUFSIZ]; 1038 1039 (void) strcpy(buf, LISTENCMD); 1040 if (!strcmp(netspec, "starlan")) 1041 (void) strcat(buf, " -m slan"); 1042 (void) strcat(buf, " "); 1043 (void) strcat(buf, netspec); 1044 return(buf); 1045 } 1046 1047 1048 /* 1049 * start_listener: start the listener 1050 */ 1051 1052 start_listener(netspec) 1053 char *netspec; 1054 { 1055 char buf[BUFSIZ]; 1056 char scratch[BUFSIZ]; 1057 int rtn; 1058 1059 sprintf(buf, SAC_STARTPM, netspec); 1060 1061 if ((rtn = system(buf)) < 0) 1062 return(NLS_SYSERR); 1063 rtn = (rtn>>8) & 0xff; 1064 switch (rtn) { 1065 case 0: 1066 break; 1067 case E_BADARGS: 1068 case E_SAFERR: 1069 case E_SYSERR: 1070 case E_RECOVER: 1071 case E_PMNOTRUN: 1072 case E_SACNOTRUN: 1073 default: 1074 return(NLS_SYSERR); 1075 break; 1076 case E_NOEXIST: 1077 case E_DUP: 1078 nlsmesg(MM_ERROR, "Non-existent port monitor."); 1079 return(NLS_BADPM); 1080 break; 1081 case E_PMRUN: 1082 nlsmesg(MM_ERROR, "Listener already running"); 1083 return(NLS_FAILED); 1084 case E_NOPRIV: 1085 no_permission(); 1086 break; 1087 } 1088 1089 sprintf(buf, SAC_ENABLPM, netspec); 1090 1091 if ((rtn = system(buf)) < 0) { 1092 return(NLS_SYSERR); 1093 } 1094 rtn = (rtn>>8) & 0xff; 1095 switch (rtn) { 1096 case 0: 1097 return(NLS_OK); 1098 break; 1099 case E_BADARGS: 1100 case E_SAFERR: 1101 case E_SYSERR: 1102 case E_RECOVER: 1103 case E_SACNOTRUN: 1104 default: 1105 return(NLS_SYSERR); 1106 break; 1107 case E_NOEXIST: 1108 case E_DUP: 1109 nlsmesg(MM_ERROR, "Non-existent port monitor."); 1110 return(NLS_BADPM); 1111 break; 1112 case E_PMRUN: 1113 nlsmesg(MM_ERROR, "Listener already running"); 1114 return(NLS_FAILED); 1115 case E_PMNOTRUN: 1116 nlsmesg(MM_ERROR, "Listener start failed"); 1117 return(NLS_FAILED); 1118 case E_NOPRIV: 1119 no_permission(); 1120 break; 1121 } 1122 } 1123 1124 1125 /* 1126 * setup_addr: setup the -l and -t addresses. 1127 */ 1128 1129 setup_addr(laddr, taddr, netspec) 1130 char *laddr; 1131 char *taddr; 1132 char *netspec; 1133 { 1134 char buf[BUFSIZ]; 1135 char mesg[BUFSIZ]; 1136 char *p; 1137 int rtn; 1138 int qlisten = FALSE; 1139 int qtty = FALSE; 1140 FILE *fp; 1141 struct svcfields entry; 1142 1143 if (laddr && *laddr == '-') 1144 qlisten = TRUE; 1145 1146 if (taddr && *taddr == '-') 1147 qtty = TRUE; 1148 1149 if (laddr) { 1150 sprintf(buf, PM_LSONE, netspec, NLPSSVCCODE); 1151 1152 if ((fp = popen(buf, "r")) == NULL) { 1153 return(NLS_SYSERR); 1154 } 1155 1156 if (fgets(buf, BUFSIZ, fp) != NULL) { 1157 if ((rtn = svc_format(buf, &entry)) != 0) { 1158 switch (rtn) { 1159 case NOTLISTEN: 1160 nlsmesg(MM_ERROR, "Incorrect port monitor type. Must be of type listen"); 1161 return(NLS_FAILED); 1162 break; 1163 case BADPMFMT: 1164 return(NLS_SYSERR); 1165 break; 1166 case BADLISFMT: 1167 sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); 1168 nlsmesg(MM_WARNING, mesg); 1169 break; 1170 } 1171 } 1172 else { 1173 if (qlisten) 1174 printf("%s\n", entry.addr); 1175 else { 1176 if (geteuid() != ROOT) 1177 no_permission(); 1178 /* add address */ 1179 remove_svc(NLPSSVCCODE, netspec, FALSE); 1180 p = strchr(entry.comment, '\n'); 1181 if (p) 1182 *p = '\0'; 1183 old_addsvc(NLPSSVCCODE, laddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec); 1184 } 1185 } 1186 pclose(fp); 1187 } 1188 else if (!qlisten) 1189 nlsmesg(MM_WARNING, "NLPS service not defined"); 1190 } 1191 if (taddr) { 1192 sprintf(buf, PM_LSONE, netspec, TTYSVCCODE); 1193 1194 if ((fp = popen(buf, "r")) == NULL) { 1195 return(NLS_SYSERR); 1196 } 1197 1198 if (fgets(buf, BUFSIZ, fp) != NULL) { 1199 if ((rtn = svc_format(buf, &entry)) != 0) { 1200 switch (rtn) { 1201 case NOTLISTEN: 1202 nlsmesg(MM_ERROR, "Incorrect port monitor type. Must be of type listen"); 1203 return(NLS_FAILED); 1204 break; 1205 case BADPMFMT: 1206 return(NLS_SYSERR); 1207 break; 1208 case BADLISFMT: 1209 sprintf(mesg, "Entry for code \"%s\" has incorrect format", entry.svc_code); 1210 nlsmesg(MM_WARNING, mesg); 1211 break; 1212 } 1213 } 1214 else { 1215 if (qtty) 1216 printf("%s\n", entry.addr); 1217 else { 1218 if (geteuid() != ROOT) 1219 no_permission(); 1220 /* add address */ 1221 remove_svc(TTYSVCCODE, netspec, FALSE); 1222 p = strchr(entry.comment, '\n'); 1223 if (p) 1224 *p = '\0'; 1225 old_addsvc(TTYSVCCODE, taddr, entry.command, entry.comment, entry.modules, entry.id, entry.flags, netspec); 1226 } 1227 } 1228 pclose(fp); 1229 } 1230 else if (!qtty) 1231 nlsmesg(MM_WARNING, "remote login service not defined"); 1232 } 1233 return(NLS_OK); 1234 } 1235 1236 1237 /* 1238 * svc_format: scan a line of output from pmadm to separate it into fields. 1239 * returns BADPMFMT for missing fields or incorrect syntax. 1240 * NOTLISTEN is the port monitor type is not listen. 1241 * BADLISFMT if the listener-specific data is incorrect. 1242 * NLS_OK if everything checked out and data is broken 1243 * into the structure. 1244 */ 1245 1246 svc_format(buf, entry) 1247 char *buf; 1248 struct svcfields *entry; 1249 { 1250 char *ptr; /* temporary pointer into buffer */ 1251 char *tmp; /* temporary pointer into buffer */ 1252 1253 entry->pmtag = buf; 1254 if ((ptr = strchr(buf, ':')) == NULL) 1255 return(BADPMFMT); 1256 *ptr++ = NULL; 1257 entry->pmtype = ptr; 1258 if ((ptr = strchr(entry->pmtype, ':')) == NULL) 1259 return(BADPMFMT); 1260 *ptr++ = NULL; 1261 entry->svc_code = ptr; 1262 1263 if (strcmp(entry->pmtype, LISTENTYPE) != 0) 1264 return(NOTLISTEN); 1265 1266 if ((ptr = strchr(entry->svc_code, ':')) == NULL) 1267 return(BADPMFMT); 1268 *ptr++ = NULL; 1269 entry->flags = ptr; 1270 if ((ptr = strchr(entry->flags, ':')) == NULL) 1271 return(BADPMFMT); 1272 *ptr++ = NULL; 1273 entry->id = ptr; 1274 if ((ptr = strchr(entry->id, ':')) == NULL) 1275 return(BADPMFMT); 1276 *ptr++ = NULL; 1277 entry->res1 = ptr; 1278 if ((ptr = strchr(entry->res1, ':')) == NULL) 1279 return(BADPMFMT); 1280 *ptr++ = NULL; 1281 entry->res2 = ptr; 1282 if ((ptr = strchr(entry->res2, ':')) == NULL) 1283 return(BADPMFMT); 1284 *ptr++ = NULL; 1285 entry->res3 = ptr; 1286 if ((ptr = strchr(entry->res3, ':')) == NULL) 1287 return(BADPMFMT); 1288 *ptr++ = NULL; 1289 entry->addr = ptr; 1290 if ((ptr = strchr(entry->addr, ':')) == NULL) 1291 return(BADLISFMT); 1292 *ptr++ = NULL; 1293 entry->rpc = ptr; 1294 if ((ptr = strchr(entry->rpc, ':')) == NULL) 1295 return(BADLISFMT); 1296 *ptr++ = NULL; 1297 if (*entry->rpc) { 1298 if ((tmp = strchr(entry->rpc, ',')) == NULL) 1299 return(BADLISFMT); 1300 *tmp = ':'; 1301 } 1302 entry->lflags = ptr; 1303 if ((ptr = strchr(entry->lflags, ':')) == NULL) 1304 return(BADLISFMT); 1305 *ptr++ = NULL; 1306 entry->modules = ptr; 1307 if ((ptr = strchr(entry->modules, ':')) == NULL) 1308 return(BADLISFMT); 1309 *ptr++ = NULL; 1310 entry->command = ptr; 1311 if ((ptr = strchr(entry->command, '#')) == NULL) 1312 return(BADLISFMT); 1313 *ptr++ = NULL; 1314 entry->comment = ptr; 1315 return(NLS_OK); 1316 } 1317 1318 1319 /* 1320 * nexttok - return next token, essentially a strtok, but it can 1321 * deal with null fields and strtok can not 1322 * 1323 * args: str - the string to be examined, NULL if we should 1324 * examine the remembered string 1325 * delim - the list of valid delimiters 1326 */ 1327 1328 1329 char * 1330 nexttok(str, delim) 1331 char *str; 1332 register char *delim; 1333 { 1334 static char *savep; /* the remembered string */ 1335 register char *p; /* pointer to start of token */ 1336 register char *ep; /* pointer to end of token */ 1337 1338 p = (str == NULL) ? savep : str ; 1339 if (p == NULL) 1340 return(NULL); 1341 ep = strpbrk(p, delim); 1342 if (ep == NULL) { 1343 savep = NULL; 1344 return(p); 1345 } 1346 savep = ep + 1; 1347 *ep = '\0'; 1348 return(p); 1349 } 1350 1351 1352 /* 1353 * pflags - put flags into intelligible form for output 1354 * 1355 * args: flags - binary representation of flags 1356 */ 1357 1358 char * 1359 pflags(flags) 1360 long flags; 1361 { 1362 register int i; /* scratch counter */ 1363 static char buf[BUFSIZ]; /* formatted flags */ 1364 1365 if (flags == 0) 1366 return(""); 1367 i = 0; 1368 if (flags & CFLAG) { 1369 buf[i++] = 'c'; 1370 flags &= ~CFLAG; 1371 } 1372 if (flags & DFLAG) { 1373 buf[i++] = 'd'; 1374 flags &= ~DFLAG; 1375 } 1376 if (flags & PFLAG) { 1377 buf[i++] = 'p'; 1378 flags &= ~PFLAG; 1379 } 1380 if (flags) { 1381 nlsmesg(MM_ERROR, "Internal error in pflags"); 1382 exit(NLS_FAILED); 1383 } 1384 buf[i] = '\0'; 1385 return(buf); 1386 } 1387