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