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