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