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