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