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