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