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