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