home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / devtools / rpcgen / rpc_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-02  |  28.3 KB  |  1,176 lines

  1. /*
  2.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  3.  * unrestricted use provided that this legend is included on all tape
  4.  * media and as a part of the software program in whole or part.  Users
  5.  * may copy or modify Sun RPC without charge, but are not authorized
  6.  * to license or distribute it to anyone else except as part of a product or
  7.  * program developed by the user or with the express written consent of
  8.  * Sun Microsystems, Inc.
  9.  *
  10.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13.  *
  14.  * Sun RPC is provided with no support and without any obligation on the
  15.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  16.  * modification or enhancement.
  17.  *
  18.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20.  * OR ANY PART THEREOF.
  21.  *
  22.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23.  * or profits or other special, indirect and consequential damages, even if
  24.  * Sun has been advised of the possibility of such damages.
  25.  *
  26.  * Sun Microsystems, Inc.
  27.  * 2550 Garcia Avenue
  28.  * Mountain View, California  94043
  29.  */
  30.  
  31. #ifndef lint
  32. static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
  33. #endif
  34.  
  35. /*
  36.  * rpc_main.c, Top level of the RPC protocol compiler. 
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42. #include <sys/param.h>
  43. #ifndef amigados
  44. #include <sys/file.h>
  45. #endif
  46. #ifdef amigados
  47. /*
  48.  * We need the original SAS/C stat.h, since we are not going to 
  49.  * link with the net.lib
  50.  */
  51. #include <include:stat.h>
  52. #else
  53. #include <sys/stat.h>
  54. #endif
  55. #include "rpc_parse.h"
  56. #include "rpc_util.h"
  57. #include "rpc_scan.h"
  58.  
  59. #ifdef amigados
  60. #include <popen.h>
  61. #include <ctype.h>
  62. #undef toupper /* we don not want the macro with sideeffects */
  63. #define MAXPATHLEN 255 /* FIXME ? */
  64. #endif
  65.  
  66. #ifdef __STDC__
  67. #include "protos.h"
  68.  
  69. int main ( int argc , char *argv []);
  70. static char *extendfile ( char *file , char *ext );
  71. static void open_output ( char *infile , char *outfile );
  72. static void add_warning ( void );
  73. static void clear_args ( void );
  74. static void find_cpp ( void );
  75. void close_on_exit ( void );
  76. static void open_input ( char *infile , char *define );
  77. static int check_nettype ( char *name , char *list_to_check []);
  78. static void c_output ( char *infile , char *define , int extend ,
  79.               char *outfile );
  80. void c_initialize ( void );
  81. char *generate_guard ( char *pathname );
  82. static void h_output ( char *infile , char *define , int extend ,
  83.               char *outfile );
  84. static void s_output ( int argc , char *argv [], char *infile , char *define ,
  85.               int extend , char *outfile , int nomain , int netflag );
  86. static void l_output ( char *infile , char *define , int extend ,
  87.               char *outfile );
  88. static void t_output ( char *infile , char *define , int extend ,
  89.               char *outfile );
  90. static void svc_output ( char *infile , char *define , int extend ,
  91.             char *outfile );
  92. static void clnt_output ( char *infile , char *define , int extend ,
  93.              char *outfile );
  94. static int do_registers ( int argc , char *argv []);
  95. static void addarg ( char *cp );
  96. static void putarg ( int where , char *cp );
  97. static void checkfiles ( char *infile , char *outfile );
  98. static int parseargs ( int argc , char *argv [], struct commandline *cmd );
  99. static void usage ( void );
  100. static void options_usage ( void );
  101.  
  102. #else
  103. extern void  write_sample_svc();
  104. int write_sample_clnt();
  105. void write_sample_clnt_main();
  106.  
  107. static svc_output();
  108. #endif
  109.  
  110. #define EXTEND    1        /* alias for TRUE */
  111. #define DONT_EXTEND    0        /* alias for FALSE */
  112.  
  113. #define SVR4_CPP "/usr/ccs/lib/cpp"
  114. #define SUNOS_CPP "/lib/cpp"
  115. static int cppDefined = 0;          /* explicit path for C preprocessor */
  116.  
  117. struct commandline {
  118.     int cflag;        /* xdr C routines */
  119.     int hflag;        /* header file */
  120.     int lflag;        /* client side stubs */
  121.     int mflag;        /* server side stubs */
  122.     int nflag;        /* netid flag */
  123.     int sflag;        /* server stubs for the given transport */
  124.     int tflag;        /* dispatch Table file */
  125.     int Ssflag;        /* produce server sample code */
  126.     int Scflag;        /* produce client sample code */
  127.     char *infile;        /* input module name */
  128.     char *outfile;        /* output module name */
  129. };
  130.  
  131.  
  132. static char *cmdname;
  133.  
  134. static char *svcclosetime = "120";
  135. #ifndef amigados
  136. static char *CPP = SVR4_CPP;
  137. static char CPPFLAGS[] = "-C";
  138. #else
  139. static char *CPP = "cpp";
  140. static char CPPFLAGS[] = "-C -P";
  141. #endif
  142. static char pathbuf[MAXPATHLEN + 1];
  143. static char *allv[] = {
  144.     "rpcgen", "-s", "udp", "-s", "tcp",
  145. };
  146. static int allc = sizeof(allv)/sizeof(allv[0]);
  147. static char *allnv[] = {
  148.     "rpcgen", "-s", "netpath",
  149. };
  150. static int allnc = sizeof(allnv)/sizeof(allnv[0]);
  151.  
  152. /*
  153.  * machinations for handling expanding argument list
  154.  */
  155. static void addarg();        /* add another argument to the list */
  156. static void putarg();        /* put argument at specified location  */
  157. static void clear_args();    /* clear argument list */
  158. static void checkfiles();    /* check if out file already exists */
  159.  
  160.  
  161.  
  162. #define ARGLISTLEN    20
  163. #define FIXEDARGS         2
  164.  
  165. static char *arglist[ARGLISTLEN];
  166. static int argcount = FIXEDARGS;
  167.  
  168.  
  169. int nonfatalerrors;    /* errors */
  170. int inetdflag/* = 1*/;    /* Support for inetd */ /* is now the default */
  171. int pmflag;        /* Support for port monitors */
  172. int logflag;        /* Use syslog instead of fprintf for errors */
  173. int tblflag;        /* Support for dispatch table file */
  174.  
  175. #define INLINE 3
  176. /*length at which to start doing an inline */
  177.  
  178. int inline=INLINE;  /* length at which to start doing an inline. 3 = default
  179.         if 0, no xdr_inline code */
  180.  
  181. int indefinitewait;    /* If started by port monitors, hang till it wants */
  182. int exitnow;        /* If started by port monitors, exit after the call */
  183. int timerflag;        /* TRUE if !indefinite && !exitnow */
  184. int newstyle;           /* newstyle of passing arguments (by value) */
  185. #if defined(linux) || defined(amigados)
  186. int Cflag = 1 ;         /* ANSI C syntax */
  187. #else
  188. int Cflag = 0 ;         /* ANSI C syntax */
  189. #endif
  190. static int allfiles;   /* generate all files */
  191. #if defined(linux) || defined(amigados)
  192. int tirpcflag = 0;       /* generating code for tirpc, by default */
  193. #else
  194. int tirpcflag = 1;       /* generating code for tirpc, by default */
  195. #endif
  196.  
  197.  
  198. int main(int argc, char *argv[])
  199. {
  200.     struct commandline cmd;
  201.  
  202.     (void) memset((char *)&cmd, 0, sizeof (struct commandline));
  203.     clear_args();
  204.     if (!parseargs(argc, argv, &cmd))
  205.         usage();
  206.  
  207.     if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || 
  208.         cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag ) {
  209.       checkfiles(cmd.infile, cmd.outfile);
  210.     }
  211.     else 
  212.       checkfiles(cmd.infile,NULL);
  213.  
  214.     if (cmd.cflag) {
  215.         c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
  216.     } else if (cmd.hflag) {
  217.         h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
  218.     } else if (cmd.lflag) {
  219.         l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
  220.     } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
  221.         s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, 
  222.              cmd.outfile, cmd.mflag, cmd.nflag);
  223.     } else if (cmd.tflag) {
  224.         t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
  225.     } else if  (cmd.Ssflag) {
  226.           svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
  227.     } else if (cmd.Scflag) {
  228.           clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
  229.     } else {
  230.         /* the rescans are required, since cpp may effect input */
  231.         c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
  232.         reinitialize();
  233.         h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
  234.         reinitialize();
  235.         l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
  236.         reinitialize();
  237.         if (inetdflag || !tirpcflag )
  238.             s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, 
  239.                  "_svc.c", cmd.mflag, cmd.nflag);
  240.         else
  241.             s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", 
  242.                  EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
  243.         if (tblflag) {
  244.             reinitialize();
  245.             t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
  246.         }
  247.         if (allfiles) {
  248.           reinitialize();
  249.           svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
  250.         }
  251.         if (allfiles) {
  252.           reinitialize();
  253.           clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
  254.         }    
  255.     }
  256.     exit(nonfatalerrors);
  257.     /* NOTREACHED */
  258. }
  259.  
  260. /*
  261.  * add extension to filename 
  262.  */
  263. static char *
  264. extendfile(file, ext)
  265.     char *file;
  266.     char *ext;
  267. {
  268.     char *res;
  269.     char *p;
  270.  
  271.     res = alloc(strlen(file) + strlen(ext) + 1);
  272.     if (res == NULL) {
  273.         abort();
  274.     }
  275.     p = strrchr(file, '.');
  276.     if (p == NULL) {
  277.         p = file + strlen(file);
  278.     }
  279.     (void) strcpy(res, file);
  280.     (void) strcpy(res + (p - file), ext);
  281.     return (res);
  282. }
  283.  
  284. /*
  285.  * Open output file with given extension 
  286.  */
  287. static void
  288. open_output(infile, outfile)
  289.     char *infile;
  290.     char *outfile;
  291. {
  292.  
  293.     if (outfile == NULL) {
  294.         fout = stdout;
  295.         return;
  296.     }
  297.  
  298.     if (infile != NULL && streq(outfile, infile)) {
  299.         f_print(stderr, "%s: output would overwrite %s\n", cmdname,
  300.             infile);
  301.         crash();
  302.     }
  303.     fout = fopen(outfile, "w");
  304.     if (fout == NULL) {
  305.         f_print(stderr, "%s: unable to open ", cmdname);
  306.         perror(outfile);
  307.         crash();
  308.     }
  309.     record_open(outfile);
  310.  
  311. }
  312.  
  313. static void
  314. add_warning()
  315. {
  316.     f_print(fout, "/*\n");
  317.     f_print(fout, " * Please do not edit this file.\n");
  318.     f_print(fout, " * It was generated using rpcgen.\n");
  319.     f_print(fout, " */\n\n");
  320. }
  321.  
  322. /* clear list of arguments */
  323. static void clear_args()
  324. {
  325.   int i;
  326.   for( i=FIXEDARGS; i<ARGLISTLEN; i++ )
  327.     arglist[i] = NULL;
  328.   argcount = FIXEDARGS;
  329. }
  330.  
  331. /* make sure that a CPP exists */
  332. static void find_cpp()
  333. {
  334.   struct stat buf;
  335.  
  336.   if( stat(CPP, &buf) < 0 )  {    /* SVR4 or explicit cpp does not exist */
  337.     if (cppDefined) {
  338.       fprintf( stderr, "cannot find C preprocessor: %s \n", CPP );
  339.       crash();
  340.     } else {            /* try the other one */
  341.       CPP = SUNOS_CPP;
  342.       if( stat( CPP, &buf ) < 0 ) { /* can't find any cpp */
  343.     fprintf( stderr, "cannot find any C preprocessor (cpp)\n" );
  344.     crash();
  345.       }
  346.     }
  347.   }
  348. }
  349.  
  350. #ifdef amigados
  351. void close_on_exit(void)
  352. {
  353.     if(fin)
  354.     pclose(fin);
  355. }
  356. #endif
  357.  
  358. /*
  359.  * Open input file with given define for C-preprocessor 
  360.  */
  361. static void
  362. open_input(infile, define)
  363.     char *infile;
  364.     char *define;
  365. {
  366. #ifndef amigados
  367.     int pd[2];
  368.  
  369.     infilename = (infile == NULL) ? "<stdin>" : infile;
  370.     (void) pipe(pd);
  371.     switch (fork()) {
  372.     case 0:
  373.         find_cpp();
  374.         putarg(0, CPP);
  375.         putarg(1, CPPFLAGS);
  376.         addarg(define);
  377.         addarg(infile);
  378.         addarg((char *)NULL);
  379.         (void) close(1);
  380.         (void) dup2(pd[1], 1);
  381.         (void) close(pd[0]);
  382.         execv(arglist[0], arglist);
  383.         perror("execv");
  384.         exit(1);
  385.     case -1:
  386.         perror("fork");
  387.         exit(1);
  388.     }
  389.     (void) close(pd[1]);
  390.     fin = fdopen(pd[0], "r");
  391.     if (fin == NULL) {
  392.         f_print(stderr, "%s: ", cmdname);
  393.         perror(infilename);
  394.         crash();
  395.     }
  396. #else
  397.     static FILE *s_fin;
  398.     char line[255];
  399.  
  400.     infilename = (infile == NULL) ? "<stdin>" : infile;
  401.  
  402.     sprintf(line,"%s %s %s %s", CPP, CPPFLAGS, define, infile);
  403.  
  404.     fin = popen(line, "r");
  405.     if (fin == NULL) {
  406.         f_print(stderr, "%s: ", cmdname);
  407.         perror(infilename);
  408.         crash();
  409.     }
  410.     if(!s_fin)
  411.         atexit(close_on_exit);
  412.     else
  413.         pclose(s_fin);
  414.     s_fin = fin;
  415. #endif
  416. }
  417.  
  418. /* valid tirpc nettypes */
  419. static char* valid_ti_nettypes[] =
  420. {
  421.   "netpath",
  422.   "visible",
  423.   "circuit_v",
  424.   "datagram_v",
  425.   "circuit_n",
  426.   "datagram_n",
  427.   "udp",
  428.   "tcp",
  429.   "raw",
  430.   NULL
  431.   };
  432.  
  433. /* valid inetd nettypes */
  434. static char* valid_i_nettypes[] =
  435. {
  436.   "udp",
  437.   "tcp",
  438.   NULL
  439. };
  440.  
  441. static int check_nettype( name, list_to_check )
  442. char* name;
  443. char* list_to_check[];
  444. {
  445.   int i;
  446.   for( i = 0; list_to_check[i] != NULL; i++ ) {
  447.       if( strcmp( name, list_to_check[i] ) == 0 ) {
  448.         return 1;
  449.       }
  450.   }
  451.   f_print( stderr, "illegal nettype :\'%s\'\n", name );
  452.   return 0;
  453. }
  454.  
  455. /*
  456.  * Compile into an XDR routine output file
  457.  */
  458.  
  459. static void
  460. c_output(char *infile, char *define, int extend, char *outfile)
  461. {
  462.     definition *def;
  463.     char *include;
  464.     char *outfilename;
  465.     long tell;
  466.  
  467.     c_initialize();
  468.     open_input(infile, define);    
  469.     outfilename = extend ? extendfile(infile, outfile) : outfile;
  470.     open_output(infile, outfilename);
  471.     add_warning();
  472.     if (infile && (include = extendfile(infile, ".h"))) {
  473.         f_print(fout, "#include \"%s\"\n", include);
  474.         free(include);
  475.         /* .h file already contains rpc/rpc.h */
  476.     } else
  477.       f_print(fout, "#include <rpc/rpc.h>\n");
  478.     tell = ftell(fout);
  479.     while (def = get_definition()) {
  480.         emit(def);
  481.     }
  482.     if (extend && tell == ftell(fout)) {
  483.         (void) unlink(outfilename);
  484.     }
  485. }
  486.  
  487.  
  488. void
  489. c_initialize()
  490. {
  491.  
  492.   /* add all the starting basic types */
  493.  
  494.   add_type(1,"int");
  495.   add_type(1,"long");
  496.   add_type(1,"short");
  497.   add_type(1,"bool");
  498.  
  499.   add_type(1,"u_int");
  500.   add_type(1,"u_long");
  501.   add_type(1,"u_short");
  502.  
  503. }
  504.  
  505. char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
  506.     char    *(*proc)();\n\
  507.     xdrproc_t    xdr_arg;\n\
  508.     unsigned    len_arg;\n\
  509.     xdrproc_t    xdr_res;\n\
  510.     unsigned    len_res;\n\
  511. };\n";
  512.  
  513.  
  514. char* generate_guard( pathname )
  515.      char* pathname;
  516. {
  517.         char* filename, *guard, *tmp;
  518.  
  519.     filename = strrchr(pathname, '/' );  /* find last component */
  520.     filename = ((filename == 0) ? pathname : filename+1);
  521.     guard = strdup(filename);
  522.     /* convert to upper case */
  523.     tmp = guard;
  524.     while (*tmp) {
  525.         if (islower(*tmp))
  526.             *tmp = toupper(*tmp);
  527.         tmp++;
  528.     }
  529.         
  530.     guard = extendfile(guard, "_H_RPCGEN");
  531.     return( guard );
  532. }
  533.  
  534. /*
  535.  * Compile into an XDR header file
  536.  */
  537.  
  538.  
  539. static void
  540. h_output(char *infile, char *define, int extend, char *outfile)
  541. {
  542.     definition *def;
  543.     char *outfilename;
  544.     long tell;
  545.     char *guard;
  546.     list *l;
  547.  
  548.     open_input(infile, define);
  549.     outfilename =  extend ? extendfile(infile, outfile) : outfile;
  550.     open_output(infile, outfilename);
  551.     add_warning();
  552.     guard = generate_guard(  outfilename ? outfilename: infile );
  553.  
  554.     f_print(fout,"#ifndef _%s\n#define _%s\n\n", guard,
  555.         guard);
  556.  
  557.     f_print(fout, "#include <rpc/rpc.h>\n\n");
  558.  
  559.     tell = ftell(fout);
  560.     /* print data definitions */
  561.     while (def = get_definition()) {
  562.         print_datadef(def);
  563.     }
  564.  
  565.     /* print function declarations.  
  566.        Do this after data definitions because they might be used as
  567.        arguments for functions */
  568.     for (l = defined; l != NULL; l = l->next) {
  569.         print_funcdef(l->val);
  570.     }
  571.     if (extend && tell == ftell(fout)) {
  572.         (void) unlink(outfilename);
  573.     } else if (tblflag) {
  574.         f_print(fout, rpcgen_table_dcl);
  575.     }
  576.     f_print(fout, "\n#endif /* !_%s */\n", guard);
  577. }
  578.  
  579. /*
  580.  * Compile into an RPC service
  581.  */
  582. static void 
  583. s_output(int argc, char *argv[], char *infile, char *define, int extend,
  584.      char *outfile, int nomain, int netflag)
  585. {
  586.     char *include;
  587.     definition *def;
  588.     int foundprogram = 0;
  589.     char *outfilename;
  590.  
  591.     open_input(infile, define);
  592.     outfilename = extend ? extendfile(infile, outfile) : outfile;
  593.     open_output(infile, outfilename);
  594.     add_warning();
  595.     if (infile && (include = extendfile(infile, ".h"))) {
  596.         f_print(fout, "#include \"%s\"\n", include);
  597.         free(include);
  598.     } else
  599.       f_print(fout, "#include <rpc/rpc.h>\n");
  600.  
  601.     f_print(fout, "#include <stdio.h>\n");
  602.     f_print(fout, "#include <stdlib.h>/* getenv, exit */\n"); 
  603.     if (Cflag) {
  604.         f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
  605.         f_print (fout, "#include <string.h> /* strcmp */ \n"); 
  606.     }
  607.     if (strcmp(svcclosetime, "-1") == 0)
  608.         indefinitewait = 1;
  609.     else if (strcmp(svcclosetime, "0") == 0)
  610.         exitnow = 1;
  611.     else if (inetdflag || pmflag) {
  612.         f_print(fout, "#include <signal.h>\n");
  613.       timerflag = 1;
  614.     }
  615.     if( !tirpcflag && inetdflag )
  616. #if defined(linux) || defined(amigados)
  617.       f_print(fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n");
  618. #else
  619.       f_print(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
  620. #endif
  621.     if( Cflag && (inetdflag || pmflag ) ) {
  622. #if defined(linux)
  623.       f_print(fout, "#include <sys/types.h> /* open */\n"); 
  624.       f_print(fout, "#include <sys/stat.h> /* open */\n"); 
  625.       f_print(fout, "#include <fcntl.h> /* open */\n"); 
  626.       f_print(fout, "#include <unistd.h> /* getdtablesize */\n"); 
  627. #elif defined(amigados)
  628.       f_print(fout, "#include <sys/types.h> /* open */\n"); 
  629.       f_print(fout, "#include <sys/stat.h> /* open */\n"); 
  630.       f_print(fout, "#include <fcntl.h> /* open */\n"); 
  631.       f_print(fout, "#include <proto/socket.h> /* getdtablesize */\n"); 
  632. #else
  633.       f_print(fout, "#ifdef __cplusplus\n");
  634.       f_print(fout, "#include <sysent.h> /* getdtablesize, open */\n"); 
  635.       f_print(fout, "#endif /* __cplusplus */\n");
  636. #endif
  637.       if( tirpcflag )
  638.         f_print(fout, "#include <unistd.h> /* setsid */\n");
  639.     }
  640.     if( tirpcflag )
  641.       f_print(fout, "#include <sys/types.h>\n");
  642.  
  643. #ifndef amigados
  644.     f_print(fout, "#include <memory.h>\n");
  645. #ifndef linux
  646.     f_print(fout, "#include <stropts.h>\n");
  647. #endif
  648. #endif
  649.     if (inetdflag || !tirpcflag ) {
  650.         f_print(fout, "#include <sys/socket.h>\n");
  651.         f_print(fout, "#include <netinet/in.h>\n");
  652.     } 
  653.  
  654.     if ( (netflag || pmflag) && tirpcflag ) {
  655.         f_print(fout, "#include <netconfig.h>\n");
  656.     }
  657.     if (/*timerflag &&*/ tirpcflag)
  658. #ifndef amigados
  659.         f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
  660. #endif
  661.     if (logflag || inetdflag || pmflag) {
  662. #if defined(linux)
  663.         f_print(fout, "#include <syslog.h>\n");
  664. #elif defined(amigados)
  665.         f_print(fout, "#include <sys/syslog.h>\n");
  666. #else
  667.         f_print(fout, "#ifdef SYSLOG\n");
  668.         f_print(fout, "#include <syslog.h>\n");
  669.         f_print(fout, "#else\n");
  670.         f_print(fout, "#define LOG_ERR 1\n");
  671.         f_print(fout, "#define openlog(a, b, c)\n");
  672.         f_print(fout, "#endif\n");
  673. #endif
  674.     }
  675.  
  676.     /* for ANSI-C */
  677.     f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n");
  678.  
  679. #if !defined(linux) && !defined(amigados)
  680.     f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
  681. #endif
  682.     if (timerflag)
  683.         f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
  684.     while (def = get_definition()) {
  685.         foundprogram |= (def->def_kind == DEF_PROGRAM);
  686.     }
  687.     if (extend && !foundprogram) {
  688.         (void) unlink(outfilename);
  689.         return;
  690.     }
  691.     write_most(infile, netflag, nomain);
  692.     if (!nomain) {
  693.         if( !do_registers(argc, argv) ) {
  694.           if (outfilename)
  695.             (void) unlink(outfilename);
  696.           usage();
  697.         }
  698.         write_rest();
  699.     }
  700. }
  701.  
  702. /*
  703.  * generate client side stubs
  704.  */
  705. static void
  706. l_output(char *infile, char *define, int extend, char *outfile)
  707. {
  708.     char *include;
  709.     definition *def;
  710.     int foundprogram = 0;
  711.     char *outfilename;
  712.  
  713.     open_input(infile, define);
  714.     outfilename = extend ? extendfile(infile, outfile) : outfile;
  715.     open_output(infile, outfilename);
  716.     add_warning();
  717. #ifdef amigados
  718.     if (Cflag)
  719.       f_print (fout, "#include <string.h> /* for memset */\n");
  720. #else
  721.     if (Cflag)
  722.       f_print (fout, "#include <memory.h> /* for memset */\n");
  723. #endif
  724.     if (infile && (include = extendfile(infile, ".h"))) {
  725.         f_print(fout, "#include \"%s\"\n", include);
  726.         free(include);
  727.     } else
  728.       f_print(fout, "#include <rpc/rpc.h>\n");
  729.     while (def = get_definition()) {
  730.         foundprogram |= (def->def_kind == DEF_PROGRAM);
  731.     }
  732.     if (extend && !foundprogram) {
  733.         (void) unlink(outfilename);
  734.         return;
  735.     }
  736.     write_stubs();
  737. }
  738.  
  739. /*
  740.  * generate the dispatch table
  741.  */
  742. static void
  743. t_output(char *infile, char *define, int extend, char *outfile)
  744. {
  745.     definition *def;
  746.     int foundprogram = 0;
  747.     char *outfilename;
  748.  
  749.     open_input(infile, define);
  750.     outfilename = extend ? extendfile(infile, outfile) : outfile;
  751.     open_output(infile, outfilename);
  752.     add_warning();
  753.     while (def = get_definition()) {
  754.         foundprogram |= (def->def_kind == DEF_PROGRAM);
  755.     }
  756.     if (extend && !foundprogram) {
  757.         (void) unlink(outfilename);
  758.         return;
  759.     }
  760.     write_tables();
  761. }
  762.  
  763. /* sample routine for the server template */
  764. static  void
  765. svc_output(char *infile, char *define, int extend, char *outfile)
  766. {
  767.   definition *def;
  768.   char *include;
  769.   char *outfilename;
  770.   long tell;
  771.   
  772.   open_input(infile, define);    
  773.   outfilename = extend ? extendfile(infile, outfile) : outfile;
  774.   checkfiles(infile,outfilename); /*check if outfile already exists.
  775.                   if so, print an error message and exit*/
  776.   open_output(infile, outfilename);
  777.   add_sample_msg();
  778.  
  779.   if (infile && (include = extendfile(infile, ".h"))) {
  780.     f_print(fout, "#include \"%s\"\n", include);
  781.     free(include);
  782.   } else
  783.     f_print(fout, "#include <rpc/rpc.h>\n");
  784.  
  785.   tell = ftell(fout);
  786.   while (def = get_definition()) {
  787.       write_sample_svc(def);
  788.   }
  789.   if (extend && tell == ftell(fout)) {
  790.       (void) unlink(outfilename);
  791.   }
  792. }
  793.  
  794.  
  795. /* sample main routine for client */
  796. static void
  797. clnt_output(char *infile, char *define, int extend, char *outfile)
  798. {
  799.   definition *def;
  800.   char *include;
  801.   char *outfilename;
  802.   long tell;
  803.   int has_program = 0;
  804.   
  805.   open_input(infile, define);    
  806.   outfilename = extend ? extendfile(infile, outfile) : outfile;
  807.   checkfiles(infile,outfilename); /*check if outfile already exists.
  808.                   if so, print an error message and exit*/
  809.  
  810.   open_output(infile, outfilename);
  811.   add_sample_msg();
  812.   if (infile && (include = extendfile(infile, ".h"))) {
  813.     f_print(fout, "#include \"%s\"\n", include);
  814.     free(include);
  815.   } else
  816.     f_print(fout, "#include <rpc/rpc.h>\n");
  817.   tell = ftell(fout);
  818.   while (def = get_definition()) {
  819.     has_program += write_sample_clnt(def);
  820.   }
  821.  
  822.   if( has_program )
  823.     write_sample_clnt_main();
  824.  
  825.   if (extend && tell == ftell(fout)) {
  826.     (void) unlink(outfilename);
  827.   }
  828. }
  829.  
  830. /*
  831.  * Perform registrations for service output 
  832.  * Return 0 if failed; 1 otherwise.
  833.  */
  834. static int 
  835. do_registers(int argc, char *argv[])
  836. {
  837.     int i;
  838.  
  839.     if ( inetdflag || !tirpcflag) {
  840.         for (i = 1; i < argc; i++) {
  841.             if (streq(argv[i], "-s")) {
  842.                     if(!check_nettype( argv[i + 1], valid_i_nettypes ))
  843.                   return 0;
  844.                 write_inetd_register(argv[i + 1]);
  845.                 i++;
  846.             }
  847.         }
  848.     } else {
  849.         for (i = 1; i < argc; i++)
  850.                 if (streq(argv[i], "-s")) {
  851.                     if(!check_nettype( argv[i + 1], valid_ti_nettypes ))
  852.                   return 0;
  853.                 write_nettype_register(argv[i + 1]);
  854.                 i++;
  855.             } else if (streq(argv[i], "-n")) {
  856.                 write_netid_register(argv[i + 1]);
  857.                 i++;
  858.             }
  859.     }
  860.     return 1;
  861. }
  862.  
  863. /*
  864.  * Add another argument to the arg list
  865.  */
  866. static void
  867. addarg(char *cp)
  868. {
  869.     if (argcount >= ARGLISTLEN) {
  870.         f_print(stderr, "rpcgen: too many defines\n");
  871.         crash();
  872.         /*NOTREACHED*/
  873.     }
  874.     arglist[argcount++] = cp;
  875.  
  876. }
  877.  
  878. static void
  879. putarg(int where, char *cp)
  880. {
  881.     if (where >= ARGLISTLEN) {
  882.         f_print(stderr, "rpcgen: arglist coding error\n");
  883.         crash();
  884.         /*NOTREACHED*/
  885.     }
  886.     arglist[where] = cp;
  887.     
  888. }
  889.  
  890. /*
  891.  * if input file is stdin and an output file is specified then complain
  892.  * if the file already exists. Otherwise the file may get overwritten
  893.  * If input file does not exist, exit with an error 
  894.  */
  895.  
  896. static void
  897. checkfiles(char *infile, char *outfile)
  898. {
  899.  
  900.   struct stat buf;
  901.  
  902.   if(infile)            /* infile ! = NULL */
  903.     if(stat(infile,&buf) < 0)
  904.       {
  905.     perror(infile);
  906.     crash();
  907.       };
  908.   if (outfile) {
  909.     if (stat(outfile, &buf) < 0) 
  910.       return;            /* file does not exist */
  911.     else {
  912.       f_print(stderr, 
  913.           "file '%s' already exists and may be overwritten\n", outfile);
  914.       crash();
  915.     }
  916.   }
  917. }
  918.  
  919. /*
  920.  * Parse command line arguments 
  921.  */
  922. static int 
  923. parseargs(int argc, char *argv[], struct commandline *cmd)
  924. {
  925.     int i;
  926.     int j;
  927.     char c;
  928.     char flag[(1 << 8 * sizeof(char))];
  929.     int nflags;
  930.  
  931.     cmdname = argv[0];
  932.     cmd->infile = cmd->outfile = NULL;
  933.     if (argc < 2) {
  934.         return (0);
  935.     }
  936.     allfiles = 0;
  937.     flag['c'] = 0;
  938.     flag['h'] = 0;
  939.     flag['l'] = 0;
  940.     flag['m'] = 0;
  941.     flag['o'] = 0;
  942.     flag['s'] = 0;
  943.     flag['n'] = 0;
  944.     flag['t'] = 0;
  945.     flag['S'] = 0;
  946.     flag['C'] = 0;
  947.     for (i = 1; i < argc; i++) {
  948.         if (argv[i][0] != '-') {
  949.             if (cmd->infile) {
  950.                     f_print( stderr, "Cannot specify more than one input file!\n");
  951.  
  952.                 return (0);
  953.             }
  954.             cmd->infile = argv[i];
  955.         } else {
  956.             for (j = 1; argv[i][j] != 0; j++) {
  957.                 c = argv[i][j];
  958.                 switch (c) {
  959.                 case 'a':
  960.                     allfiles = 1;
  961.                     break;
  962.                 case 'c':
  963.                 case 'h':
  964.                 case 'l':
  965.                 case 'm':
  966.                 case 't':
  967.                     if (flag[c]) {
  968.                         return (0);
  969.                     }
  970.                     flag[c] = 1;
  971.                     break;
  972.                 case 'S':  
  973.                     /* sample flag: Ss or Sc.
  974.                        Ss means set flag['S'];
  975.                        Sc means set flag['C']; */
  976.                     c = argv[i][++j];  /* get next char */
  977.                     if( c == 's' )
  978.                       c = 'S';
  979.                     else if( c == 'c' )
  980.                       c = 'C';
  981.                     else
  982.                       return( 0 );
  983.  
  984.                     if (flag[c]) {
  985.                         return (0);
  986.                     }
  987.                     flag[c] = 1;
  988.                     break;
  989.                 case 'C':  /* ANSI C syntax */
  990.                     Cflag = 1;
  991.                     break;
  992.  
  993. #if defined(linux) || defined(amigados)
  994.                 case 'k':  /* K&R C syntax */
  995.                     Cflag = 0;
  996.                     break;
  997.  
  998. #endif
  999.                 case 'b':  /* turn TIRPC flag off for
  1000.                         generating backward compatible
  1001.                         */
  1002.                     tirpcflag = 0;
  1003.                     break;
  1004.  
  1005. #if defined(linux) || defined(amigados)
  1006.                 case '5':  /* turn TIRPC flag on for
  1007.                         generating SysVr4 compatible
  1008.                         */
  1009.                     tirpcflag = 1;
  1010.                     break;
  1011.  
  1012. #endif
  1013.                 case 'I':
  1014.                     inetdflag = 1;
  1015.                     break;
  1016.                 case 'N':
  1017.                     newstyle = 1;
  1018.                     break;
  1019.                 case 'L':
  1020.                     logflag = 1;
  1021.                     break;
  1022.                 case 'K':
  1023.                     if (++i == argc) {
  1024.                         return (0);
  1025.                     }
  1026.                     svcclosetime = argv[i];
  1027.                     goto nextarg;
  1028.                 case 'T':
  1029.                     tblflag = 1;
  1030.                     break;
  1031.                 case 'i' :
  1032.                       if (++i == argc) {
  1033.                         return (0);
  1034.                     }
  1035.                     inline = atoi(argv[i]);
  1036.                     goto nextarg;
  1037.                 case 'n':
  1038.                 case 'o':
  1039.                 case 's':
  1040.                     if (argv[i][j - 1] != '-' || 
  1041.                         argv[i][j + 1] != 0) {
  1042.                         return (0);
  1043.                     }
  1044.                     flag[c] = 1;
  1045.                     if (++i == argc) {
  1046.                         return (0);
  1047.                     }
  1048.                     if (c == 's') {
  1049.                         if (!streq(argv[i], "udp") &&
  1050.                             !streq(argv[i], "tcp")) {
  1051.                             return (0);
  1052.                         }
  1053.                     } else if (c == 'o') {
  1054.                         if (cmd->outfile) {
  1055.                             return (0);
  1056.                         }
  1057.                         cmd->outfile = argv[i];
  1058.                     }
  1059.                     goto nextarg;
  1060.                 case 'D':
  1061.                     if (argv[i][j - 1] != '-') {
  1062.                         return (0);
  1063.                     }
  1064.                     (void) addarg(argv[i]);
  1065.                     goto nextarg;
  1066.                 case 'Y':
  1067.                     if (++i == argc) {
  1068.                         return (0);
  1069.                     }
  1070.                     (void) strcpy(pathbuf, argv[i]);
  1071.                     (void) strcat(pathbuf, "/cpp");
  1072.                     CPP = pathbuf;
  1073.                     cppDefined = 1;
  1074.                     goto nextarg;
  1075.  
  1076.  
  1077.  
  1078.                 default:
  1079.                     return (0);
  1080.                 }
  1081.             }
  1082.     nextarg:
  1083.             ;
  1084.         }
  1085.     }
  1086.  
  1087.     cmd->cflag = flag['c'];
  1088.     cmd->hflag = flag['h'];
  1089.     cmd->lflag = flag['l'];
  1090.     cmd->mflag = flag['m'];
  1091.     cmd->nflag = flag['n'];
  1092.     cmd->sflag = flag['s'];
  1093.     cmd->tflag = flag['t'];
  1094.     cmd->Ssflag = flag['S'];
  1095.     cmd->Scflag = flag['C'];
  1096.  
  1097.     if( tirpcflag ) {
  1098.       pmflag = inetdflag ? 0 : 1;      /* pmflag or inetdflag is always TRUE */
  1099.       if( (inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */
  1100.         f_print(stderr, "Cannot use netid flag with inetd flag!\n");
  1101.         return (0);
  1102.       }
  1103.     } else {  /* 4.1 mode */
  1104.       pmflag = 0;               /* set pmflag only in tirpcmode */
  1105. #if !defined(linux) && !defined(amigados)
  1106.       inetdflag = 1;            /* inetdflag is TRUE by default */
  1107. #endif
  1108.       if( cmd->nflag ) {          /* netid needs TIRPC */
  1109.         f_print( stderr, "Cannot use netid flag without TIRPC!\n");
  1110.         return( 0 );
  1111.       }
  1112.     }
  1113.  
  1114.     if( newstyle && ( tblflag || cmd->tflag) ) {
  1115.       f_print( stderr, "Cannot use table flags with newstyle!\n");
  1116.       return( 0 );
  1117.     }
  1118.  
  1119.     /* check no conflicts with file generation flags */
  1120.     nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
  1121.         cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
  1122.  
  1123.     if (nflags == 0) {
  1124.         if (cmd->outfile != NULL || cmd->infile == NULL) {
  1125.             return (0);
  1126.         }
  1127.     } else if (nflags > 1) {
  1128.             f_print( stderr, "Cannot have more than one file generation flag!\n");
  1129.         return (0);
  1130.     }
  1131.     return (1);
  1132. }
  1133.  
  1134. static void
  1135. usage()
  1136. {
  1137.     f_print(stderr, "usage:  %s infile\n", cmdname);
  1138.     f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size  [-I [-K seconds]] [-L][-N][-T] infile\n",
  1139.             cmdname);
  1140.     f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n",
  1141.             cmdname);
  1142.     f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname);
  1143.     f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname);
  1144.     options_usage();
  1145.     exit(1);
  1146. }
  1147.  
  1148. static void
  1149. options_usage()
  1150. {
  1151.     f_print(stderr, "options:\n");
  1152.     f_print(stderr, "-a\t\tgenerate all files, including samples\n");
  1153.     f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n");
  1154.     f_print(stderr, "-c\t\tgenerate XDR routines\n");
  1155.     f_print(stderr, "-C\t\tANSI C mode\n");
  1156.     f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
  1157.     f_print(stderr, "-h\t\tgenerate header file\n");
  1158.     f_print(stderr, "-i size\t\tsize at which to start generating inline code\n");
  1159.     f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n");
  1160.     f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n");
  1161.     f_print(stderr, "-l\t\tgenerate client side stubs\n");
  1162.     f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
  1163.     f_print(stderr, "-m\t\tgenerate server side stubs\n");
  1164.     f_print(stderr, "-n netid\tgenerate server code that supports named netid\n");
  1165.     f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n");
  1166.     f_print(stderr, "-o outfile\tname of the output file\n");
  1167.     f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n");
  1168.     f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n");
  1169.     f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n");
  1170.     f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
  1171.     f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
  1172.     f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n");
  1173.  
  1174.     exit(1);
  1175. }
  1176.