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