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