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