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