| /* | 
 |  * From @(#)rpc_main.c 1.30 89/03/30 | 
 |  * | 
 |  * Copyright (c) 2010, Oracle America, Inc. | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions are | 
 |  * met: | 
 |  * | 
 |  *     * Redistributions of source code must retain the above copyright | 
 |  *       notice, this list of conditions and the following disclaimer. | 
 |  *     * Redistributions in binary form must reproduce the above | 
 |  *       copyright notice, this list of conditions and the following | 
 |  *       disclaimer in the documentation and/or other materials | 
 |  *       provided with the distribution. | 
 |  *     * Neither the name of the "Oracle America, Inc." nor the names of its | 
 |  *       contributors may be used to endorse or promote products derived | 
 |  *       from this software without specific prior written permission. | 
 |  * | 
 |  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 |  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 |  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
 |  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
 |  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | 
 |  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 
 |  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
 |  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 
 |  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
 |  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 |  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  */ | 
 |  | 
 | /* | 
 |  * rpc_main.c, Top level of the RPC protocol compiler. | 
 |  */ | 
 |  | 
 | #include <errno.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 | #include <libintl.h> | 
 | #include <locale.h> | 
 | #include <ctype.h> | 
 | #include <sys/types.h> | 
 | #include <sys/param.h> | 
 | #include <sys/file.h> | 
 | #include <sys/stat.h> | 
 | #include <sys/wait.h> | 
 | #include "rpc_parse.h" | 
 | #include "rpc_util.h" | 
 | #include "rpc_scan.h" | 
 | #include "proto.h" | 
 |  | 
 | #include "../version.h" | 
 | #define PACKAGE _libc_intl_domainname | 
 |  | 
 | #define EXTEND	1		/* alias for TRUE */ | 
 | #define DONT_EXTEND	0	/* alias for FALSE */ | 
 |  | 
 | struct commandline | 
 |   { | 
 |     int cflag;			/* xdr C routines */ | 
 |     int hflag;			/* header file */ | 
 |     int lflag;			/* client side stubs */ | 
 |     int mflag;			/* server side stubs */ | 
 |     int nflag;			/* netid flag */ | 
 |     int sflag;			/* server stubs for the given transport */ | 
 |     int tflag;			/* dispatch Table file */ | 
 |     int Ssflag;			/* produce server sample code */ | 
 |     int Scflag;			/* produce client sample code */ | 
 |     int makefileflag;		/* Generate a template Makefile */ | 
 |     const char *infile;		/* input module name */ | 
 |     const char *outfile;	/* output module name */ | 
 |   }; | 
 |  | 
 |  | 
 | static const char *cmdname; | 
 |  | 
 | static const char *svcclosetime = "120"; | 
 | static int cppDefined;	/* explicit path for C preprocessor */ | 
 | static const char *CPP = "/lib/cpp"; | 
 | static const char CPPFLAGS[] = "-C"; | 
 | static char *pathbuf; | 
 | static int cpp_pid; | 
 | static const char *allv[] = | 
 | { | 
 |   "rpcgen", "-s", "udp", "-s", "tcp" | 
 | }; | 
 | static int allc = sizeof (allv) / sizeof (allv[0]); | 
 | static const char *allnv[] = | 
 | { | 
 |   "rpcgen", "-s", "netpath", | 
 | }; | 
 | static int allnc = sizeof (allnv) / sizeof (allnv[0]); | 
 |  | 
 | /* | 
 |  * machinations for handling expanding argument list | 
 |  */ | 
 | static void addarg (const char *);	/* add another argument to the list */ | 
 | static void putarg (int, const char *);		/* put argument at specified location */ | 
 | static void clear_args (void);	/* clear argument list */ | 
 | static void checkfiles (const char *, const char *); | 
 | 				       /* check if out file already exists */ | 
 |  | 
 | static void clear_args (void); | 
 | static char *extendfile (const char *file, const char *ext); | 
 | static void open_output (const char *infile, const char *outfile); | 
 | static void add_warning (void); | 
 | static void clear_args (void); | 
 | static void find_cpp (void); | 
 | static void open_input (const char *infile, const char *define); | 
 | static int check_nettype (const char *name, const char *list_to_check[]); | 
 | static void c_output (const char *infile, const char *define, | 
 | 		      int extend, const char *outfile); | 
 | static void h_output (const char *infile, const char *define, | 
 | 		      int extend, const char *outfile); | 
 | static void s_output (int argc, const char *argv[], const char *infile, | 
 | 		      const char *define, int extend, | 
 | 		      const char *outfile, int nomain, int netflag); | 
 | static void l_output (const char *infile, const char *define, | 
 | 		      int extend, const char *outfile); | 
 | static void t_output (const char *infile, const char *define, | 
 | 		      int extend, const char *outfile); | 
 | static void svc_output (const char *infile, const char *define, | 
 | 			int extend, const char *outfile); | 
 | static void clnt_output (const char *infile, const char *define, | 
 | 			 int extend, const char *outfile); | 
 | static void mkfile_output (struct commandline *cmd); | 
 | static int do_registers (int argc, const char *argv[]); | 
 | static void addarg (const char *cp); | 
 | static void putarg (int whereto, const char *cp); | 
 | static void checkfiles (const char *infile, const char *outfile); | 
 | static int parseargs (int argc, const char *argv[], struct commandline *cmd); | 
 | static void usage (FILE *stream, int status) __attribute__ ((noreturn)); | 
 | static void options_usage (FILE *stream, int status) __attribute__ ((noreturn)); | 
 | static void print_version (void); | 
 | static void c_initialize (void); | 
 | static char *generate_guard (const char *pathname); | 
 |  | 
 |  | 
 | #define ARGLISTLEN	20 | 
 | #define FIXEDARGS         2 | 
 |  | 
 | static const char *arglist[ARGLISTLEN]; | 
 | static int argcount = FIXEDARGS; | 
 |  | 
 |  | 
 | int nonfatalerrors;		/* errors */ | 
 | int inetdflag /* = 1 */ ;	/* Support for inetd *//* is now the default */ | 
 | int pmflag;			/* Support for port monitors */ | 
 | int logflag;			/* Use syslog instead of fprintf for errors */ | 
 | int tblflag;			/* Support for dispatch table file */ | 
 | int mtflag;			/* Support for MT */ | 
 |  | 
 | #define INLINE 3 | 
 | /*length at which to start doing an inline */ | 
 |  | 
 | int inlineflag = INLINE;	/* length at which to start doing an inline. 3 = default | 
 | 				   if 0, no xdr_inline code */ | 
 |  | 
 | int indefinitewait;		/* If started by port monitors, hang till it wants */ | 
 | int exitnow;			/* If started by port monitors, exit after the call */ | 
 | int timerflag;			/* TRUE if !indefinite && !exitnow */ | 
 | int newstyle;			/* newstyle of passing arguments (by value) */ | 
 | int Cflag = 1;			/* ANSI C syntax */ | 
 | int CCflag;			/* C++ files */ | 
 | static int allfiles;		/* generate all files */ | 
 | int tirpcflag;			/* generating code for tirpc, by default */ | 
 | xdrfunc *xdrfunc_head;		/* xdr function list */ | 
 | xdrfunc *xdrfunc_tail;		/* xdr function list */ | 
 |  | 
 | int | 
 | main (int argc, const char *argv[]) | 
 | { | 
 |   struct commandline cmd; | 
 |  | 
 |   setlocale (LC_ALL, ""); | 
 |   textdomain (_libc_intl_domainname); | 
 |  | 
 |   (void) memset ((char *) &cmd, 0, sizeof (struct commandline)); | 
 |   clear_args (); | 
 |   if (!parseargs (argc, argv, &cmd)) | 
 |     usage (stderr, 1); | 
 |  | 
 |   if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || | 
 |       cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) | 
 |     { | 
 |       checkfiles (cmd.infile, cmd.outfile); | 
 |     } | 
 |   else | 
 |     checkfiles (cmd.infile, NULL); | 
 |  | 
 |   if (cmd.cflag) | 
 |     c_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.hflag) | 
 |     h_output (cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.lflag) | 
 |     l_output (cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.sflag || cmd.mflag || (cmd.nflag)) | 
 |     s_output (argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, | 
 | 	      cmd.outfile, cmd.mflag, cmd.nflag); | 
 |   else if (cmd.tflag) | 
 |     t_output (cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.Ssflag) | 
 |     svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.Scflag) | 
 |     clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); | 
 |   else if (cmd.makefileflag) | 
 |     mkfile_output (&cmd); | 
 |   else | 
 |     { | 
 |       /* the rescans are required, since cpp may effect input */ | 
 |       c_output (cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); | 
 |       reinitialize (); | 
 |       h_output (cmd.infile, "-DRPC_HDR", EXTEND, ".h"); | 
 |       reinitialize (); | 
 |       l_output (cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); | 
 |       reinitialize (); | 
 |       if (inetdflag || !tirpcflag) | 
 | 	s_output (allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, | 
 | 		  "_svc.c", cmd.mflag, cmd.nflag); | 
 |       else | 
 | 	s_output (allnc, allnv, cmd.infile, "-DRPC_SVC", | 
 | 		  EXTEND, "_svc.c", cmd.mflag, cmd.nflag); | 
 |       if (tblflag) | 
 | 	{ | 
 | 	  reinitialize (); | 
 | 	  t_output (cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); | 
 | 	} | 
 |       if (allfiles) | 
 | 	{ | 
 | 	  reinitialize (); | 
 | 	  svc_output (cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); | 
 | 	  reinitialize (); | 
 | 	  clnt_output (cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); | 
 | 	} | 
 |       if (allfiles || (cmd.makefileflag == 1)) | 
 | 	{ | 
 | 	  reinitialize (); | 
 | 	  mkfile_output (&cmd); | 
 | 	} | 
 |     } | 
 |  | 
 |   return nonfatalerrors; | 
 | } | 
 |  | 
 | /* | 
 |  * add extension to filename | 
 |  */ | 
 | static char * | 
 | extendfile (const char *file, const char *ext) | 
 | { | 
 |   char *res; | 
 |   const char *p; | 
 |  | 
 |   res = alloc (strlen (file) + strlen (ext) + 1); | 
 |   if (res == NULL) | 
 |     abort (); | 
 |   p = strrchr (file, '.'); | 
 |   if (p == NULL) | 
 |     p = file + strlen (file); | 
 |   strcpy (res, file); | 
 |   strcpy (res + (p - file), ext); | 
 |   return res; | 
 | } | 
 |  | 
 | /* | 
 |  * Open output file with given extension | 
 |  */ | 
 | static void | 
 | open_output (const char *infile, const char *outfile) | 
 | { | 
 |   if (outfile == NULL) | 
 |     { | 
 |       fout = stdout; | 
 |       return; | 
 |     } | 
 |  | 
 |   if (infile != NULL && streq (outfile, infile)) | 
 |     { | 
 |       fprintf (stderr, _ ("%s: output would overwrite %s\n"), cmdname, | 
 | 	       infile); | 
 |       crash (); | 
 |     } | 
 |   fout = fopen (outfile, "w"); | 
 |   if (fout == NULL) | 
 |     { | 
 |       fprintf (stderr, _ ("%s: unable to open %s: %m\n"), cmdname, outfile); | 
 |       crash (); | 
 |     } | 
 |   record_open (outfile); | 
 | } | 
 |  | 
 | /* Close the output file and check for write errors.  */ | 
 | static void | 
 | close_output (const char *outfile) | 
 | { | 
 |   if (fclose (fout) == EOF) | 
 |     { | 
 |       fprintf (stderr, _("%s: while writing output %s: %m"), cmdname, | 
 | 	       outfile ?: "<stdout>"); | 
 |       crash (); | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | add_warning (void) | 
 | { | 
 |   fprintf (fout, "/*\n"); | 
 |   fprintf (fout, " * Please do not edit this file.\n"); | 
 |   fprintf (fout, " * It was generated using rpcgen.\n"); | 
 |   fprintf (fout, " */\n\n"); | 
 | } | 
 |  | 
 | /* clear list of arguments */ | 
 | static void | 
 | clear_args (void) | 
 | { | 
 |   int i; | 
 |   for (i = FIXEDARGS; i < ARGLISTLEN; ++i) | 
 |     arglist[i] = NULL; | 
 |   argcount = FIXEDARGS; | 
 | } | 
 |  | 
 | /* make sure that a CPP exists */ | 
 | static void | 
 | find_cpp (void) | 
 | { | 
 |   struct stat64 buf; | 
 |  | 
 |   if (stat64 (CPP, &buf) == 0) | 
 |     return; | 
 |  | 
 |   if (cppDefined) /* user specified cpp but it does not exist */ | 
 |     { | 
 |       fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); | 
 |       crash (); | 
 |     } | 
 |  | 
 |   /* fall back to system CPP */ | 
 |   CPP = "cpp"; | 
 | } | 
 |  | 
 | /* | 
 |  * Open input file with given define for C-preprocessor | 
 |  */ | 
 | static void | 
 | open_input (const char *infile, const char *define) | 
 | { | 
 |   int pd[2]; | 
 |  | 
 |   infilename = (infile == NULL) ? "<stdin>" : infile; | 
 |   if (pipe (pd) != 0) | 
 |     { | 
 |       perror ("pipe"); | 
 |       exit (1); | 
 |     } | 
 |   cpp_pid = fork (); | 
 |   switch (cpp_pid) | 
 |     { | 
 |     case 0: | 
 |       find_cpp (); | 
 |       putarg (0, CPP); | 
 |       putarg (1, CPPFLAGS); | 
 |       addarg (define); | 
 |       if (infile) | 
 | 	addarg (infile); | 
 |       addarg ((char *) NULL); | 
 |       close (1); | 
 |       dup2 (pd[1], 1); | 
 |       close (pd[0]); | 
 |       execvp (arglist[0], (char **) arglist); | 
 |       if (errno == ENOENT) | 
 |         { | 
 |           fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); | 
 |           exit (1); | 
 |         } | 
 |       perror ("execvp"); | 
 |       exit (1); | 
 |     case -1: | 
 |       perror ("fork"); | 
 |       exit (1); | 
 |     } | 
 |   close (pd[1]); | 
 |   fin = fdopen (pd[0], "r"); | 
 |   if (fin == NULL) | 
 |     { | 
 |       fprintf (stderr, "%s: ", cmdname); | 
 |       perror (infilename); | 
 |       crash (); | 
 |     } | 
 | } | 
 |  | 
 | /* Close the connection to the C-preprocessor and check for successfull | 
 |    termination.  */ | 
 | static void | 
 | close_input (void) | 
 | { | 
 |   int status; | 
 |  | 
 |   fclose (fin); | 
 |   /* Check the termination status.  */ | 
 |   if (waitpid (cpp_pid, &status, 0) < 0) | 
 |     { | 
 |       perror ("waitpid"); | 
 |       crash (); | 
 |     } | 
 |   if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0) | 
 |     { | 
 |       if (WIFSIGNALED (status)) | 
 | 	fprintf (stderr, _("%s: C preprocessor failed with signal %d\n"), | 
 | 		 cmdname, WTERMSIG (status)); | 
 |       else | 
 | 	fprintf (stderr, _("%s: C preprocessor failed with exit code %d\n"), | 
 | 		 cmdname, WEXITSTATUS (status)); | 
 |       crash (); | 
 |     } | 
 | } | 
 |  | 
 | /* valid tirpc nettypes */ | 
 | static const char *valid_ti_nettypes[] = | 
 | { | 
 |   "netpath", | 
 |   "visible", | 
 |   "circuit_v", | 
 |   "datagram_v", | 
 |   "circuit_n", | 
 |   "datagram_n", | 
 |   "udp", | 
 |   "tcp", | 
 |   "raw", | 
 |   NULL | 
 | }; | 
 |  | 
 | /* valid inetd nettypes */ | 
 | static const char *valid_i_nettypes[] = | 
 | { | 
 |   "udp", | 
 |   "tcp", | 
 |   NULL | 
 | }; | 
 |  | 
 | static int | 
 | check_nettype (const char *name, const char *list_to_check[]) | 
 | { | 
 |   int i; | 
 |   for (i = 0; list_to_check[i] != NULL; i++) | 
 |     { | 
 |       if (strcmp (name, list_to_check[i]) == 0) | 
 | 	{ | 
 | 	  return 1; | 
 | 	} | 
 |     } | 
 |   fprintf (stderr, _ ("illegal nettype: `%s'\n"), name); | 
 |   return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * Compile into an XDR routine output file | 
 |  */ | 
 |  | 
 | static void | 
 | c_output (const char *infile, const char *define, int extend, | 
 | 	  const char *outfile) | 
 | { | 
 |   definition *def; | 
 |   char *include; | 
 |   const char *outfilename; | 
 |   long tell; | 
 |  | 
 |   c_initialize (); | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   open_output (infile, outfilename); | 
 |   add_warning (); | 
 |   if (infile && (include = extendfile (infile, ".h"))) | 
 |     { | 
 |       fprintf (fout, "#include \"%s\"\n", include); | 
 |       free (include); | 
 |       /* .h file already contains rpc/rpc.h */ | 
 |     } | 
 |   else | 
 |     fprintf (fout, "#include <rpc/rpc.h>\n"); | 
 |   tell = ftell (fout); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     emit (def); | 
 |  | 
 |   if (extend && tell == ftell (fout)) | 
 |     unlink (outfilename); | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | void | 
 | c_initialize (void) | 
 | { | 
 |  | 
 |   /* add all the starting basic types */ | 
 |  | 
 |   add_type (1, "int"); | 
 |   add_type (1, "long"); | 
 |   add_type (1, "short"); | 
 |   add_type (1, "bool"); | 
 |  | 
 |   add_type (1, "u_int"); | 
 |   add_type (1, "u_long"); | 
 |   add_type (1, "u_short"); | 
 |  | 
 | } | 
 |  | 
 | char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ | 
 | 	char	*(*proc)();\n\ | 
 | 	xdrproc_t	xdr_arg;\n\ | 
 | 	unsigned	len_arg;\n\ | 
 | 	xdrproc_t	xdr_res;\n\ | 
 | 	unsigned	len_res;\n\ | 
 | };\n"; | 
 |  | 
 |  | 
 | static char * | 
 | generate_guard (const char *pathname) | 
 | { | 
 |   const char *filename; | 
 |   char *guard, *tmp; | 
 |  | 
 |   filename = strrchr (pathname, '/');	/* find last component */ | 
 |   filename = ((filename == NULL) ? pathname : filename + 1); | 
 |   guard = extendfile (filename, "_H_RPCGEN"); | 
 |   /* convert to upper case */ | 
 |   tmp = guard; | 
 |   while (*tmp) | 
 |     { | 
 |       if (islower (*tmp)) | 
 | 	*tmp = toupper (*tmp); | 
 |       tmp++; | 
 |     } | 
 |  | 
 |   return guard; | 
 | } | 
 |  | 
 | /* | 
 |  * Compile into an XDR header file | 
 |  */ | 
 |  | 
 |  | 
 | static void | 
 | h_output (const char *infile, const char *define, int extend, | 
 | 	  const char *outfile) | 
 | { | 
 |   xdrfunc *xdrfuncp; | 
 |   definition *def; | 
 |   const char *ifilename; | 
 |   const char *outfilename; | 
 |   long tell; | 
 |   char *guard; | 
 |   list *l; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   open_output (infile, outfilename); | 
 |   add_warning (); | 
 |   ifilename = (infile == NULL) ? "STDIN" : infile; | 
 |   guard = generate_guard (outfilename ? outfilename : ifilename); | 
 |  | 
 |   fprintf (fout, "#ifndef _%s\n#define _%s\n\n", guard, | 
 | 	   guard); | 
 |  | 
 |   fprintf (fout, "#include <rpc/rpc.h>\n\n"); | 
 |  | 
 |   if (mtflag) | 
 |     { | 
 |       fprintf (fout, "#include <pthread.h>\n"); | 
 |     } | 
 |  | 
 |   /* put the C++ support */ | 
 |   if (Cflag && !CCflag) | 
 |     { | 
 |       fprintf (fout, "\n#ifdef __cplusplus\n"); | 
 |       fprintf (fout, "extern \"C\" {\n"); | 
 |       fprintf (fout, "#endif\n\n"); | 
 |     } | 
 |  | 
 |   tell = ftell (fout); | 
 |   /* print data definitions */ | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       print_datadef (def); | 
 |     } | 
 |  | 
 |   /* print function declarations. | 
 |      Do this after data definitions because they might be used as | 
 |      arguments for functions */ | 
 |   for (l = defined; l != NULL; l = l->next) | 
 |     { | 
 |       print_funcdef (l->val); | 
 |     } | 
 |   /* Now  print all xdr func declarations */ | 
 |   if (xdrfunc_head != NULL) | 
 |     { | 
 |       fprintf (fout, "\n/* the xdr functions */\n"); | 
 |       if (CCflag) | 
 | 	{ | 
 | 	  fprintf (fout, "\n#ifdef __cplusplus\n"); | 
 | 	  fprintf (fout, "extern \"C\" {\n"); | 
 | 	  fprintf (fout, "#endif\n"); | 
 | 	} | 
 |       if (!Cflag) | 
 | 	{ | 
 | 	  xdrfuncp = xdrfunc_head; | 
 | 	  while (xdrfuncp != NULL) | 
 | 	    { | 
 | 	      print_xdr_func_def (xdrfuncp->name, | 
 | 				  xdrfuncp->pointerp, 2); | 
 | 	      xdrfuncp = xdrfuncp->next; | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  int i; | 
 |  | 
 | 	  for (i = 1; i < 3; ++i) | 
 | 	    { | 
 | 	      if (i == 1) | 
 | 		fprintf (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); | 
 | 	      else | 
 | 		fprintf (fout, "\n#else /* K&R C */\n"); | 
 |  | 
 | 	      xdrfuncp = xdrfunc_head; | 
 | 	      while (xdrfuncp != NULL) | 
 | 		{ | 
 | 		  print_xdr_func_def (xdrfuncp->name, | 
 | 				      xdrfuncp->pointerp, i); | 
 | 		  xdrfuncp = xdrfuncp->next; | 
 | 		} | 
 | 	    } | 
 | 	  fprintf (fout, "\n#endif /* K&R C */\n"); | 
 | 	} | 
 |     } | 
 |  | 
 |   if (extend && tell == ftell (fout)) | 
 |     { | 
 |       unlink (outfilename); | 
 |     } | 
 |   else if (tblflag) | 
 |     { | 
 |       fprintf (fout, "%s", rpcgen_table_dcl); | 
 |     } | 
 |  | 
 |   if (Cflag) | 
 |     { | 
 |       fprintf (fout, "\n#ifdef __cplusplus\n"); | 
 |       fprintf (fout, "}\n"); | 
 |       fprintf (fout, "#endif\n"); | 
 |     } | 
 |  | 
 |   fprintf (fout, "\n#endif /* !_%s */\n", guard); | 
 |   free (guard); | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | /* | 
 |  * Compile into an RPC service | 
 |  */ | 
 | static void | 
 | s_output (int argc, const char *argv[], const char *infile, const char *define, | 
 | 	  int extend, const char *outfile, int nomain, int netflag) | 
 | { | 
 |   char *include; | 
 |   definition *def; | 
 |   int foundprogram = 0; | 
 |   const char *outfilename; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   open_output (infile, outfilename); | 
 |   add_warning (); | 
 |   if (infile && (include = extendfile (infile, ".h"))) | 
 |     { | 
 |       fprintf (fout, "#include \"%s\"\n", include); | 
 |       free (include); | 
 |     } | 
 |   else | 
 |     fprintf (fout, "#include <rpc/rpc.h>\n"); | 
 |  | 
 |   fprintf (fout, "#include <stdio.h>\n"); | 
 |   fprintf (fout, "#include <stdlib.h>\n"); | 
 |   fprintf (fout, "#include <rpc/pmap_clnt.h>\n"); | 
 |   if (Cflag) | 
 |     fprintf (fout, "#include <string.h>\n"); | 
 |   if (strcmp (svcclosetime, "-1") == 0) | 
 |     indefinitewait = 1; | 
 |   else if (strcmp (svcclosetime, "0") == 0) | 
 |     exitnow = 1; | 
 |   else if (inetdflag || pmflag) | 
 |     { | 
 |       fprintf (fout, "#include <signal.h>\n"); | 
 |       timerflag = 1; | 
 |     } | 
 |  | 
 |   if (!tirpcflag && inetdflag) | 
 |     fprintf (fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n"); | 
 |   if (Cflag && (inetdflag || pmflag)) | 
 |     { | 
 |       fprintf (fout, "#include <sys/types.h> /* open */\n"); | 
 |       fprintf (fout, "#include <sys/stat.h> /* open */\n"); | 
 |       fprintf (fout, "#include <fcntl.h> /* open */\n"); | 
 |       fprintf (fout, "#include <unistd.h> /* getdtablesize */\n"); | 
 |     } | 
 |   if (tirpcflag && !(Cflag && (inetdflag || pmflag))) | 
 |     fprintf (fout, "#include <sys/types.h>\n"); | 
 |  | 
 |   fprintf (fout, "#include <memory.h>\n"); | 
 |   if (inetdflag || !tirpcflag) | 
 |     { | 
 |       fprintf (fout, "#include <sys/socket.h>\n"); | 
 |       fprintf (fout, "#include <netinet/in.h>\n"); | 
 |     } | 
 |  | 
 |   if ((netflag || pmflag) && tirpcflag && !nomain) | 
 |     { | 
 |       fprintf (fout, "#include <netconfig.h>\n"); | 
 |     } | 
 |   if ( /*timerflag && */ tirpcflag) | 
 |     fprintf (fout, "#include <sys/resource.h> /* rlimit */\n"); | 
 |   if (logflag || inetdflag || pmflag) | 
 |     { | 
 |       fprintf (fout, "#include <syslog.h>\n"); | 
 |     } | 
 |  | 
 |   /* for ANSI-C */ | 
 |   if (Cflag) | 
 |     fprintf (fout, "\n#ifndef SIG_PF\n#define SIG_PF void(*)(int)\n#endif\n"); | 
 |  | 
 |   if (timerflag) | 
 |     fprintf (fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       foundprogram |= (def->def_kind == DEF_PROGRAM); | 
 |     } | 
 |   if (extend && !foundprogram) | 
 |     { | 
 |       unlink (outfilename); | 
 |       return; | 
 |     } | 
 |   write_most (infile, netflag, nomain); | 
 |   if (!nomain) | 
 |     { | 
 |       if (!do_registers (argc, argv)) | 
 | 	{ | 
 | 	  if (outfilename) | 
 | 	    unlink (outfilename); | 
 | 	  usage (stderr, 1); | 
 | 	} | 
 |       write_rest (); | 
 |     } | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | /* | 
 |  * generate client side stubs | 
 |  */ | 
 | static void | 
 | l_output (const char *infile, const char *define, int extend, | 
 | 	  const char *outfile) | 
 | { | 
 |   char *include; | 
 |   definition *def; | 
 |   int foundprogram = 0; | 
 |   const char *outfilename; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   open_output (infile, outfilename); | 
 |   add_warning (); | 
 |   if (Cflag) | 
 |     fprintf (fout, "#include <memory.h> /* for memset */\n"); | 
 |   if (infile && (include = extendfile (infile, ".h"))) | 
 |     { | 
 |       fprintf (fout, "#include \"%s\"\n", include); | 
 |       free (include); | 
 |     } | 
 |   else | 
 |     fprintf (fout, "#include <rpc/rpc.h>\n"); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       foundprogram |= (def->def_kind == DEF_PROGRAM); | 
 |     } | 
 |   if (extend && !foundprogram) | 
 |     { | 
 |       unlink (outfilename); | 
 |       return; | 
 |     } | 
 |   write_stubs (); | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | /* | 
 |  * generate the dispatch table | 
 |  */ | 
 | static void | 
 | t_output (const char *infile, const char *define, int extend, | 
 | 	  const char *outfile) | 
 | { | 
 |   definition *def; | 
 |   int foundprogram = 0; | 
 |   const char *outfilename; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   open_output (infile, outfilename); | 
 |   add_warning (); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       foundprogram |= (def->def_kind == DEF_PROGRAM); | 
 |     } | 
 |   if (extend && !foundprogram) | 
 |     { | 
 |       unlink (outfilename); | 
 |       return; | 
 |     } | 
 |   write_tables (); | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | /* sample routine for the server template */ | 
 | static void | 
 | svc_output (const char *infile, const char *define, int extend, | 
 | 	    const char *outfile) | 
 | { | 
 |   definition *def; | 
 |   char *include; | 
 |   const char *outfilename; | 
 |   long tell; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   checkfiles (infile, outfilename); | 
 |   /*check if outfile already exists. | 
 |      if so, print an error message and exit */ | 
 |   open_output (infile, outfilename); | 
 |   add_sample_msg (); | 
 |  | 
 |   if (infile && (include = extendfile (infile, ".h"))) | 
 |     { | 
 |       fprintf (fout, "#include \"%s\"\n", include); | 
 |       free (include); | 
 |     } | 
 |   else | 
 |     fprintf (fout, "#include <rpc/rpc.h>\n"); | 
 |  | 
 |   tell = ftell (fout); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       write_sample_svc (def); | 
 |     } | 
 |   if (extend && tell == ftell (fout)) | 
 |     { | 
 |       unlink (outfilename); | 
 |     } | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 |  | 
 | /* sample main routine for client */ | 
 | static void | 
 | clnt_output (const char *infile, const char *define, int extend, | 
 | 	     const char *outfile) | 
 | { | 
 |   definition *def; | 
 |   char *include; | 
 |   const char *outfilename; | 
 |   long tell; | 
 |   int has_program = 0; | 
 |  | 
 |   open_input (infile, define); | 
 |   outfilename = extend ? extendfile (infile, outfile) : outfile; | 
 |   checkfiles (infile, outfilename); | 
 |   /*check if outfile already exists. | 
 |      if so, print an error message and exit */ | 
 |  | 
 |   open_output (infile, outfilename); | 
 |   add_sample_msg (); | 
 |   if (infile && (include = extendfile (infile, ".h"))) | 
 |     { | 
 |       fprintf (fout, "#include \"%s\"\n", include); | 
 |       free (include); | 
 |     } | 
 |   else | 
 |     fprintf (fout, "#include <rpc/rpc.h>\n"); | 
 |   tell = ftell (fout); | 
 |   while ((def = get_definition ()) != NULL) | 
 |     { | 
 |       has_program += write_sample_clnt (def); | 
 |     } | 
 |  | 
 |   if (has_program) | 
 |     write_sample_clnt_main (); | 
 |  | 
 |   if (extend && tell == ftell (fout)) | 
 |     { | 
 |       unlink (outfilename); | 
 |     } | 
 |   close_input (); | 
 |   close_output (outfilename); | 
 | } | 
 |  | 
 | static const char space[] = " "; | 
 |  | 
 | static char * | 
 | file_name (const char *file, const char *ext) | 
 | { | 
 |   char *temp; | 
 |   temp = extendfile (file, ext); | 
 |  | 
 |   if (access (temp, F_OK) != -1) | 
 |     return (temp); | 
 |  | 
 |   free (temp); | 
 |   return (char *) space; | 
 | } | 
 |  | 
 | static void | 
 | mkfile_output (struct commandline *cmd) | 
 | { | 
 |   char *mkfilename; | 
 |   char *clientname, *clntname, *xdrname, *hdrname; | 
 |   char *servername, *svcname, *servprogname, *clntprogname; | 
 |  | 
 |   svcname = file_name (cmd->infile, "_svc.c"); | 
 |   clntname = file_name (cmd->infile, "_clnt.c"); | 
 |   xdrname = file_name (cmd->infile, "_xdr.c"); | 
 |   hdrname = file_name (cmd->infile, ".h"); | 
 |  | 
 |   if (allfiles) | 
 |     { | 
 |       servername = extendfile (cmd->infile, "_server.c"); | 
 |       clientname = extendfile (cmd->infile, "_client.c"); | 
 |     } | 
 |   else | 
 |     { | 
 |       servername = (char *) space; | 
 |       clientname = (char *) space; | 
 |     } | 
 |   servprogname = extendfile (cmd->infile, "_server"); | 
 |   clntprogname = extendfile (cmd->infile, "_client"); | 
 |  | 
 |   if (allfiles) | 
 |     { | 
 |       char *cp, *temp; | 
 |  | 
 |       mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1); | 
 |       if (mkfilename == NULL) | 
 | 	abort (); | 
 |       temp = rindex (cmd->infile, '.'); | 
 |       cp = stpcpy (mkfilename, "Makefile."); | 
 |       if (temp != NULL) | 
 | 	*((char *) stpncpy (cp, cmd->infile, temp - cmd->infile)) = '\0'; | 
 |       else | 
 | 	stpcpy (cp, cmd->infile); | 
 |  | 
 |     } | 
 |   else | 
 |     mkfilename = (char *) cmd->outfile; | 
 |  | 
 |   checkfiles (NULL, mkfilename); | 
 |   open_output (NULL, mkfilename); | 
 |  | 
 |   fprintf (fout, "\n# This is a template Makefile generated by rpcgen\n"); | 
 |  | 
 |   f_print (fout, "\n# Parameters\n\n"); | 
 |  | 
 |   f_print (fout, "CLIENT = %s\nSERVER = %s\n\n", clntprogname, servprogname); | 
 |   f_print (fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); | 
 |   f_print (fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); | 
 |   f_print (fout, "SOURCES.x = %s\n\n", cmd->infile); | 
 |   f_print (fout, "TARGETS_SVC.c = %s %s %s \n", | 
 | 	   svcname, servername, xdrname); | 
 |   f_print (fout, "TARGETS_CLNT.c = %s %s %s \n", | 
 | 	   clntname, clientname, xdrname); | 
 |   f_print (fout, "TARGETS = %s %s %s %s %s %s\n\n", | 
 | 	   hdrname, xdrname, clntname, | 
 | 	   svcname, clientname, servername); | 
 |  | 
 |   f_print (fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \ | 
 | $(TARGETS_CLNT.c:%%.c=%%.o)"); | 
 |  | 
 |   f_print (fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \ | 
 | $(TARGETS_SVC.c:%%.c=%%.o)"); | 
 |  | 
 |   f_print (fout, "\n# Compiler flags \n"); | 
 |   if (mtflag) | 
 |     fprintf (fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS \ | 
 | += -lnsl -lpthread \n "); | 
 |   else | 
 |     f_print (fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); | 
 |   f_print (fout, "RPCGENFLAGS = \n"); | 
 |  | 
 |   f_print (fout, "\n# Targets \n\n"); | 
 |  | 
 |   f_print (fout, "all : $(CLIENT) $(SERVER)\n\n"); | 
 |   f_print (fout, "$(TARGETS) : $(SOURCES.x) \n"); | 
 |   f_print (fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); | 
 |   f_print (fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \ | 
 | $(TARGETS_CLNT.c) \n\n"); | 
 |  | 
 |   f_print (fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \ | 
 | $(TARGETS_SVC.c) \n\n"); | 
 |   f_print (fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); | 
 |   f_print (fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ | 
 | $(LDLIBS) \n\n"); | 
 |   f_print (fout, "$(SERVER) : $(OBJECTS_SVC) \n"); | 
 |   f_print (fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); | 
 |   f_print (fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \ | 
 | $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); | 
 |   close_output (mkfilename); | 
 |  | 
 |   free (clntprogname); | 
 |   free (servprogname); | 
 |   if (servername != space) | 
 |     free (servername); | 
 |   if (clientname != space) | 
 |     free (clientname); | 
 |   if (mkfilename != (char *) cmd->outfile) | 
 |     free (mkfilename); | 
 |   if (svcname != space) | 
 |     free (svcname); | 
 |   if (clntname != space) | 
 |     free (clntname); | 
 |   if (xdrname != space) | 
 |     free (xdrname); | 
 |   if (hdrname != space) | 
 |     free (hdrname); | 
 | } | 
 |  | 
 | /* | 
 |  * Perform registrations for service output | 
 |  * Return 0 if failed; 1 otherwise. | 
 |  */ | 
 | static int | 
 | do_registers (int argc, const char *argv[]) | 
 | { | 
 |   int i; | 
 |  | 
 |   if (inetdflag || !tirpcflag) | 
 |     { | 
 |       for (i = 1; i < argc; i++) | 
 | 	{ | 
 | 	  if (streq (argv[i], "-s")) | 
 | 	    { | 
 | 	      if (!check_nettype (argv[i + 1], valid_i_nettypes)) | 
 | 		return 0; | 
 | 	      write_inetd_register (argv[i + 1]); | 
 | 	      i++; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       for (i = 1; i < argc; i++) | 
 | 	if (streq (argv[i], "-s")) | 
 | 	  { | 
 | 	    if (!check_nettype (argv[i + 1], valid_ti_nettypes)) | 
 | 	      return 0; | 
 | 	    write_nettype_register (argv[i + 1]); | 
 | 	    i++; | 
 | 	  } | 
 | 	else if (streq (argv[i], "-n")) | 
 | 	  { | 
 | 	    write_netid_register (argv[i + 1]); | 
 | 	    i++; | 
 | 	  } | 
 |     } | 
 |   return 1; | 
 | } | 
 |  | 
 | /* | 
 |  * Add another argument to the arg list | 
 |  */ | 
 | static void | 
 | addarg (const char *cp) | 
 | { | 
 |   if (argcount >= ARGLISTLEN) | 
 |     { | 
 |       fprintf (stderr, _("rpcgen: too many defines\n")); | 
 |       crash (); | 
 |       /*NOTREACHED */ | 
 |     } | 
 |   arglist[argcount++] = cp; | 
 | } | 
 |  | 
 | static void | 
 | putarg (int whereto, const char *cp) | 
 | { | 
 |   if (whereto >= ARGLISTLEN) | 
 |     { | 
 |       fprintf (stderr, _("rpcgen: arglist coding error\n")); | 
 |       crash (); | 
 |       /*NOTREACHED */ | 
 |     } | 
 |   arglist[whereto] = cp; | 
 | } | 
 |  | 
 | /* | 
 |  * if input file is stdin and an output file is specified then complain | 
 |  * if the file already exists. Otherwise the file may get overwritten | 
 |  * If input file does not exist, exit with an error | 
 |  */ | 
 |  | 
 | static void | 
 | checkfiles (const char *infile, const char *outfile) | 
 | { | 
 |   struct stat64 buf; | 
 |  | 
 |   if (infile)			/* infile ! = NULL */ | 
 |     if (stat64 (infile, &buf) < 0) | 
 |       { | 
 | 	perror (infile); | 
 | 	crash (); | 
 |       } | 
 |   if (outfile) | 
 |     { | 
 |       if (stat64 (outfile, &buf) < 0) | 
 | 	return;			/* file does not exist */ | 
 |       else | 
 | 	{ | 
 | 	  fprintf (stderr, | 
 | 		   /* TRANS: the file will not be removed; this is an | 
 | 		      TRANS: informative message.  */ | 
 | 		   _("file `%s' already exists and may be overwritten\n"), | 
 | 		   outfile); | 
 | 	  crash (); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * Parse command line arguments | 
 |  */ | 
 | static int | 
 | parseargs (int argc, const char *argv[], struct commandline *cmd) | 
 | { | 
 |   int i; | 
 |   int j; | 
 |   int c; | 
 |   char flag[(1 << 8 * sizeof (char))]; | 
 |   int nflags; | 
 |  | 
 |   cmdname = argv[0]; | 
 |   cmd->infile = cmd->outfile = NULL; | 
 |   if (argc < 2) | 
 |     { | 
 |       return (0); | 
 |     } | 
 |   allfiles = 0; | 
 |   flag['c'] = 0; | 
 |   flag['h'] = 0; | 
 |   flag['l'] = 0; | 
 |   flag['m'] = 0; | 
 |   flag['o'] = 0; | 
 |   flag['s'] = 0; | 
 |   flag['n'] = 0; | 
 |   flag['t'] = 0; | 
 |   flag['S'] = 0; | 
 |   flag['C'] = 0; | 
 |   flag['M'] = 0; | 
 |  | 
 |   for (i = 1; i < argc; i++) | 
 |     { | 
 |       if (argv[i][0] != '-') | 
 | 	{ | 
 | 	  if (cmd->infile) | 
 | 	    { | 
 | 	      fprintf (stderr, | 
 | 		       _("Cannot specify more than one input file!\n")); | 
 | 	      return 0; | 
 | 	    } | 
 | 	  cmd->infile = argv[i]; | 
 | 	} | 
 |       else if (strcmp (argv[i], "--help") == 0) | 
 | 	usage (stdout, 0); | 
 |       else if (strcmp (argv[i], "--version") == 0) | 
 | 	print_version (); | 
 |       else | 
 | 	{ | 
 | 	  for (j = 1; argv[i][j] != 0; j++) | 
 | 	    { | 
 | 	      c = argv[i][j]; | 
 | 	      switch (c) | 
 | 		{ | 
 | 		case 'a': | 
 | 		  allfiles = 1; | 
 | 		  break; | 
 | 		case 'c': | 
 | 		case 'h': | 
 | 		case 'l': | 
 | 		case 'm': | 
 | 		case 't': | 
 | 		  if (flag[c]) | 
 | 		    return 0; | 
 | 		  flag[c] = 1; | 
 | 		  break; | 
 | 		case 'S': | 
 | 		  /* sample flag: Ss or Sc. | 
 | 		     Ss means set flag['S']; | 
 | 		     Sc means set flag['C']; | 
 | 		     Sm means set flag['M']; */ | 
 |  		  c = argv[i][++j];	/* get next char */ | 
 | 		  if (c == 's') | 
 | 		    c = 'S'; | 
 | 		  else if (c == 'c') | 
 | 		    c = 'C'; | 
 | 		  else if (c == 'm') | 
 | 		    c = 'M'; | 
 | 		  else | 
 | 		    return 0; | 
 |  | 
 | 		  if (flag[c]) | 
 | 		    return 0; | 
 | 		  flag[c] = 1; | 
 | 		  break; | 
 | 		case 'C':	/* ANSI C syntax */ | 
 | 		  Cflag = 1; | 
 | 		  break; | 
 |  | 
 | 		case 'k':  /* K&R C syntax */ | 
 | 		  Cflag = 0; | 
 | 		  break; | 
 |  | 
 | 		case 'b':  /* turn TIRPC flag off for | 
 | 			      generating backward compatible | 
 | 			   */ | 
 | 		  tirpcflag = 0; | 
 | 		  break; | 
 |  | 
 | 		case '5':  /* turn TIRPC flag on for | 
 | 			      generating SysVr4 compatible | 
 | 			   */ | 
 | 		  tirpcflag = 1; | 
 | 		  break; | 
 | 		case 'I': | 
 | 		  inetdflag = 1; | 
 | 		  break; | 
 | 		case 'N': | 
 | 		  newstyle = 1; | 
 | 		  break; | 
 | 		case 'L': | 
 | 		  logflag = 1; | 
 | 		  break; | 
 | 		case 'K': | 
 | 		  if (++i == argc) | 
 | 		    { | 
 | 		      return (0); | 
 | 		    } | 
 | 		  svcclosetime = argv[i]; | 
 | 		  goto nextarg; | 
 | 		case 'T': | 
 | 		  tblflag = 1; | 
 | 		  break; | 
 | 		case 'M': | 
 | 		  mtflag = 1; | 
 | 		  break; | 
 | 		case 'i': | 
 | 		  if (++i == argc) | 
 | 		    { | 
 | 		      return (0); | 
 | 		    } | 
 | 		  inlineflag = atoi (argv[i]); | 
 | 		  goto nextarg; | 
 | 		case 'n': | 
 | 		case 'o': | 
 | 		case 's': | 
 | 		  if (argv[i][j - 1] != '-' || | 
 | 		      argv[i][j + 1] != 0) | 
 | 		    { | 
 | 		      return (0); | 
 | 		    } | 
 | 		  flag[c] = 1; | 
 | 		  if (++i == argc) | 
 | 		    { | 
 | 		      return (0); | 
 | 		    } | 
 | 		  if (c == 's') | 
 | 		    { | 
 | 		      if (!streq (argv[i], "udp") && | 
 | 			  !streq (argv[i], "tcp")) | 
 | 			return 0; | 
 | 		    } | 
 | 		  else if (c == 'o') | 
 | 		    { | 
 | 		      if (cmd->outfile) | 
 | 			return 0; | 
 | 		      cmd->outfile = argv[i]; | 
 | 		    } | 
 | 		  goto nextarg; | 
 | 		case 'D': | 
 | 		  if (argv[i][j - 1] != '-') | 
 | 		    return 0; | 
 | 		  addarg (argv[i]); | 
 | 		  goto nextarg; | 
 | 		case 'Y': | 
 | 		  if (++i == argc) | 
 | 		    return 0; | 
 | 		  { | 
 | 		    size_t len = strlen (argv[i]); | 
 | 		    pathbuf = malloc (len + 5); | 
 | 		    if (pathbuf == NULL) | 
 | 		      { | 
 | 			perror (cmdname); | 
 | 			crash (); | 
 | 		      } | 
 | 		    stpcpy (stpcpy (pathbuf, | 
 | 				    argv[i]), | 
 | 			    "/cpp"); | 
 | 		    CPP = pathbuf; | 
 | 		    cppDefined = 1; | 
 | 		    goto nextarg; | 
 | 		  } | 
 |  | 
 | 		default: | 
 | 		  return 0; | 
 | 		} | 
 | 	      } | 
 | 	nextarg: | 
 | 	  ; | 
 | 	} | 
 |     } | 
 |  | 
 |   cmd->cflag = flag['c']; | 
 |   cmd->hflag = flag['h']; | 
 |   cmd->lflag = flag['l']; | 
 |   cmd->mflag = flag['m']; | 
 |   cmd->nflag = flag['n']; | 
 |   cmd->sflag = flag['s']; | 
 |   cmd->tflag = flag['t']; | 
 |   cmd->Ssflag = flag['S']; | 
 |   cmd->Scflag = flag['C']; | 
 |   cmd->makefileflag = flag['M']; | 
 |  | 
 | #ifndef _RPC_THREAD_SAFE_ | 
 |   if (mtflag || newstyle) | 
 |     { | 
 |       /* glibc doesn't support these flags.  */ | 
 |       f_print (stderr, | 
 | 	       _("This implementation doesn't support newstyle or MT-safe code!\n")); | 
 |       return (0); | 
 |     } | 
 | #endif | 
 |   if (tirpcflag) | 
 |     { | 
 |       pmflag = inetdflag ? 0 : 1;    /* pmflag or inetdflag is always TRUE */ | 
 |       if ((inetdflag && cmd->nflag)) | 
 | 	{			/* netid not allowed with inetdflag */ | 
 | 	  fprintf (stderr, _("Cannot use netid flag with inetd flag!\n")); | 
 | 	  return 0; | 
 | 	} | 
 |     } | 
 |   else | 
 |     {				/* 4.1 mode */ | 
 |       pmflag = 0;		/* set pmflag only in tirpcmode */ | 
 |       if (cmd->nflag) | 
 | 	{			/* netid needs TIRPC */ | 
 | 	  f_print (stderr, _("Cannot use netid flag without TIRPC!\n")); | 
 | 	  return (0); | 
 | 	} | 
 |     } | 
 |  | 
 |   if (newstyle && (tblflag || cmd->tflag)) | 
 |     { | 
 |       f_print (stderr, _("Cannot use table flags with newstyle!\n")); | 
 |       return (0); | 
 |     } | 
 |  | 
 |   /* check no conflicts with file generation flags */ | 
 |   nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + | 
 |     cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; | 
 |  | 
 |   if (nflags == 0) | 
 |     { | 
 |       if (cmd->outfile != NULL || cmd->infile == NULL) | 
 | 	{ | 
 | 	  return (0); | 
 | 	} | 
 |     } | 
 |   else if (cmd->infile == NULL && | 
 | 	   (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) | 
 |     { | 
 |       fprintf (stderr, | 
 | 	       _("\"infile\" is required for template generation flags.\n")); | 
 |       return 0; | 
 |     } | 
 |   if (nflags > 1) | 
 |     { | 
 |       fprintf (stderr, _("Cannot have more than one file generation flag!\n")); | 
 |       return 0; | 
 |     } | 
 |   return 1; | 
 | } | 
 |  | 
 | static void | 
 | usage (FILE *stream, int status) | 
 | { | 
 |   fprintf (stream, _("usage: %s infile\n"), cmdname); | 
 |   fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \ | 
 | [-I [-K seconds]] [-Y path] infile\n"), cmdname); | 
 |   fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \ | 
 | [-o outfile] [infile]\n"), cmdname); | 
 |   fprintf (stream, _("\t%s [-s nettype]* [-o outfile] [infile]\n"), cmdname); | 
 |   fprintf (stream, _("\t%s [-n netid]* [-o outfile] [infile]\n"), cmdname); | 
 |   options_usage (stream, status); | 
 |   exit (status); | 
 | } | 
 |  | 
 | static void | 
 | options_usage (FILE *stream, int status) | 
 | { | 
 |   f_print (stream, _("options:\n")); | 
 |   f_print (stream, _("-a\t\tgenerate all files, including samples\n")); | 
 |   f_print (stream, _("-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n")); | 
 |   f_print (stream, _("-c\t\tgenerate XDR routines\n")); | 
 |   f_print (stream, _("-C\t\tANSI C mode\n")); | 
 |   f_print (stream, _("-Dname[=value]\tdefine a symbol (same as #define)\n")); | 
 |   f_print (stream, _("-h\t\tgenerate header file\n")); | 
 |   f_print (stream, _("-i size\t\tsize at which to start generating inline code\n")); | 
 |   f_print (stream, _("-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n")); | 
 |   f_print (stream, _("-K seconds\tserver exits after K seconds of inactivity\n")); | 
 |   f_print (stream, _("-l\t\tgenerate client side stubs\n")); | 
 |   f_print (stream, _("-L\t\tserver errors will be printed to syslog\n")); | 
 |   f_print (stream, _("-m\t\tgenerate server side stubs\n")); | 
 |   f_print (stream, _("-M\t\tgenerate MT-safe code\n")); | 
 |   f_print (stream, _("-n netid\tgenerate server code that supports named netid\n")); | 
 |   f_print (stream, _("-N\t\tsupports multiple arguments and call-by-value\n")); | 
 |   f_print (stream, _("-o outfile\tname of the output file\n")); | 
 |   f_print (stream, _("-s nettype\tgenerate server code that supports named nettype\n")); | 
 |   f_print (stream, _("-Sc\t\tgenerate sample client code that uses remote procedures\n")); | 
 |   f_print (stream, _("-Ss\t\tgenerate sample server code that defines remote procedures\n")); | 
 |   f_print (stream, _("-Sm \t\tgenerate makefile template \n")); | 
 |   f_print (stream, _("-t\t\tgenerate RPC dispatch table\n")); | 
 |   f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n")); | 
 |   f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n")); | 
 |   f_print (stream, _("-5\t\tSysVr4 compatibility mode\n")); | 
 |   f_print (stream, _("--help\t\tgive this help list\n")); | 
 |   f_print (stream, _("--version\tprint program version\n")); | 
 |  | 
 |   f_print (stream, _("\n\ | 
 | For bug reporting instructions, please see:\n\ | 
 | %s.\n"), REPORT_BUGS_TO); | 
 |   exit (status); | 
 | } | 
 |  | 
 | static void | 
 | print_version (void) | 
 | { | 
 |   printf ("rpcgen %s%s\n", PKGVERSION, VERSION); | 
 |   exit (0); | 
 | } |