1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 */ 29 30 31 #ident "@(#)rpc_main.c 1.21 94/04/25 SMI" 32 33 #ifndef lint 34 static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI"; 35 #endif 36 37 /* 38 * rpc_main.c, Top level of the RPC protocol compiler. 39 * Copyright (C) 1987, Sun Microsystems, Inc. 40 */ 41 42 #include <stdio.h> 43 #include <string.h> 44 #include <unistd.h> 45 #include <ctype.h> 46 #include <sys/types.h> 47 #include <sys/param.h> 48 #include <sys/file.h> 49 #include <sys/stat.h> 50 #include "rpc_parse.h" 51 #include "rpc_util.h" 52 #include "rpc_scan.h" 53 54 extern void write_sample_svc __P(( definition * )); 55 extern int write_sample_clnt __P(( definition * )); 56 extern void write_sample_clnt_main __P(( void )); 57 extern void add_sample_msg __P(( void )); 58 static void c_output __P(( char *, char *, int, char * )); 59 static void h_output __P(( char *, char *, int, char * )); 60 static void l_output __P(( char *, char *, int, char * )); 61 static void t_output __P(( char *, char *, int, char * )); 62 static void clnt_output __P(( char *, char *, int, char * )); 63 64 void c_initialize __P(( void )); 65 66 #ifndef __FreeBSD__ 67 char * rindex(); 68 #endif 69 70 static void usage __P(( void )); 71 static void options_usage __P (( void )); 72 static int do_registers __P(( int, char ** )); 73 static int parseargs __P(( int, char **, struct commandline * )); 74 static void svc_output __P(( char *, char *, int, char * )); 75 static void mkfile_output __P(( struct commandline * )); 76 static void s_output __P(( int, char **, char *, char *, int, char *, int, int )); 77 78 #define EXTEND 1 /* alias for TRUE */ 79 #define DONT_EXTEND 0 /* alias for FALSE */ 80 81 #define SVR4_CPP "/usr/ccs/lib/cpp" 82 #ifdef __FreeBSD__ 83 #define SUNOS_CPP "/usr/libexec/cpp" 84 #else 85 #define SUNOS_CPP "/usr/lib/cpp" 86 #endif 87 88 static int cppDefined = 0; /* explicit path for C preprocessor */ 89 90 91 static char *cmdname; 92 93 static char *svcclosetime = "120"; 94 static char *CPP = SVR4_CPP; 95 static char CPPFLAGS[] = "-C"; 96 static char pathbuf[MAXPATHLEN + 1]; 97 static char *allv[] = { 98 "rpcgen", "-s", "udp", "-s", "tcp", 99 }; 100 static int allc = sizeof (allv)/sizeof (allv[0]); 101 static char *allnv[] = { 102 "rpcgen", "-s", "netpath", 103 }; 104 static int allnc = sizeof (allnv)/sizeof (allnv[0]); 105 106 /* 107 * machinations for handling expanding argument list 108 */ 109 static void addarg(); /* add another argument to the list */ 110 static void putarg(); /* put argument at specified location */ 111 static void clear_args(); /* clear argument list */ 112 static void checkfiles(); /* check if out file already exists */ 113 114 115 116 #define ARGLISTLEN 20 117 #define FIXEDARGS 2 118 119 static char *arglist[ARGLISTLEN]; 120 static int argcount = FIXEDARGS; 121 122 123 int nonfatalerrors; /* errors */ 124 #ifdef __FreeBSD__ 125 int inetdflag = 0; /* Support for inetd is now the default */ 126 #else 127 int inetdflag; /* Support for inetd is now the default */ 128 #endif 129 int pmflag; /* Support for port monitors */ 130 int logflag; /* Use syslog instead of fprintf for errors */ 131 int tblflag; /* Support for dispatch table file */ 132 int mtflag = 0; /* Support for MT */ 133 #ifdef __FreeBSD__ 134 #define INLINE 0 135 #else 136 #define INLINE 5 137 #endif 138 /* length at which to start doing an inline */ 139 140 int inline = INLINE; 141 /* 142 * Length at which to start doing an inline. INLINE = default 143 * if 0, no xdr_inline code 144 */ 145 146 int indefinitewait; /* If started by port monitors, hang till it wants */ 147 int exitnow; /* If started by port monitors, exit after the call */ 148 int timerflag; /* TRUE if !indefinite && !exitnow */ 149 int newstyle; /* newstyle of passing arguments (by value) */ 150 int Cflag = 0; /* ANSI C syntax */ 151 int CCflag = 0; /* C++ files */ 152 static int allfiles; /* generate all files */ 153 #ifdef __FreeBSD__ 154 int tirpcflag = 0; /* generating code for tirpc, by default */ 155 #else 156 int tirpcflag = 1; /* generating code for tirpc, by default */ 157 #endif 158 xdrfunc *xdrfunc_head = NULL; /* xdr function list */ 159 xdrfunc *xdrfunc_tail = NULL; /* xdr function list */ 160 pid_t childpid; 161 162 163 int 164 main(argc, argv) 165 int argc; 166 char *argv[]; 167 { 168 struct commandline cmd; 169 170 (void) memset((char *)&cmd, 0, sizeof (struct commandline)); 171 clear_args(); 172 if (!parseargs(argc, argv, &cmd)) 173 usage(); 174 /* 175 * Only the client and server side stubs are likely to be customized, 176 * so in that case only, check if the outfile exists, and if so, 177 * print an error message and exit. 178 */ 179 if (cmd.Ssflag || cmd.Scflag || cmd.makefileflag) { 180 checkfiles(cmd.infile, cmd.outfile); 181 } 182 else 183 checkfiles(cmd.infile, NULL); 184 185 if (cmd.cflag) { 186 c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); 187 } else if (cmd.hflag) { 188 h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); 189 } else if (cmd.lflag) { 190 l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); 191 } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) { 192 s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, 193 cmd.outfile, cmd.mflag, cmd.nflag); 194 } else if (cmd.tflag) { 195 t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); 196 } else if (cmd.Ssflag) { 197 svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, 198 cmd.outfile); 199 } else if (cmd.Scflag) { 200 clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, 201 cmd.outfile); 202 } else if (cmd.makefileflag) { 203 mkfile_output(&cmd); 204 } else { 205 /* the rescans are required, since cpp may effect input */ 206 c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); 207 reinitialize(); 208 h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h"); 209 reinitialize(); 210 l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); 211 reinitialize(); 212 if (inetdflag || !tirpcflag) 213 s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, 214 "_svc.c", cmd.mflag, cmd.nflag); 215 else 216 s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", 217 EXTEND, "_svc.c", cmd.mflag, cmd.nflag); 218 if (tblflag) { 219 reinitialize(); 220 t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); 221 } 222 223 if (allfiles) { 224 reinitialize(); 225 svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, 226 "_server.c"); 227 reinitialize(); 228 clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, 229 "_client.c"); 230 231 } 232 if (allfiles || (cmd.makefileflag == 1)){ 233 reinitialize(); 234 mkfile_output(&cmd); 235 } 236 237 } 238 exit(nonfatalerrors); 239 /* NOTREACHED */ 240 } 241 242 243 /* 244 * add extension to filename 245 */ 246 static char * 247 #ifdef __FreeBSD__ 248 extendfile(path, ext) 249 char *path; 250 #else 251 extendfile(file, ext) 252 char *file; 253 #endif 254 char *ext; 255 { 256 char *res; 257 char *p; 258 #ifdef __FreeBSD__ 259 char *file; 260 261 if ((file = rindex(path, '/')) == NULL) 262 file = path; 263 else 264 file++; 265 #endif 266 res = alloc(strlen(file) + strlen(ext) + 1); 267 if (res == NULL) { 268 abort(); 269 } 270 p = strrchr(file, '.'); 271 if (p == NULL) { 272 p = file + strlen(file); 273 } 274 (void) strcpy(res, file); 275 (void) strcpy(res + (p - file), ext); 276 return (res); 277 } 278 279 /* 280 * Open output file with given extension 281 */ 282 static void 283 open_output(infile, outfile) 284 char *infile; 285 char *outfile; 286 { 287 288 if (outfile == NULL) { 289 fout = stdout; 290 return; 291 } 292 293 if (infile != NULL && streq(outfile, infile)) { 294 f_print(stderr, "%s: %s already exists. No output generated.\n", 295 cmdname, infile); 296 crash(); 297 } 298 fout = fopen(outfile, "w"); 299 if (fout == NULL) { 300 f_print(stderr, "%s: unable to open ", cmdname); 301 perror(outfile); 302 crash(); 303 } 304 record_open(outfile); 305 306 return; 307 } 308 309 static void 310 add_warning() 311 { 312 f_print(fout, "/*\n"); 313 f_print(fout, " * Please do not edit this file.\n"); 314 f_print(fout, " * It was generated using rpcgen.\n"); 315 f_print(fout, " */\n\n"); 316 } 317 318 /* clear list of arguments */ 319 static void clear_args() 320 { 321 int i; 322 for (i = FIXEDARGS; i < ARGLISTLEN; i++) 323 arglist[i] = NULL; 324 argcount = FIXEDARGS; 325 } 326 327 /* make sure that a CPP exists */ 328 static void find_cpp() 329 { 330 struct stat buf; 331 332 if (stat(CPP, &buf) < 0) { /* SVR4 or explicit cpp does not exist */ 333 if (cppDefined) { 334 fprintf(stderr, 335 "cannot find C preprocessor: %s \n", CPP); 336 crash(); 337 } else { /* try the other one */ 338 CPP = SUNOS_CPP; 339 if (stat(CPP, &buf) < 0) { /* can't find any cpp */ 340 fprintf(stderr, 341 "cannot find any C preprocessor (cpp)\n"); 342 crash(); 343 } 344 } 345 } 346 } 347 348 /* 349 * Open input file with given define for C-preprocessor 350 */ 351 static void 352 open_input(infile, define) 353 char *infile; 354 char *define; 355 { 356 int pd[2]; 357 358 infilename = (infile == NULL) ? "<stdin>" : infile; 359 (void) pipe(pd); 360 switch (childpid = fork()) { 361 case 0: 362 find_cpp(); 363 putarg(0, CPP); 364 putarg(1, CPPFLAGS); 365 addarg(define); 366 if (infile) 367 addarg(infile); 368 addarg((char *)NULL); 369 (void) close(1); 370 (void) dup2(pd[1], 1); 371 (void) close(pd[0]); 372 execv(arglist[0], arglist); 373 perror("execv"); 374 exit(1); 375 case -1: 376 perror("fork"); 377 exit(1); 378 } 379 (void) close(pd[1]); 380 fin = fdopen(pd[0], "r"); 381 if (fin == NULL) { 382 f_print(stderr, "%s: ", cmdname); 383 perror(infilename); 384 crash(); 385 } 386 } 387 388 /* valid tirpc nettypes */ 389 static char* valid_ti_nettypes[] = 390 { 391 "netpath", 392 "visible", 393 "circuit_v", 394 "datagram_v", 395 "circuit_n", 396 "datagram_n", 397 "udp", 398 "tcp", 399 "raw", 400 NULL 401 }; 402 403 /* valid inetd nettypes */ 404 static char* valid_i_nettypes[] = 405 { 406 "udp", 407 "tcp", 408 NULL 409 }; 410 411 static int check_nettype(name, list_to_check) 412 char* name; 413 char* list_to_check[]; 414 { 415 int i; 416 for (i = 0; list_to_check[i] != NULL; i++) { 417 if (strcmp(name, list_to_check[i]) == 0) { 418 return (1); 419 } 420 } 421 f_print(stderr, "illegal nettype :\'%s\'\n", name); 422 return (0); 423 } 424 425 static char * 426 file_name(file, ext) 427 char *file; 428 char *ext; 429 { 430 char *temp; 431 temp = extendfile(file, ext); 432 433 if (access(temp, F_OK) != -1) 434 return (temp); 435 else 436 return ((char *)" "); 437 438 } 439 440 441 static void 442 c_output(infile, define, extend, outfile) 443 char *infile; 444 char *define; 445 int extend; 446 char *outfile; 447 { 448 definition *def; 449 char *include; 450 char *outfilename; 451 long tell; 452 453 c_initialize(); 454 open_input(infile, define); 455 outfilename = extend ? extendfile(infile, outfile) : outfile; 456 open_output(infile, outfilename); 457 add_warning(); 458 if (infile && (include = extendfile(infile, ".h"))) { 459 f_print(fout, "#include \"%s\"\n", include); 460 free(include); 461 /* .h file already contains rpc/rpc.h */ 462 } else 463 f_print(fout, "#include <rpc/rpc.h>\n"); 464 tell = ftell(fout); 465 while ( (def = get_definition()) ) { 466 emit(def); 467 } 468 if (extend && tell == ftell(fout)) { 469 (void) unlink(outfilename); 470 } 471 } 472 473 474 void 475 c_initialize() 476 { 477 478 /* add all the starting basic types */ 479 add_type(1, "int"); 480 add_type(1, "long"); 481 add_type(1, "short"); 482 add_type(1, "bool"); 483 add_type(1, "u_int"); 484 add_type(1, "u_long"); 485 add_type(1, "u_short"); 486 487 } 488 489 char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ 490 char *(*proc)(); \n\ 491 xdrproc_t xdr_arg; \n\ 492 unsigned len_arg; \n\ 493 xdrproc_t xdr_res; \n\ 494 unsigned len_res; \n\ 495 }; \n"; 496 497 498 char *generate_guard(pathname) 499 char* pathname; 500 { 501 char* filename, *guard, *tmp; 502 503 filename = strrchr(pathname, '/'); /* find last component */ 504 filename = ((filename == 0) ? pathname : filename+1); 505 guard = strdup(filename); 506 /* convert to upper case */ 507 tmp = guard; 508 while (*tmp) { 509 if (islower(*tmp)) 510 *tmp = toupper(*tmp); 511 tmp++; 512 } 513 guard = extendfile(guard, "_H_RPCGEN"); 514 return (guard); 515 } 516 517 /* 518 * Compile into an XDR header file 519 */ 520 521 522 static void 523 h_output(infile, define, extend, outfile) 524 char *infile; 525 char *define; 526 int extend; 527 char *outfile; 528 { 529 definition *def; 530 char *outfilename; 531 long tell; 532 char *guard; 533 list *l; 534 xdrfunc *xdrfuncp; 535 int i; 536 537 open_input(infile, define); 538 outfilename = extend ? extendfile(infile, outfile) : outfile; 539 open_output(infile, outfilename); 540 add_warning(); 541 if (outfilename || infile){ 542 guard = generate_guard(outfilename ? outfilename: infile); 543 } else 544 guard = "STDIN_"; 545 546 f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard, 547 guard); 548 549 f_print(fout, "#include <rpc/rpc.h>\n"); 550 551 if (mtflag) { 552 f_print(fout, "#include <synch.h>\n"); 553 f_print(fout, "#include <thread.h>\n"); 554 }; 555 556 /* put the C++ support */ 557 if (Cflag && !CCflag){ 558 f_print(fout, "\n#ifdef __cplusplus\n"); 559 f_print(fout, "extern \"C\" {\n"); 560 f_print(fout, "#endif\n\n"); 561 } 562 563 /* put in a typedef for quadprecision. Only with Cflag */ 564 565 tell = ftell(fout); 566 567 /* print data definitions */ 568 while ( (def = get_definition()) ) { 569 print_datadef(def); 570 } 571 572 /* 573 * print function declarations. 574 * Do this after data definitions because they might be used as 575 * arguments for functions 576 */ 577 for (l = defined; l != NULL; l = l->next) { 578 print_funcdef(l->val); 579 } 580 /* Now print all xdr func declarations */ 581 if (xdrfunc_head != NULL){ 582 583 f_print(fout, 584 "\n/* the xdr functions */\n"); 585 586 if (CCflag){ 587 f_print(fout, "\n#ifdef __cplusplus\n"); 588 f_print(fout, "extern \"C\" {\n"); 589 f_print(fout, "#endif\n"); 590 } 591 592 if (!Cflag){ 593 xdrfuncp = xdrfunc_head; 594 while (xdrfuncp != NULL){ 595 print_xdr_func_def(xdrfuncp->name, 596 xdrfuncp->pointerp, 2); 597 xdrfuncp = xdrfuncp->next; 598 } 599 } else { 600 601 for (i = 1; i < 3; i++){ 602 if (i == 1) 603 f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); 604 605 else 606 f_print(fout, "\n#else /* K&R C */\n"); 607 608 xdrfuncp = xdrfunc_head; 609 while (xdrfuncp != NULL){ 610 print_xdr_func_def(xdrfuncp->name, 611 xdrfuncp->pointerp, i); 612 xdrfuncp = xdrfuncp->next; 613 } 614 } 615 f_print(fout, "\n#endif /* K&R C */\n"); 616 } 617 } 618 619 if (extend && tell == ftell(fout)) { 620 (void) unlink(outfilename); 621 } else if (tblflag) { 622 f_print(fout, rpcgen_table_dcl); 623 } 624 625 if (Cflag){ 626 f_print(fout, "\n#ifdef __cplusplus\n"); 627 f_print(fout, "}\n"); 628 f_print(fout, "#endif\n"); 629 } 630 631 f_print(fout, "\n#endif /* !_%s */\n", guard); 632 } 633 634 /* 635 * Compile into an RPC service 636 */ 637 static void 638 s_output(argc, argv, infile, define, extend, outfile, nomain, netflag) 639 int argc; 640 char *argv[]; 641 char *infile; 642 char *define; 643 int extend; 644 char *outfile; 645 int nomain; 646 int netflag; 647 { 648 char *include; 649 definition *def; 650 int foundprogram = 0; 651 char *outfilename; 652 653 open_input(infile, define); 654 outfilename = extend ? extendfile(infile, outfile) : outfile; 655 open_output(infile, outfilename); 656 add_warning(); 657 if (infile && (include = extendfile(infile, ".h"))) { 658 f_print(fout, "#include \"%s\"\n", include); 659 free(include); 660 } else 661 f_print(fout, "#include <rpc/rpc.h>\n"); 662 663 f_print(fout, "#include <stdio.h>\n"); 664 f_print(fout, "#include <stdlib.h> /* getenv, exit */\n"); 665 if (Cflag) { 666 f_print (fout, 667 "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n"); 668 f_print (fout, "#include <string.h> /* strcmp */\n"); 669 } 670 if (strcmp(svcclosetime, "-1") == 0) 671 indefinitewait = 1; 672 else if (strcmp(svcclosetime, "0") == 0) 673 exitnow = 1; 674 else if (inetdflag || pmflag) { 675 f_print(fout, "#include <signal.h>\n"); 676 timerflag = 1; 677 } 678 679 if (!tirpcflag && inetdflag) 680 f_print(fout, "#include <sys/ttycom.h> /* TIOCNOTTY */\n"); 681 if (Cflag && (inetdflag || pmflag)) { 682 f_print(fout, "#ifdef __cplusplus\n"); 683 f_print(fout, 684 "#include <sysent.h> /* getdtablesize, open */\n"); 685 f_print(fout, "#endif /* __cplusplus */\n"); 686 if (tirpcflag) 687 f_print(fout, "#include <unistd.h> /* setsid */\n"); 688 } 689 if (tirpcflag) 690 f_print(fout, "#include <sys/types.h>\n"); 691 692 f_print(fout, "#include <memory.h>\n"); 693 #ifdef __FreeBSD__ 694 if (tirpcflag) 695 #endif 696 f_print(fout, "#include <stropts.h>\n"); 697 if (inetdflag || !tirpcflag) { 698 f_print(fout, "#include <sys/socket.h>\n"); 699 f_print(fout, "#include <netinet/in.h>\n"); 700 } 701 702 if ((netflag || pmflag) && tirpcflag && !nomain) { 703 f_print(fout, "#include <netconfig.h>\n"); 704 } 705 if (tirpcflag) 706 f_print(fout, "#include <sys/resource.h> /* rlimit */\n"); 707 if (logflag || inetdflag || pmflag) 708 f_print(fout, "#include <syslog.h>\n"); 709 710 /* for ANSI-C */ 711 if (Cflag) 712 f_print(fout, 713 "\n#ifndef SIG_PF\n#define SIG_PF void(*)\ 714 (int)\n#endif\n"); 715 716 f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); 717 if (timerflag) 718 f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", 719 svcclosetime); 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_most(infile, netflag, nomain); 728 if (!nomain) { 729 if (!do_registers(argc, argv)) { 730 if (outfilename) 731 (void) unlink(outfilename); 732 usage(); 733 } 734 write_rest(); 735 } 736 } 737 738 /* 739 * generate client side stubs 740 */ 741 static void 742 l_output(infile, define, extend, outfile) 743 char *infile; 744 char *define; 745 int extend; 746 char *outfile; 747 { 748 char *include; 749 definition *def; 750 int foundprogram = 0; 751 char *outfilename; 752 753 open_input(infile, define); 754 outfilename = extend ? extendfile(infile, outfile) : outfile; 755 open_output(infile, outfilename); 756 add_warning(); 757 if (Cflag) 758 f_print (fout, "#include <memory.h> /* for memset */\n"); 759 if (infile && (include = extendfile(infile, ".h"))) { 760 f_print(fout, "#include \"%s\"\n", include); 761 free(include); 762 } else 763 f_print(fout, "#include <rpc/rpc.h>\n"); 764 while ( (def = get_definition()) ) { 765 foundprogram |= (def->def_kind == DEF_PROGRAM); 766 } 767 if (extend && !foundprogram) { 768 (void) unlink(outfilename); 769 return; 770 } 771 write_stubs(); 772 } 773 774 /* 775 * generate the dispatch table 776 */ 777 static void 778 t_output(infile, define, extend, outfile) 779 char *infile; 780 char *define; 781 int extend; 782 char *outfile; 783 { 784 definition *def; 785 int foundprogram = 0; 786 char *outfilename; 787 788 open_input(infile, define); 789 outfilename = extend ? extendfile(infile, outfile) : outfile; 790 open_output(infile, outfilename); 791 add_warning(); 792 while ( (def = get_definition()) ) { 793 foundprogram |= (def->def_kind == DEF_PROGRAM); 794 } 795 if (extend && !foundprogram) { 796 (void) unlink(outfilename); 797 return; 798 } 799 write_tables(); 800 } 801 802 /* sample routine for the server template */ 803 static void 804 svc_output(infile, define, extend, outfile) 805 char *infile; 806 char *define; 807 int extend; 808 char *outfile; 809 { 810 definition *def; 811 char *include; 812 char *outfilename; 813 long tell; 814 open_input(infile, define); 815 outfilename = extend ? extendfile(infile, outfile) : outfile; 816 checkfiles(infile, outfilename); 817 /* 818 * Check if outfile already exists. 819 * if so, print an error message and exit 820 */ 821 open_output(infile, outfilename); 822 add_sample_msg(); 823 824 if (infile && (include = extendfile(infile, ".h"))) { 825 f_print(fout, "#include \"%s\"\n", include); 826 free(include); 827 } else 828 f_print(fout, "#include <rpc/rpc.h>\n"); 829 830 tell = ftell(fout); 831 while ( (def = get_definition()) ) { 832 write_sample_svc(def); 833 } 834 if (extend && tell == ftell(fout)) { 835 (void) unlink(outfilename); 836 } 837 } 838 839 /* sample main routine for client */ 840 static void 841 clnt_output(infile, define, extend, outfile) 842 char *infile; 843 char *define; 844 int extend; 845 char *outfile; 846 { 847 definition *def; 848 char *include; 849 char *outfilename; 850 long tell; 851 int has_program = 0; 852 853 open_input(infile, define); 854 outfilename = extend ? extendfile(infile, outfile) : outfile; 855 checkfiles(infile, outfilename); 856 /* 857 * Check if outfile already exists. 858 * if so, print an error message and exit 859 */ 860 861 open_output(infile, outfilename); 862 add_sample_msg(); 863 if (infile && (include = extendfile(infile, ".h"))) { 864 f_print(fout, "#include \"%s\"\n", include); 865 free(include); 866 } else 867 f_print(fout, "#include <rpc/rpc.h>\n"); 868 tell = ftell(fout); 869 while ( (def = get_definition()) ) { 870 has_program += write_sample_clnt(def); 871 } 872 873 if (has_program) 874 write_sample_clnt_main(); 875 876 if (extend && tell == ftell(fout)) { 877 (void) unlink(outfilename); 878 } 879 } 880 881 882 static void mkfile_output(cmd) 883 struct commandline *cmd; 884 { 885 char *mkfilename, *clientname, *clntname, *xdrname, *hdrname; 886 char *servername, *svcname, *servprogname, *clntprogname; 887 char *temp; 888 889 svcname = file_name(cmd->infile, "_svc.c"); 890 clntname = file_name(cmd->infile, "_clnt.c"); 891 xdrname = file_name(cmd->infile, "_xdr.c"); 892 hdrname = file_name(cmd->infile, ".h"); 893 894 895 if (allfiles){ 896 servername = extendfile(cmd->infile, "_server.c"); 897 clientname = extendfile(cmd->infile, "_client.c"); 898 }else{ 899 servername = " "; 900 clientname = " "; 901 } 902 servprogname = extendfile(cmd->infile, "_server"); 903 clntprogname = extendfile(cmd->infile, "_client"); 904 905 if (allfiles){ 906 mkfilename = alloc(strlen("makefile.") + 907 strlen(cmd->infile) + 1); 908 temp = (char *)rindex(cmd->infile, '.'); 909 strcat(mkfilename, "makefile."); 910 (void) strncat(mkfilename, cmd->infile, 911 (temp - cmd->infile)); 912 } else 913 mkfilename = cmd->outfile; 914 915 916 checkfiles(NULL, mkfilename); 917 open_output(NULL, mkfilename); 918 919 f_print(fout, "\n# This is a template makefile generated\ 920 by rpcgen \n"); 921 922 f_print(fout, "\n# Parameters \n\n"); 923 924 f_print(fout, "CLIENT = %s\nSERVER = %s\n\n", 925 clntprogname, servprogname); 926 f_print(fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); 927 f_print(fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); 928 f_print(fout, "SOURCES.x = %s\n\n", cmd->infile); 929 f_print(fout, "TARGETS_SVC.c = %s %s %s \n", 930 svcname, servername, xdrname); 931 f_print(fout, "TARGETS_CLNT.c = %s %s %s \n", 932 clntname, clientname, xdrname); 933 f_print(fout, "TARGETS = %s %s %s %s %s %s\n\n", 934 hdrname, xdrname, clntname, 935 svcname, clientname, servername); 936 937 f_print(fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \ 938 $(TARGETS_CLNT.c:%%.c=%%.o) "); 939 940 f_print(fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \ 941 $(TARGETS_SVC.c:%%.c=%%.o) "); 942 943 944 f_print(fout, "\n# Compiler flags \n"); 945 if (mtflag) 946 f_print(fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS += -lnsl -lthread\n"); 947 else 948 #ifdef __FreeBSD__ 949 f_print(fout, "\nCFLAGS += -g \nLDLIBS +=\n"); 950 #else 951 f_print(fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); 952 #endif 953 f_print(fout, "RPCGENFLAGS = \n"); 954 955 f_print(fout, "\n# Targets \n\n"); 956 957 f_print(fout, "all : $(CLIENT) $(SERVER)\n\n"); 958 f_print(fout, "$(TARGETS) : $(SOURCES.x) \n"); 959 f_print(fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); 960 f_print(fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \ 961 $(TARGETS_CLNT.c) \n\n"); 962 963 f_print(fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \ 964 $(TARGETS_SVC.c) \n\n"); 965 f_print(fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); 966 #ifdef __FreeBSD__ 967 f_print(fout, "\t$(CC) -o $(CLIENT) $(OBJECTS_CLNT) \ 968 $(LDLIBS) \n\n"); 969 #else 970 f_print(fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ 971 $(LDLIBS) \n\n"); 972 #endif 973 f_print(fout, "$(SERVER) : $(OBJECTS_SVC) \n"); 974 #ifdef __FreeBSD__ 975 f_print(fout, "\t$(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); 976 f_print(fout, "clean:\n\t $(RM) -f core $(TARGETS) $(OBJECTS_CLNT) \ 977 $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); 978 #else 979 f_print(fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); 980 f_print(fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \ 981 $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); 982 #endif 983 } 984 985 986 987 /* 988 * Perform registrations for service output 989 * Return 0 if failed; 1 otherwise. 990 */ 991 static int 992 do_registers(argc, argv) 993 int argc; 994 char *argv[]; 995 { 996 int i; 997 998 if (inetdflag || !tirpcflag) { 999 for (i = 1; i < argc; i++) { 1000 if (streq(argv[i], "-s")) { 1001 if (!check_nettype(argv[i + 1], 1002 valid_i_nettypes)) 1003 return (0); 1004 write_inetd_register(argv[i + 1]); 1005 i++; 1006 } 1007 } 1008 } else { 1009 for (i = 1; i < argc; i++) 1010 if (streq(argv[i], "-s")) { 1011 if (!check_nettype(argv[i + 1], 1012 valid_ti_nettypes)) 1013 return (0); 1014 write_nettype_register(argv[i + 1]); 1015 i++; 1016 } else if (streq(argv[i], "-n")) { 1017 write_netid_register(argv[i + 1]); 1018 i++; 1019 } 1020 } 1021 return (1); 1022 } 1023 1024 /* 1025 * Add another argument to the arg list 1026 */ 1027 static void 1028 addarg(cp) 1029 char *cp; 1030 { 1031 if (argcount >= ARGLISTLEN) { 1032 f_print(stderr, "rpcgen: too many defines\n"); 1033 crash(); 1034 /*NOTREACHED*/ 1035 } 1036 arglist[argcount++] = cp; 1037 1038 } 1039 1040 static void 1041 putarg(where, cp) 1042 char *cp; 1043 int where; 1044 { 1045 if (where >= ARGLISTLEN) { 1046 f_print(stderr, "rpcgen: arglist coding error\n"); 1047 crash(); 1048 /*NOTREACHED*/ 1049 } 1050 arglist[where] = cp; 1051 } 1052 1053 /* 1054 * if input file is stdin and an output file is specified then complain 1055 * if the file already exists. Otherwise the file may get overwritten 1056 * If input file does not exist, exit with an error 1057 */ 1058 1059 static void 1060 checkfiles(infile, outfile) 1061 char *infile; 1062 char *outfile; 1063 { 1064 1065 struct stat buf; 1066 1067 if (infile) /* infile ! = NULL */ 1068 if (stat(infile, &buf) < 0) 1069 { 1070 perror(infile); 1071 crash(); 1072 }; 1073 if (outfile) { 1074 if (stat(outfile, &buf) < 0) 1075 return; /* file does not exist */ 1076 else { 1077 f_print(stderr, 1078 "file '%s' already exists and may be overwritten\n", 1079 outfile); 1080 crash(); 1081 } 1082 } 1083 } 1084 1085 /* 1086 * Parse command line arguments 1087 */ 1088 static int 1089 parseargs(argc, argv, cmd) 1090 int argc; 1091 char *argv[]; 1092 struct commandline *cmd; 1093 { 1094 int i; 1095 int j; 1096 char c, ch; 1097 char flag[(1 << 8 * sizeof (char))]; 1098 int nflags; 1099 1100 cmdname = argv[0]; 1101 cmd->infile = cmd->outfile = NULL; 1102 if (argc < 2) { 1103 return (0); 1104 } 1105 allfiles = 0; 1106 flag['c'] = 0; 1107 flag['h'] = 0; 1108 flag['l'] = 0; 1109 flag['m'] = 0; 1110 flag['o'] = 0; 1111 flag['s'] = 0; 1112 flag['n'] = 0; 1113 flag['t'] = 0; 1114 flag['S'] = 0; 1115 flag['C'] = 0; 1116 flag['M'] = 0; 1117 1118 for (i = 1; i < argc; i++) { 1119 if (argv[i][0] != '-') { 1120 if (cmd->infile) { 1121 f_print(stderr, 1122 "Cannot specify more than one input file.\n"); 1123 1124 return (0); 1125 } 1126 cmd->infile = argv[i]; 1127 } else { 1128 for (j = 1; argv[i][j] != 0; j++) { 1129 c = argv[i][j]; 1130 switch (c) { 1131 case 'a': 1132 allfiles = 1; 1133 break; 1134 case 'c': 1135 case 'h': 1136 case 'l': 1137 case 'm': 1138 case 't': 1139 if (flag[(int)c]) { 1140 return (0); 1141 } 1142 flag[(int)c] = 1; 1143 break; 1144 case 'S': 1145 /* 1146 * sample flag: Ss or Sc. 1147 * Ss means set flag['S']; 1148 * Sc means set flag['C']; 1149 * Sm means set flag['M']; 1150 */ 1151 ch = argv[i][++j]; /* get next char */ 1152 if (ch == 's') 1153 ch = 'S'; 1154 else if (ch == 'c') 1155 ch = 'C'; 1156 else if (ch == 'm') 1157 ch = 'M'; 1158 else 1159 return (0); 1160 1161 if (flag[(int)ch]) { 1162 return (0); 1163 } 1164 flag[(int)ch] = 1; 1165 break; 1166 case 'C': /* ANSI C syntax */ 1167 Cflag = 1; 1168 ch = argv[i][j+1]; /* get next char */ 1169 1170 if (ch != 'C') 1171 break; 1172 CCflag = 1; 1173 break; 1174 case 'b': 1175 /* 1176 * Turn TIRPC flag off for 1177 * generating backward compatible 1178 * code 1179 */ 1180 #ifdef __FreeBSD__ 1181 tirpcflag = 1; 1182 #else 1183 tirpcflag = 0; 1184 #endif 1185 break; 1186 1187 case 'I': 1188 inetdflag = 1; 1189 break; 1190 case 'N': 1191 newstyle = 1; 1192 break; 1193 case 'L': 1194 logflag = 1; 1195 break; 1196 case 'K': 1197 if (++i == argc) { 1198 return (0); 1199 } 1200 svcclosetime = argv[i]; 1201 goto nextarg; 1202 case 'T': 1203 tblflag = 1; 1204 break; 1205 case 'M': 1206 mtflag = 1; 1207 break; 1208 case 'i' : 1209 if (++i == argc) { 1210 return (0); 1211 } 1212 inline = atoi(argv[i]); 1213 goto nextarg; 1214 case 'n': 1215 case 'o': 1216 case 's': 1217 if (argv[i][j - 1] != '-' || 1218 argv[i][j + 1] != 0) { 1219 return (0); 1220 } 1221 flag[(int)c] = 1; 1222 if (++i == argc) { 1223 return (0); 1224 } 1225 if (c == 'o') { 1226 if (cmd->outfile) { 1227 return (0); 1228 } 1229 cmd->outfile = argv[i]; 1230 } 1231 goto nextarg; 1232 case 'D': 1233 if (argv[i][j - 1] != '-') { 1234 return (0); 1235 } 1236 (void) addarg(argv[i]); 1237 goto nextarg; 1238 case 'Y': 1239 if (++i == argc) { 1240 return (0); 1241 } 1242 (void) strcpy(pathbuf, argv[i]); 1243 (void) strcat(pathbuf, "/cpp"); 1244 CPP = pathbuf; 1245 cppDefined = 1; 1246 goto nextarg; 1247 1248 1249 1250 default: 1251 return (0); 1252 } 1253 } 1254 nextarg: 1255 ; 1256 } 1257 } 1258 1259 cmd->cflag = flag['c']; 1260 cmd->hflag = flag['h']; 1261 cmd->lflag = flag['l']; 1262 cmd->mflag = flag['m']; 1263 cmd->nflag = flag['n']; 1264 cmd->sflag = flag['s']; 1265 cmd->tflag = flag['t']; 1266 cmd->Ssflag = flag['S']; 1267 cmd->Scflag = flag['C']; 1268 cmd->makefileflag = flag['M']; 1269 1270 if (tirpcflag) { 1271 pmflag = inetdflag ? 0 : 1; 1272 /* pmflag or inetdflag is always TRUE */ 1273 if ((inetdflag && cmd->nflag)) { 1274 /* netid not allowed with inetdflag */ 1275 f_print(stderr, "Cannot use netid flag with inetd flag.\n"); 1276 return (0); 1277 } 1278 } else { /* 4.1 mode */ 1279 pmflag = 0; /* set pmflag only in tirpcmode */ 1280 #ifndef __FreeBSD__ 1281 inetdflag = 1; /* inetdflag is TRUE by default */ 1282 #endif 1283 if (cmd->nflag) { /* netid needs TIRPC */ 1284 f_print(stderr, "Cannot use netid flag without TIRPC.\n"); 1285 return (0); 1286 } 1287 } 1288 1289 if (newstyle && (tblflag || cmd->tflag)) { 1290 f_print(stderr, "Cannot use table flags with newstyle.\n"); 1291 return (0); 1292 } 1293 1294 /* check no conflicts with file generation flags */ 1295 nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + 1296 cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + 1297 cmd->Scflag + cmd->makefileflag; 1298 1299 if (nflags == 0) { 1300 if (cmd->outfile != NULL || cmd->infile == NULL) { 1301 return (0); 1302 } 1303 } else if (cmd->infile == NULL && 1304 (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) { 1305 f_print(stderr, 1306 "\"infile\" is required for template generation flags.\n"); 1307 return (0); 1308 } if (nflags > 1) { 1309 f_print(stderr, 1310 "Cannot have more than one file generation flag.\n"); 1311 return (0); 1312 } 1313 return (1); 1314 } 1315 1316 static void 1317 usage() 1318 { 1319 f_print(stderr, "usage: %s infile\n", cmdname); 1320 f_print(stderr, 1321 "\t%s [-abCLNTM] [-Dname[=value]] [-i size]\ 1322 [-I [-K seconds]] [-Y path] infile\n", 1323 cmdname); 1324 f_print(stderr, 1325 "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]\ 1326 [-o outfile] [infile]\n", 1327 cmdname); 1328 f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname); 1329 f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname); 1330 options_usage(); 1331 exit(1); 1332 } 1333 1334 static void 1335 options_usage() 1336 { 1337 f_print(stderr, "options:\n"); 1338 f_print(stderr, "-a\t\tgenerate all files, including samples\n"); 1339 f_print(stderr, "-b\t\tbackward compatibility mode (generates code\ 1340 for SunOS 4.X)\n"); 1341 f_print(stderr, "-c\t\tgenerate XDR routines\n"); 1342 f_print(stderr, "-C\t\tANSI C mode\n"); 1343 f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n"); 1344 f_print(stderr, "-h\t\tgenerate header file\n"); 1345 f_print(stderr, "-i size\t\tsize at which to start generating\ 1346 inline code\n"); 1347 f_print(stderr, "-I\t\tgenerate code for inetd support in server\ 1348 (for SunOS 4.X)\n"); 1349 f_print(stderr, "-K seconds\tserver exits after K seconds of\ 1350 inactivity\n"); 1351 f_print(stderr, "-l\t\tgenerate client side stubs\n"); 1352 f_print(stderr, "-L\t\tserver errors will be printed to syslog\n"); 1353 f_print(stderr, "-m\t\tgenerate server side stubs\n"); 1354 f_print(stderr, "-M\t\tgenerate MT-safe code\n"); 1355 f_print(stderr, "-n netid\tgenerate server code that supports\ 1356 named netid\n"); 1357 f_print(stderr, "-N\t\tsupports multiple arguments and\ 1358 call-by-value\n"); 1359 f_print(stderr, "-o outfile\tname of the output file\n"); 1360 f_print(stderr, "-s nettype\tgenerate server code that supports named\ 1361 nettype\n"); 1362 f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote\ 1363 procedures\n"); 1364 f_print(stderr, "-Ss\t\tgenerate sample server code that defines\ 1365 remote procedures\n"); 1366 f_print(stderr, "-Sm \t\tgenerate makefile template \n"); 1367 1368 f_print(stderr, "-t\t\tgenerate RPC dispatch table\n"); 1369 f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n"); 1370 f_print(stderr, "-Y path\t\tpath where cpp is found\n"); 1371 exit(1); 1372 } 1373 1374 #ifndef __FreeBSD__ 1375 char * 1376 rindex(sp, c) 1377 register char *sp, c; 1378 { 1379 register char *r; 1380 1381 r = NULL; 1382 do { 1383 if (*sp == c) 1384 r = sp; 1385 } while (*sp++); 1386 return (r); 1387 } 1388 #endif 1389