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 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>
  43 #include <stdarg.h>
  44 #include "rpc_parse.h"
  45 #include "rpc_util.h"
  46 
  47 extern int nullproc(proc_list *);
  48 
  49 static char RQSTP[] = "rqstp";
  50 static char TRANSP[] = "transp";
  51 static char ARG[] = "argument";
  52 static char RESULT[] = "result";
  53 static char ROUTINE[] = "local";
  54 static char RETVAL[] = "retval";
  55 
  56 #define ERRBUFLEN       256
  57 
  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 /*
 105  * write most of the service, that is, everything but the registrations.
 106  */
 107 void
 108 write_most(char *infile, int netflag, int nomain)
 109 {
 110         if (inetdflag || pmflag) {
 111                 char *var_type;
 112                 var_type = (nomain? "extern" : "static");
 113                 f_print(fout, "%s int _rpcpmstart;", var_type);
 114                 f_print(fout, "\t\t/* Started by a port monitor ? */\n");
 115                 if (!tirpcflag) {
 116                         f_print(fout, "%s int _rpcfdtype;", var_type);
 117                         f_print(fout,
 118                             "\t\t /* Whether Stream or Datagram ? */\n");
 119                 }
 120 
 121                 if (timerflag) {
 122                         f_print(fout,
 123 "\n/* States a server can be in wrt request */\n\n");
 124                         f_print(fout, "#define\t_IDLE 0\n");
 125                         f_print(fout, "#define\t_SERVED 1\n\n");
 126                         if (nomain) {
 127                                 f_print(fout,
 128                                     "/* LINTED static unused if no main */\n");
 129                         }
 130                         f_print(fout,
 131                             "static int _rpcsvcstate = _IDLE;");
 132                         f_print(fout,
 133 "\t/* Set when a request is serviced */\n");
 134                         f_print(fout, "static int _rpcsvccount = 0;");
 135                         f_print(fout,
 136 "\t\t/* Number of requests being serviced */\n");
 137 
 138                         if (mtflag) {
 139                                 f_print(fout, "mutex_t _svcstate_lock;");
 140                                 f_print(fout,
 141 "\t\t/* lock for _rpcsvcstate, _rpcsvccount */\n");
 142 
 143                         }
 144                 }
 145 
 146                 write_svc_aux(nomain);
 147         }
 148         /* write out dispatcher and stubs */
 149         write_programs(nomain ? NULL : "static");
 150 
 151         if (nomain)
 152                 return;
 153 
 154         f_print(fout, "\nint\nmain()\n");
 155         f_print(fout, "{\n");
 156         if (inetdflag) {
 157                 write_inetmost(infile);
 158                 /* Includes call to write_rpc_svc_fg() */
 159         } else {
 160                 if (tirpcflag) {
 161                         if (netflag) {
 162                                 f_print(fout,
 163                                     "\tregister SVCXPRT *%s;\n", TRANSP);
 164                                 f_print(fout,
 165                                     "\tstruct netconfig *nconf = NULL;\n");
 166                         }
 167                         f_print(fout, "\tpid_t pid;\n");
 168                         f_print(fout, "\tint i;\n");
 169                         if (mtauto) {
 170                                 f_print(fout,
 171                                     "\tint mode = RPC_SVC_MT_AUTO;\n\n");
 172                                 write_mtauto();
 173                         } else
 174                                 f_print(fout, "\n");
 175 
 176                         if (mtflag & timerflag)
 177                                 f_print(fout,
 178 "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n");
 179 
 180                         write_pm_most(infile, netflag);
 181                         f_print(fout, "\telse {\n");
 182                         write_rpc_svc_fg(infile, "\t\t");
 183                         f_print(fout, "\t}\n");
 184                 } else {
 185                         f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
 186                         f_print(fout, "\n");
 187                         print_pmapunset("\t");
 188                 }
 189         }
 190 
 191         if (logflag && !inetdflag) {
 192                 open_log_file(infile, "\t");
 193         }
 194 }
 195 
 196 /*
 197  * write a registration for the given transport
 198  */
 199 void
 200 write_netid_register(char *transp)
 201 {
 202         list *l;
 203         definition *def;
 204         version_list *vp;
 205         char *sp;
 206         char tmpbuf[32];
 207 
 208         sp = "";
 209         f_print(fout, "\n");
 210         f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
 211         f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
 212         (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
 213         print_err_message(tmpbuf, "cannot find %s netid.", transp);
 214         f_print(fout, "%s\t\texit(1);\n", sp);
 215         f_print(fout, "%s\t}\n", sp);
 216         f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
 217             sp, TRANSP);
 218         f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
 219         print_err_message(tmpbuf, "cannot create %s service.", transp);
 220         f_print(fout, "%s\t\texit(1);\n", sp);
 221         f_print(fout, "%s\t}\n", sp);
 222 
 223         for (l = defined; l != NULL; l = l->next) {
 224                 def = (definition *) l->val;
 225                 if (def->def_kind != DEF_PROGRAM) {
 226                         continue;
 227                 }
 228                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
 229                         f_print(fout,
 230                             "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
 231                             sp, def->def_name, vp->vers_name);
 232                         f_print(fout,
 233                             "%s\tif (!svc_reg(%s, %s, %s, ",
 234                             sp, TRANSP, def->def_name, vp->vers_name);
 235                         pvname(def->def_name, vp->vers_num);
 236                         f_print(fout, ", nconf)) {\n");
 237                         print_err_message(tmpbuf,
 238                             "unable to register (%s, %s, %s).",
 239                             def->def_name, vp->vers_name, transp);
 240                         f_print(fout, "%s\t\texit(1);\n", sp);
 241                         f_print(fout, "%s\t}\n", sp);
 242                 }
 243         }
 244         f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
 245 }
 246 
 247 /*
 248  * write a registration for the given transport for TLI
 249  */
 250 void
 251 write_nettype_register(char *transp)
 252 {
 253         list *l;
 254         definition *def;
 255         version_list *vp;
 256 
 257         for (l = defined; l != NULL; l = l->next) {
 258                 def = (definition *) l->val;
 259                 if (def->def_kind != DEF_PROGRAM) {
 260                         continue;
 261                 }
 262                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
 263                         f_print(fout, "\tif (!svc_create(\n");
 264                         f_print(fout, "\t    ");
 265                         pvname(def->def_name, vp->vers_num);
 266                         f_print(fout, ", %s, %s,\n",
 267                             def->def_name, vp->vers_name);
 268                         f_print(fout, "\t    \"%s\")) {\n", transp);
 269                         print_err_message("\t\t",
 270                             "unable to create (%s, %s) for %s.",
 271                             def->def_name, vp->vers_name, transp);
 272                         f_print(fout, "\t\texit(1);\n");
 273                         f_print(fout, "\t}\n");
 274                 }
 275         }
 276 }
 277 
 278 /*
 279  * write the rest of the service
 280  */
 281 void
 282 write_rest(void)
 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 */
 324         for (l = defined; l != NULL; l = l->next) {
 325                 def = (definition *) l->val;
 326                 if (def->def_kind == DEF_PROGRAM)
 327                         write_real_program(def);
 328         }
 329 
 330         /* write out dispatcher for each program */
 331         for (l = defined; l != NULL; l = l->next) {
 332                 def = (definition *) l->val;
 333                 if (def->def_kind == DEF_PROGRAM)
 334                         write_program(def, storage);
 335         }
 336 
 337 
 338 }
 339 
 340 /*
 341  * write out definition of internal function (e.g. _printmsg_1(...))
 342  *  which calls server's defintion of actual function (e.g. printmsg_1(...)).
 343  *  Unpacks single user argument of printmsg_1 to call-by-value format
 344  *  expected by printmsg_1.
 345  */
 346 static void
 347 write_real_program(definition *def)
 348 {
 349         version_list *vp;
 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;
 481                                 f_print(fout, "\t\t%s", proc->args.argname);
 482                                 f_print(fout, " ");
 483                                 pvname(proc->proc_name, vp->vers_num);
 484                                 f_print(fout, "_arg;\n");
 485                         }
 486                 }
 487                 if (!filled) {
 488                         f_print(fout, "\t\tint fill;\n");
 489                 }
 490                 f_print(fout, "\t} %s;\n", ARG);
 491 
 492                 if (mtflag) {
 493                         filled = 0;
 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) {
 660                         f_print(fout, "\tif (_xdr_%s != NULL) {\n", RESULT);
 661                         f_print(fout, "\t\tif (!");
 662 
 663                         pvname(def->def_name, vp->vers_num);
 664                         f_print(fout, "_freeresult(%s, _xdr_%s,\n",
 665                             TRANSP, RESULT);
 666                         f_print(fout, "\t\t    (caddr_t)&%s))\n",
 667                             RESULT);
 668                         print_err_message("\t\t\t", "unable to free results");
 669                         f_print(fout, "\n");
 670                         f_print(fout, "\t}\n");
 671                 };
 672                 print_return("\t");
 673                 f_print(fout, "}\n");
 674         }
 675 }
 676 
 677 static void
 678 printerr(char *err, char *transp)
 679 {
 680         f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
 681 }
 682 
 683 static void
 684 printif(char *proc, char *transp, char *prefix, char *arg)
 685 {
 686         f_print(fout, "\tif (!svc_%s(%s, _xdr_%s, %s%s)) {\n",
 687             proc, transp, arg, prefix, arg);
 688 }
 689 
 690 int
 691 nullproc(proc_list *proc)
 692 {
 693         for (; proc != NULL; proc = proc->next) {
 694                 if (streq(proc->proc_num, "0"))
 695                         return (1);
 696         }
 697         return (0);
 698 }
 699 
 700 static void
 701 write_inetmost(char *infile)
 702 {
 703         f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
 704         f_print(fout, "\tint sock;\n");
 705         f_print(fout, "\tint proto;\n");
 706         f_print(fout, "\tstruct sockaddr_in saddr;\n");
 707         f_print(fout, "\tint asize = sizeof (saddr);\n");
 708         f_print(fout, "\n");
 709         f_print(fout,
 710         "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
 711         f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
 712         f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
 713         f_print(fout, "\t\t\texit(1);\n");
 714         f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
 715         f_print(fout, "\t\t    (char *)&_rpcfdtype, &ssize) == -1)\n");
 716         f_print(fout, "\t\t\texit(1);\n");
 717         f_print(fout, "\t\tsock = 0;\n");
 718         f_print(fout, "\t\t_rpcpmstart = 1;\n");
 719         f_print(fout, "\t\tproto = 0;\n");
 720         open_log_file(infile, "\t\t");
 721         f_print(fout, "\t} else {\n");
 722         write_rpc_svc_fg(infile, "\t\t");
 723         f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
 724         print_pmapunset("\t\t");
 725         f_print(fout, "\t}\n");
 726 }
 727 
 728 static void
 729 print_return(char *space)
 730 {
 731         if (exitnow) {
 732                 f_print(fout, "%sexit(0);\n", space);
 733                 return;
 734         }
 735         if (timerflag) {
 736                 if (mtflag) {
 737                         f_print(fout,
 738                             "%s(void) mutex_lock(&_svcstate_lock);\n",
 739                             space);
 740                 }
 741                 f_print(fout, "%s_rpcsvccount--;\n", space);
 742                 f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space);
 743                 if (mtflag) {
 744                         f_print(fout,
 745                             "%s(void) mutex_unlock(&_svcstate_lock);\n",
 746                             space);
 747                 }
 748         }
 749         f_print(fout, "%sreturn; /* CSTYLED */\n", space);
 750 }
 751 
 752 static void
 753 print_pmapunset(char *space)
 754 {
 755         list *l;
 756         definition *def;
 757         version_list *vp;
 758 
 759         for (l = defined; l != NULL; l = l->next) {
 760                 def = (definition *)l->val;
 761                 if (def->def_kind == DEF_PROGRAM) {
 762                         for (vp = def->def.pr.versions; vp != NULL;
 763                             vp = vp->next) {
 764                                 f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
 765                                     space, def->def_name, vp->vers_name);
 766                         }
 767                 }
 768         }
 769 }
 770 
 771 static void
 772 print_err_message(const char *space, const char *fmt, ...)
 773 {
 774         char errbuf[ERRBUFLEN];
 775         va_list va;
 776 
 777         va_start(va, fmt);
 778         (void) vsnprintf(errbuf, sizeof (errbuf), fmt, va);
 779         va_end(va);
 780 
 781         if (logflag)
 782                 f_print(fout, "%ssyslog(LOG_ERR, \"%%s\",\n", space);
 783         else if (inetdflag || pmflag)
 784                 f_print(fout, "%sRPC_MSGOUT(\"%%s\",\n", space);
 785         else
 786                 f_print(fout, "%sfprintf(stderr, \"%%s\",\n", space);
 787         f_print(fout, "%s    \"%s\");\n", space, errbuf);
 788 }
 789 
 790 /*
 791  * Write the server auxiliary function (RPC_MSGOUT, timeout)
 792  */
 793 static void
 794 write_svc_aux(int nomain)
 795 {
 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 {
 883                         f_print(fout, "\t\t\tif (size == 0) {\n");
 884                         f_print(fout, "\t\t\t\tsize = getdtablesize();\n");
 885                         f_print(fout, "\t\t\t}\n");
 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");
 962         f_print(fout, "\t */\n");
 963         f_print(fout, "\tif (t_getstate(0) != -1 || t_errno != TBADF) {\n");
 964         f_print(fout, "\t\tchar *netid;\n");
 965         if (!netflag) { /* Not included by -n option */
 966                 f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
 967                 f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
 968         }
 969         if (timerflag)
 970                 f_print(fout, "\t\tint pmclose;\n");
 971 /*
 972  *  Not necessary, defined in /usr/include/stdlib
 973  *  f_print(fout, "\t\textern char *getenv();\n");
 974  */
 975         f_print(fout, "\n");
 976         f_print(fout, "\t\t_rpcpmstart = 1;\n");
 977         open_log_file(infile, "\t\t");
 978         f_print(fout,
 979 "\n\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
 980 
 981         if (timerflag) {
 982                 f_print(fout, "\t\t/* started from inetd */\n");
 983                 f_print(fout, "\t\t\tpmclose = 1;\n");
 984         }
 985         f_print(fout, "\t\t} else {\n");
 986         f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n");
 987         print_err_message("\t\t\t\t", "cannot get transport info");
 988         if (timerflag)
 989                 f_print(fout,
 990                     "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
 991         f_print(fout, "\t\t}\n");
 992         f_print(fout,
 993 "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
 994             TRANSP);
 995         print_err_message("\t\t\t", "cannot create server handle");
 996         f_print(fout, "\t\t\texit(1);\n");
 997         f_print(fout, "\t\t}\n");
 998         f_print(fout, "\t\tif (nconf)\n");
 999         f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
1000         for (l = defined; l != NULL; l = l->next) {
1001                 def = (definition *) l->val;
1002                 if (def->def_kind != DEF_PROGRAM) {
1003                         continue;
1004                 }
1005                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1006                         f_print(fout,
1007                             "\t\tif (!svc_reg(%s, %s, %s,\n",
1008                             TRANSP, def->def_name, vp->vers_name);
1009                         f_print(fout, "\t\t    ");
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);
1052         f_print(fout, "%sint size;\n", sp);
1053         if (tirpcflag)
1054                 f_print(fout, "%sstruct rlimit rl;\n", sp);
1055         if (inetdflag)
1056                 f_print(fout, "%sint pid, i;\n\n", sp);
1057         f_print(fout, "%spid = fork();\n", sp);
1058         f_print(fout, "%sif (pid < 0) {\n", sp);
1059         f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
1060         f_print(fout, "%s\texit(1);\n", sp);
1061         f_print(fout, "%s}\n", sp);
1062         f_print(fout, "%sif (pid)\n", sp);
1063         f_print(fout, "%s\texit(0);\n", sp);
1064         /* close all file descriptors */
1065         if (tirpcflag) {
1066                 f_print(fout, "%sif (closefrom != NULL)\n", sp);
1067                 f_print(fout, "%s\tclosefrom(0);\n", sp);
1068                 f_print(fout, "%selse {\n", sp);
1069                 f_print(fout, "%s\trl.rlim_max = 0;\n", sp);
1070                 f_print(fout, "%s\tgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
1071                 f_print(fout, "%s\tif ((size = rl.rlim_max) == 0)\n", sp);
1072                 f_print(fout, "%s\t\texit(1);\n", sp);
1073                 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
1074                 f_print(fout, "%s\t\t(void) close(i);\n", sp);
1075                 f_print(fout, "%s}\n", sp);
1076         } else {
1077                 f_print(fout, "%s\tsize = getdtablesize();\n", sp);
1078                 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
1079                 f_print(fout, "%s\t\t(void) close(i);\n", sp);
1080         }
1081         /* Redirect stderr and stdout to /dev/null */
1082         f_print(fout, "%si = open(\"/dev/null\", 2);\n", sp);
1083         f_print(fout, "%s(void) dup2(i, 1);\n", sp);
1084         f_print(fout, "%s(void) dup2(i, 2);\n", sp);
1085         /* This removes control of the controlling terminal */
1086         if (tirpcflag)
1087                 f_print(fout, "%ssetsid();\n", sp);
1088         else {
1089                 f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
1090                 f_print(fout, "%sif (i >= 0) {\n", sp);
1091                 f_print(fout,
1092                     "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
1093                 f_print(fout, "%s\t(void) close(i);\n", sp);
1094                 f_print(fout, "%s}\n", sp);
1095         }
1096         if (!logflag)
1097                 open_log_file(infile, sp);
1098         f_print(fout, "#endif\n");
1099         if (logflag)
1100                 open_log_file(infile, sp);
1101 }
1102 
1103 static void
1104 open_log_file(char *infile, char *sp)
1105 {
1106         char *s;
1107 
1108         s = strrchr(infile, '.');
1109         if (s)
1110                 *s = '\0';
1111         f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
1112         if (s)
1113                 *s = '.';
1114 }
1115 
1116 /*
1117  * write a registration for the given transport for Inetd
1118  */
1119 void
1120 write_inetd_register(char *transp)
1121 {
1122         list *l;
1123         definition *def;
1124         version_list *vp;
1125         char *sp;
1126         int isudp;
1127         char tmpbuf[32];
1128 
1129         if (inetdflag)
1130                 sp = "\t";
1131         else
1132                 sp = "";
1133         if (streq(transp, "udp"))
1134                 isudp = 1;
1135         else
1136                 isudp = 0;
1137         f_print(fout, "\n");
1138         if (inetdflag) {
1139                 f_print(fout,
1140                     "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
1141                     isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
1142         }
1143         f_print(fout, "%s\t%s = svc%s_create(%s",
1144             sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
1145         if (!isudp)
1146                 f_print(fout, ", 0, 0");
1147         f_print(fout, ");\n");
1148         f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
1149         (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
1150         print_err_message(tmpbuf, "cannot create %s service.", transp);
1151         f_print(fout, "%s\t\texit(1);\n", sp);
1152         f_print(fout, "%s\t}\n", sp);
1153 
1154         if (inetdflag) {
1155                 f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
1156                 f_print(fout, "%s\tproto = IPPROTO_%s;\n",
1157                     sp, isudp ? "UDP": "TCP");
1158         }
1159         for (l = defined; l != NULL; l = l->next) {
1160                 def = (definition *) l->val;
1161                 if (def->def_kind != DEF_PROGRAM)
1162                         continue;
1163                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1164                         f_print(fout, "%s\tif (!svc_register(%s, %s, %s,\n",
1165                             sp, TRANSP, def->def_name, vp->vers_name);
1166                         f_print(fout, "%s\t    ", sp);
1167                         pvname(def->def_name, vp->vers_num);
1168                         if (inetdflag)
1169                                 f_print(fout, ", proto)) {\n");
1170                         else
1171                                 f_print(fout, ", IPPROTO_%s)) {\n",
1172                                     isudp ? "UDP": "TCP");
1173                         print_err_message(tmpbuf,
1174                             "unable to register (%s, %s, %s).",
1175                             def->def_name, vp->vers_name, transp);
1176                         f_print(fout, "%s\t\texit(1);\n", sp);
1177                         f_print(fout, "%s\t}\n", sp);
1178                 }
1179         }
1180         if (inetdflag)
1181                 f_print(fout, "\t}\n");
1182 }