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