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