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