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