1 /* $OpenBSD: rpc_svcout.c,v 1.21 2003/08/16 23:09:40 deraadt 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 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
p_xdrfunc(char * rname,char * typename)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
internal_proctype(plist)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
write_most(infile,netflag,nomain)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
write_netid_register(transp)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
write_nettype_register(transp)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
write_rest()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
write_programs(storage)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 defintion 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
write_real_program(def)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
write_program(def,storage)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
printerr(err,transp)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
printif(proc,transp,prefix,arg)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
nullproc(proc)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
write_inetmost(infile)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
print_return(space)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
print_pmapunset(space)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
print_err_message(space)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
write_svc_aux(nomain)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
write_msg_out()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
write_timeout_func()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
write_caller_func()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
write_pm_most(infile,netflag)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
write_rpc_svc_fg(infile,sp)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
open_log_file(infile,sp)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
write_inetd_register(transp)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