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