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