xref: /illumos-gate/usr/src/cmd/rpcgen/rpc_svcout.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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, "%smutex_t _svcstate_lock;",
140 				    nomain? "extern " : "");
141 				f_print(fout,
142 "\t\t/* lock for _rpcsvcstate, _rpcsvccount */\n");
143 
144 			}
145 		}
146 
147 		write_svc_aux(nomain);
148 	}
149 	/* write out dispatcher and stubs */
150 	write_programs(nomain ? NULL : "static");
151 
152 	if (nomain)
153 		return;
154 
155 	f_print(fout, "\nint\nmain()\n");
156 	f_print(fout, "{\n");
157 	if (inetdflag) {
158 		write_inetmost(infile);
159 		/* Includes call to write_rpc_svc_fg() */
160 	} else {
161 		if (tirpcflag) {
162 			if (netflag) {
163 				f_print(fout,
164 				    "\tregister SVCXPRT *%s;\n", TRANSP);
165 				f_print(fout,
166 				    "\tstruct netconfig *nconf = NULL;\n");
167 			}
168 			f_print(fout, "\tpid_t pid;\n");
169 			f_print(fout, "\tint i;\n");
170 			if (mtauto) {
171 				f_print(fout,
172 				    "\tint mode = RPC_SVC_MT_AUTO;\n\n");
173 				write_mtauto();
174 			} else
175 				f_print(fout, "\n");
176 
177 			if (mtflag & timerflag)
178 				f_print(fout,
179 "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n");
180 
181 			write_pm_most(infile, netflag);
182 			f_print(fout, "\telse {\n");
183 			write_rpc_svc_fg(infile, "\t\t");
184 			f_print(fout, "\t}\n");
185 		} else {
186 			f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
187 			f_print(fout, "\n");
188 			print_pmapunset("\t");
189 		}
190 	}
191 
192 	if (logflag && !inetdflag) {
193 		open_log_file(infile, "\t");
194 	}
195 }
196 
197 /*
198  * write a registration for the given transport
199  */
200 void
201 write_netid_register(char *transp)
202 {
203 	list *l;
204 	definition *def;
205 	version_list *vp;
206 	char *sp;
207 	char tmpbuf[32];
208 
209 	sp = "";
210 	f_print(fout, "\n");
211 	f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
212 	f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
213 	(void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
214 	print_err_message(tmpbuf, "cannot find %s netid.", transp);
215 	f_print(fout, "%s\t\texit(1);\n", sp);
216 	f_print(fout, "%s\t}\n", sp);
217 	f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
218 	    sp, TRANSP);
219 	f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
220 	print_err_message(tmpbuf, "cannot create %s service.", transp);
221 	f_print(fout, "%s\t\texit(1);\n", sp);
222 	f_print(fout, "%s\t}\n", sp);
223 
224 	for (l = defined; l != NULL; l = l->next) {
225 		def = (definition *) l->val;
226 		if (def->def_kind != DEF_PROGRAM) {
227 			continue;
228 		}
229 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
230 			f_print(fout,
231 			    "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
232 			    sp, def->def_name, vp->vers_name);
233 			f_print(fout,
234 			    "%s\tif (!svc_reg(%s, %s, %s, ",
235 			    sp, TRANSP, def->def_name, vp->vers_name);
236 			pvname(def->def_name, vp->vers_num);
237 			f_print(fout, ", nconf)) {\n");
238 			print_err_message(tmpbuf,
239 			    "unable to register (%s, %s, %s).",
240 			    def->def_name, vp->vers_name, transp);
241 			f_print(fout, "%s\t\texit(1);\n", sp);
242 			f_print(fout, "%s\t}\n", sp);
243 		}
244 	}
245 	f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
246 }
247 
248 /*
249  * write a registration for the given transport for TLI
250  */
251 void
252 write_nettype_register(char *transp)
253 {
254 	list *l;
255 	definition *def;
256 	version_list *vp;
257 
258 	for (l = defined; l != NULL; l = l->next) {
259 		def = (definition *) l->val;
260 		if (def->def_kind != DEF_PROGRAM) {
261 			continue;
262 		}
263 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
264 			f_print(fout, "\tif (!svc_create(\n");
265 			f_print(fout, "\t    ");
266 			pvname(def->def_name, vp->vers_num);
267 			f_print(fout, ", %s, %s,\n",
268 			    def->def_name, vp->vers_name);
269 			f_print(fout, "\t    \"%s\")) {\n", transp);
270 			print_err_message("\t\t",
271 			    "unable to create (%s, %s) for %s.",
272 			    def->def_name, vp->vers_name, transp);
273 			f_print(fout, "\t\texit(1);\n");
274 			f_print(fout, "\t}\n");
275 		}
276 	}
277 }
278 
279 /*
280  * write the rest of the service
281  */
282 void
283 write_rest(void)
284 {
285 	f_print(fout, "\n");
286 	if (inetdflag) {
287 		f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
288 		print_err_message("\t\t", "could not create a handle");
289 		f_print(fout, "\t\texit(1);\n");
290 		f_print(fout, "\t}\n");
291 		if (timerflag) {
292 			f_print(fout, "\tif (_rpcpmstart) {\n");
293 			if (mtflag) {
294 				f_print(fout,
295 "\t\tif (thr_create(NULL, 0, closedown, NULL, 0, NULL) != 0) {\n");
296 				print_err_message("\t\t\t",
297 				    "cannot create closedown thread");
298 				f_print(fout, "\t\t\texit(1);\n");
299 				f_print(fout, "\t\t}\n");
300 				f_print(fout, "\t}\n");
301 			} else {
302 				f_print(fout,
303 				"\t\t(void) signal(SIGALRM, %s closedown);\n",
304 				    Cflag? "(SIG_PF)":"(void(*)())");
305 				f_print(fout,
306 "\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
307 				f_print(fout, "\t}\n");
308 			}
309 		}
310 	}
311 	f_print(fout, "\tsvc_run();\n");
312 	print_err_message("\t", "svc_run returned");
313 	f_print(fout, "\texit(1);\n");
314 	f_print(fout, "\t/* NOTREACHED */\n");
315 	f_print(fout, "}\n");
316 }
317 
318 static void
319 write_programs(char *storage)
320 {
321 	list *l;
322 	definition *def;
323 
324 	/* write out stubs for procedure  definitions */
325 	for (l = defined; l != NULL; l = l->next) {
326 		def = (definition *) l->val;
327 		if (def->def_kind == DEF_PROGRAM)
328 			write_real_program(def);
329 	}
330 
331 	/* write out dispatcher for each program */
332 	for (l = defined; l != NULL; l = l->next) {
333 		def = (definition *) l->val;
334 		if (def->def_kind == DEF_PROGRAM)
335 			write_program(def, storage);
336 	}
337 
338 
339 }
340 
341 /*
342  * write out definition of internal function (e.g. _printmsg_1(...))
343  *  which calls server's defintion of actual function (e.g. printmsg_1(...)).
344  *  Unpacks single user argument of printmsg_1 to call-by-value format
345  *  expected by printmsg_1.
346  */
347 static void
348 write_real_program(definition *def)
349 {
350 	version_list *vp;
351 	proc_list *proc;
352 	decl_list *l;
353 
354 	if (!newstyle)
355 		return;  /* not needed for old style */
356 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
357 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
358 			int oneway = streq(proc->res_type, "oneway");
359 
360 			f_print(fout, "\n");
361 			if (proc->arg_num < 2 &&
362 			    streq(proc->args.decls->decl.type, "void")) {
363 				f_print(fout, "/* ARGSUSED */\n");
364 			}
365 			if (!mtflag)
366 				internal_proctype(proc);
367 			else
368 				f_print(fout, "int");
369 			f_print(fout, "\n_");
370 			pvname(proc->proc_name, vp->vers_num);
371 			if (Cflag) {
372 				f_print(fout, "(\n");
373 				f_print(fout, "    ");
374 				/* arg name */
375 				if (proc->arg_num > 1)
376 					/* LINTED variable format */
377 					f_print(fout, proc->args.argname);
378 				else
379 					ptype(proc->args.decls->decl.prefix,
380 					    proc->args.decls->decl.type, 0);
381 				f_print(fout, " *argp,\n");
382 				if (mtflag) {
383 					f_print(fout, "    ");
384 					ptype(proc->res_prefix,
385 					    proc->res_type, 1);
386 					f_print(fout, "*%s,\n", RESULT);
387 				}
388 				f_print(fout, "    struct svc_req *%s)\n",
389 				    RQSTP);
390 
391 			} else {
392 				if (mtflag)
393 					f_print(fout, "(argp, %s, %s)\n",
394 					    RESULT, RQSTP);
395 				else
396 					f_print(fout, "(argp, %s)\n", RQSTP);
397 				/* arg name */
398 				if (proc->arg_num > 1)
399 					f_print(fout, "\t%s *argp;\n",
400 					    proc->args.argname);
401 				else {
402 					f_print(fout, "\t");
403 					ptype(proc->args.decls->decl.prefix,
404 					    proc->args.decls->decl.type, 0);
405 					f_print(fout, " *argp;\n");
406 				}
407 				if (mtflag)
408 					f_print(fout, "\tvoid *%s;\n", RESULT);
409 				f_print(fout, "\tstruct svc_req *%s;\n", RQSTP);
410 			}
411 
412 			f_print(fout, "{\n");
413 			f_print(fout, "\treturn (");
414 			/* for mtflag, arguments are different */
415 			if (Cflag || mtflag)
416 				pvname_svc(proc->proc_name, vp->vers_num);
417 			else
418 				pvname(proc->proc_name, vp->vers_num);
419 			f_print(fout, "(");
420 			if (proc->arg_num < 2) { /* single argument */
421 				/* only print if non-void */
422 				if (!streq(proc->args.decls->decl.type, "void"))
423 					f_print(fout, "*argp, ");
424 			} else {
425 				f_print(fout, "\n");
426 				for (l = proc->args.decls;  l != NULL;
427 				    l = l->next)
428 					f_print(fout, "\t    argp->%s,\n",
429 					    l->decl.name);
430 				f_print(fout, "\t    ");
431 			}
432 			if (mtflag && !oneway)
433 				f_print(fout, "%s, ", RESULT);
434 			f_print(fout, "%s));\n}\n", RQSTP);
435 		}
436 	}
437 }
438 
439 static void
440 write_program(definition *def, char *storage)
441 {
442 	version_list *vp;
443 	proc_list *proc;
444 	int filled;
445 
446 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
447 		f_print(fout, "\n");
448 		if (storage != NULL) {
449 			f_print(fout, "%s ", storage);
450 		}
451 		f_print(fout, "void\n");
452 		pvname(def->def_name, vp->vers_num);
453 
454 		if (Cflag) {
455 			f_print(fout, "(struct svc_req *%s, ", RQSTP);
456 			f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
457 		} else {
458 			f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
459 			f_print(fout, "	struct svc_req *%s;\n", RQSTP);
460 			f_print(fout, "	register SVCXPRT *%s;\n", TRANSP);
461 		}
462 
463 		f_print(fout, "{\n");
464 
465 		filled = 0;
466 		f_print(fout, "\tunion {\n");
467 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
468 			if (proc->arg_num < 2) { /* single argument */
469 				if (streq(proc->args.decls->decl.type,
470 				    "void")) {
471 					continue;
472 				}
473 				filled = 1;
474 				f_print(fout, "\t\t");
475 				ptype(proc->args.decls->decl.prefix,
476 				    proc->args.decls->decl.type, 0);
477 				pvname(proc->proc_name, vp->vers_num);
478 				f_print(fout, "_arg;\n");
479 
480 			} else {
481 				filled = 1;
482 				f_print(fout, "\t\t%s", proc->args.argname);
483 				f_print(fout, " ");
484 				pvname(proc->proc_name, vp->vers_num);
485 				f_print(fout, "_arg;\n");
486 			}
487 		}
488 		if (!filled) {
489 			f_print(fout, "\t\tint fill;\n");
490 		}
491 		f_print(fout, "\t} %s;\n", ARG);
492 
493 		if (mtflag) {
494 			filled = 0;
495 			f_print(fout, "\tunion {\n");
496 			for (proc = vp->procs; proc != NULL;
497 			    proc = proc->next) {
498 				if (streq(proc->res_type, "void") ||
499 				    streq(proc->res_type, "oneway"))
500 					continue;
501 				filled = 1;
502 				f_print(fout, "\t\t");
503 				ptype(proc->res_prefix, proc->res_type, 0);
504 				pvname(proc->proc_name, vp->vers_num);
505 				f_print(fout, "_res;\n");
506 			}
507 			if (!filled)
508 				f_print(fout, "\t\tint fill;\n");
509 			f_print(fout, "\t} %s;\n", RESULT);
510 			f_print(fout, "\tbool_t %s;\n", RETVAL);
511 
512 		} else
513 			f_print(fout, "\tchar *%s;\n", RESULT);
514 
515 		if (Cflag) {
516 			f_print(fout, "\txdrproc_t _xdr_%s, _xdr_%s;\n",
517 			    ARG, RESULT);
518 			if (mtflag)
519 				f_print(fout,
520 "\tbool_t (*%s)(char *, void *, struct svc_req *);\n",
521 				    ROUTINE);
522 			else
523 				f_print(fout,
524 "\tchar *(*%s)(char *, struct svc_req *);\n",
525 				    ROUTINE);
526 		} else {
527 			f_print(fout,
528 			    "\tbool_t (*_xdr_%s)(), (*_xdr_%s)();\n",
529 			    ARG, RESULT);
530 			if (mtflag)
531 				f_print(fout, "\tbool_t (*%s)();\n", ROUTINE);
532 			else
533 				f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
534 		}
535 		f_print(fout, "\n");
536 
537 		if (timerflag) {
538 			if (mtflag)
539 				f_print(fout,
540 "\t(void) mutex_lock(&_svcstate_lock);\n");
541 
542 			f_print(fout, "\t_rpcsvccount++;\n");
543 			if (mtflag)
544 				f_print(fout,
545 "\t(void) mutex_unlock(&_svcstate_lock);\n");
546 		}
547 
548 		f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
549 		if (!nullproc(vp->procs)) {
550 			f_print(fout, "\tcase NULLPROC:\n");
551 			f_print(fout,
552 			    Cflag ?
553 "\t\t(void) svc_sendreply(%s,\n\t\t    (xdrproc_t)xdr_void, NULL);\n" :
554 "\t\t(void) svc_sendreply(%s, xdr_void,\n\t\t\tNULL);\n",
555 			    TRANSP);
556 			print_return("\t\t");
557 			f_print(fout, "\n");
558 		}
559 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
560 			f_print(fout, "\tcase %s:\n", proc->proc_name);
561 			if (proc->arg_num < 2) { /* single argument */
562 				p_xdrfunc(ARG, proc->args.decls->decl.type);
563 			} else {
564 				p_xdrfunc(ARG, proc->args.argname);
565 			}
566 
567 			if (streq(proc->res_type, "oneway")) {
568 				/* One-way call */
569 				f_print(fout, "\t\t_xdr_%s = NULL;\n", RESULT);
570 			} else {
571 				p_xdrfunc(RESULT, proc->res_type);
572 			}
573 			if (Cflag) {
574 				if (mtflag) {
575 					f_print(fout,
576 					    "\t\t%s = (bool_t (*) (char *,  "
577 					    "void *,  struct svc_req *))",
578 					    ROUTINE);
579 				} else {
580 					f_print(fout,
581 					    "\t\t%s = (char *(*)(char *, "
582 					    "struct svc_req *))",
583 					    ROUTINE);
584 				}
585 			} else {
586 				if (mtflag) {
587 					f_print(fout,
588 					    "\t\t%s = (bool_t (*)())",
589 					    ROUTINE);
590 				} else {
591 					f_print(fout, "\t\t%s = (char *(*)())",
592 					    ROUTINE);
593 				}
594 			}
595 
596 			f_print(fout, "\n\t\t    ");
597 			if (newstyle) { /* new style: calls internal routine */
598 				f_print(fout, "_");
599 			}
600 			if ((Cflag || mtflag) && !newstyle)
601 				pvname_svc(proc->proc_name, vp->vers_num);
602 			else
603 				pvname(proc->proc_name, vp->vers_num);
604 			f_print(fout, ";\n");
605 			f_print(fout, "\t\tbreak;\n\n");
606 		}
607 		f_print(fout, "\tdefault:\n");
608 		printerr("noproc", TRANSP);
609 		print_return("\t\t");
610 		f_print(fout, "\t}\n");
611 
612 		f_print(fout,
613 		    "\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
614 		    ARG, ARG);
615 		printif("getargs", TRANSP, "(caddr_t)&", ARG);
616 		printerr("decode", TRANSP);
617 		print_return("\t\t");
618 		f_print(fout, "\t}\n");
619 
620 		if (!mtflag)
621 			if (Cflag)
622 				f_print(fout,
623 				    "\t%s = (*%s)((char *)&%s, %s);\n",
624 				    RESULT, ROUTINE, ARG, RQSTP);
625 			else
626 				f_print(fout, "\t%s = (*%s)(&%s, %s);\n",
627 				    RESULT, ROUTINE, ARG, RQSTP);
628 		else
629 			if (Cflag)
630 				f_print(fout,
631 "\t%s = (bool_t)(*%s)((char *)&%s, (void *)&%s, %s);\n",
632 				    RETVAL, ROUTINE, ARG, RESULT, RQSTP);
633 			else
634 				f_print(fout,
635 "\t%s = (bool_t)(*%s)(&%s, &%s, %s);\n",
636 				    RETVAL, ROUTINE, ARG, RESULT, RQSTP);
637 
638 
639 
640 
641 		if (mtflag)
642 			f_print(fout,
643 "\tif (_xdr_%s && %s > 0 &&\n"
644 "\t    !svc_sendreply(%s, _xdr_%s, (char *)&%s)) {\n",
645 			    RESULT, RETVAL, TRANSP, RESULT, RESULT);
646 		else
647 			f_print(fout,
648 "\tif (_xdr_%s && %s != NULL &&\n"
649 "\t    !svc_sendreply(%s, _xdr_%s, %s)) {\n",
650 			    RESULT, RESULT, TRANSP, RESULT, RESULT);
651 
652 		printerr("systemerr", TRANSP);
653 		f_print(fout, "\t}\n");
654 
655 		printif("freeargs", TRANSP, "(caddr_t)&", ARG);
656 		print_err_message("\t\t", "unable to free arguments");
657 		f_print(fout, "\t\texit(1);\n");
658 		f_print(fout, "\t}\n");
659 		/* print out free routine */
660 		if (mtflag) {
661 			f_print(fout, "\tif (_xdr_%s != NULL) {\n", RESULT);
662 			f_print(fout, "\t\tif (!");
663 
664 			pvname(def->def_name, vp->vers_num);
665 			f_print(fout, "_freeresult(%s, _xdr_%s,\n",
666 			    TRANSP, RESULT);
667 			f_print(fout, "\t\t    (caddr_t)&%s))\n",
668 			    RESULT);
669 			print_err_message("\t\t\t", "unable to free results");
670 			f_print(fout, "\n");
671 			f_print(fout, "\t}\n");
672 		};
673 		print_return("\t");
674 		f_print(fout, "}\n");
675 	}
676 }
677 
678 static void
679 printerr(char *err, char *transp)
680 {
681 	f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
682 }
683 
684 static void
685 printif(char *proc, char *transp, char *prefix, char *arg)
686 {
687 	f_print(fout, "\tif (!svc_%s(%s, _xdr_%s, %s%s)) {\n",
688 	    proc, transp, arg, prefix, arg);
689 }
690 
691 int
692 nullproc(proc_list *proc)
693 {
694 	for (; proc != NULL; proc = proc->next) {
695 		if (streq(proc->proc_num, "0"))
696 			return (1);
697 	}
698 	return (0);
699 }
700 
701 static void
702 write_inetmost(char *infile)
703 {
704 	f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
705 	f_print(fout, "\tint sock;\n");
706 	f_print(fout, "\tint proto;\n");
707 	f_print(fout, "\tstruct sockaddr_in saddr;\n");
708 	f_print(fout, "\tint asize = sizeof (saddr);\n");
709 	f_print(fout, "\n");
710 	f_print(fout,
711 	"\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
712 	f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
713 	f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
714 	f_print(fout, "\t\t\texit(1);\n");
715 	f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
716 	f_print(fout, "\t\t    (char *)&_rpcfdtype, &ssize) == -1)\n");
717 	f_print(fout, "\t\t\texit(1);\n");
718 	f_print(fout, "\t\tsock = 0;\n");
719 	f_print(fout, "\t\t_rpcpmstart = 1;\n");
720 	f_print(fout, "\t\tproto = 0;\n");
721 	open_log_file(infile, "\t\t");
722 	f_print(fout, "\t} else {\n");
723 	write_rpc_svc_fg(infile, "\t\t");
724 	f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
725 	print_pmapunset("\t\t");
726 	f_print(fout, "\t}\n");
727 }
728 
729 static void
730 print_return(char *space)
731 {
732 	if (exitnow) {
733 		f_print(fout, "%sexit(0);\n", space);
734 		return;
735 	}
736 	if (timerflag) {
737 		if (mtflag) {
738 			f_print(fout,
739 			    "%s(void) mutex_lock(&_svcstate_lock);\n",
740 			    space);
741 		}
742 		f_print(fout, "%s_rpcsvccount--;\n", space);
743 		f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space);
744 		if (mtflag) {
745 			f_print(fout,
746 			    "%s(void) mutex_unlock(&_svcstate_lock);\n",
747 			    space);
748 		}
749 	}
750 	f_print(fout, "%sreturn; /* CSTYLED */\n", space);
751 }
752 
753 static void
754 print_pmapunset(char *space)
755 {
756 	list *l;
757 	definition *def;
758 	version_list *vp;
759 
760 	for (l = defined; l != NULL; l = l->next) {
761 		def = (definition *)l->val;
762 		if (def->def_kind == DEF_PROGRAM) {
763 			for (vp = def->def.pr.versions; vp != NULL;
764 			    vp = vp->next) {
765 				f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
766 				    space, def->def_name, vp->vers_name);
767 			}
768 		}
769 	}
770 }
771 
772 static void
773 print_err_message(const char *space, const char *fmt, ...)
774 {
775 	char errbuf[ERRBUFLEN];
776 	va_list va;
777 
778 	va_start(va, fmt);
779 	(void) vsnprintf(errbuf, sizeof (errbuf), fmt, va);
780 	va_end(va);
781 
782 	if (logflag)
783 		f_print(fout, "%ssyslog(LOG_ERR, \"%%s\",\n", space);
784 	else if (inetdflag || pmflag)
785 		f_print(fout, "%sRPC_MSGOUT(\"%%s\",\n", space);
786 	else
787 		f_print(fout, "%sfprintf(stderr, \"%%s\",\n", space);
788 	f_print(fout, "%s    \"%s\");\n", space, errbuf);
789 }
790 
791 /*
792  * Write the server auxiliary function (RPC_MSGOUT, timeout)
793  */
794 static void
795 write_svc_aux(int nomain)
796 {
797 	if (!logflag)
798 		write_msg_out();
799 	if (!nomain)
800 		write_timeout_func();
801 }
802 
803 /*
804  * Write the RPC_MSGOUT function
805  *
806  * Note that while we define RPC_MSGOUT to be printf-like, all existing
807  * calls are of the form "%s","<msg>" and this implementation assumes that
808  * trivial case.  If in the future it's desirable to generate richer calls
809  * this implementation can change to match.  This way we don't (yet) have
810  * to introduce varargs into the generated code.
811  */
812 static void
813 write_msg_out(void)
814 {
815 	f_print(fout, "\n");
816 	f_print(fout, "#if\tdefined(RPC_MSGOUT)\n");
817 	if (!Cflag) {
818 		f_print(fout, "extern void RPC_MSGOUT();\n");
819 	} else {
820 		f_print(fout, "extern void RPC_MSGOUT(const char *, ...);\n");
821 	}
822 	f_print(fout, "#else\t/* defined(RPC_MSGOUT) */\n");
823 	f_print(fout, "static ");
824 	if (!Cflag) {
825 		f_print(fout, "void\nRPC_MSGOUT(fmt, msg)\n");
826 		f_print(fout, "\tchar *fmt;\n");
827 		f_print(fout, "\tchar *msg;\n");
828 	} else {
829 		f_print(fout, "void\nRPC_MSGOUT(const char *fmt, char *msg)\n");
830 	}
831 	f_print(fout, "{\n");
832 	f_print(fout, "#ifdef RPC_SVC_FG\n");
833 	if (inetdflag || pmflag)
834 		f_print(fout, "\tif (_rpcpmstart)\n");
835 	f_print(fout, "\t\tsyslog(LOG_ERR, fmt, msg);\n");
836 	f_print(fout, "\telse {\n");
837 	f_print(fout, "\t\t(void) fprintf(stderr, fmt, msg);\n");
838 	f_print(fout, "\t\t(void) putc('\\n', stderr);\n");
839 	f_print(fout, "\t}\n");
840 	f_print(fout, "#else\n");
841 	f_print(fout, "\tsyslog(LOG_ERR, fmt, msg);\n");
842 	f_print(fout, "#endif\n");
843 	f_print(fout, "}\n");
844 	f_print(fout, "#endif\t/* defined(RPC_MSGOUT) */\n");
845 }
846 
847 /*
848  * Write the timeout function
849  */
850 static void
851 write_timeout_func(void)
852 {
853 	if (!timerflag)
854 		return;
855 
856 	f_print(fout, "\n");
857 	if (mtflag) {
858 		f_print(fout, "/*ARGSUSED*/\n");
859 		f_print(fout, "static void *\n");
860 		if (!Cflag) {
861 			f_print(fout, "closedown(arg)\n");
862 			f_print(fout, "\tvoid *arg;\n");
863 		} else
864 			f_print(fout, "closedown(void *arg)\n");
865 		f_print(fout, "{\n");
866 		f_print(fout, "\t/*CONSTCOND*/\n");
867 		f_print(fout, "\twhile (1) {\n");
868 		f_print(fout, "\t\t(void) sleep(_RPCSVC_CLOSEDOWN/2);\n\n");
869 		f_print(fout,
870 "\t\tif (mutex_trylock(&_svcstate_lock) != 0)\n");
871 		f_print(fout, "\t\t\tcontinue;\n\n");
872 		f_print(fout,
873 "\t\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
874 		if (tirpcflag) {
875 			f_print(fout, "\t\t\tint size;\n");
876 		} else {
877 			f_print(fout, "\t\t\textern fd_set svc_fdset;\n");
878 			f_print(fout, "\t\t\tstatic int size;\n");
879 		}
880 		f_print(fout, "\t\t\tint i, openfd = 0;\n\n");
881 		if (tirpcflag) {
882 			f_print(fout, "\t\t\tsize = svc_max_pollfd;\n");
883 		} else {
884 			f_print(fout, "\t\t\tif (size == 0) {\n");
885 			f_print(fout, "\t\t\t\tsize = getdtablesize();\n");
886 			f_print(fout, "\t\t\t}\n");
887 		}
888 		f_print(fout,
889 "\t\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
890 		if (tirpcflag) {
891 			f_print(fout, "\t\t\t\tif (svc_pollfd[i].fd >= 0)\n");
892 		} else {
893 			f_print(fout, "\t\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
894 		}
895 		f_print(fout, "\t\t\t\t\topenfd++;\n");
896 		f_print(fout, "\t\t\tif (openfd <= 1)\n");
897 		f_print(fout, "\t\t\t\texit(0);\n");
898 		f_print(fout, "\t\t} else\n");
899 		f_print(fout, "\t\t\t_rpcsvcstate = _IDLE;\n\n");
900 		f_print(fout, "\t\t(void) mutex_unlock(&_svcstate_lock);\n");
901 		f_print(fout, "\t}\n");
902 		f_print(fout, "}\n");
903 		return;
904 	}
905 
906 	f_print(fout, "static void\n");
907 	if (!Cflag) {
908 		f_print(fout, "closedown(sig)\n");
909 		f_print(fout, "\tint sig;\n");
910 	} else
911 		f_print(fout, "closedown(int sig)\n");
912 	f_print(fout, "{\n");
913 	f_print(fout, "\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
914 	if (tirpcflag) {
915 		f_print(fout, "\t\tint size;\n");
916 	} else {
917 		f_print(fout, "\t\textern fd_set svc_fdset;\n");
918 		f_print(fout, "\t\tstatic int size;\n");
919 	}
920 	f_print(fout, "\t\tint i, openfd = 0;\n\n");
921 	if (tirpcflag) {
922 		f_print(fout, "\t\tsize = svc_max_pollfd;\n");
923 	} else {
924 		f_print(fout, "\t\tif (size == 0) {\n");
925 		f_print(fout, "\t\t\tsize = getdtablesize();\n");
926 		f_print(fout, "\t\t}\n");
927 	}
928 	f_print(fout,
929 	    "\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
930 	if (tirpcflag) {
931 		f_print(fout, "\t\t\tif (svc_pollfd[i].fd >= 0)\n");
932 	} else {
933 		f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
934 	}
935 	f_print(fout, "\t\t\t\topenfd++;\n");
936 	f_print(fout, "\t\tif (openfd <= 1)\n");
937 	f_print(fout, "\t\t\texit(0);\n");
938 	f_print(fout, "\t} else\n");
939 	f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n");
940 
941 	f_print(fout, "\t(void) signal(SIGALRM, %s closedown);\n",
942 	    Cflag? "(SIG_PF)" : "(void(*)())");
943 	f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
944 	f_print(fout, "}\n");
945 }
946 
947 /*
948  * Write the most of port monitor support
949  */
950 static void
951 write_pm_most(char *infile, int netflag)
952 {
953 	list *l;
954 	definition *def;
955 	version_list *vp;
956 
957 	f_print(fout, "\t(void) sigset(SIGPIPE, SIG_IGN);\n\n");
958 	f_print(fout, "\t/*\n");
959 	f_print(fout, "\t * If stdin looks like a TLI endpoint, we assume\n");
960 	f_print(fout, "\t * that we were started by a port monitor. If\n");
961 	f_print(fout, "\t * t_getstate fails with TBADF, this is not a\n");
962 	f_print(fout, "\t * TLI endpoint.\n");
963 	f_print(fout, "\t */\n");
964 	f_print(fout, "\tif (t_getstate(0) != -1 || t_errno != TBADF) {\n");
965 	f_print(fout, "\t\tchar *netid;\n");
966 	if (!netflag) {	/* Not included by -n option */
967 		f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
968 		f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
969 	}
970 	if (timerflag)
971 		f_print(fout, "\t\tint pmclose;\n");
972 /*
973  *  Not necessary, defined in /usr/include/stdlib
974  *  f_print(fout, "\t\textern char *getenv();\n");
975  */
976 	f_print(fout, "\n");
977 	f_print(fout, "\t\t_rpcpmstart = 1;\n");
978 	open_log_file(infile, "\t\t");
979 	f_print(fout,
980 "\n\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
981 
982 	if (timerflag) {
983 		f_print(fout, "\t\t/* started from inetd */\n");
984 		f_print(fout, "\t\t\tpmclose = 1;\n");
985 	}
986 	f_print(fout, "\t\t} else {\n");
987 	f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n");
988 	print_err_message("\t\t\t\t", "cannot get transport info");
989 	if (timerflag)
990 		f_print(fout,
991 		    "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
992 	f_print(fout, "\t\t}\n");
993 	f_print(fout,
994 "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
995 	    TRANSP);
996 	print_err_message("\t\t\t", "cannot create server handle");
997 	f_print(fout, "\t\t\texit(1);\n");
998 	f_print(fout, "\t\t}\n");
999 	f_print(fout, "\t\tif (nconf)\n");
1000 	f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
1001 	for (l = defined; l != NULL; l = l->next) {
1002 		def = (definition *) l->val;
1003 		if (def->def_kind != DEF_PROGRAM) {
1004 			continue;
1005 		}
1006 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1007 			f_print(fout,
1008 			    "\t\tif (!svc_reg(%s, %s, %s,\n",
1009 			    TRANSP, def->def_name, vp->vers_name);
1010 			f_print(fout, "\t\t    ");
1011 			pvname(def->def_name, vp->vers_num);
1012 			f_print(fout, ", 0)) {\n");
1013 			print_err_message("\t\t\t",
1014 			    "unable to register (%s, %s).",
1015 			    def->def_name, vp->vers_name);
1016 			f_print(fout, "\t\t\texit(1);\n");
1017 			f_print(fout, "\t\t}\n");
1018 		}
1019 	}
1020 	if (timerflag) {
1021 		f_print(fout, "\t\tif (pmclose) {\n");
1022 		if (mtflag) {
1023 			f_print(fout,
1024 "\t\t\tif (thr_create(NULL, 0, closedown, NULL,\n\t\t\t    0, NULL) != 0) {\n");
1025 			print_err_message("\t\t\t\t",
1026 			    "cannot create closedown thread");
1027 			f_print(fout, "\t\t\t\texit(1);\n");
1028 			f_print(fout, "\t\t\t}\n");
1029 		} else {
1030 			f_print(fout,
1031 "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
1032 			    Cflag? "(SIG_PF)" : "(void(*)())");
1033 			f_print(fout,
1034 "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
1035 		}
1036 		f_print(fout, "\t\t}\n");
1037 	}
1038 	f_print(fout, "\t\tsvc_run();\n");
1039 	f_print(fout, "\t\texit(1);\n");
1040 	f_print(fout, "\t\t/* NOTREACHED */\n");
1041 	f_print(fout, "\t}");
1042 }
1043 
1044 /*
1045  * Support for backgrounding the server if self started.
1046  */
1047 static void
1048 write_rpc_svc_fg(char *infile, char *sp)
1049 {
1050 	f_print(fout, "#ifndef RPC_SVC_FG\n");
1051 	f_print(fout, "#pragma weak closefrom\n");
1052 	f_print(fout, "%sextern void closefrom();\n", sp);
1053 	f_print(fout, "%sint size;\n", sp);
1054 	if (tirpcflag)
1055 		f_print(fout, "%sstruct rlimit rl;\n", sp);
1056 	if (inetdflag)
1057 		f_print(fout, "%sint pid, i;\n\n", sp);
1058 	f_print(fout, "%spid = fork();\n", sp);
1059 	f_print(fout, "%sif (pid < 0) {\n", sp);
1060 	f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
1061 	f_print(fout, "%s\texit(1);\n", sp);
1062 	f_print(fout, "%s}\n", sp);
1063 	f_print(fout, "%sif (pid)\n", sp);
1064 	f_print(fout, "%s\texit(0);\n", sp);
1065 	/* close all file descriptors */
1066 	if (tirpcflag) {
1067 		f_print(fout, "%sif (closefrom != NULL)\n", sp);
1068 		f_print(fout, "%s\tclosefrom(0);\n", sp);
1069 		f_print(fout, "%selse {\n", sp);
1070 		f_print(fout, "%s\trl.rlim_max = 0;\n", sp);
1071 		f_print(fout, "%s\tgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
1072 		f_print(fout, "%s\tif ((size = rl.rlim_max) == 0)\n", sp);
1073 		f_print(fout, "%s\t\texit(1);\n", sp);
1074 		f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
1075 		f_print(fout, "%s\t\t(void) close(i);\n", sp);
1076 		f_print(fout, "%s}\n", sp);
1077 	} else {
1078 		f_print(fout, "%s\tsize = getdtablesize();\n", sp);
1079 		f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
1080 		f_print(fout, "%s\t\t(void) close(i);\n", sp);
1081 	}
1082 	/* Redirect stderr and stdout to /dev/null */
1083 	f_print(fout, "%si = open(\"/dev/null\", 2);\n", sp);
1084 	f_print(fout, "%s(void) dup2(i, 1);\n", sp);
1085 	f_print(fout, "%s(void) dup2(i, 2);\n", sp);
1086 	/* This removes control of the controlling terminal */
1087 	if (tirpcflag)
1088 		f_print(fout, "%ssetsid();\n", sp);
1089 	else {
1090 		f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
1091 		f_print(fout, "%sif (i >= 0) {\n", sp);
1092 		f_print(fout,
1093 		    "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
1094 		f_print(fout, "%s\t(void) close(i);\n", sp);
1095 		f_print(fout, "%s}\n", sp);
1096 	}
1097 	if (!logflag)
1098 		open_log_file(infile, sp);
1099 	f_print(fout, "#endif\n");
1100 	if (logflag)
1101 		open_log_file(infile, sp);
1102 }
1103 
1104 static void
1105 open_log_file(char *infile, char *sp)
1106 {
1107 	char *s;
1108 
1109 	s = strrchr(infile, '.');
1110 	if (s)
1111 		*s = '\0';
1112 	f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
1113 	if (s)
1114 		*s = '.';
1115 }
1116 
1117 /*
1118  * write a registration for the given transport for Inetd
1119  */
1120 void
1121 write_inetd_register(char *transp)
1122 {
1123 	list *l;
1124 	definition *def;
1125 	version_list *vp;
1126 	char *sp;
1127 	int isudp;
1128 	char tmpbuf[32];
1129 
1130 	if (inetdflag)
1131 		sp = "\t";
1132 	else
1133 		sp = "";
1134 	if (streq(transp, "udp"))
1135 		isudp = 1;
1136 	else
1137 		isudp = 0;
1138 	f_print(fout, "\n");
1139 	if (inetdflag) {
1140 		f_print(fout,
1141 		    "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
1142 		    isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
1143 	}
1144 	f_print(fout, "%s\t%s = svc%s_create(%s",
1145 	    sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
1146 	if (!isudp)
1147 		f_print(fout, ", 0, 0");
1148 	f_print(fout, ");\n");
1149 	f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
1150 	(void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
1151 	print_err_message(tmpbuf, "cannot create %s service.", transp);
1152 	f_print(fout, "%s\t\texit(1);\n", sp);
1153 	f_print(fout, "%s\t}\n", sp);
1154 
1155 	if (inetdflag) {
1156 		f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
1157 		f_print(fout, "%s\tproto = IPPROTO_%s;\n",
1158 		    sp, isudp ? "UDP": "TCP");
1159 	}
1160 	for (l = defined; l != NULL; l = l->next) {
1161 		def = (definition *) l->val;
1162 		if (def->def_kind != DEF_PROGRAM)
1163 			continue;
1164 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1165 			f_print(fout, "%s\tif (!svc_register(%s, %s, %s,\n",
1166 			    sp, TRANSP, def->def_name, vp->vers_name);
1167 			f_print(fout, "%s\t    ", sp);
1168 			pvname(def->def_name, vp->vers_num);
1169 			if (inetdflag)
1170 				f_print(fout, ", proto)) {\n");
1171 			else
1172 				f_print(fout, ", IPPROTO_%s)) {\n",
1173 				    isudp ? "UDP": "TCP");
1174 			print_err_message(tmpbuf,
1175 			    "unable to register (%s, %s, %s).",
1176 			    def->def_name, vp->vers_name, transp);
1177 			f_print(fout, "%s\t\texit(1);\n", sp);
1178 			f_print(fout, "%s\t}\n", sp);
1179 		}
1180 	}
1181 	if (inetdflag)
1182 		f_print(fout, "\t}\n");
1183 }
1184