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