Fix "make xcheck" in sunrpc.
[platform/upstream/glibc.git] / sunrpc / rpc_main.c
1 /*
2  * From @(#)rpc_main.c 1.30 89/03/30
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials
14  *       provided with the distribution.
15  *     * Neither the name of the "Oracle America, Inc." nor the names of its
16  *       contributors may be used to endorse or promote products derived
17  *       from this software without specific prior written permission.
18  *
19  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * rpc_main.c, Top level of the RPC protocol compiler.
35  */
36
37 #include <errno.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <libintl.h>
42 #include <ctype.h>
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/file.h>
46 #include <sys/stat.h>
47 #include <sys/wait.h>
48 #include "rpc_parse.h"
49 #include "rpc_util.h"
50 #include "rpc_scan.h"
51 #include "proto.h"
52
53 #include "../version.h"
54 #define PACKAGE _libc_intl_domainname
55
56 #define EXTEND  1               /* alias for TRUE */
57 #define DONT_EXTEND     0       /* alias for FALSE */
58
59 struct commandline
60   {
61     int cflag;                  /* xdr C routines */
62     int hflag;                  /* header file */
63     int lflag;                  /* client side stubs */
64     int mflag;                  /* server side stubs */
65     int nflag;                  /* netid flag */
66     int sflag;                  /* server stubs for the given transport */
67     int tflag;                  /* dispatch Table file */
68     int Ssflag;                 /* produce server sample code */
69     int Scflag;                 /* produce client sample code */
70     int makefileflag;           /* Generate a template Makefile */
71     const char *infile;         /* input module name */
72     const char *outfile;        /* output module name */
73   };
74
75
76 static const char *cmdname;
77
78 #define SVR4_CPP "/usr/ccs/lib/cpp"
79 #define SUNOS_CPP "/lib/cpp"
80
81 static const char *svcclosetime = "120";
82 static int cppDefined;  /* explicit path for C preprocessor */
83 static const char *CPP = SUNOS_CPP;
84 static const char CPPFLAGS[] = "-C";
85 static char *pathbuf;
86 static int cpp_pid;
87 static const char *allv[] =
88 {
89   "rpcgen", "-s", "udp", "-s", "tcp"
90 };
91 static int allc = sizeof (allv) / sizeof (allv[0]);
92 static const char *allnv[] =
93 {
94   "rpcgen", "-s", "netpath",
95 };
96 static int allnc = sizeof (allnv) / sizeof (allnv[0]);
97
98 /*
99  * machinations for handling expanding argument list
100  */
101 static void addarg (const char *);      /* add another argument to the list */
102 static void putarg (int, const char *);         /* put argument at specified location */
103 static void clear_args (void);  /* clear argument list */
104 static void checkfiles (const char *, const char *);
105                                        /* check if out file already exists */
106
107 static void clear_args (void);
108 static char *extendfile (const char *file, const char *ext);
109 static void open_output (const char *infile, const char *outfile);
110 static void add_warning (void);
111 static void clear_args (void);
112 static void find_cpp (void);
113 static void open_input (const char *infile, const char *define);
114 static int check_nettype (const char *name, const char *list_to_check[]);
115 static void c_output (const char *infile, const char *define,
116                       int extend, const char *outfile);
117 static void h_output (const char *infile, const char *define,
118                       int extend, const char *outfile);
119 static void s_output (int argc, const char *argv[], const char *infile,
120                       const char *define, int extend,
121                       const char *outfile, int nomain, int netflag);
122 static void l_output (const char *infile, const char *define,
123                       int extend, const char *outfile);
124 static void t_output (const char *infile, const char *define,
125                       int extend, const char *outfile);
126 static void svc_output (const char *infile, const char *define,
127                         int extend, const char *outfile);
128 static void clnt_output (const char *infile, const char *define,
129                          int extend, const char *outfile);
130 static void mkfile_output (struct commandline *cmd);
131 static int do_registers (int argc, const char *argv[]);
132 static void addarg (const char *cp);
133 static void putarg (int whereto, const char *cp);
134 static void checkfiles (const char *infile, const char *outfile);
135 static int parseargs (int argc, const char *argv[], struct commandline *cmd);
136 static void usage (FILE *stream, int status) __attribute__ ((noreturn));
137 static void options_usage (FILE *stream, int status) __attribute__ ((noreturn));
138 static void print_version (void);
139 static void c_initialize (void);
140 static char *generate_guard (const char *pathname);
141
142
143 #define ARGLISTLEN      20
144 #define FIXEDARGS         2
145
146 static const char *arglist[ARGLISTLEN];
147 static int argcount = FIXEDARGS;
148
149
150 int nonfatalerrors;             /* errors */
151 int inetdflag /* = 1 */ ;       /* Support for inetd *//* is now the default */
152 int pmflag;                     /* Support for port monitors */
153 int logflag;                    /* Use syslog instead of fprintf for errors */
154 int tblflag;                    /* Support for dispatch table file */
155 int mtflag;                     /* Support for MT */
156
157 #define INLINE 3
158 /*length at which to start doing an inline */
159
160 int inlineflag = INLINE;        /* length at which to start doing an inline. 3 = default
161                                    if 0, no xdr_inline code */
162
163 int indefinitewait;             /* If started by port monitors, hang till it wants */
164 int exitnow;                    /* If started by port monitors, exit after the call */
165 int timerflag;                  /* TRUE if !indefinite && !exitnow */
166 int newstyle;                   /* newstyle of passing arguments (by value) */
167 #ifdef __GNU_LIBRARY__
168 int Cflag = 1;                  /* ANSI C syntax */
169 #else
170 int Cflag;                      /* ANSI C/C++ syntax */
171 #endif
172 int CCflag;                     /* C++ files */
173 static int allfiles;            /* generate all files */
174 #ifdef __GNU_LIBRARY__
175 int tirpcflag;                  /* generating code for tirpc, by default */
176 #else
177 int tirpcflag = 1;              /* generating code for tirpc, by default */
178 #endif
179 xdrfunc *xdrfunc_head;          /* xdr function list */
180 xdrfunc *xdrfunc_tail;          /* xdr function list */
181
182 int
183 main (int argc, const char *argv[])
184 {
185   struct commandline cmd;
186
187   (void) memset ((char *) &cmd, 0, sizeof (struct commandline));
188   clear_args ();
189   if (!parseargs (argc, argv, &cmd))
190     usage (stderr, 1);
191
192   if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag ||
193       cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag)
194     {
195       checkfiles (cmd.infile, cmd.outfile);
196     }
197   else
198     checkfiles (cmd.infile, NULL);
199
200   if (cmd.cflag)
201     c_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
202   else if (cmd.hflag)
203     h_output (cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
204   else if (cmd.lflag)
205     l_output (cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
206   else if (cmd.sflag || cmd.mflag || (cmd.nflag))
207     s_output (argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
208               cmd.outfile, cmd.mflag, cmd.nflag);
209   else if (cmd.tflag)
210     t_output (cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
211   else if (cmd.Ssflag)
212     svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
213   else if (cmd.Scflag)
214     clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
215   else if (cmd.makefileflag)
216     mkfile_output (&cmd);
217   else
218     {
219       /* the rescans are required, since cpp may effect input */
220       c_output (cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
221       reinitialize ();
222       h_output (cmd.infile, "-DRPC_HDR", EXTEND, ".h");
223       reinitialize ();
224       l_output (cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
225       reinitialize ();
226       if (inetdflag || !tirpcflag)
227         s_output (allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
228                   "_svc.c", cmd.mflag, cmd.nflag);
229       else
230         s_output (allnc, allnv, cmd.infile, "-DRPC_SVC",
231                   EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
232       if (tblflag)
233         {
234           reinitialize ();
235           t_output (cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
236         }
237       if (allfiles)
238         {
239           reinitialize ();
240           svc_output (cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
241           reinitialize ();
242           clnt_output (cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
243         }
244       if (allfiles || (cmd.makefileflag == 1))
245         {
246           reinitialize ();
247           mkfile_output (&cmd);
248         }
249     }
250
251   return nonfatalerrors;
252 }
253
254 /*
255  * add extension to filename
256  */
257 static char *
258 extendfile (const char *file, const char *ext)
259 {
260   char *res;
261   const char *p;
262
263   res = alloc (strlen (file) + strlen (ext) + 1);
264   if (res == NULL)
265     abort ();
266   p = strrchr (file, '.');
267   if (p == NULL)
268     p = file + strlen (file);
269   strcpy (res, file);
270   strcpy (res + (p - file), ext);
271   return res;
272 }
273
274 /*
275  * Open output file with given extension
276  */
277 static void
278 open_output (const char *infile, const char *outfile)
279 {
280   if (outfile == NULL)
281     {
282       fout = stdout;
283       return;
284     }
285
286   if (infile != NULL && streq (outfile, infile))
287     {
288       fprintf (stderr, _ ("%s: output would overwrite %s\n"), cmdname,
289                infile);
290       crash ();
291     }
292   fout = fopen (outfile, "w");
293   if (fout == NULL)
294     {
295       fprintf (stderr, _ ("%s: unable to open %s: %m\n"), cmdname, outfile);
296       crash ();
297     }
298   record_open (outfile);
299 }
300
301 /* Close the output file and check for write errors.  */
302 static void
303 close_output (const char *outfile)
304 {
305   if (fclose (fout) == EOF)
306     {
307       fprintf (stderr, _("%s: while writing output %s: %m"), cmdname,
308                outfile ?: "<stdout>");
309       crash ();
310     }
311 }
312
313 static void
314 add_warning (void)
315 {
316   fprintf (fout, "/*\n");
317   fprintf (fout, " * Please do not edit this file.\n");
318   fprintf (fout, " * It was generated using rpcgen.\n");
319   fprintf (fout, " */\n\n");
320 }
321
322 /* clear list of arguments */
323 static void
324 clear_args (void)
325 {
326   int i;
327   for (i = FIXEDARGS; i < ARGLISTLEN; ++i)
328     arglist[i] = NULL;
329   argcount = FIXEDARGS;
330 }
331
332 /* make sure that a CPP exists */
333 static void
334 find_cpp (void)
335 {
336   struct stat buf;
337
338   if (stat (CPP, &buf) < 0)
339     {                           /* /lib/cpp or explicit cpp does not exist */
340       if (cppDefined)
341         {
342           fprintf (stderr, _ ("cannot find C preprocessor: %s \n"), CPP);
343           crash ();
344         }
345       else
346         {                       /* try the other one */
347           CPP = SVR4_CPP;
348           if (stat (CPP, &buf) < 0)
349             {                   /* can't find any cpp */
350               fputs (_ ("cannot find any C preprocessor (cpp)\n"), stdout);
351               crash ();
352             }
353         }
354     }
355 }
356
357 /*
358  * Open input file with given define for C-preprocessor
359  */
360 static void
361 open_input (const char *infile, const char *define)
362 {
363   int pd[2];
364
365   infilename = (infile == NULL) ? "<stdin>" : infile;
366   if (pipe (pd) != 0)
367     {
368       perror ("pipe");
369       exit (1);
370     }
371   cpp_pid = fork ();
372   switch (cpp_pid)
373     {
374     case 0:
375       find_cpp ();
376       putarg (0, CPP);
377       putarg (1, CPPFLAGS);
378       addarg (define);
379       if (infile)
380         addarg (infile);
381       addarg ((char *) NULL);
382       close (1);
383       dup2 (pd[1], 1);
384       close (pd[0]);
385       execv (arglist[0], (char **) arglist);
386       perror ("execv");
387       exit (1);
388     case -1:
389       perror ("fork");
390       exit (1);
391     }
392   close (pd[1]);
393   fin = fdopen (pd[0], "r");
394   if (fin == NULL)
395     {
396       fprintf (stderr, "%s: ", cmdname);
397       perror (infilename);
398       crash ();
399     }
400 }
401
402 /* Close the connection to the C-preprocessor and check for successfull
403    termination.  */
404 static void
405 close_input (void)
406 {
407   int status;
408
409   fclose (fin);
410   /* Check the termination status.  */
411   if (waitpid (cpp_pid, &status, 0) < 0)
412     {
413       perror ("waitpid");
414       crash ();
415     }
416   if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
417     {
418       if (WIFSIGNALED (status))
419         fprintf (stderr, _("%s: C preprocessor failed with signal %d\n"),
420                  cmdname, WTERMSIG (status));
421       else
422         fprintf (stderr, _("%s: C preprocessor failed with exit code %d\n"),
423                  cmdname, WEXITSTATUS (status));
424       crash ();
425     }
426 }
427
428 /* valid tirpc nettypes */
429 static const char *valid_ti_nettypes[] =
430 {
431   "netpath",
432   "visible",
433   "circuit_v",
434   "datagram_v",
435   "circuit_n",
436   "datagram_n",
437   "udp",
438   "tcp",
439   "raw",
440   NULL
441 };
442
443 /* valid inetd nettypes */
444 static const char *valid_i_nettypes[] =
445 {
446   "udp",
447   "tcp",
448   NULL
449 };
450
451 static int
452 check_nettype (const char *name, const char *list_to_check[])
453 {
454   int i;
455   for (i = 0; list_to_check[i] != NULL; i++)
456     {
457       if (strcmp (name, list_to_check[i]) == 0)
458         {
459           return 1;
460         }
461     }
462   fprintf (stderr, _ ("illegal nettype: `%s'\n"), name);
463   return 0;
464 }
465
466 /*
467  * Compile into an XDR routine output file
468  */
469
470 static void
471 c_output (const char *infile, const char *define, int extend,
472           const char *outfile)
473 {
474   definition *def;
475   char *include;
476   const char *outfilename;
477   long tell;
478
479   c_initialize ();
480   open_input (infile, define);
481   outfilename = extend ? extendfile (infile, outfile) : outfile;
482   open_output (infile, outfilename);
483   add_warning ();
484   if (infile && (include = extendfile (infile, ".h")))
485     {
486       fprintf (fout, "#include \"%s\"\n", include);
487       free (include);
488       /* .h file already contains rpc/rpc.h */
489     }
490   else
491     fprintf (fout, "#include <rpc/rpc.h>\n");
492   tell = ftell (fout);
493   while ((def = get_definition ()) != NULL)
494     emit (def);
495
496   if (extend && tell == ftell (fout))
497     unlink (outfilename);
498   close_input ();
499   close_output (outfilename);
500 }
501
502 void
503 c_initialize (void)
504 {
505
506   /* add all the starting basic types */
507
508   add_type (1, "int");
509   add_type (1, "long");
510   add_type (1, "short");
511   add_type (1, "bool");
512
513   add_type (1, "u_int");
514   add_type (1, "u_long");
515   add_type (1, "u_short");
516
517 }
518
519 char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
520         char    *(*proc)();\n\
521         xdrproc_t       xdr_arg;\n\
522         unsigned        len_arg;\n\
523         xdrproc_t       xdr_res;\n\
524         unsigned        len_res;\n\
525 };\n";
526
527
528 static char *
529 generate_guard (const char *pathname)
530 {
531   const char *filename;
532   char *guard, *tmp;
533
534   filename = strrchr (pathname, '/');   /* find last component */
535   filename = ((filename == NULL) ? pathname : filename + 1);
536   guard = extendfile (filename, "_H_RPCGEN");
537   /* convert to upper case */
538   tmp = guard;
539   while (*tmp)
540     {
541       if (islower (*tmp))
542         *tmp = toupper (*tmp);
543       tmp++;
544     }
545
546   return guard;
547 }
548
549 /*
550  * Compile into an XDR header file
551  */
552
553
554 static void
555 h_output (const char *infile, const char *define, int extend,
556           const char *outfile)
557 {
558   xdrfunc *xdrfuncp;
559   definition *def;
560   const char *ifilename;
561   const char *outfilename;
562   long tell;
563   char *guard;
564   list *l;
565
566   open_input (infile, define);
567   outfilename = extend ? extendfile (infile, outfile) : outfile;
568   open_output (infile, outfilename);
569   add_warning ();
570   ifilename = (infile == NULL) ? "STDIN" : infile;
571   guard = generate_guard (outfilename ? outfilename : ifilename);
572
573   fprintf (fout, "#ifndef _%s\n#define _%s\n\n", guard,
574            guard);
575
576   fprintf (fout, "#include <rpc/rpc.h>\n\n");
577
578   if (mtflag)
579     {
580       fprintf (fout, "#include <pthread.h>\n");
581     }
582
583   /* put the C++ support */
584   if (Cflag && !CCflag)
585     {
586       fprintf (fout, "\n#ifdef __cplusplus\n");
587       fprintf (fout, "extern \"C\" {\n");
588       fprintf (fout, "#endif\n\n");
589     }
590
591   tell = ftell (fout);
592   /* print data definitions */
593   while ((def = get_definition ()) != NULL)
594     {
595       print_datadef (def);
596     }
597
598   /* print function declarations.
599      Do this after data definitions because they might be used as
600      arguments for functions */
601   for (l = defined; l != NULL; l = l->next)
602     {
603       print_funcdef (l->val);
604     }
605   /* Now  print all xdr func declarations */
606   if (xdrfunc_head != NULL)
607     {
608       fprintf (fout, "\n/* the xdr functions */\n");
609       if (CCflag)
610         {
611           fprintf (fout, "\n#ifdef __cplusplus\n");
612           fprintf (fout, "extern \"C\" {\n");
613           fprintf (fout, "#endif\n");
614         }
615       if (!Cflag)
616         {
617           xdrfuncp = xdrfunc_head;
618           while (xdrfuncp != NULL)
619             {
620               print_xdr_func_def (xdrfuncp->name,
621                                   xdrfuncp->pointerp, 2);
622               xdrfuncp = xdrfuncp->next;
623             }
624         }
625       else
626         {
627           int i;
628
629           for (i = 1; i < 3; ++i)
630             {
631               if (i == 1)
632                 fprintf (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n");
633               else
634                 fprintf (fout, "\n#else /* K&R C */\n");
635
636               xdrfuncp = xdrfunc_head;
637               while (xdrfuncp != NULL)
638                 {
639                   print_xdr_func_def (xdrfuncp->name,
640                                       xdrfuncp->pointerp, i);
641                   xdrfuncp = xdrfuncp->next;
642                 }
643             }
644           fprintf (fout, "\n#endif /* K&R C */\n");
645         }
646     }
647
648   if (extend && tell == ftell (fout))
649     {
650       unlink (outfilename);
651     }
652   else if (tblflag)
653     {
654       fprintf (fout, rpcgen_table_dcl);
655     }
656
657   if (Cflag)
658     {
659       fprintf (fout, "\n#ifdef __cplusplus\n");
660       fprintf (fout, "}\n");
661       fprintf (fout, "#endif\n");
662     }
663
664   fprintf (fout, "\n#endif /* !_%s */\n", guard);
665   free (guard);
666   close_input ();
667   close_output (outfilename);
668 }
669
670 /*
671  * Compile into an RPC service
672  */
673 static void
674 s_output (int argc, const char *argv[], const char *infile, const char *define,
675           int extend, const char *outfile, int nomain, int netflag)
676 {
677   char *include;
678   definition *def;
679   int foundprogram = 0;
680   const char *outfilename;
681
682   open_input (infile, define);
683   outfilename = extend ? extendfile (infile, outfile) : outfile;
684   open_output (infile, outfilename);
685   add_warning ();
686   if (infile && (include = extendfile (infile, ".h")))
687     {
688       fprintf (fout, "#include \"%s\"\n", include);
689       free (include);
690     }
691   else
692     fprintf (fout, "#include <rpc/rpc.h>\n");
693
694   fprintf (fout, "#include <stdio.h>\n");
695   fprintf (fout, "#include <stdlib.h>\n");
696   fprintf (fout, "#include <rpc/pmap_clnt.h>\n");
697   if (Cflag)
698     fprintf (fout, "#include <string.h>\n");
699   if (strcmp (svcclosetime, "-1") == 0)
700     indefinitewait = 1;
701   else if (strcmp (svcclosetime, "0") == 0)
702     exitnow = 1;
703   else if (inetdflag || pmflag)
704     {
705       fprintf (fout, "#include <signal.h>\n");
706       timerflag = 1;
707     }
708
709   if (!tirpcflag && inetdflag)
710 #ifdef __GNU_LIBRARY__
711     fprintf (fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n");
712 #else
713     fprintf (fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
714 #endif
715   if (Cflag && (inetdflag || pmflag))
716     {
717 #ifdef __GNU_LIBRARY__
718       fprintf (fout, "#include <sys/types.h> /* open */\n");
719       fprintf (fout, "#include <sys/stat.h> /* open */\n");
720       fprintf (fout, "#include <fcntl.h> /* open */\n");
721       fprintf (fout, "#include <unistd.h> /* getdtablesize */\n");
722 #else
723       fprintf (fout, "#ifdef __cplusplus\n");
724       fprintf (fout, "#include <sysent.h> /* getdtablesize, open */\n");
725       fprintf (fout, "#endif /* __cplusplus */\n");
726       if (tirpcflag)
727         fprintf (fout, "#include <unistd.h> /* setsid */\n");
728 #endif
729     }
730 #ifdef __GNU_LIBRARY__
731   if (tirpcflag && !(Cflag && (inetdflag || pmflag)))
732 #else
733   if (tirpcflag)
734 #endif
735     fprintf (fout, "#include <sys/types.h>\n");
736
737   fprintf (fout, "#include <memory.h>\n");
738 #ifndef __GNU_LIBRARY__
739   fprintf (fout, "#include <stropts.h>\n");
740 #endif
741   if (inetdflag || !tirpcflag)
742     {
743       fprintf (fout, "#include <sys/socket.h>\n");
744       fprintf (fout, "#include <netinet/in.h>\n");
745     }
746
747   if ((netflag || pmflag) && tirpcflag && !nomain)
748     {
749       fprintf (fout, "#include <netconfig.h>\n");
750     }
751   if ( /*timerflag && */ tirpcflag)
752     fprintf (fout, "#include <sys/resource.h> /* rlimit */\n");
753   if (logflag || inetdflag || pmflag)
754     {
755 #ifdef __GNU_LIBRARY__
756       fprintf (fout, "#include <syslog.h>\n");
757 #else
758       fprintf (fout, "#ifdef SYSLOG\n");
759       fprintf (fout, "#include <syslog.h>\n");
760       fprintf (fout, "#else\n");
761       fprintf (fout, "#define LOG_ERR 1\n");
762       fprintf (fout, "#define openlog(a, b, c)\n");
763       fprintf (fout, "#endif\n");
764 #endif
765     }
766
767   /* for ANSI-C */
768   if (Cflag)
769     fprintf (fout, "\n#ifndef SIG_PF\n#define SIG_PF void(*)(int)\n#endif\n");
770
771 #ifndef __GNU_LIBRARY__
772   fprintf (fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
773 #endif
774   if (timerflag)
775     fprintf (fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
776   while ((def = get_definition ()) != NULL)
777     {
778       foundprogram |= (def->def_kind == DEF_PROGRAM);
779     }
780   if (extend && !foundprogram)
781     {
782       unlink (outfilename);
783       return;
784     }
785   write_most (infile, netflag, nomain);
786   if (!nomain)
787     {
788       if (!do_registers (argc, argv))
789         {
790           if (outfilename)
791             unlink (outfilename);
792           usage (stderr, 1);
793         }
794       write_rest ();
795     }
796   close_input ();
797   close_output (outfilename);
798 }
799
800 /*
801  * generate client side stubs
802  */
803 static void
804 l_output (const char *infile, const char *define, int extend,
805           const char *outfile)
806 {
807   char *include;
808   definition *def;
809   int foundprogram = 0;
810   const char *outfilename;
811
812   open_input (infile, define);
813   outfilename = extend ? extendfile (infile, outfile) : outfile;
814   open_output (infile, outfilename);
815   add_warning ();
816   if (Cflag)
817     fprintf (fout, "#include <memory.h> /* for memset */\n");
818   if (infile && (include = extendfile (infile, ".h")))
819     {
820       fprintf (fout, "#include \"%s\"\n", include);
821       free (include);
822     }
823   else
824     fprintf (fout, "#include <rpc/rpc.h>\n");
825   while ((def = get_definition ()) != NULL)
826     {
827       foundprogram |= (def->def_kind == DEF_PROGRAM);
828     }
829   if (extend && !foundprogram)
830     {
831       unlink (outfilename);
832       return;
833     }
834   write_stubs ();
835   close_input ();
836   close_output (outfilename);
837 }
838
839 /*
840  * generate the dispatch table
841  */
842 static void
843 t_output (const char *infile, const char *define, int extend,
844           const char *outfile)
845 {
846   definition *def;
847   int foundprogram = 0;
848   const char *outfilename;
849
850   open_input (infile, define);
851   outfilename = extend ? extendfile (infile, outfile) : outfile;
852   open_output (infile, outfilename);
853   add_warning ();
854   while ((def = get_definition ()) != NULL)
855     {
856       foundprogram |= (def->def_kind == DEF_PROGRAM);
857     }
858   if (extend && !foundprogram)
859     {
860       unlink (outfilename);
861       return;
862     }
863   write_tables ();
864   close_input ();
865   close_output (outfilename);
866 }
867
868 /* sample routine for the server template */
869 static void
870 svc_output (const char *infile, const char *define, int extend,
871             const char *outfile)
872 {
873   definition *def;
874   char *include;
875   const char *outfilename;
876   long tell;
877
878   open_input (infile, define);
879   outfilename = extend ? extendfile (infile, outfile) : outfile;
880   checkfiles (infile, outfilename);
881   /*check if outfile already exists.
882      if so, print an error message and exit */
883   open_output (infile, outfilename);
884   add_sample_msg ();
885
886   if (infile && (include = extendfile (infile, ".h")))
887     {
888       fprintf (fout, "#include \"%s\"\n", include);
889       free (include);
890     }
891   else
892     fprintf (fout, "#include <rpc/rpc.h>\n");
893
894   tell = ftell (fout);
895   while ((def = get_definition ()) != NULL)
896     {
897       write_sample_svc (def);
898     }
899   if (extend && tell == ftell (fout))
900     {
901       unlink (outfilename);
902     }
903   close_input ();
904   close_output (outfilename);
905 }
906
907
908 /* sample main routine for client */
909 static void
910 clnt_output (const char *infile, const char *define, int extend,
911              const char *outfile)
912 {
913   definition *def;
914   char *include;
915   const char *outfilename;
916   long tell;
917   int has_program = 0;
918
919   open_input (infile, define);
920   outfilename = extend ? extendfile (infile, outfile) : outfile;
921   checkfiles (infile, outfilename);
922   /*check if outfile already exists.
923      if so, print an error message and exit */
924
925   open_output (infile, outfilename);
926   add_sample_msg ();
927   if (infile && (include = extendfile (infile, ".h")))
928     {
929       fprintf (fout, "#include \"%s\"\n", include);
930       free (include);
931     }
932   else
933     fprintf (fout, "#include <rpc/rpc.h>\n");
934   tell = ftell (fout);
935   while ((def = get_definition ()) != NULL)
936     {
937       has_program += write_sample_clnt (def);
938     }
939
940   if (has_program)
941     write_sample_clnt_main ();
942
943   if (extend && tell == ftell (fout))
944     {
945       unlink (outfilename);
946     }
947   close_input ();
948   close_output (outfilename);
949 }
950
951 static const char space[] = " ";
952
953 static char *
954 file_name (const char *file, const char *ext)
955 {
956   char *temp;
957   temp = extendfile (file, ext);
958
959   if (access (temp, F_OK) != -1)
960     return (temp);
961
962   free (temp);
963   return (char *) space;
964 }
965
966 static void
967 mkfile_output (struct commandline *cmd)
968 {
969   char *mkfilename;
970   char *clientname, *clntname, *xdrname, *hdrname;
971   char *servername, *svcname, *servprogname, *clntprogname;
972
973   svcname = file_name (cmd->infile, "_svc.c");
974   clntname = file_name (cmd->infile, "_clnt.c");
975   xdrname = file_name (cmd->infile, "_xdr.c");
976   hdrname = file_name (cmd->infile, ".h");
977
978   if (allfiles)
979     {
980       servername = extendfile (cmd->infile, "_server.c");
981       clientname = extendfile (cmd->infile, "_client.c");
982     }
983   else
984     {
985       servername = (char *) space;
986       clientname = (char *) space;
987     }
988   servprogname = extendfile (cmd->infile, "_server");
989   clntprogname = extendfile (cmd->infile, "_client");
990
991   if (allfiles)
992     {
993       char *cp, *temp;
994
995       mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1);
996       if (mkfilename == NULL)
997         abort ();
998       temp = rindex (cmd->infile, '.');
999       cp = stpcpy (mkfilename, "Makefile.");
1000       if (temp != NULL)
1001         *((char *) stpncpy (cp, cmd->infile, temp - cmd->infile)) = '\0';
1002       else
1003         stpcpy (cp, cmd->infile);
1004
1005     }
1006   else
1007     mkfilename = (char *) cmd->outfile;
1008
1009   checkfiles (NULL, mkfilename);
1010   open_output (NULL, mkfilename);
1011
1012   fprintf (fout, "\n# This is a template Makefile generated by rpcgen\n");
1013
1014   f_print (fout, "\n# Parameters\n\n");
1015
1016   f_print (fout, "CLIENT = %s\nSERVER = %s\n\n", clntprogname, servprogname);
1017   f_print (fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n");
1018   f_print (fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n");
1019   f_print (fout, "SOURCES.x = %s\n\n", cmd->infile);
1020   f_print (fout, "TARGETS_SVC.c = %s %s %s \n",
1021            svcname, servername, xdrname);
1022   f_print (fout, "TARGETS_CLNT.c = %s %s %s \n",
1023            clntname, clientname, xdrname);
1024   f_print (fout, "TARGETS = %s %s %s %s %s %s\n\n",
1025            hdrname, xdrname, clntname,
1026            svcname, clientname, servername);
1027
1028   f_print (fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \
1029 $(TARGETS_CLNT.c:%%.c=%%.o)");
1030
1031   f_print (fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \
1032 $(TARGETS_SVC.c:%%.c=%%.o)");
1033
1034   f_print (fout, "\n# Compiler flags \n");
1035   if (mtflag)
1036     fprintf (fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS \
1037 += -lnsl -lpthread \n ");
1038   else
1039     f_print (fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n");
1040   f_print (fout, "RPCGENFLAGS = \n");
1041
1042   f_print (fout, "\n# Targets \n\n");
1043
1044   f_print (fout, "all : $(CLIENT) $(SERVER)\n\n");
1045   f_print (fout, "$(TARGETS) : $(SOURCES.x) \n");
1046   f_print (fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n");
1047   f_print (fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \
1048 $(TARGETS_CLNT.c) \n\n");
1049
1050   f_print (fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \
1051 $(TARGETS_SVC.c) \n\n");
1052   f_print (fout, "$(CLIENT) : $(OBJECTS_CLNT) \n");
1053   f_print (fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \
1054 $(LDLIBS) \n\n");
1055   f_print (fout, "$(SERVER) : $(OBJECTS_SVC) \n");
1056   f_print (fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n ");
1057   f_print (fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \
1058 $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n");
1059   close_output (mkfilename);
1060
1061   free (clntprogname);
1062   free (servprogname);
1063   if (servername != space)
1064     free (servername);
1065   if (clientname != space)
1066     free (clientname);
1067   if (mkfilename != (char *) cmd->outfile)
1068     free (mkfilename);
1069   if (svcname != space)
1070     free (svcname);
1071   if (clntname != space)
1072     free (clntname);
1073   if (xdrname != space)
1074     free (xdrname);
1075   if (hdrname != space)
1076     free (hdrname);
1077 }
1078
1079 /*
1080  * Perform registrations for service output
1081  * Return 0 if failed; 1 otherwise.
1082  */
1083 static int
1084 do_registers (int argc, const char *argv[])
1085 {
1086   int i;
1087
1088   if (inetdflag || !tirpcflag)
1089     {
1090       for (i = 1; i < argc; i++)
1091         {
1092           if (streq (argv[i], "-s"))
1093             {
1094               if (!check_nettype (argv[i + 1], valid_i_nettypes))
1095                 return 0;
1096               write_inetd_register (argv[i + 1]);
1097               i++;
1098             }
1099         }
1100     }
1101   else
1102     {
1103       for (i = 1; i < argc; i++)
1104         if (streq (argv[i], "-s"))
1105           {
1106             if (!check_nettype (argv[i + 1], valid_ti_nettypes))
1107               return 0;
1108             write_nettype_register (argv[i + 1]);
1109             i++;
1110           }
1111         else if (streq (argv[i], "-n"))
1112           {
1113             write_netid_register (argv[i + 1]);
1114             i++;
1115           }
1116     }
1117   return 1;
1118 }
1119
1120 /*
1121  * Add another argument to the arg list
1122  */
1123 static void
1124 addarg (const char *cp)
1125 {
1126   if (argcount >= ARGLISTLEN)
1127     {
1128       fprintf (stderr, _("rpcgen: too many defines\n"));
1129       crash ();
1130       /*NOTREACHED */
1131     }
1132   arglist[argcount++] = cp;
1133 }
1134
1135 static void
1136 putarg (int whereto, const char *cp)
1137 {
1138   if (whereto >= ARGLISTLEN)
1139     {
1140       fprintf (stderr, _("rpcgen: arglist coding error\n"));
1141       crash ();
1142       /*NOTREACHED */
1143     }
1144   arglist[whereto] = cp;
1145 }
1146
1147 /*
1148  * if input file is stdin and an output file is specified then complain
1149  * if the file already exists. Otherwise the file may get overwritten
1150  * If input file does not exist, exit with an error
1151  */
1152
1153 static void
1154 checkfiles (const char *infile, const char *outfile)
1155 {
1156   struct stat buf;
1157
1158   if (infile)                   /* infile ! = NULL */
1159     if (stat (infile, &buf) < 0)
1160       {
1161         perror (infile);
1162         crash ();
1163       }
1164   if (outfile)
1165     {
1166       if (stat (outfile, &buf) < 0)
1167         return;                 /* file does not exist */
1168       else
1169         {
1170           fprintf (stderr,
1171                    /* TRANS: the file will not be removed; this is an
1172                       TRANS: informative message.  */
1173                    _("file `%s' already exists and may be overwritten\n"),
1174                    outfile);
1175           crash ();
1176         }
1177     }
1178 }
1179
1180 /*
1181  * Parse command line arguments
1182  */
1183 static int
1184 parseargs (int argc, const char *argv[], struct commandline *cmd)
1185 {
1186   int i;
1187   int j;
1188   int c;
1189   char flag[(1 << 8 * sizeof (char))];
1190   int nflags;
1191
1192   cmdname = argv[0];
1193   cmd->infile = cmd->outfile = NULL;
1194   if (argc < 2)
1195     {
1196       return (0);
1197     }
1198   allfiles = 0;
1199   flag['c'] = 0;
1200   flag['h'] = 0;
1201   flag['l'] = 0;
1202   flag['m'] = 0;
1203   flag['o'] = 0;
1204   flag['s'] = 0;
1205   flag['n'] = 0;
1206   flag['t'] = 0;
1207   flag['S'] = 0;
1208   flag['C'] = 0;
1209   flag['M'] = 0;
1210
1211   for (i = 1; i < argc; i++)
1212     {
1213       if (argv[i][0] != '-')
1214         {
1215           if (cmd->infile)
1216             {
1217               fprintf (stderr,
1218                        _("Cannot specify more than one input file!\n"));
1219               return 0;
1220             }
1221           cmd->infile = argv[i];
1222         }
1223       else if (strcmp (argv[i], "--help") == 0)
1224         usage (stdout, 0);
1225       else if (strcmp (argv[i], "--version") == 0)
1226         print_version ();
1227       else
1228         {
1229           for (j = 1; argv[i][j] != 0; j++)
1230             {
1231               c = argv[i][j];
1232               switch (c)
1233                 {
1234                 case 'a':
1235                   allfiles = 1;
1236                   break;
1237                 case 'c':
1238                 case 'h':
1239                 case 'l':
1240                 case 'm':
1241                 case 't':
1242                   if (flag[c])
1243                     return 0;
1244                   flag[c] = 1;
1245                   break;
1246                 case 'S':
1247                   /* sample flag: Ss or Sc.
1248                      Ss means set flag['S'];
1249                      Sc means set flag['C'];
1250                      Sm means set flag['M']; */
1251                   c = argv[i][++j];     /* get next char */
1252                   if (c == 's')
1253                     c = 'S';
1254                   else if (c == 'c')
1255                     c = 'C';
1256                   else if (c == 'm')
1257                     c = 'M';
1258                   else
1259                     return 0;
1260
1261                   if (flag[c])
1262                     return 0;
1263                   flag[c] = 1;
1264                   break;
1265                 case 'C':       /* ANSI C syntax */
1266                   Cflag = 1;
1267                   break;
1268
1269 #ifdef __GNU_LIBRARY__
1270                 case 'k':  /* K&R C syntax */
1271                   Cflag = 0;
1272                   break;
1273
1274 #endif
1275                 case 'b':  /* turn TIRPC flag off for
1276                               generating backward compatible
1277                            */
1278                   tirpcflag = 0;
1279                   break;
1280
1281 #ifdef __GNU_LIBRARY__
1282                 case '5':  /* turn TIRPC flag on for
1283                               generating SysVr4 compatible
1284                            */
1285                   tirpcflag = 1;
1286                   break;
1287 #endif
1288                 case 'I':
1289                   inetdflag = 1;
1290                   break;
1291                 case 'N':
1292                   newstyle = 1;
1293                   break;
1294                 case 'L':
1295                   logflag = 1;
1296                   break;
1297                 case 'K':
1298                   if (++i == argc)
1299                     {
1300                       return (0);
1301                     }
1302                   svcclosetime = argv[i];
1303                   goto nextarg;
1304                 case 'T':
1305                   tblflag = 1;
1306                   break;
1307                 case 'M':
1308                   mtflag = 1;
1309                   break;
1310                 case 'i':
1311                   if (++i == argc)
1312                     {
1313                       return (0);
1314                     }
1315                   inlineflag = atoi (argv[i]);
1316                   goto nextarg;
1317                 case 'n':
1318                 case 'o':
1319                 case 's':
1320                   if (argv[i][j - 1] != '-' ||
1321                       argv[i][j + 1] != 0)
1322                     {
1323                       return (0);
1324                     }
1325                   flag[c] = 1;
1326                   if (++i == argc)
1327                     {
1328                       return (0);
1329                     }
1330                   if (c == 's')
1331                     {
1332                       if (!streq (argv[i], "udp") &&
1333                           !streq (argv[i], "tcp"))
1334                         return 0;
1335                     }
1336                   else if (c == 'o')
1337                     {
1338                       if (cmd->outfile)
1339                         return 0;
1340                       cmd->outfile = argv[i];
1341                     }
1342                   goto nextarg;
1343                 case 'D':
1344                   if (argv[i][j - 1] != '-')
1345                     return 0;
1346                   addarg (argv[i]);
1347                   goto nextarg;
1348                 case 'Y':
1349                   if (++i == argc)
1350                     return 0;
1351                   {
1352                     size_t len = strlen (argv[i]);
1353                     pathbuf = malloc (len + 5);
1354                     if (pathbuf == NULL)
1355                       {
1356                         perror (cmdname);
1357                         crash ();
1358                       }
1359                     stpcpy (stpcpy (pathbuf,
1360                                     argv[i]),
1361                             "/cpp");
1362                     CPP = pathbuf;
1363                     cppDefined = 1;
1364                     goto nextarg;
1365                   }
1366
1367                 default:
1368                   return 0;
1369                 }
1370               }
1371         nextarg:
1372           ;
1373         }
1374     }
1375
1376   cmd->cflag = flag['c'];
1377   cmd->hflag = flag['h'];
1378   cmd->lflag = flag['l'];
1379   cmd->mflag = flag['m'];
1380   cmd->nflag = flag['n'];
1381   cmd->sflag = flag['s'];
1382   cmd->tflag = flag['t'];
1383   cmd->Ssflag = flag['S'];
1384   cmd->Scflag = flag['C'];
1385   cmd->makefileflag = flag['M'];
1386
1387 #ifndef _RPC_THREAD_SAFE_
1388   if (mtflag || newstyle)
1389     {
1390       /* glibc doesn't support these flags.  */
1391       f_print (stderr,
1392                _("This implementation doesn't support newstyle or MT-safe code!\n"));
1393       return (0);
1394     }
1395 #endif
1396   if (tirpcflag)
1397     {
1398       pmflag = inetdflag ? 0 : 1;    /* pmflag or inetdflag is always TRUE */
1399       if ((inetdflag && cmd->nflag))
1400         {                       /* netid not allowed with inetdflag */
1401           fprintf (stderr, _("Cannot use netid flag with inetd flag!\n"));
1402           return 0;
1403         }
1404     }
1405   else
1406     {                           /* 4.1 mode */
1407       pmflag = 0;               /* set pmflag only in tirpcmode */
1408 #ifndef __GNU_LIBRARY__
1409       inetdflag = 1;            /* inetdflag is TRUE by default */
1410 #endif
1411       if (cmd->nflag)
1412         {                       /* netid needs TIRPC */
1413           f_print (stderr, _("Cannot use netid flag without TIRPC!\n"));
1414           return (0);
1415         }
1416     }
1417
1418   if (newstyle && (tblflag || cmd->tflag))
1419     {
1420       f_print (stderr, _("Cannot use table flags with newstyle!\n"));
1421       return (0);
1422     }
1423
1424   /* check no conflicts with file generation flags */
1425   nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
1426     cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
1427
1428   if (nflags == 0)
1429     {
1430       if (cmd->outfile != NULL || cmd->infile == NULL)
1431         {
1432           return (0);
1433         }
1434     }
1435   else if (cmd->infile == NULL &&
1436            (cmd->Ssflag || cmd->Scflag || cmd->makefileflag))
1437     {
1438       fprintf (stderr,
1439                _("\"infile\" is required for template generation flags.\n"));
1440       return 0;
1441     }
1442   if (nflags > 1)
1443     {
1444       fprintf (stderr, _("Cannot have more than one file generation flag!\n"));
1445       return 0;
1446     }
1447   return 1;
1448 }
1449
1450 static void
1451 usage (FILE *stream, int status)
1452 {
1453   fprintf (stream, _("usage: %s infile\n"), cmdname);
1454   fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \
1455 [-I [-K seconds]] [-Y path] infile\n"), cmdname);
1456   fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \
1457 [-o outfile] [infile]\n"), cmdname);
1458   fprintf (stream, _("\t%s [-s nettype]* [-o outfile] [infile]\n"), cmdname);
1459   fprintf (stream, _("\t%s [-n netid]* [-o outfile] [infile]\n"), cmdname);
1460   options_usage (stream, status);
1461   exit (status);
1462 }
1463
1464 static void
1465 options_usage (FILE *stream, int status)
1466 {
1467   f_print (stream, _("options:\n"));
1468   f_print (stream, _("-a\t\tgenerate all files, including samples\n"));
1469   f_print (stream, _("-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n"));
1470   f_print (stream, _("-c\t\tgenerate XDR routines\n"));
1471   f_print (stream, _("-C\t\tANSI C mode\n"));
1472   f_print (stream, _("-Dname[=value]\tdefine a symbol (same as #define)\n"));
1473   f_print (stream, _("-h\t\tgenerate header file\n"));
1474   f_print (stream, _("-i size\t\tsize at which to start generating inline code\n"));
1475   f_print (stream, _("-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n"));
1476   f_print (stream, _("-K seconds\tserver exits after K seconds of inactivity\n"));
1477   f_print (stream, _("-l\t\tgenerate client side stubs\n"));
1478   f_print (stream, _("-L\t\tserver errors will be printed to syslog\n"));
1479   f_print (stream, _("-m\t\tgenerate server side stubs\n"));
1480   f_print (stream, _("-M\t\tgenerate MT-safe code\n"));
1481   f_print (stream, _("-n netid\tgenerate server code that supports named netid\n"));
1482   f_print (stream, _("-N\t\tsupports multiple arguments and call-by-value\n"));
1483   f_print (stream, _("-o outfile\tname of the output file\n"));
1484   f_print (stream, _("-s nettype\tgenerate server code that supports named nettype\n"));
1485   f_print (stream, _("-Sc\t\tgenerate sample client code that uses remote procedures\n"));
1486   f_print (stream, _("-Ss\t\tgenerate sample server code that defines remote procedures\n"));
1487   f_print (stream, _("-Sm \t\tgenerate makefile template \n"));
1488   f_print (stream, _("-t\t\tgenerate RPC dispatch table\n"));
1489   f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n"));
1490   f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n"));
1491
1492   f_print (stream, "\n%s", _("\
1493 For bug reporting instructions, please see:\n\
1494 <http://www.gnu.org/software/libc/bugs.html>.\n"));
1495   exit (status);
1496 }
1497
1498 static void
1499 print_version (void)
1500 {
1501   printf ("rpcgen (GNU %s) %s\n", PACKAGE, VERSION);
1502   exit (0);
1503 }