1 /*
2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
6 */
7
8 static char RCSid[] = "$Id: itox.c,v 1.4 2007-09-20 17:13:24 bbraun Exp $" ;
9
10 #include "config.h"
11 #define EQ( s1, s2 ) ( strcmp( s1, s2 ) == 0 )
12
13 #define NUL '\0'
14 #define static static
15
16 #define FIELD_WIDTH 15
17 #define DAEMON_DIR_OPTION "-daemon_dir"
18 #define TCPD_NAME "tcpd"
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include "sio.h"
23 #include "str.h"
24 #if !defined(linux)
25 #include "misc.h"
26 #else
27 #include <libgen.h>
28 #endif
29
30 str_h strp ;
31 int line_count ;
32 static void print_line( const char *name, const char *value );
33 static char *next_word( const char *description );
34 static char *make_string_cat( register unsigned count, ... );
35 static char *make_pathname( register unsigned count, ... );
36
37
38 /*
39 * This program works only as a filter.
40 * Options:
41 * -daemon_dir <dir_name> : if you use tcpd, this option specifies the
42 * directory where all the daemons are.
43 * You must specify this option if you use tcpd
44 *
45 * Note that we don't bother to free the memory we malloc.
46 */
main(int argc,char * argv[])47 int main(int argc, char *argv[] )
48 {
49 char *s ;
50 int uses_tcpd ;
51 char *daemon_dirpath = NULL ;
52
53 if ( argc != 1 && argc != 3 )
54 {
55 Sprint( 2, "Usage: %s [%s dir_path]\n",
56 basename( argv[ 0 ] ), DAEMON_DIR_OPTION ) ;
57 exit( 1 ) ;
58 }
59
60 uses_tcpd = ( argc == 3 ) ;
61
62 if ( uses_tcpd )
63 {
64 int len ;
65
66 daemon_dirpath = argv[ 2 ] ;
67 len = strlen( daemon_dirpath ) ;
68 if ( daemon_dirpath[ len-1 ] == '/' )
69 daemon_dirpath[ --len ] = NUL ;
70 }
71
72 strp = str_parse( (char *)0, " \t", STR_NOFLAGS, (int *)0 ) ;
73
74 while ( (s = Srdline( 0 )) )
75 {
76 char *word ;
77 char *p ;
78 char *socket_type, *protocol ;
79 char *service ;
80 int is_rpc ;
81
82 line_count++ ;
83
84 if ( SIOLINELEN( 0 ) == 0 || s[ 0 ] == '#' )
85 continue ;
86
87 str_setstr( strp, s ) ;
88
89 service = word = next_word( "service name" ) ;
90
91 /*
92 * Check if it is an RPC service
93 */
94 p = strchr( word, '/' ) ;
95 if ( p != NULL )
96 *p = 0 ;
97 Sprint( 1, "service %s\n{\n", word ) ;
98 if ( (is_rpc = ( p != NULL )) )
99 {
100 print_line( "type", "RPC" ) ;
101 print_line( "rpc_version", p+1 ) ;
102 }
103
104 socket_type = word = next_word( "socket type" ) ;
105 print_line( "socket_type", socket_type ) ;
106
107 word = next_word( "protocol" ) ;
108 p = strchr( word, '/' ) ;
109 protocol = ( p == NULL ) ? word : p+1 ;
110
111 print_line( "protocol", protocol ) ;
112
113 word = next_word( "wait/nowait" ) ;
114 p = strchr(word, '.');
115 if (p != NULL)
116 {
117 Sprint( 2,
118 "The entry for service %s/%s may be wrong, because\n",
119 service, protocol);
120 Sprint( 2,
121 "we can't convert .max option for wait/nowait field\n");
122 *p = '\0';
123 print_line( "wait", EQ( word, "wait" ) ? "yes" : "no" );
124 }
125 else
126 print_line( "wait", EQ( word, "wait" ) ? "yes" : "no" );
127
128 word = next_word( "user[.group]" ) ;
129 p = strchr(word, '.');
130 if (p != NULL)
131 {
132 *p = '\0';
133 print_line( "user", word ) ;
134 word = ++p;
135 print_line( "group", word );
136 }
137 else
138 print_line( "user", word ) ;
139
140 word = next_word( "server" ) ;
141 if ( EQ( word, "internal" ) )
142 {
143 /*
144 * We are in trouble if this is an RPC service
145 */
146 if ( is_rpc )
147 {
148 Sprint( 2,
149 "The entry for service %s will be wrong because\n", service ) ;
150 Sprint( 2, "we can't handle internal RPC services\n" ) ;
151 }
152 else
153 {
154 print_line( "type", "INTERNAL" ) ;
155 print_line( "id",
156 make_string_cat( 3, service,
157 "-", socket_type ) ) ;
158 }
159 }
160 else
161 {
162 char *server_path = word ; /* from inetd.conf */
163 char *server_of_server_path = basename( server_path ) ;
164 char *server_name = next_word( "server name" ) ;
165 char *server ; /* for xinetd config file */
166
167 if ( EQ( server_of_server_path, TCPD_NAME ) )
168 {
169 if ( ! uses_tcpd )
170 {
171 Sprint( 2, "You must use option %s if you use %s\n",
172 DAEMON_DIR_OPTION, TCPD_NAME ) ;
173 exit( 1 ) ;
174 }
175 if ( server_name[ 0 ] == '/' )
176 server = server_name ;
177 else
178 server = make_pathname( 2,
179 daemon_dirpath, server_name ) ;
180 }
181 else
182 server = server_path ;
183
184 print_line( "server", server ) ;
185
186 word = str_component( strp ) ; /* 1st arg */
187 if ( word != NULL )
188 {
189 Sprint( 1, "\t%-*s = %s", FIELD_WIDTH,
190 "server_args", word ) ;
191 while ( (word = str_component( strp )) )
192 Sprint( 1, " %s", word ) ;
193 Sputchar( 1, '\n' ) ;
194 }
195 }
196
197 Sprint( 1, "}\n\n" ) ;
198 }
199 Sflush( 1 ) ;
200 exit( 0 ) ;
201 }
202
203
print_line(const char * name,const char * value)204 static void print_line( const char *name, const char *value )
205 {
206 Sprint( 1, "\t%-*s = %s\n", FIELD_WIDTH, name, value ) ;
207 }
208
209
next_word(const char * description)210 static char *next_word( const char *description )
211 {
212 char *word = str_component( strp ) ;
213
214 if ( word == NULL )
215 {
216 Sprint( 2, "Line %d: %s missing \n", line_count, description ) ;
217 exit( 1 ) ;
218 }
219 return( word ) ;
220 }
221
make_string_cat(register unsigned count,...)222 static char *make_string_cat( register unsigned count, ... )
223 {
224 va_list ap ;
225 register unsigned i ;
226 register unsigned len = 0 ;
227 register char *s, *p ;
228 char *newstring ;
229
230 if ( count == 0 )
231 return( NULL ) ;
232
233 va_start( ap, count ) ;
234 if (count == 1)
235 { /* 9 out of 10 have just 1, so this optimizes it */
236 s = va_arg( ap, char * ) ;
237 va_end( ap );
238 if ( s == NULL )
239 return strdup("");
240 else
241 return strdup(s);
242 }
243 for ( i = 0 ; i < count ; i++ )
244 {
245 s = va_arg( ap, char * ) ;
246 if ( s == NULL )
247 continue ;
248 len += strlen( s ) ;
249 }
250 va_end( ap ) ;
251
252 newstring = (char *)malloc( len + 1 ) ;
253 if ( newstring == NULL )
254 return( NULL ) ;
255
256 p = newstring ;
257 va_start( ap, count ) ;
258 for ( i = 0 ; i < count ; i++ )
259 {
260 s = va_arg( ap, char * ) ;
261 if ( s == NULL )
262 continue ;
263 while ( (*p++ = *s++) ) ;
264 p-- ;
265 }
266 va_end( ap ) ;
267 newstring[len] = 0; /* if len == 0, must terminate or boom! */
268 return newstring ;
269 }
270
make_pathname(register unsigned count,...)271 static char *make_pathname( register unsigned count, ... )
272 {
273 va_list ap ;
274 register unsigned i ;
275 register unsigned len = 0 ;
276 register char *s, *p ;
277 char *pathname ;
278
279 if ( count == 0 )
280 return( NULL ) ;
281
282 va_start( ap, count ) ;
283 for ( i = 0 ; i < count ; i++ )
284 {
285 s = va_arg( ap, char * ) ;
286 len += strlen( s ) ;
287 }
288 va_end( ap ) ;
289
290 pathname = (char *)malloc( len + count ) ;
291 if ( pathname == NULL )
292 return( NULL ) ;
293
294 p = pathname ;
295 va_start( ap, count ) ;
296 for ( i = 0 ; i < count ; i++ )
297 {
298 s = va_arg( ap, char * ) ;
299 while ( (*p++ = *s++) ) ;
300 *(p-1) = '/' ; /* change '\0' to '/' */
301 }
302 *(p-1) = '\0' ;
303 va_end( ap ) ;
304 return( pathname ) ;
305 }
306
307