]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.bin/rpcgen/rpc_svcout.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 static 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 definition 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                                 fputs(proc->args.argname, fout);
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                                 if (streq(proc->res_type, "void")) {
437                                         continue;
438                                 }
439                                 f_print(fout, "\t\t");
440                                 ptype(proc->res_prefix, proc->res_type, 0);
441                                 pvname(proc->proc_name, vp->vers_num);
442                                 f_print(fout, "_res;\n");
443                         }
444                         f_print(fout, "\t} %s;\n", RESULT);
445                         f_print(fout, "\tbool_t %s;\n", RETVAL);
446                         
447                 } else
448                         f_print(fout, "\tchar *%s;\n", RESULT);
449
450                 f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
451                 if (mtflag)
452                         f_print(fout,
453                                 "\tbool_t (*%s)(char *, void *, struct svc_req *);\n",
454                                 ROUTINE);
455                 else
456                         f_print(fout,
457                                 "\tchar *(*%s)(char *, struct svc_req *);\n",
458                                 ROUTINE);
459                 f_print(fout, "\n");
460
461                 if (timerflag) {
462                         if (mtflag)
463                                 f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n");
464
465                         f_print(fout, "\t_rpcsvcstate = _SERVING;\n");                          
466                         if (mtflag)
467                                 f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n");
468                 }
469
470                 f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
471                 if (!nullproc(vp->procs)) {
472                         f_print(fout, "\tcase NULLPROC:\n");
473                         f_print(fout,
474                                 "\t\t(void) svc_sendreply(%s,\n\t\t\t"
475                                 "(xdrproc_t) xdr_void, (char *)NULL);\n",
476                                 TRANSP);
477                         print_return("\t\t");
478                         f_print(fout, "\n");
479                 }
480                 for (proc = vp->procs; proc != NULL; proc = proc->next) {
481                         f_print(fout, "\tcase %s:\n", proc->proc_name);
482                         if (proc->arg_num < 2) { /* single argument */
483                                 p_xdrfunc(ARG, proc->args.decls->decl.type);
484                         } else {
485                                 p_xdrfunc(ARG, proc->args.argname);
486                         }
487                         p_xdrfunc(RESULT, proc->res_type);
488
489                         if (mtflag)
490                                 f_print(fout,
491                                         "\t\t%s = (bool_t (*) (char *,  void *,  struct svc_req *))",
492                                         ROUTINE);
493                         else
494                                 f_print(fout,
495                                         "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
496                                         ROUTINE);
497                         if (newstyle) { /* new style: calls internal routine */
498                                 f_print(fout, "_");
499                         }
500                         if (!newstyle)
501                                 pvname_svc(proc->proc_name, vp->vers_num);
502                         else
503                                 pvname(proc->proc_name, vp->vers_num);
504                         f_print(fout, ";\n");
505                         f_print(fout, "\t\tbreak;\n\n");
506                 }
507                 f_print(fout, "\tdefault:\n");
508                 printerr("noproc", TRANSP);
509                 print_return("\t\t");
510                 f_print(fout, "\t}\n");
511
512                 f_print(fout,
513                         "\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
514                         ARG, ARG);
515                 printif("getargs", TRANSP, "(caddr_t) &", ARG);
516                 printerr("decode", TRANSP);
517                 print_return("\t\t");
518                 f_print(fout, "\t}\n");
519
520                 if (!mtflag)
521                         f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
522                                 RESULT, ROUTINE, ARG, RQSTP);
523                 else
524                         f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n",
525                                 RETVAL, ROUTINE, ARG, RESULT, RQSTP);
526
527
528                 if (mtflag)
529                         f_print(fout,
530                                 "\tif (%s > 0 && !svc_sendreply(%s, xdr_%s, (char *)&%s)) {\n",
531                                 RETVAL, TRANSP, RESULT, RESULT);
532                 else
533                         f_print(fout,
534                                 "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n",
535                                 RESULT, TRANSP, RESULT, RESULT);
536
537                 printerr("systemerr", TRANSP);
538                 f_print(fout, "\t}\n");
539
540                 printif("freeargs", TRANSP, "(caddr_t) &", ARG);
541                 (void) sprintf(_errbuf, "unable to free arguments");
542                 print_err_message("\t\t");
543                 f_print(fout, "\t\texit(1);\n");
544                 f_print(fout, "\t}\n");
545                 /* print out free routine */
546                 if (mtflag) {
547                         f_print(fout,"\tif (!");
548                         pvname(def->def_name, vp->vers_num);
549                         f_print(fout,"_freeresult(%s, xdr_%s, (caddr_t) &%s))\n",
550                                 TRANSP, RESULT, RESULT);
551                         (void) sprintf(_errbuf, "unable to free results");
552                         print_err_message("\t\t");
553                         f_print(fout, "\n");
554                 };
555                 print_return("\t");
556                 f_print(fout, "}\n");
557         }
558 }
559
560 static void
561 printerr(const char *err, const char *transp)
562 {
563         f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
564 }
565
566 static void
567 printif(const char *proc, const char *transp, const char *prefix,
568     const char *arg)
569 {
570         f_print(fout, "\tif (!svc_%s(%s, xdr_%s, (char *)%s%s)) {\n",
571                 proc, transp, arg, prefix, arg);
572 }
573
574 int
575 nullproc(proc_list *proc)
576 {
577         for (; proc != NULL; proc = proc->next) {
578                 if (streq(proc->proc_num, "0")) {
579                         return (1);
580                 }
581         }
582         return (0);
583 }
584
585 static void
586 write_inetmost(const char *infile)
587 {
588         f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
589         f_print(fout, "\tint sock;\n");
590         f_print(fout, "\tint proto;\n");
591         f_print(fout, "\tstruct sockaddr_in saddr;\n");
592         f_print(fout, "\tsocklen_t asize = sizeof (saddr);\n");
593         f_print(fout, "\n");
594         f_print(fout,
595         "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
596         f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n\n");
597         f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
598         f_print(fout, "\t\t\texit(1);\n");
599         f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
600         f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
601         f_print(fout, "\t\t\texit(1);\n");
602         f_print(fout, "\t\tsock = 0;\n");
603         f_print(fout, "\t\t_rpcpmstart = 1;\n");
604         f_print(fout, "\t\tproto = 0;\n");
605         open_log_file(infile, "\t\t");
606         f_print(fout, "\t} else {\n");
607         write_rpc_svc_fg(infile, "\t\t");
608         f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
609         print_pmapunset("\t\t");
610         f_print(fout, "\t}\n");
611 }
612
613 static void
614 print_return(const char *space)
615 {
616         if (exitnow)
617                 f_print(fout, "%sexit(0);\n", space);
618         else {
619                 if (timerflag) {
620                         if (mtflag)
621                                 f_print(fout, "%spthread_mutex_lock(&_svcstate_lock);\n", space);
622                                 f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space);
623                         if (mtflag)
624                                 f_print(fout, "%spthread_mutex_unlock(&_svcstate_lock);\n", space);
625                 }
626                 f_print(fout, "%sreturn;\n", space);
627         }
628 }
629
630 static void
631 print_pmapunset(const char *space)
632 {
633         list *l;
634         definition *def;
635         version_list *vp;
636
637         for (l = defined; l != NULL; l = l->next) {
638                 def = (definition *) l->val;
639                 if (def->def_kind == DEF_PROGRAM) {
640                         for (vp = def->def.pr.versions; vp != NULL;
641                                         vp = vp->next) {
642                                 f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
643                                         space, def->def_name, vp->vers_name);
644                         }
645                 }
646         }
647 }
648
649 static void
650 print_err_message(const char *space)
651 {
652         if (logflag)
653                 f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf);
654         else if (inetdflag || pmflag)
655                 f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
656         else
657                 f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
658 }
659
660 /*
661  * Write the server auxiliary function (_msgout, timeout)
662  */
663 void
664 write_svc_aux(int nomain)
665 {
666         if (!logflag)
667                 write_msg_out();
668         if (!nomain)
669                 write_timeout_func();
670 }
671
672 /*
673  * Write the _msgout function
674  */
675
676 static void
677 write_msg_out(void)
678 {
679         f_print(fout, "\n");
680 /*
681  * Avoid making _msgout() static -- it's useful to have it visible
682  * in the toplevel RPC server code.
683  */
684         f_print(fout, "static\n");
685         f_print(fout, "void _msgout(const char* msg)\n");
686         f_print(fout, "{\n");
687         f_print(fout, "#ifdef RPC_SVC_FG\n");
688         if (inetdflag || pmflag)
689                 f_print(fout, "\tif (_rpcpmstart)\n");
690         f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
691         f_print(fout, "\telse\n");
692         f_print(fout,
693                 "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
694         f_print(fout, "#else\n");
695         f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
696         f_print(fout, "#endif\n");
697         f_print(fout, "}\n");
698 }
699
700 /*
701  * Write the timeout function
702  */
703 static void
704 write_timeout_func(void)
705 {
706         if (!timerflag)
707                 return;
708
709         f_print(fout, "\n");
710         f_print(fout, "static void\n");
711         f_print(fout, "closedown(int sig)\n");
712         f_print(fout, "{\n");
713         if (mtflag)
714                 f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n");
715         f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\n");
716         f_print(fout, "\t\textern fd_set svc_fdset;\n");
717         f_print(fout, "\t\tstatic int size;\n");
718         f_print(fout, "\t\tint i, openfd;\n");
719         if (tirpcflag && pmflag) {
720                 f_print(fout, "\t\tstruct t_info tinfo;\n\n");
721                 f_print(fout,
722                         "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
723         } else {
724                 f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
725         }
726         f_print(fout, "\t\t\texit(0);\n");
727         f_print(fout, "\t\tif (size == 0) {\n");
728         if (tirpcflag) {
729                 f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
730                 f_print(fout, "\t\t\trl.rlim_max = 0;\n");
731                 f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n");
732                 f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0) {\n");
733                 
734                 if (mtflag)
735                         f_print(fout, "\t\t\t\tpthread_mutex_unlock(&_svcstate_lock);\n");
736
737                 f_print(fout, "\t\t\t\treturn;\n\t\t\t}\n");
738         } else {
739                 f_print(fout, "\t\t\tsize = getdtablesize();\n");
740         }
741         f_print(fout, "\t\t}\n");
742         f_print(fout,
743                 "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
744         f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
745         f_print(fout, "\t\t\t\topenfd++;\n");
746         f_print(fout, "\t\tif (openfd <= 1)\n");
747         f_print(fout, "\t\t\texit(0);\n");
748         f_print(fout, "\t}\n");
749         f_print(fout, "\tif (_rpcsvcstate == _SERVED)\n");
750         f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n");
751         if (mtflag)
752                 f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n");
753
754         f_print(fout, "\t(void) signal(SIGALRM, closedown);\n");
755         f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
756         f_print(fout, "}\n");
757
758 }
759
760 /*
761  * Write the most of port monitor support
762  */
763 static void
764 write_pm_most(const char *infile, int netflag)
765 {
766         list *l;
767         definition *def;
768         version_list *vp;
769
770         if (tirpc_socket) {
771                 f_print(fout,
772                 "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
773                 f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n");
774         } else {
775                 f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
776                 f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
777                 f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
778         }
779         f_print(fout, "\t\tchar *netid;\n");
780         if (!netflag) { /* Not included by -n option */
781                 f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
782                 f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
783         }
784         if (timerflag)
785                 f_print(fout, "\t\tint pmclose;\n");
786 /*
787  *  Not necessary, defined in /usr/include/stdlib
788  *  f_print(fout, "\t\textern char *getenv();\n");
789  */
790         f_print(fout, "\n");
791         if (tirpc_socket) {
792                 f_print(fout, "\t\tif (saddr.ss_family != AF_INET &&\n");
793                 f_print(fout, "\t\t    saddr.ss_family != AF_INET6)\n");
794                 f_print(fout, "\t\t\texit(1);\n");
795                 f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
796                 f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
797                 f_print(fout, "\t\t\texit(1);\n");
798         }
799         f_print(fout, "\t\t_rpcpmstart = 1;\n");
800         open_log_file(infile, "\t\t");
801         f_print(fout, "\n\t\tif ((netid = \
802 getenv(\"NLSPROVIDER\")) == NULL) {\n");
803
804         if (timerflag) {
805                 f_print(fout, "\t\t/* started from inetd */\n");
806                 f_print(fout, "\t\t\tpmclose = 1;\n");
807         }
808         f_print(fout,
809                 "\t\t} else {\n");
810         f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n");
811         sprintf(_errbuf, "cannot get transport info");
812         print_err_message("\t\t\t\t");
813        if (timerflag) {
814                 if (tirpc_socket)
815                         f_print(fout, "\n\t\t\tpmclose = 1;\t/* XXX */\n");
816                 else
817                         f_print(fout,
818                             "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
819         }
820         f_print(fout, "\t\t}\n");
821         /*
822          * A kludgy support for inetd services. Inetd only works with
823          * sockmod, and RPC works only with timod, hence all this jugglery
824          */
825         if (!tirpc_socket) {
826                 f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
827                 f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ");
828                 f_print(fout, "ioctl(0, I_PUSH, \"timod\")) {\n");
829                 sprintf(_errbuf, "could not get the right module");
830                 print_err_message("\t\t\t\t");
831                 f_print(fout, "\t\t\t\texit(1);\n");
832                 f_print(fout, "\t\t\t}\n");
833                 f_print(fout, "\t\t}\n");
834         }
835         if (tirpcflag) {
836                 f_print(fout,
837                 "\t\tif ((%s = svc_tli_create(0, nconf, NULL, \
838                 RPC_MAXDATASIZE, RPC_MAXDATASIZE)) \
839                 == NULL) {\n",
840                 TRANSP);
841         } else {
842                 f_print(fout,
843                     "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) \
844                     == NULL) {\n",
845                     TRANSP);
846         }
847         sprintf(_errbuf, "cannot create server handle");
848         print_err_message("\t\t\t");
849         f_print(fout, "\t\t\texit(1);\n");
850         f_print(fout, "\t\t}\n");
851         f_print(fout, "\t\tif (nconf)\n");
852         f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
853         for (l = defined; l != NULL; l = l->next) {
854                 def = (definition *) l->val;
855                 if (def->def_kind != DEF_PROGRAM) {
856                         continue;
857                 }
858                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
859                         f_print(fout,
860                                 "\t\tif (!svc_reg(%s, %s, %s, ",
861                                 TRANSP, def->def_name, vp->vers_name);
862                         pvname(def->def_name, vp->vers_num);
863                         f_print(fout, ", 0)) {\n");
864                         (void) sprintf(_errbuf, "unable to register (%s, %s).",
865                                         def->def_name, vp->vers_name);
866                         print_err_message("\t\t\t");
867                         f_print(fout, "\t\t\texit(1);\n");
868                         f_print(fout, "\t\t}\n");
869                 }
870         }
871         if (timerflag) {
872                 f_print(fout, "\t\tif (pmclose) {\n");
873                 f_print(fout, "\t\t\t(void) signal(SIGALRM, closedown);\n");
874                 f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
875                 f_print(fout, "\t\t}\n");
876         }
877         f_print(fout, "\t\tsvc_run();\n");
878         f_print(fout, "\t\texit(1);\n");
879         f_print(fout, "\t\t/* NOTREACHED */\n");
880         f_print(fout, "\t}");
881 }
882
883 /*
884  * Support for backgrounding the server if self started.
885  */
886 static void
887 write_rpc_svc_fg(const char *infile, const char *sp)
888 {
889         f_print(fout, "#ifndef RPC_SVC_FG\n");
890         f_print(fout, "%sint size;\n", sp);
891         if (tirpcflag)
892                 f_print(fout, "%sstruct rlimit rl;\n", sp);
893         if (inetdflag)
894                 f_print(fout, "%sint pid, i;\n\n", sp);
895         f_print(fout, "%spid = fork();\n", sp);
896         f_print(fout, "%sif (pid < 0) {\n", sp);
897         f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
898         f_print(fout, "%s\texit(1);\n", sp);
899         f_print(fout, "%s}\n", sp);
900         f_print(fout, "%sif (pid)\n", sp);
901         f_print(fout, "%s\texit(0);\n", sp);
902         /* get number of file descriptors */
903         if (tirpcflag) {
904                 f_print(fout, "%srl.rlim_max = 0;\n", sp);
905                 f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
906                 f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
907                 f_print(fout, "%s\texit(1);\n", sp);
908         } else {
909                 f_print(fout, "%ssize = getdtablesize();\n", sp);
910         }
911
912         f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp);
913         f_print(fout, "%s\t(void) close(i);\n", sp);
914         /* Redirect stderr and stdout to console */
915         f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp);
916         f_print(fout, "%s(void) dup2(i, 1);\n", sp);
917         f_print(fout, "%s(void) dup2(i, 2);\n", sp);
918         /* This removes control of the controlling terminal */
919         if (tirpcflag)
920                 f_print(fout, "%ssetsid();\n", sp);
921         else {
922                 f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
923                 f_print(fout, "%sif (i >= 0) {\n", sp);
924                 f_print(fout,
925                         "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
926                 f_print(fout, "%s\t(void) close(i);\n", sp);
927                 f_print(fout, "%s}\n", sp);
928         }
929         if (!logflag)
930                 open_log_file(infile, sp);
931         f_print(fout, "#endif\n");
932         if (logflag)
933                 open_log_file(infile, sp);
934 }
935
936 static void
937 open_log_file(const char *infile, const char *sp)
938 {
939         char *s;
940
941         s = strrchr(infile, '.');
942         if (s)
943                 *s = '\0';
944         f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
945         if (s)
946                 *s = '.';
947 }
948
949
950
951
952 /*
953  * write a registration for the given transport for Inetd
954  */
955 void
956 write_inetd_register(const char *transp)
957 {
958         list *l;
959         definition *def;
960         version_list *vp;
961         const char *sp;
962         int isudp;
963         char tmpbuf[32];
964
965         if (inetdflag)
966                 sp = "\t";
967         else
968                 sp = "";
969         if (streq(transp, "udp"))
970                 isudp = 1;
971         else
972                 isudp = 0;
973         f_print(fout, "\n");
974         if (inetdflag) {
975                 f_print(fout,
976                         "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
977                         isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
978         }
979         f_print(fout, "%s\t%s = svc%s_create(%s",
980                 sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
981         if (!isudp)
982                 f_print(fout, ", 0, 0");
983         f_print(fout, ");\n");
984         f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
985         (void) sprintf(_errbuf, "cannot create %s service.", transp);
986         (void) sprintf(tmpbuf, "%s\t\t", sp);
987         print_err_message(tmpbuf);
988         f_print(fout, "%s\t\texit(1);\n", sp);
989         f_print(fout, "%s\t}\n", sp);
990
991         if (inetdflag) {
992                 f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
993                 f_print(fout, "%s\tproto = IPPROTO_%s;\n",
994                                 sp, isudp ? "UDP": "TCP");
995         }
996         for (l = defined; l != NULL; l = l->next) {
997                 def = (definition *) l->val;
998                 if (def->def_kind != DEF_PROGRAM) {
999                         continue;
1000                 }
1001                 for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
1002                         f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
1003                                 sp, TRANSP, def->def_name, vp->vers_name);
1004                         pvname(def->def_name, vp->vers_num);
1005                         if (inetdflag)
1006                                 f_print(fout, ", proto)) {\n");
1007                         else
1008                                 f_print(fout, ", IPPROTO_%s)) {\n",
1009                                         isudp ? "UDP": "TCP");
1010                         (void) sprintf(_errbuf,
1011                                 "unable to register (%s, %s, %s).",
1012                                 def->def_name, vp->vers_name, transp);
1013                         print_err_message(tmpbuf);
1014                         f_print(fout, "%s\t\texit(1);\n", sp);
1015                         f_print(fout, "%s\t}\n", sp);
1016                 }
1017         }
1018         if (inetdflag)
1019                 f_print(fout, "\t}\n");
1020 }