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