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