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