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