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