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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 24 * 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 /* 41 * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler 42 */ 43 #include <stdio.h> 44 #include <string.h> 45 #include <stdarg.h> 46 #include "rpc_parse.h" 47 #include "rpc_util.h" 48 49 extern int nullproc(proc_list *); 50 51 static char RQSTP[] = "rqstp"; 52 static char TRANSP[] = "transp"; 53 static char ARG[] = "argument"; 54 static char RESULT[] = "result"; 55 static char ROUTINE[] = "local"; 56 static char RETVAL[] = "retval"; 57 58 #define ERRBUFLEN 256 59 60 static void internal_proctype(proc_list *); 61 static void write_real_program(definition *); 62 static void write_programs(char *); 63 static void write_program(definition *, char *); 64 static void printerr(char *, char *); 65 static void write_svc_aux(int); 66 static void printif(char *, char *, char *, char *); 67 static void write_inetmost(char *); 68 static void print_return(char *); 69 static void print_pmapunset(char *); 70 static void print_err_message(const char *, const char *, ...); 71 static void write_msg_out(void); 72 static void write_timeout_func(void); 73 static void write_pm_most(char *, int); 74 static void write_rpc_svc_fg(char *, char *); 75 static void open_log_file(char *, char *); 76 77 static void 78 p_xdrfunc(char *rname, char *typename) 79 { 80 f_print(fout, "\t\t_xdr_%s = (xdrproc_t)\n", rname); 81 f_print(fout, "\t\t xdr_%s;\n", stringfix(typename)); 82 } 83 84 static void 85 internal_proctype(proc_list *plist) 86 { 87 f_print(fout, "static "); 88 ptype(plist->res_prefix, plist->res_type, 1); 89 f_print(fout, "*"); 90 } 91 92 93 static void 94 write_mtauto(void) 95 { 96 f_print(fout, "\tif (!rpc_control(RPC_SVC_MTMODE_SET, &mode)) {\n"); 97 print_err_message("\t\t", "unable to set automatic MT mode."); 98 f_print(fout, "\t\texit(1);\n\t}\n"); 99 } 100 101 /* 102 * write most of the service, that is, everything but the registrations. 103 */ 104 void 105 write_most(char *infile, int netflag, int nomain) 106 { 107 if (inetdflag || pmflag) { 108 char *var_type; 109 var_type = (nomain? "extern" : "static"); 110 f_print(fout, "%s int _rpcpmstart;", var_type); 111 f_print(fout, "\t\t/* Started by a port monitor ? */\n"); 112 if (!tirpcflag) { 113 f_print(fout, "%s int _rpcfdtype;", var_type); 114 f_print(fout, 115 "\t\t /* Whether Stream or Datagram ? */\n"); 116 } 117 118 if (timerflag) { 119 f_print(fout, 120 "\n/* States a server can be in wrt request */\n\n"); 121 f_print(fout, "#define\t_IDLE 0\n"); 122 f_print(fout, "#define\t_SERVED 1\n\n"); 123 if (nomain) { 124 f_print(fout, 125 "/* LINTED static unused if no main */\n"); 126 } 127 f_print(fout, 128 "static int _rpcsvcstate = _IDLE;"); 129 f_print(fout, 130 "\t/* Set when a request is serviced */\n"); 131 f_print(fout, "static int _rpcsvccount = 0;"); 132 f_print(fout, 133 "\t\t/* Number of requests being serviced */\n"); 134 135 if (mtflag) { 136 f_print(fout, "mutex_t _svcstate_lock;"); 137 f_print(fout, 138 "\t\t/* lock for _rpcsvcstate, _rpcsvccount */\n"); 139 140 } 141 } 142 143 write_svc_aux(nomain); 144 } 145 /* write out dispatcher and stubs */ 146 write_programs(nomain ? NULL : "static"); 147 148 if (nomain) 149 return; 150 151 f_print(fout, "\nint\nmain()\n"); 152 f_print(fout, "{\n"); 153 if (inetdflag) { 154 write_inetmost(infile); 155 /* Includes call to write_rpc_svc_fg() */ 156 } else { 157 if (tirpcflag) { 158 if (netflag) { 159 f_print(fout, 160 "\tregister SVCXPRT *%s;\n", TRANSP); 161 f_print(fout, 162 "\tstruct netconfig *nconf = NULL;\n"); 163 } 164 f_print(fout, "\tpid_t pid;\n"); 165 f_print(fout, "\tint i;\n"); 166 if (mtauto) { 167 f_print(fout, 168 "\tint mode = RPC_SVC_MT_AUTO;\n\n"); 169 write_mtauto(); 170 } else 171 f_print(fout, "\n"); 172 173 if (mtflag & timerflag) 174 f_print(fout, 175 "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n"); 176 177 write_pm_most(infile, netflag); 178 f_print(fout, "\telse {\n"); 179 write_rpc_svc_fg(infile, "\t\t"); 180 f_print(fout, "\t}\n"); 181 } else { 182 f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); 183 f_print(fout, "\n"); 184 print_pmapunset("\t"); 185 } 186 } 187 188 if (logflag && !inetdflag) { 189 open_log_file(infile, "\t"); 190 } 191 } 192 193 /* 194 * write a registration for the given transport 195 */ 196 void 197 write_netid_register(char *transp) 198 { 199 list *l; 200 definition *def; 201 version_list *vp; 202 char *sp; 203 char tmpbuf[32]; 204 205 sp = ""; 206 f_print(fout, "\n"); 207 f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp); 208 f_print(fout, "%s\tif (nconf == NULL) {\n", sp); 209 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp); 210 print_err_message(tmpbuf, "cannot find %s netid.", transp); 211 f_print(fout, "%s\t\texit(1);\n", sp); 212 f_print(fout, "%s\t}\n", sp); 213 f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", 214 sp, TRANSP); 215 f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); 216 print_err_message(tmpbuf, "cannot create %s service.", transp); 217 f_print(fout, "%s\t\texit(1);\n", sp); 218 f_print(fout, "%s\t}\n", sp); 219 220 for (l = defined; l != NULL; l = l->next) { 221 def = (definition *) l->val; 222 if (def->def_kind != DEF_PROGRAM) { 223 continue; 224 } 225 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 226 f_print(fout, 227 "%s\t(void) rpcb_unset(%s, %s, nconf);\n", 228 sp, def->def_name, vp->vers_name); 229 f_print(fout, 230 "%s\tif (!svc_reg(%s, %s, %s, ", 231 sp, TRANSP, def->def_name, vp->vers_name); 232 pvname(def->def_name, vp->vers_num); 233 f_print(fout, ", nconf)) {\n"); 234 print_err_message(tmpbuf, 235 "unable to register (%s, %s, %s).", 236 def->def_name, vp->vers_name, transp); 237 f_print(fout, "%s\t\texit(1);\n", sp); 238 f_print(fout, "%s\t}\n", sp); 239 } 240 } 241 f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp); 242 } 243 244 /* 245 * write a registration for the given transport for TLI 246 */ 247 void 248 write_nettype_register(char *transp) 249 { 250 list *l; 251 definition *def; 252 version_list *vp; 253 254 for (l = defined; l != NULL; l = l->next) { 255 def = (definition *) l->val; 256 if (def->def_kind != DEF_PROGRAM) { 257 continue; 258 } 259 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 260 f_print(fout, "\tif (!svc_create(\n"); 261 f_print(fout, "\t "); 262 pvname(def->def_name, vp->vers_num); 263 f_print(fout, ", %s, %s,\n", 264 def->def_name, vp->vers_name); 265 f_print(fout, "\t \"%s\")) {\n", transp); 266 print_err_message("\t\t", 267 "unable to create (%s, %s) for %s.", 268 def->def_name, vp->vers_name, transp); 269 f_print(fout, "\t\texit(1);\n"); 270 f_print(fout, "\t}\n"); 271 } 272 } 273 } 274 275 /* 276 * write the rest of the service 277 */ 278 void 279 write_rest(void) 280 { 281 f_print(fout, "\n"); 282 if (inetdflag) { 283 f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); 284 print_err_message("\t\t", "could not create a handle"); 285 f_print(fout, "\t\texit(1);\n"); 286 f_print(fout, "\t}\n"); 287 if (timerflag) { 288 f_print(fout, "\tif (_rpcpmstart) {\n"); 289 if (mtflag) { 290 f_print(fout, 291 "\t\tif (thr_create(NULL, 0, closedown, NULL, 0, NULL) != 0) {\n"); 292 print_err_message("\t\t\t", 293 "cannot create closedown thread"); 294 f_print(fout, "\t\t\texit(1);\n"); 295 f_print(fout, "\t\t}\n"); 296 f_print(fout, "\t}\n"); 297 } else { 298 f_print(fout, 299 "\t\t(void) signal(SIGALRM, %s closedown);\n", 300 "(SIG_PF)"); 301 f_print(fout, 302 "\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); 303 f_print(fout, "\t}\n"); 304 } 305 } 306 } 307 f_print(fout, "\tsvc_run();\n"); 308 print_err_message("\t", "svc_run returned"); 309 f_print(fout, "\texit(1);\n"); 310 f_print(fout, "\t/* NOTREACHED */\n"); 311 f_print(fout, "}\n"); 312 } 313 314 static void 315 write_programs(char *storage) 316 { 317 list *l; 318 definition *def; 319 320 /* write out stubs for procedure definitions */ 321 for (l = defined; l != NULL; l = l->next) { 322 def = (definition *) l->val; 323 if (def->def_kind == DEF_PROGRAM) 324 write_real_program(def); 325 } 326 327 /* write out dispatcher for each program */ 328 for (l = defined; l != NULL; l = l->next) { 329 def = (definition *) l->val; 330 if (def->def_kind == DEF_PROGRAM) 331 write_program(def, storage); 332 } 333 334 335 } 336 337 /* 338 * write out definition of internal function (e.g. _printmsg_1(...)) 339 * which calls server's defintion of actual function (e.g. printmsg_1(...)). 340 * Unpacks single user argument of printmsg_1 to call-by-value format 341 * expected by printmsg_1. 342 */ 343 static void 344 write_real_program(definition *def) 345 { 346 version_list *vp; 347 proc_list *proc; 348 decl_list *l; 349 350 if (!newstyle) 351 return; /* not needed for old style */ 352 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 353 for (proc = vp->procs; proc != NULL; proc = proc->next) { 354 int oneway = streq(proc->res_type, "oneway"); 355 356 f_print(fout, "\n"); 357 if (proc->arg_num < 2 && 358 streq(proc->args.decls->decl.type, "void")) { 359 f_print(fout, "/* ARGSUSED */\n"); 360 } 361 if (!mtflag) 362 internal_proctype(proc); 363 else 364 f_print(fout, "int"); 365 f_print(fout, "\n_"); 366 pvname(proc->proc_name, vp->vers_num); 367 368 f_print(fout, "(\n"); 369 f_print(fout, " "); 370 /* arg name */ 371 if (proc->arg_num > 1) 372 /* LINTED variable format */ 373 f_print(fout, proc->args.argname); 374 else 375 ptype(proc->args.decls->decl.prefix, 376 proc->args.decls->decl.type, 0); 377 f_print(fout, " *argp,\n"); 378 if (mtflag) { 379 f_print(fout, " "); 380 ptype(proc->res_prefix, proc->res_type, 1); 381 f_print(fout, "*%s,\n", RESULT); 382 } 383 f_print(fout, " struct svc_req *%s)\n", RQSTP); 384 385 f_print(fout, "{\n"); 386 f_print(fout, "\treturn ("); 387 /* for mtflag, arguments are different */ 388 pvname_svc(proc->proc_name, vp->vers_num); 389 f_print(fout, "("); 390 if (proc->arg_num < 2) { /* single argument */ 391 /* only print if non-void */ 392 if (!streq(proc->args.decls->decl.type, "void")) 393 f_print(fout, "*argp, "); 394 } else { 395 f_print(fout, "\n"); 396 for (l = proc->args.decls; l != NULL; 397 l = l->next) 398 f_print(fout, "\t argp->%s,\n", 399 l->decl.name); 400 f_print(fout, "\t "); 401 } 402 if (mtflag && !oneway) 403 f_print(fout, "%s, ", RESULT); 404 f_print(fout, "%s));\n}\n", RQSTP); 405 } 406 } 407 } 408 409 static void 410 write_program(definition *def, char *storage) 411 { 412 version_list *vp; 413 proc_list *proc; 414 int filled; 415 416 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 417 f_print(fout, "\n"); 418 if (storage != NULL) { 419 f_print(fout, "%s ", storage); 420 } 421 f_print(fout, "void\n"); 422 pvname(def->def_name, vp->vers_num); 423 424 f_print(fout, "(struct svc_req *%s, ", RQSTP); 425 f_print(fout, "register SVCXPRT *%s)\n", TRANSP); 426 427 f_print(fout, "{\n"); 428 429 filled = 0; 430 f_print(fout, "\tunion {\n"); 431 for (proc = vp->procs; proc != NULL; proc = proc->next) { 432 if (proc->arg_num < 2) { /* single argument */ 433 if (streq(proc->args.decls->decl.type, 434 "void")) { 435 continue; 436 } 437 filled = 1; 438 f_print(fout, "\t\t"); 439 ptype(proc->args.decls->decl.prefix, 440 proc->args.decls->decl.type, 0); 441 pvname(proc->proc_name, vp->vers_num); 442 f_print(fout, "_arg;\n"); 443 444 } else { 445 filled = 1; 446 f_print(fout, "\t\t%s", proc->args.argname); 447 f_print(fout, " "); 448 pvname(proc->proc_name, vp->vers_num); 449 f_print(fout, "_arg;\n"); 450 } 451 } 452 if (!filled) { 453 f_print(fout, "\t\tint fill;\n"); 454 } 455 f_print(fout, "\t} %s;\n", ARG); 456 457 if (mtflag) { 458 filled = 0; 459 f_print(fout, "\tunion {\n"); 460 for (proc = vp->procs; proc != NULL; 461 proc = proc->next) { 462 if (streq(proc->res_type, "void") || 463 streq(proc->res_type, "oneway")) 464 continue; 465 filled = 1; 466 f_print(fout, "\t\t"); 467 ptype(proc->res_prefix, proc->res_type, 0); 468 pvname(proc->proc_name, vp->vers_num); 469 f_print(fout, "_res;\n"); 470 } 471 if (!filled) 472 f_print(fout, "\t\tint fill;\n"); 473 f_print(fout, "\t} %s;\n", RESULT); 474 f_print(fout, "\tbool_t %s;\n", RETVAL); 475 476 } else 477 f_print(fout, "\tchar *%s;\n", RESULT); 478 479 f_print(fout, "\txdrproc_t _xdr_%s, _xdr_%s;\n", ARG, RESULT); 480 if (mtflag) 481 f_print(fout, "\tbool_t " 482 "(*%s)(char *, void *, struct svc_req *);\n", 483 ROUTINE); 484 else 485 f_print(fout, "\tchar *(*%s)" 486 "(char *, struct svc_req *);\n", 487 ROUTINE); 488 f_print(fout, "\n"); 489 490 if (timerflag) { 491 if (mtflag) 492 f_print(fout, 493 "\t(void) mutex_lock(&_svcstate_lock);\n"); 494 495 f_print(fout, "\t_rpcsvccount++;\n"); 496 if (mtflag) 497 f_print(fout, 498 "\t(void) mutex_unlock(&_svcstate_lock);\n"); 499 } 500 501 f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); 502 if (!nullproc(vp->procs)) { 503 f_print(fout, "\tcase NULLPROC:\n"); 504 f_print(fout, 505 "\t\t(void) svc_sendreply(%s,\n\t\t (xdrproc_t)xdr_void, NULL);\n", 506 TRANSP); 507 print_return("\t\t"); 508 f_print(fout, "\n"); 509 } 510 for (proc = vp->procs; proc != NULL; proc = proc->next) { 511 f_print(fout, "\tcase %s:\n", proc->proc_name); 512 if (proc->arg_num < 2) { /* single argument */ 513 p_xdrfunc(ARG, proc->args.decls->decl.type); 514 } else { 515 p_xdrfunc(ARG, proc->args.argname); 516 } 517 518 if (streq(proc->res_type, "oneway")) { 519 /* One-way call */ 520 f_print(fout, "\t\t_xdr_%s = NULL;\n", RESULT); 521 } else { 522 p_xdrfunc(RESULT, proc->res_type); 523 } 524 if (mtflag) { 525 f_print(fout, 526 "\t\t%s = (bool_t (*) (char *, " 527 "void *, struct svc_req *))", 528 ROUTINE); 529 } else { 530 f_print(fout, 531 "\t\t%s = (char *(*)(char *, " 532 "struct svc_req *))", 533 ROUTINE); 534 } 535 536 f_print(fout, "\n\t\t "); 537 if (newstyle) { /* new style: calls internal routine */ 538 f_print(fout, "_"); 539 } 540 if (!newstyle) 541 pvname_svc(proc->proc_name, vp->vers_num); 542 else 543 pvname(proc->proc_name, vp->vers_num); 544 f_print(fout, ";\n"); 545 f_print(fout, "\t\tbreak;\n\n"); 546 } 547 f_print(fout, "\tdefault:\n"); 548 printerr("noproc", TRANSP); 549 print_return("\t\t"); 550 f_print(fout, "\t}\n"); 551 552 f_print(fout, 553 "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", 554 ARG, ARG); 555 printif("getargs", TRANSP, "(caddr_t)&", ARG); 556 printerr("decode", TRANSP); 557 print_return("\t\t"); 558 f_print(fout, "\t}\n"); 559 560 if (!mtflag) 561 f_print(fout, 562 "\t%s = (*%s)((char *)&%s, %s);\n", 563 RESULT, ROUTINE, ARG, RQSTP); 564 else 565 f_print(fout, 566 "\t%s = (bool_t)(*%s)" 567 "((char *)&%s, (void *)&%s, %s);\n", 568 RETVAL, ROUTINE, ARG, RESULT, RQSTP); 569 570 571 572 if (mtflag) 573 f_print(fout, 574 "\tif (_xdr_%s && %s > 0 &&\n" 575 "\t !svc_sendreply(%s, _xdr_%s, (char *)&%s)) {\n", 576 RESULT, RETVAL, TRANSP, RESULT, RESULT); 577 else 578 f_print(fout, 579 "\tif (_xdr_%s && %s != NULL &&\n" 580 "\t !svc_sendreply(%s, _xdr_%s, %s)) {\n", 581 RESULT, RESULT, TRANSP, RESULT, RESULT); 582 583 printerr("systemerr", TRANSP); 584 f_print(fout, "\t}\n"); 585 586 printif("freeargs", TRANSP, "(caddr_t)&", ARG); 587 print_err_message("\t\t", "unable to free arguments"); 588 f_print(fout, "\t\texit(1);\n"); 589 f_print(fout, "\t}\n"); 590 /* print out free routine */ 591 if (mtflag) { 592 f_print(fout, "\tif (_xdr_%s != NULL) {\n", RESULT); 593 f_print(fout, "\t\tif (!"); 594 595 pvname(def->def_name, vp->vers_num); 596 f_print(fout, "_freeresult(%s, _xdr_%s,\n", 597 TRANSP, RESULT); 598 f_print(fout, "\t\t (caddr_t)&%s))\n", 599 RESULT); 600 print_err_message("\t\t\t", "unable to free results"); 601 f_print(fout, "\n"); 602 f_print(fout, "\t}\n"); 603 }; 604 print_return("\t"); 605 f_print(fout, "}\n"); 606 } 607 } 608 609 static void 610 printerr(char *err, char *transp) 611 { 612 f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp); 613 } 614 615 static void 616 printif(char *proc, char *transp, char *prefix, char *arg) 617 { 618 f_print(fout, "\tif (!svc_%s(%s, _xdr_%s, %s%s)) {\n", 619 proc, transp, arg, prefix, arg); 620 } 621 622 int 623 nullproc(proc_list *proc) 624 { 625 for (; proc != NULL; proc = proc->next) { 626 if (streq(proc->proc_num, "0")) 627 return (1); 628 } 629 return (0); 630 } 631 632 static void 633 write_inetmost(char *infile) 634 { 635 f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP); 636 f_print(fout, "\tint sock;\n"); 637 f_print(fout, "\tint proto;\n"); 638 f_print(fout, "\tstruct sockaddr_in saddr;\n"); 639 f_print(fout, "\tint asize = sizeof (saddr);\n"); 640 f_print(fout, "\n"); 641 f_print(fout, 642 "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); 643 f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); 644 f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); 645 f_print(fout, "\t\t\texit(1);\n"); 646 f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); 647 f_print(fout, "\t\t (char *)&_rpcfdtype, &ssize) == -1)\n"); 648 f_print(fout, "\t\t\texit(1);\n"); 649 f_print(fout, "\t\tsock = 0;\n"); 650 f_print(fout, "\t\t_rpcpmstart = 1;\n"); 651 f_print(fout, "\t\tproto = 0;\n"); 652 open_log_file(infile, "\t\t"); 653 f_print(fout, "\t} else {\n"); 654 write_rpc_svc_fg(infile, "\t\t"); 655 f_print(fout, "\t\tsock = RPC_ANYSOCK;\n"); 656 print_pmapunset("\t\t"); 657 f_print(fout, "\t}\n"); 658 } 659 660 static void 661 print_return(char *space) 662 { 663 if (exitnow) { 664 f_print(fout, "%sexit(0);\n", space); 665 return; 666 } 667 if (timerflag) { 668 if (mtflag) { 669 f_print(fout, 670 "%s(void) mutex_lock(&_svcstate_lock);\n", 671 space); 672 } 673 f_print(fout, "%s_rpcsvccount--;\n", space); 674 f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space); 675 if (mtflag) { 676 f_print(fout, 677 "%s(void) mutex_unlock(&_svcstate_lock);\n", 678 space); 679 } 680 } 681 f_print(fout, "%sreturn; /* CSTYLED */\n", space); 682 } 683 684 static void 685 print_pmapunset(char *space) 686 { 687 list *l; 688 definition *def; 689 version_list *vp; 690 691 for (l = defined; l != NULL; l = l->next) { 692 def = (definition *)l->val; 693 if (def->def_kind == DEF_PROGRAM) { 694 for (vp = def->def.pr.versions; vp != NULL; 695 vp = vp->next) { 696 f_print(fout, "%s(void) pmap_unset(%s, %s);\n", 697 space, def->def_name, vp->vers_name); 698 } 699 } 700 } 701 } 702 703 static void 704 print_err_message(const char *space, const char *fmt, ...) 705 { 706 char errbuf[ERRBUFLEN]; 707 va_list va; 708 709 va_start(va, fmt); 710 (void) vsnprintf(errbuf, sizeof (errbuf), fmt, va); 711 va_end(va); 712 713 if (logflag) 714 f_print(fout, "%ssyslog(LOG_ERR, \"%%s\",\n", space); 715 else if (inetdflag || pmflag) 716 f_print(fout, "%sRPC_MSGOUT(\"%%s\",\n", space); 717 else 718 f_print(fout, "%sfprintf(stderr, \"%%s\",\n", space); 719 f_print(fout, "%s \"%s\");\n", space, errbuf); 720 } 721 722 /* 723 * Write the server auxiliary function (RPC_MSGOUT, timeout) 724 */ 725 static void 726 write_svc_aux(int nomain) 727 { 728 if (!logflag) 729 write_msg_out(); 730 if (!nomain) 731 write_timeout_func(); 732 } 733 734 /* 735 * Write the RPC_MSGOUT function 736 * 737 * Note that while we define RPC_MSGOUT to be printf-like, all existing 738 * calls are of the form "%s","<msg>" and this implementation assumes that 739 * trivial case. If in the future it's desirable to generate richer calls 740 * this implementation can change to match. This way we don't (yet) have 741 * to introduce varargs into the generated code. 742 */ 743 static void 744 write_msg_out(void) 745 { 746 f_print(fout, "\n"); 747 f_print(fout, "#if\tdefined(RPC_MSGOUT)\n"); 748 f_print(fout, "extern void RPC_MSGOUT(const char *, ...);\n"); 749 f_print(fout, "#else\t/* defined(RPC_MSGOUT) */\n"); 750 f_print(fout, "static "); 751 f_print(fout, "void\nRPC_MSGOUT(const char *fmt, char *msg)\n"); 752 f_print(fout, "{\n"); 753 f_print(fout, "#ifdef RPC_SVC_FG\n"); 754 if (inetdflag || pmflag) 755 f_print(fout, "\tif (_rpcpmstart)\n"); 756 f_print(fout, "\t\tsyslog(LOG_ERR, fmt, msg);\n"); 757 f_print(fout, "\telse {\n"); 758 f_print(fout, "\t\t(void) fprintf(stderr, fmt, msg);\n"); 759 f_print(fout, "\t\t(void) putc('\\n', stderr);\n"); 760 f_print(fout, "\t}\n"); 761 f_print(fout, "#else\n"); 762 f_print(fout, "\tsyslog(LOG_ERR, fmt, msg);\n"); 763 f_print(fout, "#endif\n"); 764 f_print(fout, "}\n"); 765 f_print(fout, "#endif\t/* defined(RPC_MSGOUT) */\n"); 766 } 767 768 /* 769 * Write the timeout function 770 */ 771 static void 772 write_timeout_func(void) 773 { 774 if (!timerflag) 775 return; 776 777 f_print(fout, "\n"); 778 if (mtflag) { 779 f_print(fout, "/*ARGSUSED*/\n"); 780 f_print(fout, "static void *\n"); 781 f_print(fout, "closedown(void *arg)\n"); 782 f_print(fout, "{\n"); 783 f_print(fout, "\t/*CONSTCOND*/\n"); 784 f_print(fout, "\twhile (1) {\n"); 785 f_print(fout, "\t\t(void) sleep(_RPCSVC_CLOSEDOWN/2);\n\n"); 786 f_print(fout, 787 "\t\tif (mutex_trylock(&_svcstate_lock) != 0)\n"); 788 f_print(fout, "\t\t\tcontinue;\n\n"); 789 f_print(fout, 790 "\t\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n"); 791 if (tirpcflag) { 792 f_print(fout, "\t\t\tint size;\n"); 793 } else { 794 f_print(fout, "\t\t\textern fd_set svc_fdset;\n"); 795 f_print(fout, "\t\t\tstatic int size;\n"); 796 } 797 f_print(fout, "\t\t\tint i, openfd = 0;\n\n"); 798 if (tirpcflag) { 799 f_print(fout, "\t\t\tsize = svc_max_pollfd;\n"); 800 } else { 801 f_print(fout, "\t\t\tif (size == 0) {\n"); 802 f_print(fout, "\t\t\t\tsize = getdtablesize();\n"); 803 f_print(fout, "\t\t\t}\n"); 804 } 805 f_print(fout, 806 "\t\t\tfor (i = 0; i < size && openfd < 2; i++)\n"); 807 if (tirpcflag) { 808 f_print(fout, "\t\t\t\tif (svc_pollfd[i].fd >= 0)\n"); 809 } else { 810 f_print(fout, "\t\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); 811 } 812 f_print(fout, "\t\t\t\t\topenfd++;\n"); 813 f_print(fout, "\t\t\tif (openfd <= 1)\n"); 814 f_print(fout, "\t\t\t\texit(0);\n"); 815 f_print(fout, "\t\t} else\n"); 816 f_print(fout, "\t\t\t_rpcsvcstate = _IDLE;\n\n"); 817 f_print(fout, "\t\t(void) mutex_unlock(&_svcstate_lock);\n"); 818 f_print(fout, "\t}\n"); 819 f_print(fout, "}\n"); 820 return; 821 } 822 823 f_print(fout, "static void\n"); 824 f_print(fout, "closedown(int sig)\n"); 825 f_print(fout, "{\n"); 826 f_print(fout, "\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n"); 827 if (tirpcflag) { 828 f_print(fout, "\t\tint size;\n"); 829 } else { 830 f_print(fout, "\t\textern fd_set svc_fdset;\n"); 831 f_print(fout, "\t\tstatic int size;\n"); 832 } 833 f_print(fout, "\t\tint i, openfd = 0;\n\n"); 834 if (tirpcflag) { 835 f_print(fout, "\t\tsize = svc_max_pollfd;\n"); 836 } else { 837 f_print(fout, "\t\tif (size == 0) {\n"); 838 f_print(fout, "\t\t\tsize = getdtablesize();\n"); 839 f_print(fout, "\t\t}\n"); 840 } 841 f_print(fout, 842 "\t\tfor (i = 0; i < size && openfd < 2; i++)\n"); 843 if (tirpcflag) { 844 f_print(fout, "\t\t\tif (svc_pollfd[i].fd >= 0)\n"); 845 } else { 846 f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); 847 } 848 f_print(fout, "\t\t\t\topenfd++;\n"); 849 f_print(fout, "\t\tif (openfd <= 1)\n"); 850 f_print(fout, "\t\t\texit(0);\n"); 851 f_print(fout, "\t} else\n"); 852 f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n"); 853 854 f_print(fout, "\t(void) signal(SIGALRM, (SIG_PF) closedown);\n"); 855 f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); 856 f_print(fout, "}\n"); 857 } 858 859 /* 860 * Write the most of port monitor support 861 */ 862 static void 863 write_pm_most(char *infile, int netflag) 864 { 865 list *l; 866 definition *def; 867 version_list *vp; 868 869 f_print(fout, "\t(void) sigset(SIGPIPE, SIG_IGN);\n\n"); 870 f_print(fout, "\t/*\n"); 871 f_print(fout, "\t * If stdin looks like a TLI endpoint, we assume\n"); 872 f_print(fout, "\t * that we were started by a port monitor. If\n"); 873 f_print(fout, "\t * t_getstate fails with TBADF, this is not a\n"); 874 f_print(fout, "\t * TLI endpoint.\n"); 875 f_print(fout, "\t */\n"); 876 f_print(fout, "\tif (t_getstate(0) != -1 || t_errno != TBADF) {\n"); 877 f_print(fout, "\t\tchar *netid;\n"); 878 if (!netflag) { /* Not included by -n option */ 879 f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n"); 880 f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP); 881 } 882 if (timerflag) 883 f_print(fout, "\t\tint pmclose;\n"); 884 /* 885 * Not necessary, defined in /usr/include/stdlib 886 * f_print(fout, "\t\textern char *getenv();\n"); 887 */ 888 f_print(fout, "\n"); 889 f_print(fout, "\t\t_rpcpmstart = 1;\n"); 890 open_log_file(infile, "\t\t"); 891 f_print(fout, 892 "\n\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); 893 894 if (timerflag) { 895 f_print(fout, "\t\t/* started from inetd */\n"); 896 f_print(fout, "\t\t\tpmclose = 1;\n"); 897 } 898 f_print(fout, "\t\t} else {\n"); 899 f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n"); 900 print_err_message("\t\t\t\t", "cannot get transport info"); 901 if (timerflag) 902 f_print(fout, 903 "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); 904 f_print(fout, "\t\t}\n"); 905 f_print(fout, 906 "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", 907 TRANSP); 908 print_err_message("\t\t\t", "cannot create server handle"); 909 f_print(fout, "\t\t\texit(1);\n"); 910 f_print(fout, "\t\t}\n"); 911 f_print(fout, "\t\tif (nconf)\n"); 912 f_print(fout, "\t\t\tfreenetconfigent(nconf);\n"); 913 for (l = defined; l != NULL; l = l->next) { 914 def = (definition *) l->val; 915 if (def->def_kind != DEF_PROGRAM) { 916 continue; 917 } 918 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 919 f_print(fout, 920 "\t\tif (!svc_reg(%s, %s, %s,\n", 921 TRANSP, def->def_name, vp->vers_name); 922 f_print(fout, "\t\t "); 923 pvname(def->def_name, vp->vers_num); 924 f_print(fout, ", 0)) {\n"); 925 print_err_message("\t\t\t", 926 "unable to register (%s, %s).", 927 def->def_name, vp->vers_name); 928 f_print(fout, "\t\t\texit(1);\n"); 929 f_print(fout, "\t\t}\n"); 930 } 931 } 932 if (timerflag) { 933 f_print(fout, "\t\tif (pmclose) {\n"); 934 if (mtflag) { 935 f_print(fout, 936 "\t\t\tif (thr_create(NULL, 0, closedown, NULL,\n\t\t\t 0, NULL) != 0) {\n"); 937 print_err_message("\t\t\t\t", 938 "cannot create closedown thread"); 939 f_print(fout, "\t\t\t\texit(1);\n"); 940 f_print(fout, "\t\t\t}\n"); 941 } else { 942 f_print(fout, 943 "\t\t\t(void) signal(SIGALRM, (SIG_PF) closedown);\n"); 944 f_print(fout, 945 "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n"); 946 } 947 f_print(fout, "\t\t}\n"); 948 } 949 f_print(fout, "\t\tsvc_run();\n"); 950 f_print(fout, "\t\texit(1);\n"); 951 f_print(fout, "\t\t/* NOTREACHED */\n"); 952 f_print(fout, "\t}"); 953 } 954 955 /* 956 * Support for backgrounding the server if self started. 957 */ 958 static void 959 write_rpc_svc_fg(char *infile, char *sp) 960 { 961 f_print(fout, "#ifndef RPC_SVC_FG\n"); 962 f_print(fout, "#pragma weak closefrom\n"); 963 f_print(fout, "%sextern void closefrom();\n", sp); 964 f_print(fout, "%sint size;\n", sp); 965 if (tirpcflag) 966 f_print(fout, "%sstruct rlimit rl;\n", sp); 967 if (inetdflag) 968 f_print(fout, "%sint pid, i;\n\n", sp); 969 f_print(fout, "%spid = fork();\n", sp); 970 f_print(fout, "%sif (pid < 0) {\n", sp); 971 f_print(fout, "%s\tperror(\"cannot fork\");\n", sp); 972 f_print(fout, "%s\texit(1);\n", sp); 973 f_print(fout, "%s}\n", sp); 974 f_print(fout, "%sif (pid)\n", sp); 975 f_print(fout, "%s\texit(0);\n", sp); 976 /* close all file descriptors */ 977 if (tirpcflag) { 978 f_print(fout, "%sif (closefrom != NULL)\n", sp); 979 f_print(fout, "%s\tclosefrom(0);\n", sp); 980 f_print(fout, "%selse {\n", sp); 981 f_print(fout, "%s\trl.rlim_max = 0;\n", sp); 982 f_print(fout, "%s\tgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); 983 f_print(fout, "%s\tif ((size = rl.rlim_max) == 0)\n", sp); 984 f_print(fout, "%s\t\texit(1);\n", sp); 985 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp); 986 f_print(fout, "%s\t\t(void) close(i);\n", sp); 987 f_print(fout, "%s}\n", sp); 988 } else { 989 f_print(fout, "%s\tsize = getdtablesize();\n", sp); 990 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp); 991 f_print(fout, "%s\t\t(void) close(i);\n", sp); 992 } 993 /* Redirect stderr and stdout to /dev/null */ 994 f_print(fout, "%si = open(\"/dev/null\", 2);\n", sp); 995 f_print(fout, "%s(void) dup2(i, 1);\n", sp); 996 f_print(fout, "%s(void) dup2(i, 2);\n", sp); 997 /* This removes control of the controlling terminal */ 998 if (tirpcflag) 999 f_print(fout, "%ssetsid();\n", sp); 1000 else { 1001 f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp); 1002 f_print(fout, "%sif (i >= 0) {\n", sp); 1003 f_print(fout, 1004 "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp); 1005 f_print(fout, "%s\t(void) close(i);\n", sp); 1006 f_print(fout, "%s}\n", sp); 1007 } 1008 if (!logflag) 1009 open_log_file(infile, sp); 1010 f_print(fout, "#endif\n"); 1011 if (logflag) 1012 open_log_file(infile, sp); 1013 } 1014 1015 static void 1016 open_log_file(char *infile, char *sp) 1017 { 1018 char *s; 1019 1020 s = strrchr(infile, '.'); 1021 if (s) 1022 *s = '\0'; 1023 f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile); 1024 if (s) 1025 *s = '.'; 1026 } 1027 1028 /* 1029 * write a registration for the given transport for Inetd 1030 */ 1031 void 1032 write_inetd_register(char *transp) 1033 { 1034 list *l; 1035 definition *def; 1036 version_list *vp; 1037 char *sp; 1038 int isudp; 1039 char tmpbuf[32]; 1040 1041 if (inetdflag) 1042 sp = "\t"; 1043 else 1044 sp = ""; 1045 if (streq(transp, "udp")) 1046 isudp = 1; 1047 else 1048 isudp = 0; 1049 f_print(fout, "\n"); 1050 if (inetdflag) { 1051 f_print(fout, 1052 "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n", 1053 isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); 1054 } 1055 f_print(fout, "%s\t%s = svc%s_create(%s", 1056 sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK"); 1057 if (!isudp) 1058 f_print(fout, ", 0, 0"); 1059 f_print(fout, ");\n"); 1060 f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); 1061 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp); 1062 print_err_message(tmpbuf, "cannot create %s service.", transp); 1063 f_print(fout, "%s\t\texit(1);\n", sp); 1064 f_print(fout, "%s\t}\n", sp); 1065 1066 if (inetdflag) { 1067 f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp); 1068 f_print(fout, "%s\tproto = IPPROTO_%s;\n", 1069 sp, isudp ? "UDP": "TCP"); 1070 } 1071 for (l = defined; l != NULL; l = l->next) { 1072 def = (definition *) l->val; 1073 if (def->def_kind != DEF_PROGRAM) 1074 continue; 1075 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { 1076 f_print(fout, "%s\tif (!svc_register(%s, %s, %s,\n", 1077 sp, TRANSP, def->def_name, vp->vers_name); 1078 f_print(fout, "%s\t ", sp); 1079 pvname(def->def_name, vp->vers_num); 1080 if (inetdflag) 1081 f_print(fout, ", proto)) {\n"); 1082 else 1083 f_print(fout, ", IPPROTO_%s)) {\n", 1084 isudp ? "UDP": "TCP"); 1085 print_err_message(tmpbuf, 1086 "unable to register (%s, %s, %s).", 1087 def->def_name, vp->vers_name, transp); 1088 f_print(fout, "%s\t\texit(1);\n", sp); 1089 f_print(fout, "%s\t}\n", sp); 1090 } 1091 } 1092 if (inetdflag) 1093 f_print(fout, "\t}\n"); 1094 }