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