1 /* $OpenBSD: rpc_svcout.c,v 1.26 2010/09/01 14:43:34 millert Exp $ */ 2 /* $NetBSD: rpc_svcout.c,v 1.7 1995/06/24 14:59:59 pk Exp $ */ 3 4 /* 5 * Copyright (c) 2010, Oracle America, Inc. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials 16 * provided with the distribution. 17 * * Neither the name of the "Oracle America, Inc." nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler 37 */ 38 #include <sys/cdefs.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include "rpc_parse.h" 42 #include "rpc_util.h" 43 44 static char RQSTP[] = "rqstp"; 45 static char TRANSP[] = "transp"; 46 static char ARG[] = "argument"; 47 static char RESULT[] = "result"; 48 static char ROUTINE[] = "local"; 49 50 char _errbuf[256]; /* For all messages */ 51 52 void internal_proctype(proc_list *); 53 static void write_real_program(definition *); 54 static void write_program(definition *, char *); 55 static void printerr(char *, char *); 56 static void printif(char *, char *, char *, char *); 57 static void write_inetmost(char *); 58 static void print_return(char *); 59 static void print_pmapunset(char *); 60 static void print_err_message(char *); 61 static void write_timeout_func(void); 62 static void write_pm_most(char *, int); 63 static void write_caller_func(void); 64 static void write_rpc_svc_fg(char *, char *); 65 static void write_msg_out(void); 66 static void open_log_file(char *, char *); 67 68 static void 69 p_xdrfunc(char *rname, char *typename) 70 { 71 if (Cflag) 72 fprintf(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", 73 rname, stringfix(typename)); 74 else 75 fprintf(fout, "\t\txdr_%s = xdr_%s;\n", rname, 76 stringfix(typename)); 77 } 78 79 void 80 internal_proctype(plist) 81 proc_list *plist; 82 { 83 fprintf(fout, "static "); 84 ptype(plist->res_prefix, plist->res_type, 1); 85 fprintf(fout, "*"); 86 } 87 88 /* 89 * write most of the service, that is, everything but the registrations. 90 */ 91 void 92 write_most(infile, netflag, nomain) 93 char *infile; /* our name */ 94 int netflag; 95 int nomain; 96 { 97 if (inetdflag || pmflag) { 98 char *var_type; 99 var_type = (nomain? "extern" : "static"); 100 fprintf(fout, "%s int _rpcpmstart;", var_type); 101 fprintf(fout, "\t\t/* Started by a port monitor ? */\n"); 102 fprintf(fout, "%s int _rpcfdtype;", var_type); 103 fprintf(fout, "\t\t/* Whether Stream or Datagram ? */\n"); 104 if (timerflag) { 105 fprintf(fout, "%s int _rpcsvcdirty;", var_type); 106 fprintf(fout, "\t/* Still serving ? */\n"); 107 } 108 write_svc_aux(nomain); 109 } 110 /* write out dispatcher and stubs */ 111 write_programs(nomain? (char *)NULL : "static"); 112 113 if (nomain) 114 return; 115 116 fprintf(fout, "\nmain()\n"); 117 fprintf(fout, "{\n"); 118 if (inetdflag) { 119 write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */ 120 } else { 121 if (tirpcflag) { 122 if (netflag) { 123 fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP); 124 fprintf(fout, "\tstruct netconfig *nconf = NULL;\n"); 125 } 126 fprintf(fout, "\tpid_t pid;\n"); 127 fprintf(fout, "\tint i;\n"); 128 fprintf(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); 129 write_pm_most(infile, netflag); 130 fprintf(fout, "\telse {\n"); 131 write_rpc_svc_fg(infile, "\t\t"); 132 fprintf(fout, "\t}\n"); 133 } else { 134 fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP); 135 fprintf(fout, "\n"); 136 print_pmapunset("\t"); 137 } 138 } 139 140 if (logflag && !inetdflag) { 141 open_log_file(infile, "\t"); 142 } 143 } 144 145 /* 146 * write a registration for the given transport 147 */ 148 void 149 write_netid_register(transp) 150 char *transp; 151 { 152 list *l; 153 definition *def; 154 version_list *vp; 155 char *sp; 156 char tmpbuf[32]; 157 158 sp = ""; 159 fprintf(fout, "\n"); 160 fprintf(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp); 161 fprintf(fout, "%s\tif (nconf == NULL) {\n", sp); 162 (void) snprintf(_errbuf, sizeof _errbuf, "cannot find %s netid.", transp); 163 snprintf(tmpbuf, sizeof tmpbuf, "%s\t\t", sp); 164 print_err_message(tmpbuf); 165 fprintf(fout, "%s\t\texit(1);\n", sp); 166 fprintf(fout, "%s\t}\n", sp); 167 fprintf(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", 168 sp, TRANSP); 169 fprintf(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); 170 (void) snprintf(_errbuf, sizeof _errbuf, "cannot create %s service.", transp); 171 print_err_message(tmpbuf); 172 fprintf(fout, "%s\t\texit(1);\n", sp); 173 fprintf(fout, "%s\t}\n", sp); 174 175 for (l = defined; l != NULL; l = l->next) { 176 def = (definition *) l->val; 177 if (def->def_kind != DEF_PROGRAM) 178 continue; 179 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 180 fprintf(fout, 181 "%s\t(void) rpcb_unset(%s, %s, nconf);\n", 182 sp, def->def_name, vp->vers_name); 183 fprintf(fout, 184 "%s\tif (!svc_reg(%s, %s, %s, ", 185 sp, TRANSP, def->def_name, vp->vers_name); 186 pvname(def->def_name, vp->vers_num); 187 fprintf(fout, ", nconf)) {\n"); 188 (void) snprintf(_errbuf, sizeof _errbuf, 189 "unable to register (%s, %s, %s).", 190 def->def_name, vp->vers_name, transp); 191 print_err_message(tmpbuf); 192 fprintf(fout, "%s\t\texit(1);\n", sp); 193 fprintf(fout, "%s\t}\n", sp); 194 } 195 } 196 fprintf(fout, "%s\tfreenetconfigent(nconf);\n", sp); 197 } 198 199 /* 200 * write a registration for the given transport for TLI 201 */ 202 void 203 write_nettype_register(transp) 204 char *transp; 205 { 206 list *l; 207 definition *def; 208 version_list *vp; 209 210 for (l = defined; l != NULL; l = l->next) { 211 def = (definition *) l->val; 212 if (def->def_kind != DEF_PROGRAM) 213 continue; 214 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 215 fprintf(fout, "\tif (!svc_create("); 216 pvname(def->def_name, vp->vers_num); 217 fprintf(fout, ", %s, %s, \"%s\")) {\n", 218 def->def_name, vp->vers_name, transp); 219 (void) snprintf(_errbuf, sizeof _errbuf, 220 "unable to create (%s, %s) for %s.", 221 def->def_name, vp->vers_name, transp); 222 print_err_message("\t\t"); 223 fprintf(fout, "\t\texit(1);\n"); 224 fprintf(fout, "\t}\n"); 225 } 226 } 227 } 228 229 /* 230 * write the rest of the service 231 */ 232 void 233 write_rest() 234 { 235 fprintf(fout, "\n"); 236 if (inetdflag) { 237 fprintf(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); 238 (void) snprintf(_errbuf, sizeof _errbuf, "could not create a handle"); 239 print_err_message("\t\t"); 240 fprintf(fout, "\t\texit(1);\n"); 241 fprintf(fout, "\t}\n"); 242 if (timerflag) { 243 fprintf(fout, "\tif (_rpcpmstart) {\n"); 244 fprintf(fout, 245 "\t\t(void) signal(SIGALRM, %s closedown);\n", 246 Cflag? "(SIG_PF)" : "(void(*)())"); 247 fprintf(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); 248 fprintf(fout, "\t}\n"); 249 } 250 } 251 fprintf(fout, "\tsvc_run();\n"); 252 (void) snprintf(_errbuf, sizeof _errbuf, "svc_run returned"); 253 print_err_message("\t"); 254 fprintf(fout, "\texit(1);\n"); 255 fprintf(fout, "\t/* NOTREACHED */\n"); 256 fprintf(fout, "}\n"); 257 } 258 259 void 260 write_programs(storage) 261 char *storage; 262 { 263 definition *def; 264 list *l; 265 266 /* write out stubs for procedure definitions */ 267 for (l = defined; l != NULL; l = l->next) { 268 def = (definition *) l->val; 269 if (def->def_kind == DEF_PROGRAM) 270 write_real_program(def); 271 } 272 273 /* write out dispatcher for each program */ 274 for (l = defined; l != NULL; l = l->next) { 275 def = (definition *) l->val; 276 if (def->def_kind == DEF_PROGRAM) 277 write_program(def, storage); 278 } 279 } 280 281 /* write out definition of internal function (e.g. _printmsg_1(...)) 282 which calls server's definition of actual function (e.g. printmsg_1(...)). 283 Unpacks single user argument of printmsg_1 to call-by-value format 284 expected by printmsg_1. */ 285 static void 286 write_real_program(def) 287 definition *def; 288 { 289 version_list *vp; 290 proc_list *proc; 291 decl_list *l; 292 293 if (!newstyle) return; /* not needed for old style */ 294 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 295 for (proc = vp->procs; proc != NULL; proc = proc->next) { 296 fprintf(fout, "\n"); 297 internal_proctype(proc); 298 fprintf(fout, "\n_"); 299 pvname(proc->proc_name, vp->vers_num); 300 if (Cflag) { 301 fprintf(fout, "("); 302 /* arg name */ 303 if (proc->arg_num > 1) 304 fprintf(fout, "%s", proc->args.argname); 305 else 306 ptype(proc->args.decls->decl.prefix, 307 proc->args.decls->decl.type, 0); 308 fprintf(fout, " *argp, struct svc_req *%s)\n", 309 RQSTP); 310 } else { 311 fprintf(fout, "(argp, %s)\n", RQSTP); 312 /* arg name */ 313 if (proc->arg_num > 1) 314 fprintf(fout, "\t%s *argp;\n", 315 proc->args.argname); 316 else { 317 fprintf(fout, "\t"); 318 ptype(proc->args.decls->decl.prefix, 319 proc->args.decls->decl.type, 0); 320 fprintf(fout, " *argp;\n"); 321 } 322 fprintf(fout, " struct svc_req *%s;\n", RQSTP); 323 } 324 325 fprintf(fout, "{\n"); 326 fprintf(fout, "\treturn("); 327 pvname_svc(proc->proc_name, vp->vers_num); 328 fprintf(fout, "("); 329 if (proc->arg_num < 2) { /* single argument */ 330 if (!streq(proc->args.decls->decl.type, "void")) 331 fprintf(fout, "*argp, "); /* non-void */ 332 } else { 333 for (l = proc->args.decls; l != NULL; l = l->next) 334 fprintf(fout, "argp->%s, ", l->decl.name); 335 } 336 fprintf(fout, "%s));\n}\n", RQSTP); 337 } 338 } 339 } 340 341 static void 342 write_program(def, storage) 343 definition *def; 344 char *storage; 345 { 346 version_list *vp; 347 proc_list *proc; 348 int filled; 349 350 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 351 fprintf(fout, "\n"); 352 if (storage != NULL) 353 fprintf(fout, "%s ", storage); 354 fprintf(fout, "void\t"); 355 pvname(def->def_name, vp->vers_num); 356 357 if (Cflag) { 358 fprintf(fout, "(struct svc_req *%s, ", RQSTP); 359 fprintf(fout, "SVCXPRT *%s);\n", TRANSP); 360 } else { 361 fprintf(fout, "();\n"); 362 } 363 fprintf(fout, "\n"); 364 365 if (storage != NULL) 366 fprintf(fout, "%s ", storage); 367 fprintf(fout, "void\n"); 368 pvname(def->def_name, vp->vers_num); 369 370 if (Cflag) { 371 fprintf(fout, "(struct svc_req *%s, ", RQSTP); 372 fprintf(fout, "SVCXPRT *%s)\n", TRANSP); 373 } else { 374 fprintf(fout, "(%s, %s)\n", RQSTP, TRANSP); 375 fprintf(fout, " struct svc_req *%s;\n", RQSTP); 376 fprintf(fout, " SVCXPRT *%s;\n", TRANSP); 377 } 378 fprintf(fout, "{\n"); 379 380 filled = 0; 381 fprintf(fout, "\tunion {\n"); 382 for (proc = vp->procs; proc != NULL; proc = proc->next) { 383 if (proc->arg_num < 2) { /* single argument */ 384 if (streq(proc->args.decls->decl.type, 385 "void")) 386 continue; 387 filled = 1; 388 fprintf(fout, "\t\t"); 389 ptype(proc->args.decls->decl.prefix, 390 proc->args.decls->decl.type, 0); 391 pvname(proc->proc_name, vp->vers_num); 392 fprintf(fout, "_arg;\n"); 393 394 } else { 395 filled = 1; 396 fprintf(fout, "\t\t%s", proc->args.argname); 397 fprintf(fout, " "); 398 pvname(proc->proc_name, vp->vers_num); 399 fprintf(fout, "_arg;\n"); 400 } 401 } 402 if (!filled) 403 fprintf(fout, "\t\tint fill;\n"); 404 fprintf(fout, "\t} %s;\n", ARG); 405 fprintf(fout, "\tchar *%s;\n", RESULT); 406 407 if (Cflag) { 408 fprintf(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT); 409 fprintf(fout, 410 "\tchar *(*%s)(char *, struct svc_req *);\n", 411 ROUTINE); 412 } else { 413 fprintf(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", 414 ARG, RESULT); 415 fprintf(fout, "\tchar *(*%s)();\n", ROUTINE); 416 } 417 fprintf(fout, "\n"); 418 419 if (callerflag) 420 fprintf(fout, "\tcaller = transp;\n"); /*EVAS*/ 421 if (timerflag) 422 fprintf(fout, "\t_rpcsvcdirty = 1;\n"); 423 fprintf(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); 424 if (!nullproc(vp->procs)) { 425 fprintf(fout, "\tcase NULLPROC:\n"); 426 fprintf(fout, 427 Cflag 428 ? "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n" 429 : "\t\t(void) svc_sendreply(%s, xdr_void, (char *)NULL);\n", 430 TRANSP); 431 print_return("\t\t"); 432 fprintf(fout, "\n"); 433 } 434 for (proc = vp->procs; proc != NULL; proc = proc->next) { 435 fprintf(fout, "\tcase %s:\n", proc->proc_name); 436 if (proc->arg_num < 2) { /* single argument */ 437 p_xdrfunc(ARG, proc->args.decls->decl.type); 438 } else { 439 p_xdrfunc(ARG, proc->args.argname); 440 } 441 p_xdrfunc(RESULT, proc->res_type); 442 if (Cflag) 443 fprintf(fout, 444 "\t\t%s = (char *(*)(char *, struct svc_req *)) ", 445 ROUTINE); 446 else 447 fprintf(fout, "\t\t%s = (char *(*)()) ", ROUTINE); 448 449 if (newstyle) { /* new style: calls internal routine */ 450 fprintf(fout,"_"); 451 } 452 if (!newstyle) 453 pvname_svc(proc->proc_name, vp->vers_num); 454 else 455 pvname(proc->proc_name, vp->vers_num); 456 fprintf(fout, ";\n"); 457 fprintf(fout, "\t\tbreak;\n\n"); 458 } 459 fprintf(fout, "\tdefault:\n"); 460 printerr("noproc", TRANSP); 461 print_return("\t\t"); 462 fprintf(fout, "\t}\n"); 463 464 fprintf(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); 465 printif ("getargs", TRANSP, "(caddr_t) &", ARG); 466 printerr("decode", TRANSP); 467 print_return("\t\t"); 468 fprintf(fout, "\t}\n"); 469 470 if (Cflag) 471 fprintf(fout, "\t%s = (*%s)((char *)&%s, %s);\n", 472 RESULT, ROUTINE, ARG, RQSTP); 473 else 474 fprintf(fout, "\t%s = (*%s)(&%s, %s);\n", 475 RESULT, ROUTINE, ARG, RQSTP); 476 fprintf(fout, 477 "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n", 478 RESULT, TRANSP, RESULT, RESULT); 479 printerr("systemerr", TRANSP); 480 fprintf(fout, "\t}\n"); 481 482 printif ("freeargs", TRANSP, "(caddr_t) &", ARG); 483 (void) snprintf(_errbuf, sizeof _errbuf, "unable to free arguments"); 484 print_err_message("\t\t"); 485 fprintf(fout, "\t\texit(1);\n"); 486 fprintf(fout, "\t}\n"); 487 print_return("\t"); 488 fprintf(fout, "}\n"); 489 } 490 } 491 492 static void 493 printerr(err, transp) 494 char *err; 495 char *transp; 496 { 497 fprintf(fout, "\t\tsvcerr_%s(%s);\n", err, transp); 498 } 499 500 static void 501 printif(proc, transp, prefix, arg) 502 char *proc; 503 char *transp; 504 char *prefix; 505 char *arg; 506 { 507 fprintf(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n", 508 proc, transp, arg, prefix, arg); 509 } 510 511 int 512 nullproc(proc) 513 proc_list *proc; 514 { 515 for (; proc != NULL; proc = proc->next) { 516 if (streq(proc->proc_num, "0")) 517 return (1); 518 } 519 return (0); 520 } 521 522 static void 523 write_inetmost(infile) 524 char *infile; 525 { 526 fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP); 527 fprintf(fout, "\tint sock;\n"); 528 fprintf(fout, "\tint proto;\n"); 529 fprintf(fout, "\tstruct sockaddr_in saddr;\n"); 530 fprintf(fout, "\tint asize = sizeof (saddr);\n"); 531 fprintf(fout, "\n"); 532 fprintf(fout, 533 "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); 534 fprintf(fout, "\t\tint ssize = sizeof (int);\n\n"); 535 fprintf(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); 536 fprintf(fout, "\t\t\texit(1);\n"); 537 fprintf(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); 538 fprintf(fout, "\t\t (char *)&_rpcfdtype, &ssize) == -1)\n"); 539 fprintf(fout, "\t\t\texit(1);\n"); 540 fprintf(fout, "\t\tsock = 0;\n"); 541 fprintf(fout, "\t\t_rpcpmstart = 1;\n"); 542 fprintf(fout, "\t\tproto = 0;\n"); 543 open_log_file(infile, "\t\t"); 544 fprintf(fout, "\t} else {\n"); 545 write_rpc_svc_fg(infile, "\t\t"); 546 fprintf(fout, "\t\tsock = RPC_ANYSOCK;\n"); 547 print_pmapunset("\t\t"); 548 fprintf(fout, "\t}\n"); 549 } 550 551 static void 552 print_return(space) 553 char *space; 554 { 555 if (exitnow) 556 fprintf(fout, "%sexit(0);\n", space); 557 else { 558 if (timerflag) 559 fprintf(fout, "%s_rpcsvcdirty = 0;\n", space); 560 fprintf(fout, "%sreturn;\n", space); 561 } 562 } 563 564 static void 565 print_pmapunset(space) 566 char *space; 567 { 568 version_list *vp; 569 definition *def; 570 list *l; 571 572 for (l = defined; l != NULL; l = l->next) { 573 def = (definition *) l->val; 574 if (def->def_kind == DEF_PROGRAM) { 575 for (vp = def->def.pr.versions; vp != NULL; 576 vp = vp->next) { 577 fprintf(fout, "%s(void) pmap_unset(%s, %s);\n", 578 space, def->def_name, vp->vers_name); 579 } 580 } 581 } 582 } 583 584 static void 585 print_err_message(space) 586 char *space; 587 { 588 if (logflag) 589 fprintf(fout, "%ssyslog(LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf); 590 else if (inetdflag || pmflag) 591 fprintf(fout, "%s_msgout(\"%s\");\n", space, _errbuf); 592 else 593 fprintf(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf); 594 } 595 596 /* 597 * Write the server auxiliary function (_msgout, timeout) 598 */ 599 void 600 write_svc_aux(nomain) 601 int nomain; 602 { 603 if (!logflag) 604 write_msg_out(); 605 if (!nomain) 606 write_timeout_func(); 607 if (callerflag) /*EVAS*/ 608 write_caller_func(); /*EVAS*/ 609 } 610 611 /* 612 * Write the _msgout function 613 */ 614 615 void 616 write_msg_out() 617 { 618 fprintf(fout, "\n"); 619 fprintf(fout, "static\n"); 620 if (!Cflag) { 621 fprintf(fout, "void _msgout(msg)\n"); 622 fprintf(fout, "\tchar *msg;\n"); 623 } else { 624 fprintf(fout, "void _msgout(char *msg)\n"); 625 } 626 fprintf(fout, "{\n"); 627 fprintf(fout, "#ifdef RPC_SVC_FG\n"); 628 if (inetdflag || pmflag) 629 fprintf(fout, "\tif (_rpcpmstart)\n"); 630 fprintf(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n"); 631 fprintf(fout, "\telse {\n"); 632 fprintf(fout, "\t\t(void) write(STDERR_FILENO, msg, strlen(msg));\n"); 633 fprintf(fout, "\t\t(void) write(STDERR_FILENO, \"\\n\", 1);\n"); 634 fprintf(fout, "\t}\n#else\n"); 635 fprintf(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n"); 636 fprintf(fout, "#endif\n"); 637 fprintf(fout, "}\n"); 638 } 639 640 /* 641 * Write the timeout function 642 */ 643 static void 644 write_timeout_func() 645 { 646 if (!timerflag) 647 return; 648 fprintf(fout, "\n"); 649 fprintf(fout, "static void\n"); 650 fprintf(fout, "closedown()\n"); 651 fprintf(fout, "{\n"); 652 fprintf(fout, "\tint save_errno = errno;\n\n"); 653 fprintf(fout, "\tif (_rpcsvcdirty == 0) {\n"); 654 fprintf(fout, "\t\textern fd_set *__svc_fdset;\n"); 655 fprintf(fout, "\t\textern int __svc_fdsetsize;\n"); 656 fprintf(fout, "\t\tint i, openfd;\n"); 657 if (tirpcflag && pmflag) { 658 fprintf(fout, "\t\tstruct t_info tinfo;\n\n"); 659 fprintf(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n"); 660 } else { 661 fprintf(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n"); 662 } 663 fprintf(fout, "\t\t\t_exit(0);\n"); 664 fprintf(fout, "\t\tfor (i = 0, openfd = 0; i < __svc_fdsetsize && openfd < 2; i++)\n"); 665 fprintf(fout, "\t\t\tif (FD_ISSET(i, __svc_fdset))\n"); 666 fprintf(fout, "\t\t\t\topenfd++;\n"); 667 fprintf(fout, "\t\tif (openfd <= (_rpcpmstart?0:1))\n"); 668 fprintf(fout, "\t\t\t_exit(0);\n"); 669 fprintf(fout, "\t}\n"); 670 fprintf(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); 671 fprintf(fout, "\terrno = save_errno;\n"); 672 fprintf(fout, "}\n"); 673 } 674 675 static void 676 write_caller_func() /*EVAS*/ 677 { 678 #define P(s) fprintf(fout, s); 679 680 P("\n"); 681 P("char *svc_caller()\n"); 682 P("{\n"); 683 P(" struct sockaddr_in actual;\n"); 684 P(" struct hostent *hp;\n"); 685 P(" static struct in_addr prev;\n"); 686 P(" static char cname[256];\n\n"); 687 688 P(" actual = *svc_getcaller(caller);\n\n"); 689 690 P(" if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n"); 691 P(" sizeof(struct in_addr)) == 0)\n"); 692 P(" return (cname);\n\n"); 693 694 P(" prev = actual.sin_addr;\n\n"); 695 696 P(" hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n"); 697 P(" if (hp == NULL) { /* dummy one up */\n"); 698 P(" extern char *inet_ntoa();\n"); 699 P(" strlcpy(cname, inet_ntoa(actual.sin_addr), sizeof cname);\n"); 700 P(" } else {\n"); 701 P(" strlcpy(cname, hp->h_name, sizeof cname);\n"); 702 P(" }\n\n"); 703 704 P(" return (cname);\n"); 705 P("}\n"); 706 707 #undef P 708 } 709 710 /* 711 * Write the most of port monitor support 712 */ 713 static void 714 write_pm_most(infile, netflag) 715 char *infile; 716 int netflag; 717 { 718 list *l; 719 definition *def; 720 version_list *vp; 721 722 fprintf(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); 723 fprintf(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); 724 fprintf(fout, " !strcmp(mname, \"timod\"))) {\n"); 725 fprintf(fout, "\t\tchar *netid;\n"); 726 if (!netflag) { /* Not included by -n option */ 727 fprintf(fout, "\t\tstruct netconfig *nconf = NULL;\n"); 728 fprintf(fout, "\t\tSVCXPRT *%s;\n", TRANSP); 729 } 730 if (timerflag) 731 fprintf(fout, "\t\tint pmclose;\n"); 732 /* not necessary, defined in /usr/include/stdlib */ 733 /* fprintf(fout, "\t\textern char *getenv();\n");*/ 734 fprintf(fout, "\n"); 735 fprintf(fout, "\t\t_rpcpmstart = 1;\n"); 736 if (logflag) 737 open_log_file(infile, "\t\t"); 738 fprintf(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); 739 snprintf(_errbuf, sizeof _errbuf, "cannot get transport name"); 740 print_err_message("\t\t\t"); 741 fprintf(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); 742 snprintf(_errbuf, sizeof _errbuf, "cannot get transport info"); 743 print_err_message("\t\t\t"); 744 fprintf(fout, "\t\t}\n"); 745 /* 746 * A kludgy support for inetd services. Inetd only works with 747 * sockmod, and RPC works only with timod, hence all this jugglery 748 */ 749 fprintf(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); 750 fprintf(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); 751 snprintf(_errbuf, sizeof _errbuf, "could not get the right module"); 752 print_err_message("\t\t\t\t"); 753 fprintf(fout, "\t\t\t\texit(1);\n"); 754 fprintf(fout, "\t\t\t}\n"); 755 fprintf(fout, "\t\t}\n"); 756 if (timerflag) 757 fprintf(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); 758 fprintf(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", 759 TRANSP); 760 snprintf(_errbuf, sizeof _errbuf, "cannot create server handle"); 761 print_err_message("\t\t\t"); 762 fprintf(fout, "\t\t\texit(1);\n"); 763 fprintf(fout, "\t\t}\n"); 764 fprintf(fout, "\t\tif (nconf)\n"); 765 fprintf(fout, "\t\t\tfreenetconfigent(nconf);\n"); 766 for (l = defined; l != NULL; l = l->next) { 767 def = (definition *) l->val; 768 if (def->def_kind != DEF_PROGRAM) { 769 continue; 770 } 771 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 772 fprintf(fout, 773 "\t\tif (!svc_reg(%s, %s, %s, ", 774 TRANSP, def->def_name, vp->vers_name); 775 pvname(def->def_name, vp->vers_num); 776 fprintf(fout, ", 0)) {\n"); 777 (void) snprintf(_errbuf, sizeof _errbuf, "unable to register (%s, %s).", 778 def->def_name, vp->vers_name); 779 print_err_message("\t\t\t"); 780 fprintf(fout, "\t\t\texit(1);\n"); 781 fprintf(fout, "\t\t}\n"); 782 } 783 } 784 if (timerflag) { 785 fprintf(fout, "\t\tif (pmclose) {\n"); 786 fprintf(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", 787 Cflag? "(SIG_PF)" : "(void(*)())"); 788 fprintf(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); 789 fprintf(fout, "\t\t}\n"); 790 } 791 fprintf(fout, "\t\tsvc_run();\n"); 792 fprintf(fout, "\t\texit(1);\n"); 793 fprintf(fout, "\t\t/* NOTREACHED */\n"); 794 fprintf(fout, "\t}\n"); 795 } 796 797 /* 798 * Support for backgrounding the server if self started. 799 */ 800 static void 801 write_rpc_svc_fg(infile, sp) 802 char *infile; 803 char *sp; 804 { 805 fprintf(fout, "#ifndef RPC_SVC_FG\n"); 806 fprintf(fout, "%sint size;\n", sp); 807 if (tirpcflag) 808 fprintf(fout, "%sstruct rlimit rl;\n", sp); 809 if (inetdflag) { 810 fprintf(fout, "%sint i;\n\n", sp); 811 fprintf(fout, "%spid_t pid;\n\n", sp); 812 } 813 fprintf(fout, "%spid = fork();\n", sp); 814 fprintf(fout, "%sif (pid < 0) {\n", sp); 815 fprintf(fout, "%s\tperror(\"cannot fork\");\n", sp); 816 fprintf(fout, "%s\texit(1);\n", sp); 817 fprintf(fout, "%s}\n", sp); 818 fprintf(fout, "%sif (pid)\n", sp); 819 fprintf(fout, "%s\texit(0);\n", sp); 820 /* get number of file descriptors */ 821 if (tirpcflag) { 822 fprintf(fout, "%srl.rlim_max = 0;\n", sp); 823 fprintf(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); 824 fprintf(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); 825 fprintf(fout, "%s\texit(1);\n", sp); 826 } else { 827 fprintf(fout, "%ssize = getdtablesize();\n", sp); 828 } 829 830 fprintf(fout, "%sfor (i = 0; i < size; i++)\n", sp); 831 fprintf(fout, "%s\t(void) close(i);\n", sp); 832 /* Redirect stderr and stdout to console */ 833 fprintf(fout, "%si = open(\"/dev/console\", 2);\n", sp); 834 fprintf(fout, "%s(void) dup2(i, 1);\n", sp); 835 fprintf(fout, "%s(void) dup2(i, 2);\n", sp); 836 /* This removes control of the controlling terminal */ 837 if (tirpcflag) 838 fprintf(fout, "%ssetsid();\n", sp); 839 else { 840 fprintf(fout, "%si = open(\"/dev/tty\", 2);\n", sp); 841 fprintf(fout, "%sif (i >= 0) {\n", sp); 842 fprintf(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp); 843 fprintf(fout, "%s\t(void) close(i);\n", sp); 844 fprintf(fout, "%s}\n", sp); 845 } 846 if (!logflag) 847 open_log_file(infile, sp); 848 fprintf(fout, "#endif\n"); 849 if (logflag) 850 open_log_file(infile, sp); 851 } 852 853 static void 854 open_log_file(infile, sp) 855 char *infile; 856 char *sp; 857 { 858 char *s; 859 860 s = strrchr(infile, '.'); 861 if (s) 862 *s = '\0'; 863 fprintf(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile); 864 if (s) 865 *s = '.'; 866 } 867 868 /* 869 * write a registration for the given transport for Inetd 870 */ 871 void 872 write_inetd_register(transp) 873 char *transp; 874 { 875 list *l; 876 definition *def; 877 version_list *vp; 878 char *sp; 879 int isudp; 880 char tmpbuf[32]; 881 882 if (inetdflag) 883 sp = "\t"; 884 else 885 sp = ""; 886 if (streq(transp, "udp")) 887 isudp = 1; 888 else 889 isudp = 0; 890 fprintf(fout, "\n"); 891 if (inetdflag) { 892 fprintf(fout, "\tif (_rpcfdtype == 0 || _rpcfdtype == %s) {\n", 893 isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); 894 } 895 if (inetdflag && streq(transp, "tcp")) { 896 fprintf(fout, "%s\tif (_rpcpmstart)\n", sp); 897 898 fprintf(fout, "%s\t\t%s = svc%s_create(%s", 899 sp, TRANSP, "fd", inetdflag? "sock": "RPC_ANYSOCK"); 900 if (!isudp) 901 fprintf(fout, ", 0, 0"); 902 fprintf(fout, ");\n"); 903 904 fprintf(fout, "%s\telse\n", sp); 905 906 fprintf(fout, "%s\t\t%s = svc%s_create(%s", 907 sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK"); 908 if (!isudp) 909 fprintf(fout, ", 0, 0"); 910 fprintf(fout, ");\n"); 911 912 } else { 913 fprintf(fout, "%s\t%s = svc%s_create(%s", 914 sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK"); 915 if (!isudp) 916 fprintf(fout, ", 0, 0"); 917 fprintf(fout, ");\n"); 918 } 919 fprintf(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); 920 (void) snprintf(_errbuf, sizeof _errbuf, "cannot create %s service.", transp); 921 (void) snprintf(tmpbuf, sizeof tmpbuf, "%s\t\t", sp); 922 print_err_message(tmpbuf); 923 fprintf(fout, "%s\t\texit(1);\n", sp); 924 fprintf(fout, "%s\t}\n", sp); 925 926 if (inetdflag) { 927 fprintf(fout, "%s\tif (!_rpcpmstart)\n\t", sp); 928 fprintf(fout, "%s\tproto = IPPROTO_%s;\n", 929 sp, isudp ? "UDP": "TCP"); 930 } 931 for (l = defined; l != NULL; l = l->next) { 932 def = (definition *) l->val; 933 if (def->def_kind != DEF_PROGRAM) { 934 continue; 935 } 936 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 937 fprintf(fout, "%s\tif (!svc_register(%s, %s, %s, ", 938 sp, TRANSP, def->def_name, vp->vers_name); 939 pvname(def->def_name, vp->vers_num); 940 if (inetdflag) 941 fprintf(fout, ", proto)) {\n"); 942 else 943 fprintf(fout, ", IPPROTO_%s)) {\n", 944 isudp ? "UDP": "TCP"); 945 (void) snprintf(_errbuf, sizeof _errbuf, "unable to register (%s, %s, %s).", 946 def->def_name, vp->vers_name, transp); 947 print_err_message(tmpbuf); 948 fprintf(fout, "%s\t\texit(1);\n", sp); 949 fprintf(fout, "%s\t}\n", sp); 950 } 951 } 952 if (inetdflag) 953 fprintf(fout, "\t}\n"); 954 } 955