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