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
9 #include "config.h"
10 #include <sys/types.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <ctype.h>
14 #if defined (HAVE_SYS_SOCKET_H)
15 #include <sys/socket.h>
16 #endif
17 /*
18 * The following ifdef is for TIOCNOTTY
19 */
20 #ifndef NO_TERMIOS
21 #ifdef HAVE_SYS_TERMIOS_H
22 #include <sys/termios.h>
23 #endif
24 #ifdef HAVE_TERMIOS_H
25 #include <termios.h>
26 #endif
27 #else
28 #include <sys/ioctl.h>
29 #endif
30 #include <fcntl.h>
31 #ifdef HAVE_SYS_FILE_H
32 #include <sys/file.h>
33 #endif
34
35 #ifdef HAVE_SYS_IOCTL_H
36 #include <sys/ioctl.h>
37 #endif
38
39 #include <memory.h>
40 #include <syslog.h>
41 #include <errno.h>
42
43 #include "sio.h"
44 #include "str.h"
45 #include "util.h"
46 #include "msg.h"
47
out_of_memory(const char * func)48 void out_of_memory( const char *func )
49 {
50 msg( LOG_CRIT, func, ES_NOMEM ) ;
51 }
52
53
nv_find_value(const struct name_value nv_array[],const char * name)54 const struct name_value *nv_find_value( const struct name_value nv_array[], const char *name )
55 {
56 const struct name_value *nvp ;
57
58 for ( nvp = nv_array ; nvp->name ; nvp++ )
59 {
60 if ( EQ( name, nvp->name ) )
61 return( nvp ) ;
62 }
63 return( NULL ) ;
64 }
65
66
nv_find_name(const struct name_value nv_array[],int value)67 const struct name_value *nv_find_name( const struct name_value nv_array[], int value )
68 {
69 const struct name_value *nvp ;
70
71 for ( nvp = nv_array ; nvp->name ; nvp++ )
72 {
73 if ( value == nvp->value )
74 return( nvp ) ;
75 }
76 return( NULL ) ;
77 }
78
79
80 /*
81 * A name-value list is exactly what its name says.
82 * The functions nv_get_name() and nv_get_value() return a pointer to
83 * the entry with the specified value or name respectively.
84 *
85 * The list ends when an antry with a NULL name is encountered.
86 * The value field of that entry is treated in a special manner: if it
87 * is non-zero, it is assumed that there exists one more entry whose
88 * name field will be returned by the nv_get_name function if it can't
89 * find an entry whose value field is equal to its 2nd parameter.
90 * If the value field of the NULL entry is 0, then nv_get_name() will
91 * return NULL.
92 */
nv_get_name(const struct name_value nv_array[],int value)93 const char *nv_get_name( const struct name_value nv_array[], int value )
94 {
95 const struct name_value *nvp ;
96
97 for ( nvp = nv_array ; nvp->name ; nvp++ )
98 {
99 if ( value == nvp->value )
100 return( nvp->name ) ;
101 }
102 return( nvp->value ? (nvp+1)->name : NULL ) ;
103 }
104
105
106
argv_alloc(unsigned count)107 char **argv_alloc( unsigned count )
108 {
109 unsigned argv_size = (count + 1) * sizeof( char *) ;
110 char **argv ;
111 const char *func = "new_argv" ;
112
113 argv = (char **) malloc( argv_size ) ;
114 if ( argv == NULL )
115 {
116 out_of_memory( func ) ;
117 return( NULL ) ;
118 }
119 (void) memset( (char *)argv, 0, argv_size ) ;
120 return( argv ) ;
121 }
122
123
124 /*
125 * If size is 0, the pset holds strings
126 */
copy_pset(const pset_h from,pset_h * to,unsigned size)127 status_e copy_pset( const pset_h from, pset_h *to, unsigned size )
128 {
129 unsigned u ;
130 const char *func = "copy_pset" ;
131
132 if ( *to == NULL )
133 {
134 *to = pset_create( pset_count( from ), 0 ) ;
135 if ( *to == NULL )
136 {
137 out_of_memory( func ) ;
138 return( FAILED ) ;
139 }
140 }
141
142 for ( u = 0 ; u < pset_count( from ) ; u++ )
143 {
144 char *p = (char *) pset_pointer( from, u ) ;
145 char *new_s ;
146
147 if ( size == 0 )
148 new_s = new_string( p ) ;
149 else
150 new_s = (char *)malloc( size ) ;
151
152 if ( new_s == NULL )
153 {
154 out_of_memory( func ) ;
155 return( FAILED ) ;
156 }
157
158 if ( size != 0 )
159 (void) memcpy( new_s, p, size ) ;
160
161 if ( pset_add( *to, new_s ) == NULL )
162 {
163 free( new_s ) ;
164 out_of_memory( func ) ;
165 return( FAILED ) ;
166 }
167 }
168 return( OK ) ;
169 }
170
171
172 /*
173 * Disassociate from controlling terminal
174 */
no_control_tty(void)175 void no_control_tty(void)
176 {
177 #if !defined(HAVE_SETSID)
178 int fd ;
179 const char *func = "no_control_tty" ;
180
181 if ( ( fd = open( "/dev/tty", O_RDWR ) ) == -1 )
182 msg( LOG_WARNING, func, "open of /dev/tty failed: %m" ) ;
183 else
184 {
185 if ( ioctl( fd, TIOCNOTTY, (caddr_t)0 ) == -1 )
186 msg( LOG_WARNING, func, "ioctl on /dev/tty failed: %m" ) ;
187 (void) Sclose( fd ) ;
188 }
189 (void) setpgrp( getpid(), 0 ) ;
190 #else
191 (void) setsid() ;
192 #endif
193 }
194
195
196 /*
197 * Write the whole buffer to the given file descriptor ignoring interrupts
198 */
write_buf(int fd,const char * buf,int len)199 status_e write_buf( int fd, const char *buf, int len )
200 {
201 int i ;
202 ssize_t cc;
203
204 for ( i = 0 ; len > 0 ; i += cc, len -= cc )
205 {
206 cc = write( fd, buf+i, len ) ;
207 if ( cc == -1 )
208 {
209 if ( errno != EINTR )
210 return( FAILED ) ;
211 cc = 0 ;
212 }
213 }
214 return( OK ) ;
215 }
216
217
tabprint(int fd,int tab_level,const char * fmt,...)218 void tabprint( int fd, int tab_level, const char *fmt, ...)
219 {
220 va_list ap ;
221 int i ;
222
223 for ( i = 0 ; i < tab_level ; i++ )
224 Sputchar( fd, '\t' ) ;
225
226 va_start( ap, fmt ) ;
227 Sprintv( fd, fmt, ap ) ;
228 va_end( ap ) ;
229 }
230
231
232 /*
233 * Empty the socket receive buffers of all data.
234 */
drain(int sd)235 void drain( int sd )
236 {
237 char buf[ 256 ] ; /* This size is arbitrarily chosen */
238 ssize_t ret ;
239 int old_val ;
240
241 /* Put in non-blocking mode so we don't hang. */
242 old_val = fcntl( sd, F_GETFL, FNDELAY );
243 if ( fcntl( sd, F_SETFL, FNDELAY ) < 0 )
244 {
245 if ( debug.on )
246 msg( LOG_DEBUG, "drain",
247 "UDP socket could not be made non-blocking: %m" ) ;
248 return;
249 }
250
251 do {
252 ret = recv( sd, buf, sizeof( buf ), 0 ) ;
253 } while (ret > 0);
254
255 /* Restore the value since the connection will be freed, not closed. */
256 if (old_val >= 0)
257 fcntl( sd, F_SETFL, old_val );
258
259 if ( debug.on )
260 msg( LOG_DEBUG, "drain", "UDP socket should be empty" ) ;
261 }
262
263 /*
264 * Convert string to an int detecting errors.
265 */
parse_int(const char * str,int base,int term,int * res)266 int parse_int(const char *str, int base, int term, int *res)
267 {
268 char *endptr;
269 long strtol_res;
270
271 /* SUSv2 says:
272 * "Because 0, LONG_MIN and LONG_MAX are returned on error and are also
273 * valid returns on success, an application wishing to check for error
274 * situations should set errno to 0, then call strtol(), then check errno." */
275 errno = 0;
276 strtol_res = strtol(str, (char **)&endptr, base);
277
278 if (errno == 0 && *str != NUL) {
279 /* Special case: -1 means allow trailing whitespace */
280 if (term == -1) {
281 while (*endptr != NUL && isspace(*endptr))
282 endptr++;
283 term = NUL;
284 }
285
286 if (*endptr == term) {
287 *res = strtol_res;
288 return 0;
289 }
290 }
291
292 *res = 0;
293 return -1;
294 }
295
parse_uint(const char * str,int base,int term,unsigned int * res)296 int parse_uint(const char *str, int base, int term, unsigned int *res)
297 {
298 unsigned long long tmp;
299 int ret;
300 ret = parse_ull(str, base, term, &tmp);
301 *res = (unsigned int)tmp;
302 return ret;
303 }
304
parse_ull(const char * str,int base,int term,unsigned long long * res)305 int parse_ull(const char *str, int base, int term, unsigned long long *res)
306 {
307 char *endptr;
308 unsigned long long strtol_res;
309
310 /* SUSv2 says:
311 * "Because 0, LONG_MIN and LONG_MAX are returned on error and are also
312 * valid returns on success, an application wishing to check for error
313 * situations should set errno to 0, then call strtol(), then check errno." */
314 errno = 0;
315 strtol_res = strtoull(str, (char **)&endptr, base);
316
317 if (errno == 0 && *str != NUL) {
318 /* Special case: -1 means allow trailing whitespace */
319 if (term == -1) {
320 while (*endptr != NUL && isspace(*endptr))
321 endptr++;
322 term = NUL;
323 }
324
325 if (*endptr == term) {
326 *res = strtol_res;
327 return 0;
328 }
329 }
330
331 *res = 0;
332 return -1;
333 }
334
parse_ubase10(const char * str,unsigned int * res)335 int parse_ubase10(const char *str, unsigned int *res)
336 {
337 return parse_uint(str, 10, -1, res);
338 }
339
parse_base10(const char * str,int * res)340 int parse_base10(const char *str, int *res)
341 {
342 return parse_int(str, 10, -1, res);
343 }
344
parse_all_digits(const char * ptr)345 bool_int parse_all_digits(const char *ptr)
346 {
347 size_t num=0, len = strlen(ptr);
348
349 while (isdigit(*ptr++))
350 num++;
351 if (num == len)
352 return TRUE;
353 else
354 return FALSE;
355 }
356