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