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