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