xref: /openbsd/usr.bin/rpcgen/rpc_svcout.c (revision f7e76a9c)
1 /*	$OpenBSD: rpc_svcout.c,v 1.29 2021/10/24 21:27:07 deraadt Exp $	*/
2 /*	$NetBSD: rpc_svcout.c,v 1.7 1995/06/24 14:59:59 pk Exp $	*/
3 
4 /*
5  * Copyright (c) 2010, Oracle America, Inc.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above
14  *       copyright notice, this list of conditions and the following
15  *       disclaimer in the documentation and/or other materials
16  *       provided with the distribution.
17  *     * Neither the name of the "Oracle America, Inc." nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
37  */
38 #include <stdio.h>
39 #include <string.h>
40 #include "rpc_parse.h"
41 #include "rpc_util.h"
42 
43 static char RQSTP[] = "rqstp";
44 static char TRANSP[] = "transp";
45 static char ARG[] = "argument";
46 static char RESULT[] = "result";
47 static char ROUTINE[] = "local";
48 
49 char _errbuf[256];	/* For all messages */
50 
51 void internal_proctype(proc_list *);
52 static void write_real_program(definition *);
53 static void write_program(definition *, char *);
54 static void printerr(char *, char *);
55 static void printif(char *, char *, char *, char *);
56 static void write_inetmost(char *);
57 static void print_return(char *);
58 static void print_pmapunset(char *);
59 static void print_err_message(char *);
60 static void write_timeout_func(void);
61 static void write_pm_most(char *, int);
62 static void write_caller_func(void);
63 static void write_rpc_svc_fg(char *, char *);
64 static void write_msg_out(void);
65 static void open_log_file(char *, char *);
66 
67 static void
p_xdrfunc(char * rname,char * typename)68 p_xdrfunc(char *rname, char *typename)
69 {
70 	if (Cflag)
71 		fprintf(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n",
72 		    rname, stringfix(typename));
73 	else
74 		fprintf(fout, "\t\txdr_%s = xdr_%s;\n", rname,
75 		    stringfix(typename));
76 }
77 
78 void
internal_proctype(plist)79 internal_proctype(plist)
80 	proc_list *plist;
81 {
82 	fprintf(fout, "static ");
83 	ptype(plist->res_prefix, plist->res_type, 1);
84 	fprintf(fout, "*");
85 }
86 
87 /*
88  * write most of the service, that is, everything but the registrations.
89  */
90 void
write_most(infile,netflag,nomain)91 write_most(infile, netflag, nomain)
92 	char *infile;		/* our name */
93 	int netflag;
94 	int nomain;
95 {
96 	if (inetdflag || pmflag) {
97 		char *var_type;
98 		var_type = (nomain? "extern" : "static");
99 		fprintf(fout, "%s int _rpcpmstart;", var_type);
100 		fprintf(fout, "\t\t/* Started by a port monitor ? */\n");
101 		fprintf(fout, "%s int _rpcfdtype;", var_type);
102 		fprintf(fout, "\t\t/* Whether Stream or Datagram ? */\n");
103 		if (timerflag) {
104 			fprintf(fout, "%s int _rpcsvcdirty;", var_type);
105 			fprintf(fout, "\t/* Still serving ? */\n");
106 		}
107 		write_svc_aux(nomain);
108 	}
109 	/* write out dispatcher and stubs */
110 	write_programs(nomain? (char *)NULL : "static");
111 
112 	if (nomain)
113 		return;
114 
115 	fprintf(fout, "\nmain()\n");
116 	fprintf(fout, "{\n");
117 	if (inetdflag) {
118 		write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */
119 	} else {
120 		if (tirpcflag) {
121 			if (netflag) {
122 				fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP);
123 				fprintf(fout, "\tstruct netconfig *nconf = NULL;\n");
124 			}
125 			fprintf(fout, "\tpid_t pid;\n");
126 			fprintf(fout, "\tint i;\n");
127 			fprintf(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
128 			write_pm_most(infile, netflag);
129 			fprintf(fout, "\telse {\n");
130 			write_rpc_svc_fg(infile, "\t\t");
131 			fprintf(fout, "\t}\n");
132 		} else {
133 			fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP);
134 			fprintf(fout, "\n");
135 			print_pmapunset("\t");
136 		}
137 	}
138 
139 	if (logflag && !inetdflag) {
140 		open_log_file(infile, "\t");
141 	}
142 }
143 
144 /*
145  * write a registration for the given transport
146  */
147 void
write_netid_register(transp)148 write_netid_register(transp)
149 	char *transp;
150 {
151 	list *l;
152 	definition *def;
153 	version_list *vp;
154 	char *sp;
155 	char tmpbuf[32];
156 
157 	sp = "";
158 	fprintf(fout, "\n");
159 	fprintf(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
160 	fprintf(fout, "%s\tif (nconf == NULL) {\n", sp);
161 	(void) snprintf(_errbuf, sizeof _errbuf, "cannot find %s netid.", transp);
162 	snprintf(tmpbuf, sizeof tmpbuf, "%s\t\t", sp);
163 	print_err_message(tmpbuf);
164 	fprintf(fout, "%s\t\texit(1);\n", sp);
165 	fprintf(fout, "%s\t}\n", sp);
166 	fprintf(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
167 	    sp, TRANSP);
168 	fprintf(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
169 	(void) snprintf(_errbuf, sizeof _errbuf, "cannot create %s service.", transp);
170 	print_err_message(tmpbuf);
171 	fprintf(fout, "%s\t\texit(1);\n", sp);
172 	fprintf(fout, "%s\t}\n", sp);
173 
174 	for (l = defined; l != NULL; l = l->next) {
175 		def = (definition *) l->val;
176 		if (def->def_kind != DEF_PROGRAM)
177 			continue;
178 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
179 			fprintf(fout,
180 			    "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
181 			    sp, def->def_name, vp->vers_name);
182 			fprintf(fout,
183 			    "%s\tif (!svc_reg(%s, %s, %s, ",
184 			    sp, TRANSP, def->def_name, vp->vers_name);
185 			pvname(def->def_name, vp->vers_num);
186 			fprintf(fout, ", nconf)) {\n");
187 			(void) snprintf(_errbuf, sizeof _errbuf,
188 			    "unable to register (%s, %s, %s).",
189 			    def->def_name, vp->vers_name, transp);
190 			print_err_message(tmpbuf);
191 			fprintf(fout, "%s\t\texit(1);\n", sp);
192 			fprintf(fout, "%s\t}\n", sp);
193 		}
194 	}
195 	fprintf(fout, "%s\tfreenetconfigent(nconf);\n", sp);
196 }
197 
198 /*
199  * write a registration for the given transport for TLI
200  */
201 void
write_nettype_register(transp)202 write_nettype_register(transp)
203 	char *transp;
204 {
205 	list *l;
206 	definition *def;
207 	version_list *vp;
208 
209 	for (l = defined; l != NULL; l = l->next) {
210 		def = (definition *) l->val;
211 		if (def->def_kind != DEF_PROGRAM)
212 			continue;
213 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
214 			fprintf(fout, "\tif (!svc_create(");
215 			pvname(def->def_name, vp->vers_num);
216 			fprintf(fout, ", %s, %s, \"%s\")) {\n",
217 			    def->def_name, vp->vers_name, transp);
218 			(void) snprintf(_errbuf, sizeof _errbuf,
219 			    "unable to create (%s, %s) for %s.",
220 			    def->def_name, vp->vers_name, transp);
221 			print_err_message("\t\t");
222 			fprintf(fout, "\t\texit(1);\n");
223 			fprintf(fout, "\t}\n");
224 		}
225 	}
226 }
227 
228 /*
229  * write the rest of the service
230  */
231 void
write_rest()232 write_rest()
233 {
234 	fprintf(fout, "\n");
235 	if (inetdflag) {
236 		fprintf(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
237 		(void) snprintf(_errbuf, sizeof _errbuf, "could not create a handle");
238 		print_err_message("\t\t");
239 		fprintf(fout, "\t\texit(1);\n");
240 		fprintf(fout, "\t}\n");
241 		if (timerflag) {
242 			fprintf(fout, "\tif (_rpcpmstart) {\n");
243 			fprintf(fout,
244 			    "\t\t(void) signal(SIGALRM, %s closedown);\n",
245 			    Cflag? "(SIG_PF)" : "(void(*)())");
246 			fprintf(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
247 			fprintf(fout, "\t}\n");
248 		}
249 	}
250 	fprintf(fout, "\tsvc_run();\n");
251 	(void) snprintf(_errbuf, sizeof _errbuf, "svc_run returned");
252 	print_err_message("\t");
253 	fprintf(fout, "\texit(1);\n");
254 	fprintf(fout, "\t/* NOTREACHED */\n");
255 	fprintf(fout, "}\n");
256 }
257 
258 void
write_programs(storage)259 write_programs(storage)
260 	char *storage;
261 {
262 	definition *def;
263 	list *l;
264 
265 	/* write out stubs for procedure  definitions */
266 	for (l = defined; l != NULL; l = l->next) {
267 		def = (definition *) l->val;
268 		if (def->def_kind == DEF_PROGRAM)
269 			write_real_program(def);
270 	}
271 
272 	/* write out dispatcher for each program */
273 	for (l = defined; l != NULL; l = l->next) {
274 		def = (definition *) l->val;
275 		if (def->def_kind == DEF_PROGRAM)
276 			write_program(def, storage);
277 	}
278 }
279 
280 /* write out definition of internal function (e.g. _printmsg_1(...))
281    which calls server's definition of actual function (e.g. printmsg_1(...)).
282    Unpacks single user argument of printmsg_1 to call-by-value format
283    expected by printmsg_1. */
284 static void
write_real_program(def)285 write_real_program(def)
286 	definition *def;
287 {
288 	version_list *vp;
289 	proc_list *proc;
290 	decl_list *l;
291 
292 	if (!newstyle) return;  /* not needed for old style */
293 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
294 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
295 			fprintf(fout, "\n");
296 			internal_proctype(proc);
297 			fprintf(fout, "\n_");
298 			pvname(proc->proc_name, vp->vers_num);
299 			if (Cflag) {
300 				fprintf(fout, "(");
301 				/* arg name */
302 				if (proc->arg_num > 1)
303 					fprintf(fout, "%s", proc->args.argname);
304 				else
305 					ptype(proc->args.decls->decl.prefix,
306 					    proc->args.decls->decl.type, 0);
307 				fprintf(fout, " *argp, struct svc_req *%s)\n",
308 				    RQSTP);
309 			} else {
310 				fprintf(fout, "(argp, %s)\n", RQSTP);
311 				/* arg name */
312 				if (proc->arg_num > 1)
313 					fprintf(fout, "\t%s *argp;\n",
314 					    proc->args.argname);
315 				else {
316 					fprintf(fout, "\t");
317 					ptype(proc->args.decls->decl.prefix,
318 					    proc->args.decls->decl.type, 0);
319 					fprintf(fout, " *argp;\n");
320 				}
321 				fprintf(fout, "	struct svc_req *%s;\n", RQSTP);
322 			}
323 
324 			fprintf(fout, "{\n");
325 			fprintf(fout, "\treturn(");
326 			pvname_svc(proc->proc_name, vp->vers_num);
327 			fprintf(fout, "(");
328 			if (proc->arg_num < 2) { /* single argument */
329 				if (!streq(proc->args.decls->decl.type, "void"))
330 					fprintf(fout, "*argp, ");  /* non-void */
331 			} else {
332 				for (l = proc->args.decls;  l != NULL; l = l->next)
333 					fprintf(fout, "argp->%s, ", l->decl.name);
334 			}
335 			fprintf(fout, "%s));\n}\n", RQSTP);
336 		}
337 	}
338 }
339 
340 static void
write_program(def,storage)341 write_program(def, storage)
342 	definition *def;
343 	char *storage;
344 {
345 	version_list *vp;
346 	proc_list *proc;
347 	int filled;
348 
349 	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
350 		fprintf(fout, "\n");
351 		if (storage != NULL)
352 			fprintf(fout, "%s ", storage);
353 		fprintf(fout, "void\t");
354 		pvname(def->def_name, vp->vers_num);
355 
356 		if (Cflag) {
357 			fprintf(fout, "(struct svc_req *%s, ", RQSTP);
358 			fprintf(fout, "SVCXPRT *%s);\n", TRANSP);
359 		} else {
360 			fprintf(fout, "();\n");
361 		}
362 		fprintf(fout, "\n");
363 
364 		if (storage != NULL)
365 			fprintf(fout, "%s ", storage);
366 		fprintf(fout, "void\n");
367 		pvname(def->def_name, vp->vers_num);
368 
369 		if (Cflag) {
370 			fprintf(fout, "(struct svc_req *%s, ", RQSTP);
371 			fprintf(fout, "SVCXPRT *%s)\n", TRANSP);
372 		} else {
373 			fprintf(fout, "(%s, %s)\n", RQSTP, TRANSP);
374 			fprintf(fout, "    struct svc_req *%s;\n", RQSTP);
375 			fprintf(fout, "    SVCXPRT *%s;\n", TRANSP);
376 		}
377 		fprintf(fout, "{\n");
378 
379 		filled = 0;
380 		fprintf(fout, "\tunion {\n");
381 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
382 			if (proc->arg_num < 2) { /* single argument */
383 				if (streq(proc->args.decls->decl.type,
384 				    "void"))
385 					continue;
386 				filled = 1;
387 				fprintf(fout, "\t\t");
388 				ptype(proc->args.decls->decl.prefix,
389 				    proc->args.decls->decl.type, 0);
390 				pvname(proc->proc_name, vp->vers_num);
391 				fprintf(fout, "_arg;\n");
392 
393 			} else {
394 				filled = 1;
395 				fprintf(fout, "\t\t%s", proc->args.argname);
396 				fprintf(fout, " ");
397 				pvname(proc->proc_name, vp->vers_num);
398 				fprintf(fout, "_arg;\n");
399 			}
400 		}
401 		if (!filled)
402 			fprintf(fout, "\t\tint fill;\n");
403 		fprintf(fout, "\t} %s;\n", ARG);
404 		fprintf(fout, "\tchar *%s;\n", RESULT);
405 
406 		if (Cflag) {
407 			fprintf(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
408 			fprintf(fout,
409 			    "\tchar *(*%s)(char *, struct svc_req *);\n",
410 			    ROUTINE);
411 		} else {
412 			fprintf(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n",
413 			    ARG, RESULT);
414 			fprintf(fout, "\tchar *(*%s)();\n", ROUTINE);
415 		}
416 		fprintf(fout, "\n");
417 
418 		if (callerflag)
419 			fprintf(fout, "\tcaller = transp;\n"); /*EVAS*/
420 		if (timerflag)
421 			fprintf(fout, "\t_rpcsvcdirty = 1;\n");
422 		fprintf(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
423 		if (!nullproc(vp->procs)) {
424 			fprintf(fout, "\tcase NULLPROC:\n");
425 			fprintf(fout,
426 			    Cflag
427 			    ? "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n"
428 			    : "\t\t(void) svc_sendreply(%s, xdr_void, (char *)NULL);\n",
429 			    TRANSP);
430 			print_return("\t\t");
431 			fprintf(fout, "\n");
432 		}
433 		for (proc = vp->procs; proc != NULL; proc = proc->next) {
434 			fprintf(fout, "\tcase %s:\n", proc->proc_name);
435 			if (proc->arg_num < 2) { /* single argument */
436 				p_xdrfunc(ARG, proc->args.decls->decl.type);
437 			} else {
438 				p_xdrfunc(ARG, proc->args.argname);
439 			}
440 			p_xdrfunc(RESULT, proc->res_type);
441 			if (Cflag)
442 				fprintf(fout,
443 				    "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
444 				    ROUTINE);
445 			else
446 				fprintf(fout, "\t\t%s = (char *(*)()) ", ROUTINE);
447 
448 			if (newstyle) { /* new style: calls internal routine */
449 				fprintf(fout,"_");
450 			}
451 			if (!newstyle)
452 				pvname_svc(proc->proc_name, vp->vers_num);
453 			else
454 				pvname(proc->proc_name, vp->vers_num);
455 			fprintf(fout, ";\n");
456 			fprintf(fout, "\t\tbreak;\n\n");
457 		}
458 		fprintf(fout, "\tdefault:\n");
459 		printerr("noproc", TRANSP);
460 		print_return("\t\t");
461 		fprintf(fout, "\t}\n");
462 
463 		fprintf(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG);
464 		printif ("getargs", TRANSP, "(caddr_t) &", ARG);
465 		printerr("decode", TRANSP);
466 		print_return("\t\t");
467 		fprintf(fout, "\t}\n");
468 
469 		if (Cflag)
470 			fprintf(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
471 			    RESULT, ROUTINE, ARG, RQSTP);
472 		else
473 			fprintf(fout, "\t%s = (*%s)(&%s, %s);\n",
474 			    RESULT, ROUTINE, ARG, RQSTP);
475 		fprintf(fout,
476 		    "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n",
477 		    RESULT, TRANSP, RESULT, RESULT);
478 		printerr("systemerr", TRANSP);
479 		fprintf(fout, "\t}\n");
480 
481 		printif ("freeargs", TRANSP, "(caddr_t) &", ARG);
482 		(void) snprintf(_errbuf, sizeof _errbuf, "unable to free arguments");
483 		print_err_message("\t\t");
484 		fprintf(fout, "\t\texit(1);\n");
485 		fprintf(fout, "\t}\n");
486 		print_return("\t");
487 		fprintf(fout, "}\n");
488 	}
489 }
490 
491 static void
printerr(err,transp)492 printerr(err, transp)
493 	char *err;
494 	char *transp;
495 {
496 	fprintf(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
497 }
498 
499 static void
printif(proc,transp,prefix,arg)500 printif(proc, transp, prefix, arg)
501 	char *proc;
502 	char *transp;
503 	char *prefix;
504 	char *arg;
505 {
506 	fprintf(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n",
507 	    proc, transp, arg, prefix, arg);
508 }
509 
510 int
nullproc(proc)511 nullproc(proc)
512 	proc_list *proc;
513 {
514 	for (; proc != NULL; proc = proc->next) {
515 		if (streq(proc->proc_num, "0"))
516 			return (1);
517 	}
518 	return (0);
519 }
520 
521 static void
write_inetmost(infile)522 write_inetmost(infile)
523 	char *infile;
524 {
525 	fprintf(fout, "\tSVCXPRT *%s;\n", TRANSP);
526 	fprintf(fout, "\tint sock;\n");
527 	fprintf(fout, "\tint proto;\n");
528 	fprintf(fout, "\tstruct sockaddr_in saddr;\n");
529 	fprintf(fout, "\tint asize = sizeof (saddr);\n");
530 	fprintf(fout, "\n");
531 	fprintf(fout,
532 	"\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
533 	fprintf(fout, "\t\tint ssize = sizeof (int);\n\n");
534 	fprintf(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
535 	fprintf(fout, "\t\t\texit(1);\n");
536 	fprintf(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
537 	fprintf(fout, "\t\t    (char *)&_rpcfdtype, &ssize) == -1)\n");
538 	fprintf(fout, "\t\t\texit(1);\n");
539 	fprintf(fout, "\t\tsock = 0;\n");
540 	fprintf(fout, "\t\t_rpcpmstart = 1;\n");
541 	fprintf(fout, "\t\tproto = 0;\n");
542 	open_log_file(infile, "\t\t");
543 	fprintf(fout, "\t} else {\n");
544 	write_rpc_svc_fg(infile, "\t\t");
545 	fprintf(fout, "\t\tsock = RPC_ANYSOCK;\n");
546 	print_pmapunset("\t\t");
547 	fprintf(fout, "\t}\n");
548 }
549 
550 static void
print_return(space)551 print_return(space)
552 	char *space;
553 {
554 	if (exitnow)
555 		fprintf(fout, "%sexit(0);\n", space);
556 	else {
557 		if (timerflag)
558 			fprintf(fout, "%s_rpcsvcdirty = 0;\n", space);
559 		fprintf(fout, "%sreturn;\n", space);
560 	}
561 }
562 
563 static void
print_pmapunset(space)564 print_pmapunset(space)
565 	char *space;
566 {
567 	version_list *vp;
568 	definition *def;
569 	list *l;
570 
571 	for (l = defined; l != NULL; l = l->next) {
572 		def = (definition *) l->val;
573 		if (def->def_kind == DEF_PROGRAM) {
574 			for (vp = def->def.pr.versions; vp != NULL;
575 			    vp = vp->next) {
576 				fprintf(fout, "%s(void) pmap_unset(%s, %s);\n",
577 				    space, def->def_name, vp->vers_name);
578 			}
579 		}
580 	}
581 }
582 
583 static void
print_err_message(space)584 print_err_message(space)
585 	char *space;
586 {
587 	if (logflag)
588 		fprintf(fout, "%ssyslog(LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf);
589 	else if (inetdflag || pmflag)
590 		fprintf(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
591 	else
592 		fprintf(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
593 }
594 
595 /*
596  * Write the server auxiliary function (_msgout, timeout)
597  */
598 void
write_svc_aux(nomain)599 write_svc_aux(nomain)
600 	int nomain;
601 {
602 	if (!logflag)
603 		write_msg_out();
604 	if (!nomain)
605 		write_timeout_func();
606 	if (callerflag)			/*EVAS*/
607 		write_caller_func();	/*EVAS*/
608 }
609 
610 /*
611  * Write the _msgout function
612  */
613 
614 void
write_msg_out()615 write_msg_out()
616 {
617 	fprintf(fout, "\n");
618 	fprintf(fout, "static\n");
619 	if (!Cflag) {
620 		fprintf(fout, "void _msgout(msg)\n");
621 		fprintf(fout, "\tchar *msg;\n");
622 	} else {
623 		fprintf(fout, "void _msgout(char *msg)\n");
624 	}
625 	fprintf(fout, "{\n");
626 	fprintf(fout, "#ifdef RPC_SVC_FG\n");
627 	if (inetdflag || pmflag)
628 		fprintf(fout, "\tif (_rpcpmstart)\n");
629 	fprintf(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
630 	fprintf(fout, "\telse {\n");
631 	fprintf(fout, "\t\t(void) write(STDERR_FILENO, msg, strlen(msg));\n");
632 	fprintf(fout, "\t\t(void) write(STDERR_FILENO, \"\\n\", 1);\n");
633 	fprintf(fout, "\t}\n#else\n");
634 	fprintf(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
635 	fprintf(fout, "#endif\n");
636 	fprintf(fout, "}\n");
637 }
638 
639 /*
640  * Write the timeout function
641  */
642 static void
write_timeout_func()643 write_timeout_func()
644 {
645 	if (!timerflag)
646 		return;
647 	fprintf(fout, "\n");
648 	fprintf(fout, "static void\n");
649 	fprintf(fout, "closedown()\n");
650 	fprintf(fout, "{\n");
651 	fprintf(fout, "\tint save_errno = errno;\n\n");
652 	fprintf(fout, "\tif (_rpcsvcdirty == 0) {\n");
653 	fprintf(fout, "\t\textern fd_set *__svc_fdset;\n");
654 	fprintf(fout, "\t\textern int __svc_fdsetsize;\n");
655 	fprintf(fout, "\t\tint i, openfd;\n");
656 	if (tirpcflag && pmflag) {
657 		fprintf(fout, "\t\tstruct t_info tinfo;\n\n");
658 		fprintf(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
659 	} else {
660 		fprintf(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
661 	}
662 	fprintf(fout, "\t\t\t_exit(0);\n");
663 	fprintf(fout, "\t\tfor (i = 0, openfd = 0; i < __svc_fdsetsize && openfd < 2; i++)\n");
664 	fprintf(fout, "\t\t\tif (FD_ISSET(i, __svc_fdset))\n");
665 	fprintf(fout, "\t\t\t\topenfd++;\n");
666 	fprintf(fout, "\t\tif (openfd <= (_rpcpmstart?0:1))\n");
667 	fprintf(fout, "\t\t\t_exit(0);\n");
668 	fprintf(fout, "\t}\n");
669 	fprintf(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
670 	fprintf(fout, "\terrno = save_errno;\n");
671 	fprintf(fout, "}\n");
672 }
673 
674 static void
write_caller_func()675 write_caller_func()			/*EVAS*/
676 {
677 #define	P(s)	fprintf(fout, s);
678 
679 P("\n");
680 P("char *svc_caller()\n");
681 P("{\n");
682 P("	struct sockaddr_in actual;\n");
683 P("	struct hostent *hp;\n");
684 P("	static struct in_addr prev;\n");
685 P("	static char cname[256];\n\n");
686 
687 P("	actual = *svc_getcaller(caller);\n\n");
688 
689 P("	if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n");
690 P("		 sizeof(struct in_addr)) == 0)\n");
691 P("		return (cname);\n\n");
692 
693 P("	prev = actual.sin_addr;\n\n");
694 
695 P("	hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n");
696 P("	if (hp == NULL) {                       /* dummy one up */\n");
697 P("		extern char *inet_ntoa();\n");
698 P("		strlcpy(cname, inet_ntoa(actual.sin_addr), sizeof cname);\n");
699 P("	} else {\n");
700 P("		strlcpy(cname, hp->h_name, sizeof cname);\n");
701 P("	}\n\n");
702 
703 P("	return (cname);\n");
704 P("}\n");
705 
706 #undef P
707 }
708 
709 /*
710  * Write the most of port monitor support
711  */
712 static void
write_pm_most(infile,netflag)713 write_pm_most(infile, netflag)
714 	char *infile;
715 	int netflag;
716 {
717 	list *l;
718 	definition *def;
719 	version_list *vp;
720 
721 	fprintf(fout, "\tif (!ioctl(0, I_LOOK, mname) == -1 &&\n");
722 	fprintf(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
723 	fprintf(fout, " !strcmp(mname, \"timod\"))) {\n");
724 	fprintf(fout, "\t\tchar *netid;\n");
725 	if (!netflag) {	/* Not included by -n option */
726 		fprintf(fout, "\t\tstruct netconfig *nconf = NULL;\n");
727 		fprintf(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
728 	}
729 	if (timerflag)
730 		fprintf(fout, "\t\tint pmclose;\n");
731 /* not necessary, defined in /usr/include/stdlib */
732 /*	fprintf(fout, "\t\textern char *getenv();\n");*/
733 	fprintf(fout, "\n");
734 	fprintf(fout, "\t\t_rpcpmstart = 1;\n");
735 	if (logflag)
736 		open_log_file(infile, "\t\t");
737 	fprintf(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
738 	snprintf(_errbuf, sizeof _errbuf, "cannot get transport name");
739 	print_err_message("\t\t\t");
740 	fprintf(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n");
741 	snprintf(_errbuf, sizeof _errbuf, "cannot get transport info");
742 	print_err_message("\t\t\t");
743 	fprintf(fout, "\t\t}\n");
744 	/*
745 	 * A kludgy support for inetd services. Inetd only works with
746 	 * sockmod, and RPC works only with timod, hence all this jugglery
747 	 */
748 	fprintf(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
749 	fprintf(fout, "\t\t\tif (ioctl(0, I_POP, 0) == -1 || ioctl(0, I_PUSH, \"timod\") == -1) {\n");
750 	snprintf(_errbuf, sizeof _errbuf, "could not get the right module");
751 	print_err_message("\t\t\t\t");
752 	fprintf(fout, "\t\t\t\texit(1);\n");
753 	fprintf(fout, "\t\t\t}\n");
754 	fprintf(fout, "\t\t}\n");
755 	if (timerflag)
756 		fprintf(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
757 	fprintf(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
758 			TRANSP);
759 	snprintf(_errbuf, sizeof _errbuf, "cannot create server handle");
760 	print_err_message("\t\t\t");
761 	fprintf(fout, "\t\t\texit(1);\n");
762 	fprintf(fout, "\t\t}\n");
763 	fprintf(fout, "\t\tif (nconf)\n");
764 	fprintf(fout, "\t\t\tfreenetconfigent(nconf);\n");
765 	for (l = defined; l != NULL; l = l->next) {
766 		def = (definition *) l->val;
767 		if (def->def_kind != DEF_PROGRAM) {
768 			continue;
769 		}
770 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
771 			fprintf(fout,
772 				"\t\tif (!svc_reg(%s, %s, %s, ",
773 				TRANSP, def->def_name, vp->vers_name);
774 			pvname(def->def_name, vp->vers_num);
775 			fprintf(fout, ", 0)) {\n");
776 			(void) snprintf(_errbuf, sizeof _errbuf, "unable to register (%s, %s).",
777 					def->def_name, vp->vers_name);
778 			print_err_message("\t\t\t");
779 			fprintf(fout, "\t\t\texit(1);\n");
780 			fprintf(fout, "\t\t}\n");
781 		}
782 	}
783 	if (timerflag) {
784 		fprintf(fout, "\t\tif (pmclose) {\n");
785 		fprintf(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
786 				Cflag? "(SIG_PF)" : "(void(*)())");
787 		fprintf(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
788 		fprintf(fout, "\t\t}\n");
789 	}
790 	fprintf(fout, "\t\tsvc_run();\n");
791 	fprintf(fout, "\t\texit(1);\n");
792 	fprintf(fout, "\t\t/* NOTREACHED */\n");
793 	fprintf(fout, "\t}\n");
794 }
795 
796 /*
797  * Support for backgrounding the server if self started.
798  */
799 static void
write_rpc_svc_fg(infile,sp)800 write_rpc_svc_fg(infile, sp)
801 	char *infile;
802 	char *sp;
803 {
804 	fprintf(fout, "#ifndef RPC_SVC_FG\n");
805 	fprintf(fout, "%sint size;\n", sp);
806 	if (tirpcflag)
807 		fprintf(fout, "%sstruct rlimit rl;\n", sp);
808 	if (inetdflag) {
809 		fprintf(fout, "%sint i;\n\n", sp);
810 		fprintf(fout, "%spid_t pid;\n\n", sp);
811 	}
812 	fprintf(fout, "%spid = fork();\n", sp);
813 	fprintf(fout, "%sif (pid == -1) {\n", sp);
814 	fprintf(fout, "%s\tperror(\"cannot fork\");\n", sp);
815 	fprintf(fout, "%s\texit(1);\n", sp);
816 	fprintf(fout, "%s}\n", sp);
817 	fprintf(fout, "%sif (pid)\n", sp);
818 	fprintf(fout, "%s\texit(0);\n", sp);
819 	/* get number of file descriptors */
820 	if (tirpcflag) {
821 		fprintf(fout, "%srl.rlim_max = 0;\n", sp);
822 		fprintf(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
823 		fprintf(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
824 		fprintf(fout, "%s\texit(1);\n", sp);
825 	} else {
826 		fprintf(fout, "%ssize = getdtablesize();\n", sp);
827 	}
828 
829 	fprintf(fout, "%sfor (i = 0; i < size; i++)\n", sp);
830 	fprintf(fout, "%s\t(void) close(i);\n", sp);
831 	/* Redirect stderr and stdout to console */
832 	fprintf(fout, "%si = open(\"/dev/console\", O_RDWR);\n", sp);
833 	fprintf(fout, "%s(void) dup2(i, 1);\n", sp);
834 	fprintf(fout, "%s(void) dup2(i, 2);\n", sp);
835 	/* This removes control of the controlling terminal */
836 	if (tirpcflag)
837 		fprintf(fout, "%ssetsid();\n", sp);
838 	else {
839 		fprintf(fout, "%si = open(\"/dev/tty\", O_RDWR);\n", sp);
840 		fprintf(fout, "%sif (i != -1) {\n", sp);
841 		fprintf(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
842 		fprintf(fout, "%s\t(void) close(i);\n", sp);
843 		fprintf(fout, "%s}\n", sp);
844 	}
845 	if (!logflag)
846 		open_log_file(infile, sp);
847 	fprintf(fout, "#endif\n");
848 	if (logflag)
849 		open_log_file(infile, sp);
850 }
851 
852 static void
open_log_file(infile,sp)853 open_log_file(infile, sp)
854 	char *infile;
855 	char *sp;
856 {
857 	char *s;
858 
859 	s = strrchr(infile, '.');
860 	if (s)
861 		*s = '\0';
862 	fprintf(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
863 	if (s)
864 		*s = '.';
865 }
866 
867 /*
868  * write a registration for the given transport for Inetd
869  */
870 void
write_inetd_register(transp)871 write_inetd_register(transp)
872 	char *transp;
873 {
874 	list *l;
875 	definition *def;
876 	version_list *vp;
877 	char *sp;
878 	int isudp;
879 	char tmpbuf[32];
880 
881 	if (inetdflag)
882 		sp = "\t";
883 	else
884 		sp = "";
885 	if (streq(transp, "udp"))
886 		isudp = 1;
887 	else
888 		isudp = 0;
889 	fprintf(fout, "\n");
890 	if (inetdflag) {
891 		fprintf(fout, "\tif (_rpcfdtype == 0 || _rpcfdtype == %s) {\n",
892 				isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
893 	}
894 	if (inetdflag && streq(transp, "tcp")) {
895 		fprintf(fout, "%s\tif (_rpcpmstart)\n", sp);
896 
897 		fprintf(fout, "%s\t\t%s = svc%s_create(%s",
898 			sp, TRANSP, "fd", inetdflag? "sock": "RPC_ANYSOCK");
899 		if (!isudp)
900 			fprintf(fout, ", 0, 0");
901 		fprintf(fout, ");\n");
902 
903 		fprintf(fout, "%s\telse\n", sp);
904 
905 		fprintf(fout, "%s\t\t%s = svc%s_create(%s",
906 			sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
907 		if (!isudp)
908 			fprintf(fout, ", 0, 0");
909 		fprintf(fout, ");\n");
910 
911 	} else {
912 		fprintf(fout, "%s\t%s = svc%s_create(%s",
913 			sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
914 		if (!isudp)
915 			fprintf(fout, ", 0, 0");
916 		fprintf(fout, ");\n");
917 	}
918 	fprintf(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
919 	(void) snprintf(_errbuf, sizeof _errbuf, "cannot create %s service.", transp);
920 	(void) snprintf(tmpbuf, sizeof tmpbuf, "%s\t\t", sp);
921 	print_err_message(tmpbuf);
922 	fprintf(fout, "%s\t\texit(1);\n", sp);
923 	fprintf(fout, "%s\t}\n", sp);
924 
925 	if (inetdflag) {
926 		fprintf(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
927 		fprintf(fout, "%s\tproto = IPPROTO_%s;\n",
928 				sp, isudp ? "UDP": "TCP");
929 	}
930 	for (l = defined; l != NULL; l = l->next) {
931 		def = (definition *) l->val;
932 		if (def->def_kind != DEF_PROGRAM) {
933 			continue;
934 		}
935 		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
936 			fprintf(fout, "%s\tif (!svc_register(%s, %s, %s, ",
937 				sp, TRANSP, def->def_name, vp->vers_name);
938 			pvname(def->def_name, vp->vers_num);
939 			if (inetdflag)
940 				fprintf(fout, ", proto)) {\n");
941 			else
942 				fprintf(fout, ", IPPROTO_%s)) {\n",
943 					isudp ? "UDP": "TCP");
944 			(void) snprintf(_errbuf, sizeof _errbuf, "unable to register (%s, %s, %s).",
945 					def->def_name, vp->vers_name, transp);
946 			print_err_message(tmpbuf);
947 			fprintf(fout, "%s\t\texit(1);\n", sp);
948 			fprintf(fout, "%s\t}\n", sp);
949 		}
950 	}
951 	if (inetdflag)
952 		fprintf(fout, "\t}\n");
953 }
954