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