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