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