1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
24 *
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*
41 * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
42 */
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdarg.h>
46 #include "rpc_parse.h"
47 #include "rpc_util.h"
48
49 extern int nullproc(proc_list *);
50
51 static char RQSTP[] = "rqstp";
52 static char TRANSP[] = "transp";
53 static char ARG[] = "argument";
54 static char RESULT[] = "result";
55 static char ROUTINE[] = "local";
56 static char RETVAL[] = "retval";
57
58 #define ERRBUFLEN 256
59
60 static void internal_proctype(proc_list *);
61 static void write_real_program(definition *);
62 static void write_programs(char *);
63 static void write_program(definition *, char *);
64 static void printerr(char *, char *);
65 static void write_svc_aux(int);
66 static void printif(char *, char *, char *, char *);
67 static void write_inetmost(char *);
68 static void print_return(char *);
69 static void print_pmapunset(char *);
70 static void print_err_message(const char *, const char *, ...);
71 static void write_msg_out(void);
72 static void write_timeout_func(void);
73 static void write_pm_most(char *, int);
74 static void write_rpc_svc_fg(char *, char *);
75 static void open_log_file(char *, char *);
76
77 static void
78 p_xdrfunc(char *rname, char *typename)
79 {
80 f_print(fout, "\t\t_xdr_%s = (xdrproc_t)\n", rname);
81 f_print(fout, "\t\t xdr_%s;\n", stringfix(typename));
82 }
83
84 static void
85 internal_proctype(proc_list *plist)
86 {
87 f_print(fout, "static ");
88 ptype(plist->res_prefix, plist->res_type, 1);
89 f_print(fout, "*");
90 }
91
92
93 static void
94 write_mtauto(void)
95 {
96 f_print(fout, "\tif (!rpc_control(RPC_SVC_MTMODE_SET, &mode)) {\n");
97 print_err_message("\t\t", "unable to set automatic MT mode.");
98 f_print(fout, "\t\texit(1);\n\t}\n");
99 }
100
101 /*
102 * write most of the service, that is, everything but the registrations.
103 */
104 void
105 write_most(char *infile, int netflag, int nomain)
106 {
107 if (inetdflag || pmflag) {
108 char *var_type;
109 var_type = (nomain? "extern" : "static");
110 f_print(fout, "%s int _rpcpmstart;", var_type);
111 f_print(fout, "\t\t/* Started by a port monitor ? */\n");
112 if (!tirpcflag) {
113 f_print(fout, "%s int _rpcfdtype;", var_type);
114 f_print(fout,
115 "\t\t /* Whether Stream or Datagram ? */\n");
116 }
117
118 if (timerflag) {
119 f_print(fout,
120 "\n/* States a server can be in wrt request */\n\n");
121 f_print(fout, "#define\t_IDLE 0\n");
122 f_print(fout, "#define\t_SERVED 1\n\n");
123 if (nomain) {
124 f_print(fout,
125 "/* LINTED static unused if no main */\n");
126 }
127 f_print(fout,
128 "static int _rpcsvcstate = _IDLE;");
129 f_print(fout,
130 "\t/* Set when a request is serviced */\n");
131 f_print(fout, "static int _rpcsvccount = 0;");
132 f_print(fout,
133 "\t\t/* Number of requests being serviced */\n");
134
135 if (mtflag) {
136 f_print(fout, "mutex_t _svcstate_lock;");
137 f_print(fout,
138 "\t\t/* lock for _rpcsvcstate, _rpcsvccount */\n");
139
140 }
141 }
142
143 write_svc_aux(nomain);
144 }
145 /* write out dispatcher and stubs */
146 write_programs(nomain ? NULL : "static");
147
148 if (nomain)
149 return;
150
151 f_print(fout, "\nint\nmain()\n");
152 f_print(fout, "{\n");
153 if (inetdflag) {
154 write_inetmost(infile);
155 /* Includes call to write_rpc_svc_fg() */
156 } else {
157 if (tirpcflag) {
158 if (netflag) {
159 f_print(fout,
160 "\tregister SVCXPRT *%s;\n", TRANSP);
161 f_print(fout,
162 "\tstruct netconfig *nconf = NULL;\n");
163 }
164 f_print(fout, "\tpid_t pid;\n");
165 f_print(fout, "\tint i;\n");
166 if (mtauto) {
167 f_print(fout,
168 "\tint mode = RPC_SVC_MT_AUTO;\n\n");
169 write_mtauto();
170 } else
171 f_print(fout, "\n");
172
173 if (mtflag & timerflag)
174 f_print(fout,
175 "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n");
176
177 write_pm_most(infile, netflag);
178 f_print(fout, "\telse {\n");
179 write_rpc_svc_fg(infile, "\t\t");
180 f_print(fout, "\t}\n");
181 } else {
182 f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
183 f_print(fout, "\n");
184 print_pmapunset("\t");
185 }
186 }
187
188 if (logflag && !inetdflag) {
189 open_log_file(infile, "\t");
190 }
191 }
192
193 /*
194 * write a registration for the given transport
195 */
196 void
197 write_netid_register(char *transp)
198 {
199 list *l;
200 definition *def;
201 version_list *vp;
202 char *sp;
203 char tmpbuf[32];
204
205 sp = "";
206 f_print(fout, "\n");
207 f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
208 f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
209 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
210 print_err_message(tmpbuf, "cannot find %s netid.", transp);
211 f_print(fout, "%s\t\texit(1);\n", sp);
212 f_print(fout, "%s\t}\n", sp);
213 f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
214 sp, TRANSP);
215 f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
216 print_err_message(tmpbuf, "cannot create %s service.", transp);
217 f_print(fout, "%s\t\texit(1);\n", sp);
218 f_print(fout, "%s\t}\n", sp);
219
220 for (l = defined; l != NULL; l = l->next) {
221 def = (definition *) l->val;
222 if (def->def_kind != DEF_PROGRAM) {
223 continue;
224 }
225 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
226 f_print(fout,
227 "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
228 sp, def->def_name, vp->vers_name);
229 f_print(fout,
230 "%s\tif (!svc_reg(%s, %s, %s, ",
231 sp, TRANSP, def->def_name, vp->vers_name);
232 pvname(def->def_name, vp->vers_num);
233 f_print(fout, ", nconf)) {\n");
234 print_err_message(tmpbuf,
235 "unable to register (%s, %s, %s).",
236 def->def_name, vp->vers_name, transp);
237 f_print(fout, "%s\t\texit(1);\n", sp);
238 f_print(fout, "%s\t}\n", sp);
239 }
240 }
241 f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
242 }
243
244 /*
245 * write a registration for the given transport for TLI
246 */
247 void
248 write_nettype_register(char *transp)
249 {
250 list *l;
251 definition *def;
252 version_list *vp;
253
254 for (l = defined; l != NULL; l = l->next) {
255 def = (definition *) l->val;
256 if (def->def_kind != DEF_PROGRAM) {
257 continue;
258 }
259 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
260 f_print(fout, "\tif (!svc_create(\n");
261 f_print(fout, "\t ");
262 pvname(def->def_name, vp->vers_num);
263 f_print(fout, ", %s, %s,\n",
264 def->def_name, vp->vers_name);
265 f_print(fout, "\t \"%s\")) {\n", transp);
266 print_err_message("\t\t",
267 "unable to create (%s, %s) for %s.",
268 def->def_name, vp->vers_name, transp);
269 f_print(fout, "\t\texit(1);\n");
270 f_print(fout, "\t}\n");
271 }
272 }
273 }
274
275 /*
276 * write the rest of the service
277 */
278 void
279 write_rest(void)
280 {
281 f_print(fout, "\n");
282 if (inetdflag) {
283 f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
284 print_err_message("\t\t", "could not create a handle");
285 f_print(fout, "\t\texit(1);\n");
286 f_print(fout, "\t}\n");
287 if (timerflag) {
288 f_print(fout, "\tif (_rpcpmstart) {\n");
289 if (mtflag) {
290 f_print(fout,
291 "\t\tif (thr_create(NULL, 0, closedown, NULL, 0, NULL) != 0) {\n");
292 print_err_message("\t\t\t",
293 "cannot create closedown thread");
294 f_print(fout, "\t\t\texit(1);\n");
295 f_print(fout, "\t\t}\n");
296 f_print(fout, "\t}\n");
297 } else {
298 f_print(fout,
299 "\t\t(void) signal(SIGALRM, %s closedown);\n",
300 "(SIG_PF)");
301 f_print(fout,
302 "\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
303 f_print(fout, "\t}\n");
304 }
305 }
306 }
307 f_print(fout, "\tsvc_run();\n");
308 print_err_message("\t", "svc_run returned");
309 f_print(fout, "\texit(1);\n");
310 f_print(fout, "\t/* NOTREACHED */\n");
311 f_print(fout, "}\n");
312 }
313
314 static void
315 write_programs(char *storage)
316 {
317 list *l;
318 definition *def;
319
320 /* write out stubs for procedure definitions */
321 for (l = defined; l != NULL; l = l->next) {
322 def = (definition *) l->val;
323 if (def->def_kind == DEF_PROGRAM)
324 write_real_program(def);
325 }
326
327 /* write out dispatcher for each program */
328 for (l = defined; l != NULL; l = l->next) {
329 def = (definition *) l->val;
330 if (def->def_kind == DEF_PROGRAM)
331 write_program(def, storage);
332 }
333
334
335 }
336
337 /*
338 * write out definition of internal function (e.g. _printmsg_1(...))
339 * which calls server's defintion of actual function (e.g. printmsg_1(...)).
340 * Unpacks single user argument of printmsg_1 to call-by-value format
341 * expected by printmsg_1.
342 */
343 static void
344 write_real_program(definition *def)
345 {
346 version_list *vp;
347 proc_list *proc;
348 decl_list *l;
349
350 if (!newstyle)
351 return; /* not needed for old style */
352 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
353 for (proc = vp->procs; proc != NULL; proc = proc->next) {
354 int oneway = streq(proc->res_type, "oneway");
355
356 f_print(fout, "\n");
357 if (proc->arg_num < 2 &&
358 streq(proc->args.decls->decl.type, "void")) {
359 f_print(fout, "/* ARGSUSED */\n");
360 }
361 if (!mtflag)
362 internal_proctype(proc);
363 else
364 f_print(fout, "int");
365 f_print(fout, "\n_");
366 pvname(proc->proc_name, vp->vers_num);
367
368 f_print(fout, "(\n");
369 f_print(fout, " ");
370 /* arg name */
371 if (proc->arg_num > 1)
372 /* LINTED variable format */
373 f_print(fout, proc->args.argname);
374 else
375 ptype(proc->args.decls->decl.prefix,
376 proc->args.decls->decl.type, 0);
377 f_print(fout, " *argp,\n");
378 if (mtflag) {
379 f_print(fout, " ");
380 ptype(proc->res_prefix, proc->res_type, 1);
381 f_print(fout, "*%s,\n", RESULT);
382 }
383 f_print(fout, " struct svc_req *%s)\n", RQSTP);
384
385 f_print(fout, "{\n");
386 f_print(fout, "\treturn (");
387 /* for mtflag, arguments are different */
388 pvname_svc(proc->proc_name, vp->vers_num);
389 f_print(fout, "(");
390 if (proc->arg_num < 2) { /* single argument */
391 /* only print if non-void */
392 if (!streq(proc->args.decls->decl.type, "void"))
393 f_print(fout, "*argp, ");
394 } else {
395 f_print(fout, "\n");
396 for (l = proc->args.decls; l != NULL;
397 l = l->next)
398 f_print(fout, "\t argp->%s,\n",
399 l->decl.name);
400 f_print(fout, "\t ");
401 }
402 if (mtflag && !oneway)
403 f_print(fout, "%s, ", RESULT);
404 f_print(fout, "%s));\n}\n", RQSTP);
405 }
406 }
407 }
408
409 static void
410 write_program(definition *def, char *storage)
411 {
412 version_list *vp;
413 proc_list *proc;
414 int filled;
415
416 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
417 f_print(fout, "\n");
418 if (storage != NULL) {
419 f_print(fout, "%s ", storage);
420 }
421 f_print(fout, "void\n");
422 pvname(def->def_name, vp->vers_num);
423
424 f_print(fout, "(struct svc_req *%s, ", RQSTP);
425 f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
426
427 f_print(fout, "{\n");
428
429 filled = 0;
430 f_print(fout, "\tunion {\n");
431 for (proc = vp->procs; proc != NULL; proc = proc->next) {
432 if (proc->arg_num < 2) { /* single argument */
433 if (streq(proc->args.decls->decl.type,
434 "void")) {
435 continue;
436 }
437 filled = 1;
438 f_print(fout, "\t\t");
439 ptype(proc->args.decls->decl.prefix,
440 proc->args.decls->decl.type, 0);
441 pvname(proc->proc_name, vp->vers_num);
442 f_print(fout, "_arg;\n");
443
444 } else {
445 filled = 1;
446 f_print(fout, "\t\t%s", proc->args.argname);
447 f_print(fout, " ");
448 pvname(proc->proc_name, vp->vers_num);
449 f_print(fout, "_arg;\n");
450 }
451 }
452 if (!filled) {
453 f_print(fout, "\t\tint fill;\n");
454 }
455 f_print(fout, "\t} %s;\n", ARG);
456
457 if (mtflag) {
458 filled = 0;
459 f_print(fout, "\tunion {\n");
460 for (proc = vp->procs; proc != NULL;
461 proc = proc->next) {
462 if (streq(proc->res_type, "void") ||
463 streq(proc->res_type, "oneway"))
464 continue;
465 filled = 1;
466 f_print(fout, "\t\t");
467 ptype(proc->res_prefix, proc->res_type, 0);
468 pvname(proc->proc_name, vp->vers_num);
469 f_print(fout, "_res;\n");
470 }
471 if (!filled)
472 f_print(fout, "\t\tint fill;\n");
473 f_print(fout, "\t} %s;\n", RESULT);
474 f_print(fout, "\tbool_t %s;\n", RETVAL);
475
476 } else
477 f_print(fout, "\tchar *%s;\n", RESULT);
478
479 f_print(fout, "\txdrproc_t _xdr_%s, _xdr_%s;\n", ARG, RESULT);
480 if (mtflag)
481 f_print(fout, "\tbool_t "
482 "(*%s)(char *, void *, struct svc_req *);\n",
483 ROUTINE);
484 else
485 f_print(fout, "\tchar *(*%s)"
486 "(char *, struct svc_req *);\n",
487 ROUTINE);
488 f_print(fout, "\n");
489
490 if (timerflag) {
491 if (mtflag)
492 f_print(fout,
493 "\t(void) mutex_lock(&_svcstate_lock);\n");
494
495 f_print(fout, "\t_rpcsvccount++;\n");
496 if (mtflag)
497 f_print(fout,
498 "\t(void) mutex_unlock(&_svcstate_lock);\n");
499 }
500
501 f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
502 if (!nullproc(vp->procs)) {
503 f_print(fout, "\tcase NULLPROC:\n");
504 f_print(fout,
505 "\t\t(void) svc_sendreply(%s,\n\t\t (xdrproc_t)xdr_void, NULL);\n",
506 TRANSP);
507 print_return("\t\t");
508 f_print(fout, "\n");
509 }
510 for (proc = vp->procs; proc != NULL; proc = proc->next) {
511 f_print(fout, "\tcase %s:\n", proc->proc_name);
512 if (proc->arg_num < 2) { /* single argument */
513 p_xdrfunc(ARG, proc->args.decls->decl.type);
514 } else {
515 p_xdrfunc(ARG, proc->args.argname);
516 }
517
518 if (streq(proc->res_type, "oneway")) {
519 /* One-way call */
520 f_print(fout, "\t\t_xdr_%s = NULL;\n", RESULT);
521 } else {
522 p_xdrfunc(RESULT, proc->res_type);
523 }
524 if (mtflag) {
525 f_print(fout,
526 "\t\t%s = (bool_t (*) (char *, "
527 "void *, struct svc_req *))",
528 ROUTINE);
529 } else {
530 f_print(fout,
531 "\t\t%s = (char *(*)(char *, "
532 "struct svc_req *))",
533 ROUTINE);
534 }
535
536 f_print(fout, "\n\t\t ");
537 if (newstyle) { /* new style: calls internal routine */
538 f_print(fout, "_");
539 }
540 if (!newstyle)
541 pvname_svc(proc->proc_name, vp->vers_num);
542 else
543 pvname(proc->proc_name, vp->vers_num);
544 f_print(fout, ";\n");
545 f_print(fout, "\t\tbreak;\n\n");
546 }
547 f_print(fout, "\tdefault:\n");
548 printerr("noproc", TRANSP);
549 print_return("\t\t");
550 f_print(fout, "\t}\n");
551
552 f_print(fout,
553 "\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
554 ARG, ARG);
555 printif("getargs", TRANSP, "(caddr_t)&", ARG);
556 printerr("decode", TRANSP);
557 print_return("\t\t");
558 f_print(fout, "\t}\n");
559
560 if (!mtflag)
561 f_print(fout,
562 "\t%s = (*%s)((char *)&%s, %s);\n",
563 RESULT, ROUTINE, ARG, RQSTP);
564 else
565 f_print(fout,
566 "\t%s = (bool_t)(*%s)"
567 "((char *)&%s, (void *)&%s, %s);\n",
568 RETVAL, ROUTINE, ARG, RESULT, RQSTP);
569
570
571
572 if (mtflag)
573 f_print(fout,
574 "\tif (_xdr_%s && %s > 0 &&\n"
575 "\t !svc_sendreply(%s, _xdr_%s, (char *)&%s)) {\n",
576 RESULT, RETVAL, TRANSP, RESULT, RESULT);
577 else
578 f_print(fout,
579 "\tif (_xdr_%s && %s != NULL &&\n"
580 "\t !svc_sendreply(%s, _xdr_%s, %s)) {\n",
581 RESULT, RESULT, TRANSP, RESULT, RESULT);
582
583 printerr("systemerr", TRANSP);
584 f_print(fout, "\t}\n");
585
586 printif("freeargs", TRANSP, "(caddr_t)&", ARG);
587 print_err_message("\t\t", "unable to free arguments");
588 f_print(fout, "\t\texit(1);\n");
589 f_print(fout, "\t}\n");
590 /* print out free routine */
591 if (mtflag) {
592 f_print(fout, "\tif (_xdr_%s != NULL) {\n", RESULT);
593 f_print(fout, "\t\tif (!");
594
595 pvname(def->def_name, vp->vers_num);
596 f_print(fout, "_freeresult(%s, _xdr_%s,\n",
597 TRANSP, RESULT);
598 f_print(fout, "\t\t (caddr_t)&%s))\n",
599 RESULT);
600 print_err_message("\t\t\t", "unable to free results");
601 f_print(fout, "\n");
602 f_print(fout, "\t}\n");
603 };
604 print_return("\t");
605 f_print(fout, "}\n");
606 }
607 }
608
609 static void
610 printerr(char *err, char *transp)
611 {
612 f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
613 }
614
615 static void
616 printif(char *proc, char *transp, char *prefix, char *arg)
617 {
618 f_print(fout, "\tif (!svc_%s(%s, _xdr_%s, %s%s)) {\n",
619 proc, transp, arg, prefix, arg);
620 }
621
622 int
623 nullproc(proc_list *proc)
624 {
625 for (; proc != NULL; proc = proc->next) {
626 if (streq(proc->proc_num, "0"))
627 return (1);
628 }
629 return (0);
630 }
631
632 static void
633 write_inetmost(char *infile)
634 {
635 f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
636 f_print(fout, "\tint sock;\n");
637 f_print(fout, "\tint proto;\n");
638 f_print(fout, "\tstruct sockaddr_in saddr;\n");
639 f_print(fout, "\tint asize = sizeof (saddr);\n");
640 f_print(fout, "\n");
641 f_print(fout,
642 "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
643 f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
644 f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
645 f_print(fout, "\t\t\texit(1);\n");
646 f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
647 f_print(fout, "\t\t (char *)&_rpcfdtype, &ssize) == -1)\n");
648 f_print(fout, "\t\t\texit(1);\n");
649 f_print(fout, "\t\tsock = 0;\n");
650 f_print(fout, "\t\t_rpcpmstart = 1;\n");
651 f_print(fout, "\t\tproto = 0;\n");
652 open_log_file(infile, "\t\t");
653 f_print(fout, "\t} else {\n");
654 write_rpc_svc_fg(infile, "\t\t");
655 f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
656 print_pmapunset("\t\t");
657 f_print(fout, "\t}\n");
658 }
659
660 static void
661 print_return(char *space)
662 {
663 if (exitnow) {
664 f_print(fout, "%sexit(0);\n", space);
665 return;
666 }
667 if (timerflag) {
668 if (mtflag) {
669 f_print(fout,
670 "%s(void) mutex_lock(&_svcstate_lock);\n",
671 space);
672 }
673 f_print(fout, "%s_rpcsvccount--;\n", space);
674 f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space);
675 if (mtflag) {
676 f_print(fout,
677 "%s(void) mutex_unlock(&_svcstate_lock);\n",
678 space);
679 }
680 }
681 f_print(fout, "%sreturn; /* CSTYLED */\n", space);
682 }
683
684 static void
685 print_pmapunset(char *space)
686 {
687 list *l;
688 definition *def;
689 version_list *vp;
690
691 for (l = defined; l != NULL; l = l->next) {
692 def = (definition *)l->val;
693 if (def->def_kind == DEF_PROGRAM) {
694 for (vp = def->def.pr.versions; vp != NULL;
695 vp = vp->next) {
696 f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
697 space, def->def_name, vp->vers_name);
698 }
699 }
700 }
701 }
702
703 static void
704 print_err_message(const char *space, const char *fmt, ...)
705 {
706 char errbuf[ERRBUFLEN];
707 va_list va;
708
709 va_start(va, fmt);
710 (void) vsnprintf(errbuf, sizeof (errbuf), fmt, va);
711 va_end(va);
712
713 if (logflag)
714 f_print(fout, "%ssyslog(LOG_ERR, \"%%s\",\n", space);
715 else if (inetdflag || pmflag)
716 f_print(fout, "%sRPC_MSGOUT(\"%%s\",\n", space);
717 else
718 f_print(fout, "%sfprintf(stderr, \"%%s\",\n", space);
719 f_print(fout, "%s \"%s\");\n", space, errbuf);
720 }
721
722 /*
723 * Write the server auxiliary function (RPC_MSGOUT, timeout)
724 */
725 static void
726 write_svc_aux(int nomain)
727 {
728 if (!logflag)
729 write_msg_out();
730 if (!nomain)
731 write_timeout_func();
732 }
733
734 /*
735 * Write the RPC_MSGOUT function
736 *
737 * Note that while we define RPC_MSGOUT to be printf-like, all existing
738 * calls are of the form "%s","<msg>" and this implementation assumes that
739 * trivial case. If in the future it's desirable to generate richer calls
740 * this implementation can change to match. This way we don't (yet) have
741 * to introduce varargs into the generated code.
742 */
743 static void
744 write_msg_out(void)
745 {
746 f_print(fout, "\n");
747 f_print(fout, "#if\tdefined(RPC_MSGOUT)\n");
748 f_print(fout, "extern void RPC_MSGOUT(const char *, ...);\n");
749 f_print(fout, "#else\t/* defined(RPC_MSGOUT) */\n");
750 f_print(fout, "static ");
751 f_print(fout, "void\nRPC_MSGOUT(const char *fmt, char *msg)\n");
752 f_print(fout, "{\n");
753 f_print(fout, "#ifdef RPC_SVC_FG\n");
754 if (inetdflag || pmflag)
755 f_print(fout, "\tif (_rpcpmstart)\n");
756 f_print(fout, "\t\tsyslog(LOG_ERR, fmt, msg);\n");
757 f_print(fout, "\telse {\n");
758 f_print(fout, "\t\t(void) fprintf(stderr, fmt, msg);\n");
759 f_print(fout, "\t\t(void) putc('\\n', stderr);\n");
760 f_print(fout, "\t}\n");
761 f_print(fout, "#else\n");
762 f_print(fout, "\tsyslog(LOG_ERR, fmt, msg);\n");
763 f_print(fout, "#endif\n");
764 f_print(fout, "}\n");
765 f_print(fout, "#endif\t/* defined(RPC_MSGOUT) */\n");
766 }
767
768 /*
769 * Write the timeout function
770 */
771 static void
772 write_timeout_func(void)
773 {
774 if (!timerflag)
775 return;
776
777 f_print(fout, "\n");
778 if (mtflag) {
779 f_print(fout, "/*ARGSUSED*/\n");
780 f_print(fout, "static void *\n");
781 f_print(fout, "closedown(void *arg)\n");
782 f_print(fout, "{\n");
783 f_print(fout, "\t/*CONSTCOND*/\n");
784 f_print(fout, "\twhile (1) {\n");
785 f_print(fout, "\t\t(void) sleep(_RPCSVC_CLOSEDOWN/2);\n\n");
786 f_print(fout,
787 "\t\tif (mutex_trylock(&_svcstate_lock) != 0)\n");
788 f_print(fout, "\t\t\tcontinue;\n\n");
789 f_print(fout,
790 "\t\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
791 if (tirpcflag) {
792 f_print(fout, "\t\t\tint size;\n");
793 } else {
794 f_print(fout, "\t\t\textern fd_set svc_fdset;\n");
795 f_print(fout, "\t\t\tstatic int size;\n");
796 }
797 f_print(fout, "\t\t\tint i, openfd = 0;\n\n");
798 if (tirpcflag) {
799 f_print(fout, "\t\t\tsize = svc_max_pollfd;\n");
800 } else {
801 f_print(fout, "\t\t\tif (size == 0) {\n");
802 f_print(fout, "\t\t\t\tsize = getdtablesize();\n");
803 f_print(fout, "\t\t\t}\n");
804 }
805 f_print(fout,
806 "\t\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
807 if (tirpcflag) {
808 f_print(fout, "\t\t\t\tif (svc_pollfd[i].fd >= 0)\n");
809 } else {
810 f_print(fout, "\t\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
811 }
812 f_print(fout, "\t\t\t\t\topenfd++;\n");
813 f_print(fout, "\t\t\tif (openfd <= 1)\n");
814 f_print(fout, "\t\t\t\texit(0);\n");
815 f_print(fout, "\t\t} else\n");
816 f_print(fout, "\t\t\t_rpcsvcstate = _IDLE;\n\n");
817 f_print(fout, "\t\t(void) mutex_unlock(&_svcstate_lock);\n");
818 f_print(fout, "\t}\n");
819 f_print(fout, "}\n");
820 return;
821 }
822
823 f_print(fout, "static void\n");
824 f_print(fout, "closedown(int sig)\n");
825 f_print(fout, "{\n");
826 f_print(fout, "\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
827 if (tirpcflag) {
828 f_print(fout, "\t\tint size;\n");
829 } else {
830 f_print(fout, "\t\textern fd_set svc_fdset;\n");
831 f_print(fout, "\t\tstatic int size;\n");
832 }
833 f_print(fout, "\t\tint i, openfd = 0;\n\n");
834 if (tirpcflag) {
835 f_print(fout, "\t\tsize = svc_max_pollfd;\n");
836 } else {
837 f_print(fout, "\t\tif (size == 0) {\n");
838 f_print(fout, "\t\t\tsize = getdtablesize();\n");
839 f_print(fout, "\t\t}\n");
840 }
841 f_print(fout,
842 "\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
843 if (tirpcflag) {
844 f_print(fout, "\t\t\tif (svc_pollfd[i].fd >= 0)\n");
845 } else {
846 f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
847 }
848 f_print(fout, "\t\t\t\topenfd++;\n");
849 f_print(fout, "\t\tif (openfd <= 1)\n");
850 f_print(fout, "\t\t\texit(0);\n");
851 f_print(fout, "\t} else\n");
852 f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n");
853
854 f_print(fout, "\t(void) signal(SIGALRM, (SIG_PF) closedown);\n");
855 f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
856 f_print(fout, "}\n");
857 }
858
859 /*
860 * Write the most of port monitor support
861 */
862 static void
863 write_pm_most(char *infile, int netflag)
864 {
865 list *l;
866 definition *def;
867 version_list *vp;
868
869 f_print(fout, "\t(void) sigset(SIGPIPE, SIG_IGN);\n\n");
870 f_print(fout, "\t/*\n");
871 f_print(fout, "\t * If stdin looks like a TLI endpoint, we assume\n");
872 f_print(fout, "\t * that we were started by a port monitor. If\n");
873 f_print(fout, "\t * t_getstate fails with TBADF, this is not a\n");
874 f_print(fout, "\t * TLI endpoint.\n");
875 f_print(fout, "\t */\n");
876 f_print(fout, "\tif (t_getstate(0) != -1 || t_errno != TBADF) {\n");
877 f_print(fout, "\t\tchar *netid;\n");
878 if (!netflag) { /* Not included by -n option */
879 f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
880 f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
881 }
882 if (timerflag)
883 f_print(fout, "\t\tint pmclose;\n");
884 /*
885 * Not necessary, defined in /usr/include/stdlib
886 * f_print(fout, "\t\textern char *getenv();\n");
887 */
888 f_print(fout, "\n");
889 f_print(fout, "\t\t_rpcpmstart = 1;\n");
890 open_log_file(infile, "\t\t");
891 f_print(fout,
892 "\n\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
893
894 if (timerflag) {
895 f_print(fout, "\t\t/* started from inetd */\n");
896 f_print(fout, "\t\t\tpmclose = 1;\n");
897 }
898 f_print(fout, "\t\t} else {\n");
899 f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n");
900 print_err_message("\t\t\t\t", "cannot get transport info");
901 if (timerflag)
902 f_print(fout,
903 "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
904 f_print(fout, "\t\t}\n");
905 f_print(fout,
906 "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
907 TRANSP);
908 print_err_message("\t\t\t", "cannot create server handle");
909 f_print(fout, "\t\t\texit(1);\n");
910 f_print(fout, "\t\t}\n");
911 f_print(fout, "\t\tif (nconf)\n");
912 f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
913 for (l = defined; l != NULL; l = l->next) {
914 def = (definition *) l->val;
915 if (def->def_kind != DEF_PROGRAM) {
916 continue;
917 }
918 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
919 f_print(fout,
920 "\t\tif (!svc_reg(%s, %s, %s,\n",
921 TRANSP, def->def_name, vp->vers_name);
922 f_print(fout, "\t\t ");
923 pvname(def->def_name, vp->vers_num);
924 f_print(fout, ", 0)) {\n");
925 print_err_message("\t\t\t",
926 "unable to register (%s, %s).",
927 def->def_name, vp->vers_name);
928 f_print(fout, "\t\t\texit(1);\n");
929 f_print(fout, "\t\t}\n");
930 }
931 }
932 if (timerflag) {
933 f_print(fout, "\t\tif (pmclose) {\n");
934 if (mtflag) {
935 f_print(fout,
936 "\t\t\tif (thr_create(NULL, 0, closedown, NULL,\n\t\t\t 0, NULL) != 0) {\n");
937 print_err_message("\t\t\t\t",
938 "cannot create closedown thread");
939 f_print(fout, "\t\t\t\texit(1);\n");
940 f_print(fout, "\t\t\t}\n");
941 } else {
942 f_print(fout,
943 "\t\t\t(void) signal(SIGALRM, (SIG_PF) closedown);\n");
944 f_print(fout,
945 "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
946 }
947 f_print(fout, "\t\t}\n");
948 }
949 f_print(fout, "\t\tsvc_run();\n");
950 f_print(fout, "\t\texit(1);\n");
951 f_print(fout, "\t\t/* NOTREACHED */\n");
952 f_print(fout, "\t}");
953 }
954
955 /*
956 * Support for backgrounding the server if self started.
957 */
958 static void
959 write_rpc_svc_fg(char *infile, char *sp)
960 {
961 f_print(fout, "#ifndef RPC_SVC_FG\n");
962 f_print(fout, "#pragma weak closefrom\n");
963 f_print(fout, "%sextern void closefrom();\n", sp);
964 f_print(fout, "%sint size;\n", sp);
965 if (tirpcflag)
966 f_print(fout, "%sstruct rlimit rl;\n", sp);
967 if (inetdflag)
968 f_print(fout, "%sint pid, i;\n\n", sp);
969 f_print(fout, "%spid = fork();\n", sp);
970 f_print(fout, "%sif (pid < 0) {\n", sp);
971 f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
972 f_print(fout, "%s\texit(1);\n", sp);
973 f_print(fout, "%s}\n", sp);
974 f_print(fout, "%sif (pid)\n", sp);
975 f_print(fout, "%s\texit(0);\n", sp);
976 /* close all file descriptors */
977 if (tirpcflag) {
978 f_print(fout, "%sif (closefrom != NULL)\n", sp);
979 f_print(fout, "%s\tclosefrom(0);\n", sp);
980 f_print(fout, "%selse {\n", sp);
981 f_print(fout, "%s\trl.rlim_max = 0;\n", sp);
982 f_print(fout, "%s\tgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
983 f_print(fout, "%s\tif ((size = rl.rlim_max) == 0)\n", sp);
984 f_print(fout, "%s\t\texit(1);\n", sp);
985 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
986 f_print(fout, "%s\t\t(void) close(i);\n", sp);
987 f_print(fout, "%s}\n", sp);
988 } else {
989 f_print(fout, "%s\tsize = getdtablesize();\n", sp);
990 f_print(fout, "%s\tfor (i = 0; i < size; i++)\n", sp);
991 f_print(fout, "%s\t\t(void) close(i);\n", sp);
992 }
993 /* Redirect stderr and stdout to /dev/null */
994 f_print(fout, "%si = open(\"/dev/null\", 2);\n", sp);
995 f_print(fout, "%s(void) dup2(i, 1);\n", sp);
996 f_print(fout, "%s(void) dup2(i, 2);\n", sp);
997 /* This removes control of the controlling terminal */
998 if (tirpcflag)
999 f_print(fout, "%ssetsid();\n", sp);
1000 else {
1001 f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
1002 f_print(fout, "%sif (i >= 0) {\n", sp);
1003 f_print(fout,
1004 "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
1005 f_print(fout, "%s\t(void) close(i);\n", sp);
1006 f_print(fout, "%s}\n", sp);
1007 }
1008 if (!logflag)
1009 open_log_file(infile, sp);
1010 f_print(fout, "#endif\n");
1011 if (logflag)
1012 open_log_file(infile, sp);
1013 }
1014
1015 static void
1016 open_log_file(char *infile, char *sp)
1017 {
1018 char *s;
1019
1020 s = strrchr(infile, '.');
1021 if (s)
1022 *s = '\0';
1023 f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
1024 if (s)
1025 *s = '.';
1026 }
1027
1028 /*
1029 * write a registration for the given transport for Inetd
1030 */
1031 void
1032 write_inetd_register(char *transp)
1033 {
1034 list *l;
1035 definition *def;
1036 version_list *vp;
1037 char *sp;
1038 int isudp;
1039 char tmpbuf[32];
1040
1041 if (inetdflag)
1042 sp = "\t";
1043 else
1044 sp = "";
1045 if (streq(transp, "udp"))
1046 isudp = 1;
1047 else
1048 isudp = 0;
1049 f_print(fout, "\n");
1050 if (inetdflag) {
1051 f_print(fout,
1052 "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
1053 isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
1054 }
1055 f_print(fout, "%s\t%s = svc%s_create(%s",
1056 sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
1057 if (!isudp)
1058 f_print(fout, ", 0, 0");
1059 f_print(fout, ");\n");
1060 f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
1061 (void) snprintf(tmpbuf, sizeof (tmpbuf), "%s\t\t", sp);
1062 print_err_message(tmpbuf, "cannot create %s service.", transp);
1063 f_print(fout, "%s\t\texit(1);\n", sp);
1064 f_print(fout, "%s\t}\n", sp);
1065
1066 if (inetdflag) {
1067 f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
1068 f_print(fout, "%s\tproto = IPPROTO_%s;\n",
1069 sp, isudp ? "UDP": "TCP");
1070 }
1071 for (l = defined; l != NULL; l = l->next) {
1072 def = (definition *) l->val;
1073 if (def->def_kind != DEF_PROGRAM)
1074 continue;
1075 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1076 f_print(fout, "%s\tif (!svc_register(%s, %s, %s,\n",
1077 sp, TRANSP, def->def_name, vp->vers_name);
1078 f_print(fout, "%s\t ", sp);
1079 pvname(def->def_name, vp->vers_num);
1080 if (inetdflag)
1081 f_print(fout, ", proto)) {\n");
1082 else
1083 f_print(fout, ", IPPROTO_%s)) {\n",
1084 isudp ? "UDP": "TCP");
1085 print_err_message(tmpbuf,
1086 "unable to register (%s, %s, %s).",
1087 def->def_name, vp->vers_name, transp);
1088 f_print(fout, "%s\t\texit(1);\n", sp);
1089 f_print(fout, "%s\t}\n", sp);
1090 }
1091 }
1092 if (inetdflag)
1093 f_print(fout, "\t}\n");
1094 }