Print this page
rpcgen should only produce ANSI code


   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 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  27 /* All Rights Reserved */
  28 /*
  29  * University Copyright- Copyright (c) 1982, 1986, 1988
  30  * The Regents of the University of California
  31  * All Rights Reserved
  32  *
  33  * University Acknowledgment- Portions of this document are derived from
  34  * software developed by the University of California, Berkeley, and its
  35  * contributors.
  36  */
  37 
  38 /*
  39  * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
  40  */
  41 #include <stdio.h>
  42 #include <string.h>


  58 static void internal_proctype(proc_list *);
  59 static void write_real_program(definition *);
  60 static void write_programs(char *);
  61 static void write_program(definition *, char *);
  62 static void printerr(char *, char *);
  63 static void write_svc_aux(int);
  64 static void printif(char *, char *, char *, char *);
  65 static void write_inetmost(char *);
  66 static void print_return(char *);
  67 static void print_pmapunset(char *);
  68 static void print_err_message(const char *, const char *, ...);
  69 static void write_msg_out(void);
  70 static void write_timeout_func(void);
  71 static void write_pm_most(char *, int);
  72 static void write_rpc_svc_fg(char *, char *);
  73 static void open_log_file(char *, char *);
  74 
  75 static void
  76 p_xdrfunc(char *rname, char *typename)
  77 {
  78         if (Cflag) {
  79                 f_print(fout, "\t\t_xdr_%s = (xdrproc_t)\n", rname);
  80                 f_print(fout, "\t\t    xdr_%s;\n", stringfix(typename));
  81         } else {
  82                 f_print(fout, "\t\t_xdr_%s = xdr_%s;\n",
  83                     rname, stringfix(typename));
  84         }
  85 }
  86 
  87 static void
  88 internal_proctype(proc_list *plist)
  89 {
  90         f_print(fout, "static ");
  91         ptype(plist->res_prefix, plist->res_type, 1);
  92         f_print(fout, "*");
  93 }
  94 
  95 
  96 static void
  97 write_mtauto(void)
  98 {
  99         f_print(fout, "\tif (!rpc_control(RPC_SVC_MTMODE_SET, &mode)) {\n");
 100         print_err_message("\t\t", "unable to set automatic MT mode.");
 101         f_print(fout, "\t\texit(1);\n\t}\n");
 102 }
 103 
 104 /*


 283 {
 284         f_print(fout, "\n");
 285         if (inetdflag) {
 286                 f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
 287                 print_err_message("\t\t", "could not create a handle");
 288                 f_print(fout, "\t\texit(1);\n");
 289                 f_print(fout, "\t}\n");
 290                 if (timerflag) {
 291                         f_print(fout, "\tif (_rpcpmstart) {\n");
 292                         if (mtflag) {
 293                                 f_print(fout,
 294 "\t\tif (thr_create(NULL, 0, closedown, NULL, 0, NULL) != 0) {\n");
 295                                 print_err_message("\t\t\t",
 296                                     "cannot create closedown thread");
 297                                 f_print(fout, "\t\t\texit(1);\n");
 298                                 f_print(fout, "\t\t}\n");
 299                                 f_print(fout, "\t}\n");
 300                         } else {
 301                                 f_print(fout,
 302                                 "\t\t(void) signal(SIGALRM, %s closedown);\n",
 303                                     Cflag? "(SIG_PF)":"(void(*)())");
 304                                 f_print(fout,
 305 "\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
 306                                 f_print(fout, "\t}\n");
 307                         }
 308                 }
 309         }
 310         f_print(fout, "\tsvc_run();\n");
 311         print_err_message("\t", "svc_run returned");
 312         f_print(fout, "\texit(1);\n");
 313         f_print(fout, "\t/* NOTREACHED */\n");
 314         f_print(fout, "}\n");
 315 }
 316 
 317 static void
 318 write_programs(char *storage)
 319 {
 320         list *l;
 321         definition *def;
 322 
 323         /* write out stubs for procedure  definitions */


 350         proc_list *proc;
 351         decl_list *l;
 352 
 353         if (!newstyle)
 354                 return;  /* not needed for old style */
 355         for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
 356                 for (proc = vp->procs; proc != NULL; proc = proc->next) {
 357                         int oneway = streq(proc->res_type, "oneway");
 358 
 359                         f_print(fout, "\n");
 360                         if (proc->arg_num < 2 &&
 361                             streq(proc->args.decls->decl.type, "void")) {
 362                                 f_print(fout, "/* ARGSUSED */\n");
 363                         }
 364                         if (!mtflag)
 365                                 internal_proctype(proc);
 366                         else
 367                                 f_print(fout, "int");
 368                         f_print(fout, "\n_");
 369                         pvname(proc->proc_name, vp->vers_num);
 370                         if (Cflag) {
 371                                 f_print(fout, "(\n");
 372                                 f_print(fout, "    ");
 373                                 /* arg name */
 374                                 if (proc->arg_num > 1)
 375                                         /* LINTED variable format */
 376                                         f_print(fout, proc->args.argname);
 377                                 else
 378                                         ptype(proc->args.decls->decl.prefix,
 379                                             proc->args.decls->decl.type, 0);
 380                                 f_print(fout, " *argp,\n");
 381                                 if (mtflag) {
 382                                         f_print(fout, "    ");
 383                                         ptype(proc->res_prefix,
 384                                             proc->res_type, 1);
 385                                         f_print(fout, "*%s,\n", RESULT);
 386                                 }
 387                                 f_print(fout, "    struct svc_req *%s)\n",
 388                                     RQSTP);
 389 
 390                         } else {
 391                                 if (mtflag)
 392                                         f_print(fout, "(argp, %s, %s)\n",
 393                                             RESULT, RQSTP);
 394                                 else
 395                                         f_print(fout, "(argp, %s)\n", RQSTP);
 396                                 /* arg name */
 397                                 if (proc->arg_num > 1)
 398                                         f_print(fout, "\t%s *argp;\n",
 399                                             proc->args.argname);
 400                                 else {
 401                                         f_print(fout, "\t");
 402                                         ptype(proc->args.decls->decl.prefix,
 403                                             proc->args.decls->decl.type, 0);
 404                                         f_print(fout, " *argp;\n");
 405                                 }
 406                                 if (mtflag)
 407                                         f_print(fout, "\tvoid *%s;\n", RESULT);
 408                                 f_print(fout, "\tstruct svc_req *%s;\n", RQSTP);
 409                         }
 410 
 411                         f_print(fout, "{\n");
 412                         f_print(fout, "\treturn (");
 413                         /* for mtflag, arguments are different */
 414                         if (Cflag || mtflag)
 415                                 pvname_svc(proc->proc_name, vp->vers_num);
 416                         else
 417                                 pvname(proc->proc_name, vp->vers_num);
 418                         f_print(fout, "(");
 419                         if (proc->arg_num < 2) { /* single argument */
 420                                 /* only print if non-void */
 421                                 if (!streq(proc->args.decls->decl.type, "void"))
 422                                         f_print(fout, "*argp, ");
 423                         } else {
 424                                 f_print(fout, "\n");
 425                                 for (l = proc->args.decls;  l != NULL;
 426                                     l = l->next)
 427                                         f_print(fout, "\t    argp->%s,\n",
 428                                             l->decl.name);
 429                                 f_print(fout, "\t    ");
 430                         }
 431                         if (mtflag && !oneway)
 432                                 f_print(fout, "%s, ", RESULT);
 433                         f_print(fout, "%s));\n}\n", RQSTP);
 434                 }
 435         }
 436 }
 437 
 438 static void
 439 write_program(definition *def, char *storage)
 440 {
 441         version_list *vp;
 442         proc_list *proc;
 443         int filled;
 444 
 445         for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
 446                 f_print(fout, "\n");
 447                 if (storage != NULL) {
 448                         f_print(fout, "%s ", storage);
 449                 }
 450                 f_print(fout, "void\n");
 451                 pvname(def->def_name, vp->vers_num);
 452 
 453                 if (Cflag) {
 454                         f_print(fout, "(struct svc_req *%s, ", RQSTP);
 455                         f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
 456                 } else {
 457                         f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
 458                         f_print(fout, " struct svc_req *%s;\n", RQSTP);
 459                         f_print(fout, " register SVCXPRT *%s;\n", TRANSP);
 460                 }
 461 
 462                 f_print(fout, "{\n");
 463 
 464                 filled = 0;
 465                 f_print(fout, "\tunion {\n");
 466                 for (proc = vp->procs; proc != NULL; proc = proc->next) {
 467                         if (proc->arg_num < 2) { /* single argument */
 468                                 if (streq(proc->args.decls->decl.type,
 469                                     "void")) {
 470                                         continue;
 471                                 }
 472                                 filled = 1;
 473                                 f_print(fout, "\t\t");
 474                                 ptype(proc->args.decls->decl.prefix,
 475                                     proc->args.decls->decl.type, 0);
 476                                 pvname(proc->proc_name, vp->vers_num);
 477                                 f_print(fout, "_arg;\n");
 478 
 479                         } else {
 480                                 filled = 1;


 494                         f_print(fout, "\tunion {\n");
 495                         for (proc = vp->procs; proc != NULL;
 496                             proc = proc->next) {
 497                                 if (streq(proc->res_type, "void") ||
 498                                     streq(proc->res_type, "oneway"))
 499                                         continue;
 500                                 filled = 1;
 501                                 f_print(fout, "\t\t");
 502                                 ptype(proc->res_prefix, proc->res_type, 0);
 503                                 pvname(proc->proc_name, vp->vers_num);
 504                                 f_print(fout, "_res;\n");
 505                         }
 506                         if (!filled)
 507                                 f_print(fout, "\t\tint fill;\n");
 508                         f_print(fout, "\t} %s;\n", RESULT);
 509                         f_print(fout, "\tbool_t %s;\n", RETVAL);
 510 
 511                 } else
 512                         f_print(fout, "\tchar *%s;\n", RESULT);
 513 
 514                 if (Cflag) {
 515                         f_print(fout, "\txdrproc_t _xdr_%s, _xdr_%s;\n",
 516                             ARG, RESULT);
 517                         if (mtflag)
 518                                 f_print(fout,
 519 "\tbool_t (*%s)(char *, void *, struct svc_req *);\n",
 520                                     ROUTINE);
 521                         else
 522                                 f_print(fout,
 523 "\tchar *(*%s)(char *, struct svc_req *);\n",
 524                                     ROUTINE);
 525                 } else {
 526                         f_print(fout,
 527                             "\tbool_t (*_xdr_%s)(), (*_xdr_%s)();\n",
 528                             ARG, RESULT);
 529                         if (mtflag)
 530                                 f_print(fout, "\tbool_t (*%s)();\n", ROUTINE);
 531                         else
 532                                 f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
 533                 }
 534                 f_print(fout, "\n");
 535 
 536                 if (timerflag) {
 537                         if (mtflag)
 538                                 f_print(fout,
 539 "\t(void) mutex_lock(&_svcstate_lock);\n");
 540 
 541                         f_print(fout, "\t_rpcsvccount++;\n");
 542                         if (mtflag)
 543                                 f_print(fout,
 544 "\t(void) mutex_unlock(&_svcstate_lock);\n");
 545                 }
 546 
 547                 f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
 548                 if (!nullproc(vp->procs)) {
 549                         f_print(fout, "\tcase NULLPROC:\n");
 550                         f_print(fout,
 551                             Cflag ?
 552 "\t\t(void) svc_sendreply(%s,\n\t\t    (xdrproc_t)xdr_void, NULL);\n" :
 553 "\t\t(void) svc_sendreply(%s, xdr_void,\n\t\t\tNULL);\n",
 554                             TRANSP);
 555                         print_return("\t\t");
 556                         f_print(fout, "\n");
 557                 }
 558                 for (proc = vp->procs; proc != NULL; proc = proc->next) {
 559                         f_print(fout, "\tcase %s:\n", proc->proc_name);
 560                         if (proc->arg_num < 2) { /* single argument */
 561                                 p_xdrfunc(ARG, proc->args.decls->decl.type);
 562                         } else {
 563                                 p_xdrfunc(ARG, proc->args.argname);
 564                         }
 565 
 566                         if (streq(proc->res_type, "oneway")) {
 567                                 /* One-way call */
 568                                 f_print(fout, "\t\t_xdr_%s = NULL;\n", RESULT);
 569                         } else {
 570                                 p_xdrfunc(RESULT, proc->res_type);
 571                         }
 572                         if (Cflag) {
 573                                 if (mtflag) {
 574                                         f_print(fout,
 575                                             "\t\t%s = (bool_t (*) (char *,  "
 576                                             "void *,  struct svc_req *))",
 577                                             ROUTINE);
 578                                 } else {
 579                                         f_print(fout,
 580                                             "\t\t%s = (char *(*)(char *, "
 581                                             "struct svc_req *))",
 582                                             ROUTINE);
 583                                 }
 584                         } else {
 585                                 if (mtflag) {
 586                                         f_print(fout,
 587                                             "\t\t%s = (bool_t (*)())",
 588                                             ROUTINE);
 589                                 } else {
 590                                         f_print(fout, "\t\t%s = (char *(*)())",
 591                                             ROUTINE);
 592                                 }
 593                         }
 594 
 595                         f_print(fout, "\n\t\t    ");
 596                         if (newstyle) { /* new style: calls internal routine */
 597                                 f_print(fout, "_");
 598                         }
 599                         if ((Cflag || mtflag) && !newstyle)
 600                                 pvname_svc(proc->proc_name, vp->vers_num);
 601                         else
 602                                 pvname(proc->proc_name, vp->vers_num);
 603                         f_print(fout, ";\n");
 604                         f_print(fout, "\t\tbreak;\n\n");
 605                 }
 606                 f_print(fout, "\tdefault:\n");
 607                 printerr("noproc", TRANSP);
 608                 print_return("\t\t");
 609                 f_print(fout, "\t}\n");
 610 
 611                 f_print(fout,
 612                     "\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
 613                     ARG, ARG);
 614                 printif("getargs", TRANSP, "(caddr_t)&", ARG);
 615                 printerr("decode", TRANSP);
 616                 print_return("\t\t");
 617                 f_print(fout, "\t}\n");
 618 
 619                 if (!mtflag)
 620                         if (Cflag)
 621                                 f_print(fout,
 622                                     "\t%s = (*%s)((char *)&%s, %s);\n",
 623                                     RESULT, ROUTINE, ARG, RQSTP);
 624                         else
 625                                 f_print(fout, "\t%s = (*%s)(&%s, %s);\n",
 626                                     RESULT, ROUTINE, ARG, RQSTP);
 627                 else
 628                         if (Cflag)
 629                                 f_print(fout,
 630 "\t%s = (bool_t)(*%s)((char *)&%s, (void *)&%s, %s);\n",

 631                                     RETVAL, ROUTINE, ARG, RESULT, RQSTP);
 632                         else
 633                                 f_print(fout,
 634 "\t%s = (bool_t)(*%s)(&%s, &%s, %s);\n",
 635                                     RETVAL, ROUTINE, ARG, RESULT, RQSTP);
 636 
 637 
 638 
 639 
 640                 if (mtflag)
 641                         f_print(fout,
 642 "\tif (_xdr_%s && %s > 0 &&\n"
 643 "\t    !svc_sendreply(%s, _xdr_%s, (char *)&%s)) {\n",
 644                             RESULT, RETVAL, TRANSP, RESULT, RESULT);
 645                 else
 646                         f_print(fout,
 647 "\tif (_xdr_%s && %s != NULL &&\n"
 648 "\t    !svc_sendreply(%s, _xdr_%s, %s)) {\n",
 649                             RESULT, RESULT, TRANSP, RESULT, RESULT);
 650 
 651                 printerr("systemerr", TRANSP);
 652                 f_print(fout, "\t}\n");
 653 
 654                 printif("freeargs", TRANSP, "(caddr_t)&", ARG);
 655                 print_err_message("\t\t", "unable to free arguments");
 656                 f_print(fout, "\t\texit(1);\n");
 657                 f_print(fout, "\t}\n");
 658                 /* print out free routine */
 659                 if (mtflag) {


 796         if (!logflag)
 797                 write_msg_out();
 798         if (!nomain)
 799                 write_timeout_func();
 800 }
 801 
 802 /*
 803  * Write the RPC_MSGOUT function
 804  *
 805  * Note that while we define RPC_MSGOUT to be printf-like, all existing
 806  * calls are of the form "%s","<msg>" and this implementation assumes that
 807  * trivial case.  If in the future it's desirable to generate richer calls
 808  * this implementation can change to match.  This way we don't (yet) have
 809  * to introduce varargs into the generated code.
 810  */
 811 static void
 812 write_msg_out(void)
 813 {
 814         f_print(fout, "\n");
 815         f_print(fout, "#if\tdefined(RPC_MSGOUT)\n");
 816         if (!Cflag) {
 817                 f_print(fout, "extern void RPC_MSGOUT();\n");
 818         } else {
 819                 f_print(fout, "extern void RPC_MSGOUT(const char *, ...);\n");
 820         }
 821         f_print(fout, "#else\t/* defined(RPC_MSGOUT) */\n");
 822         f_print(fout, "static ");
 823         if (!Cflag) {
 824                 f_print(fout, "void\nRPC_MSGOUT(fmt, msg)\n");
 825                 f_print(fout, "\tchar *fmt;\n");
 826                 f_print(fout, "\tchar *msg;\n");
 827         } else {
 828                 f_print(fout, "void\nRPC_MSGOUT(const char *fmt, char *msg)\n");
 829         }
 830         f_print(fout, "{\n");
 831         f_print(fout, "#ifdef RPC_SVC_FG\n");
 832         if (inetdflag || pmflag)
 833                 f_print(fout, "\tif (_rpcpmstart)\n");
 834         f_print(fout, "\t\tsyslog(LOG_ERR, fmt, msg);\n");
 835         f_print(fout, "\telse {\n");
 836         f_print(fout, "\t\t(void) fprintf(stderr, fmt, msg);\n");
 837         f_print(fout, "\t\t(void) putc('\\n', stderr);\n");
 838         f_print(fout, "\t}\n");
 839         f_print(fout, "#else\n");
 840         f_print(fout, "\tsyslog(LOG_ERR, fmt, msg);\n");
 841         f_print(fout, "#endif\n");
 842         f_print(fout, "}\n");
 843         f_print(fout, "#endif\t/* defined(RPC_MSGOUT) */\n");
 844 }
 845 
 846 /*
 847  * Write the timeout function
 848  */
 849 static void
 850 write_timeout_func(void)
 851 {
 852         if (!timerflag)
 853                 return;
 854 
 855         f_print(fout, "\n");
 856         if (mtflag) {
 857                 f_print(fout, "/*ARGSUSED*/\n");
 858                 f_print(fout, "static void *\n");
 859                 if (!Cflag) {
 860                         f_print(fout, "closedown(arg)\n");
 861                         f_print(fout, "\tvoid *arg;\n");
 862                 } else
 863                         f_print(fout, "closedown(void *arg)\n");
 864                 f_print(fout, "{\n");
 865                 f_print(fout, "\t/*CONSTCOND*/\n");
 866                 f_print(fout, "\twhile (1) {\n");
 867                 f_print(fout, "\t\t(void) sleep(_RPCSVC_CLOSEDOWN/2);\n\n");
 868                 f_print(fout,
 869 "\t\tif (mutex_trylock(&_svcstate_lock) != 0)\n");
 870                 f_print(fout, "\t\t\tcontinue;\n\n");
 871                 f_print(fout,
 872 "\t\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
 873                 if (tirpcflag) {
 874                         f_print(fout, "\t\t\tint size;\n");
 875                 } else {
 876                         f_print(fout, "\t\t\textern fd_set svc_fdset;\n");
 877                         f_print(fout, "\t\t\tstatic int size;\n");
 878                 }
 879                 f_print(fout, "\t\t\tint i, openfd = 0;\n\n");
 880                 if (tirpcflag) {
 881                         f_print(fout, "\t\t\tsize = svc_max_pollfd;\n");
 882                 } else {


 886                 }
 887                 f_print(fout,
 888 "\t\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
 889                 if (tirpcflag) {
 890                         f_print(fout, "\t\t\t\tif (svc_pollfd[i].fd >= 0)\n");
 891                 } else {
 892                         f_print(fout, "\t\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
 893                 }
 894                 f_print(fout, "\t\t\t\t\topenfd++;\n");
 895                 f_print(fout, "\t\t\tif (openfd <= 1)\n");
 896                 f_print(fout, "\t\t\t\texit(0);\n");
 897                 f_print(fout, "\t\t} else\n");
 898                 f_print(fout, "\t\t\t_rpcsvcstate = _IDLE;\n\n");
 899                 f_print(fout, "\t\t(void) mutex_unlock(&_svcstate_lock);\n");
 900                 f_print(fout, "\t}\n");
 901                 f_print(fout, "}\n");
 902                 return;
 903         }
 904 
 905         f_print(fout, "static void\n");
 906         if (!Cflag) {
 907                 f_print(fout, "closedown(sig)\n");
 908                 f_print(fout, "\tint sig;\n");
 909         } else
 910                 f_print(fout, "closedown(int sig)\n");
 911         f_print(fout, "{\n");
 912         f_print(fout, "\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
 913         if (tirpcflag) {
 914                 f_print(fout, "\t\tint size;\n");
 915         } else {
 916                 f_print(fout, "\t\textern fd_set svc_fdset;\n");
 917                 f_print(fout, "\t\tstatic int size;\n");
 918         }
 919         f_print(fout, "\t\tint i, openfd = 0;\n\n");
 920         if (tirpcflag) {
 921                 f_print(fout, "\t\tsize = svc_max_pollfd;\n");
 922         } else {
 923                 f_print(fout, "\t\tif (size == 0) {\n");
 924                 f_print(fout, "\t\t\tsize = getdtablesize();\n");
 925                 f_print(fout, "\t\t}\n");
 926         }
 927         f_print(fout,
 928             "\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
 929         if (tirpcflag) {
 930                 f_print(fout, "\t\t\tif (svc_pollfd[i].fd >= 0)\n");
 931         } else {
 932                 f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
 933         }
 934         f_print(fout, "\t\t\t\topenfd++;\n");
 935         f_print(fout, "\t\tif (openfd <= 1)\n");
 936         f_print(fout, "\t\t\texit(0);\n");
 937         f_print(fout, "\t} else\n");
 938         f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n");
 939 
 940         f_print(fout, "\t(void) signal(SIGALRM, %s closedown);\n",
 941             Cflag? "(SIG_PF)" : "(void(*)())");
 942         f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
 943         f_print(fout, "}\n");
 944 }
 945 
 946 /*
 947  * Write the most of port monitor support
 948  */
 949 static void
 950 write_pm_most(char *infile, int netflag)
 951 {
 952         list *l;
 953         definition *def;
 954         version_list *vp;
 955 
 956         f_print(fout, "\t(void) sigset(SIGPIPE, SIG_IGN);\n\n");
 957         f_print(fout, "\t/*\n");
 958         f_print(fout, "\t * If stdin looks like a TLI endpoint, we assume\n");
 959         f_print(fout, "\t * that we were started by a port monitor. If\n");
 960         f_print(fout, "\t * t_getstate fails with TBADF, this is not a\n");
 961         f_print(fout, "\t * TLI endpoint.\n");


1010                         pvname(def->def_name, vp->vers_num);
1011                         f_print(fout, ", 0)) {\n");
1012                         print_err_message("\t\t\t",
1013                             "unable to register (%s, %s).",
1014                             def->def_name, vp->vers_name);
1015                         f_print(fout, "\t\t\texit(1);\n");
1016                         f_print(fout, "\t\t}\n");
1017                 }
1018         }
1019         if (timerflag) {
1020                 f_print(fout, "\t\tif (pmclose) {\n");
1021                 if (mtflag) {
1022                         f_print(fout,
1023 "\t\t\tif (thr_create(NULL, 0, closedown, NULL,\n\t\t\t    0, NULL) != 0) {\n");
1024                         print_err_message("\t\t\t\t",
1025                             "cannot create closedown thread");
1026                         f_print(fout, "\t\t\t\texit(1);\n");
1027                         f_print(fout, "\t\t\t}\n");
1028                 } else {
1029                         f_print(fout,
1030 "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
1031                             Cflag? "(SIG_PF)" : "(void(*)())");
1032                         f_print(fout,
1033 "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
1034                 }
1035                 f_print(fout, "\t\t}\n");
1036         }
1037         f_print(fout, "\t\tsvc_run();\n");
1038         f_print(fout, "\t\texit(1);\n");
1039         f_print(fout, "\t\t/* NOTREACHED */\n");
1040         f_print(fout, "\t}");
1041 }
1042 
1043 /*
1044  * Support for backgrounding the server if self started.
1045  */
1046 static void
1047 write_rpc_svc_fg(char *infile, char *sp)
1048 {
1049         f_print(fout, "#ifndef RPC_SVC_FG\n");
1050         f_print(fout, "#pragma weak closefrom\n");
1051         f_print(fout, "%sextern void closefrom();\n", sp);




   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>


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


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


 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;


 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) {


 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 {


 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");


 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);