1 /**********************************************************
2  * functions for all qico related programs
3  **********************************************************/
4 /*
5  * $Id: qslib.c,v 1.12 2005/08/12 16:40:51 mitry Exp $
6  *
7  * $Log: qslib.c,v $
8  * Revision 1.12  2005/08/12 16:40:51  mitry
9  * Added wktime_str()
10  *
11  * Revision 1.11  2005/08/12 15:36:19  mitry
12  * Changed gmtoff()
13  *
14  * Revision 1.10  2005/05/16 11:20:13  mitry
15  * Updated function prototypes. Changed code a bit.
16  *
17  * Revision 1.9  2005/05/11 18:08:04  mitry
18  * Changed xrealloc() code
19  *
20  * Revision 1.8  2005/05/06 20:41:07  mitry
21  * Changed setproctitle() code
22  *
23  * Revision 1.7  2005/04/05 09:31:12  mitry
24  * New xstrcpy() and xstrcat()
25  *
26  * Revision 1.6  2005/03/31 19:40:38  mitry
27  * Update function prototypes and it's duplication
28  *
29  * Revision 1.5  2005/03/28 16:42:13  mitry
30  * Moved common bin2strhex() and strhex2bin() funcs here
31  *
32  * Revision 1.4  2005/02/08 20:02:58  mitry
33  * Some code cleaning
34  *
35  */
36 
37 #include "headers.h"
38 #include <sys/utsname.h>
39 #include "cvsdate.h"
40 
41 #ifdef DEBUG
42 #  undef DEBUG
43 #endif
44 
45 #define DEBUG(p)
46 
47 
48 char *osname = "Unix";
49 char version[] = PACKAGE_VERSION;
50 
51 char *hexdigitslower = "0123456789abcdef";
52 char *hexdigitsupper = "0123456789ABCDEF";
53 char *hexdigitsall = "0123456789abcdefABCDEF";
54 
55 char *engms[13] = {
56 	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
57 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Any"};
58 
59 char *infostrs[] = {
60 	"Address",
61 	"Station",
62 	"  Place",
63 	"  Sysop",
64 	"  Phone",
65 	"  Flags",
66 	"  Speed",
67 	NULL
68 };
69 
70 
71 
_xmalloc(size_t size)72 void *_xmalloc(size_t size)
73 {
74 	void	*p = malloc( size );
75 
76 	if ( p )
77 		return p;
78 
79 	write_log( "!!! xmalloc(): could not allocate %d bytes of memory", size );
80 	abort();
81 }
82 
83 
_xcalloc(size_t number,size_t size)84 void *_xcalloc(size_t number, size_t size)
85 {
86 	void	*p = calloc( number, size );
87 
88 	if ( p )
89 		return p;
90 
91 	write_log( "!!! xcalloc(): could not allocate %dx%d bytes of memory", number, size );
92 	abort();
93 }
94 
95 
xrealloc(void * ptr,size_t size)96 void *xrealloc(void *ptr, size_t size)
97 {
98 	void *p;
99 
100 	if ( ptr )
101 		p = realloc( ptr, size );
102 	else
103 		p = ptr = malloc( size );
104 
105 	if ( p )
106 		return p;
107 
108 	write_log( "!!! xrealloc(): could not allocate %d bytes of memory", size );
109 	abort();
110 }
111 
112 
strlwr(char * s)113 void strlwr(char *s)
114 {
115 	while( s && *s ) {
116 		*s = tolower( *s );
117 		s++;
118 	}
119 }
120 
121 
strupr(char * s)122 void strupr(char *s)
123 {
124 	while( s && *s ) {
125 		*s = toupper( *s );
126 		s++;
127 	}
128 }
129 
130 
strtr(char * s,char a,char b)131 void strtr(char *s, char a, char b)
132 {
133 	while( s && *s ) {
134 		if( *s == a )
135 			*s = b;
136 		s++;
137 	}
138 }
139 
140 
chop(char * str,int n)141 void chop(char *str, int n)
142 {
143 	char	*p;
144 
145 	if ( str ) {
146 		p = strchr( str, 0 );
147 		while( p && n-- )
148 			*--p = 0;
149 	}
150 }
151 
152 
chopc(char * str,char ch)153 size_t chopc(char *str, char ch)
154 {
155 	size_t	slen = strlen ( str ) - 1;
156 
157 	while( slen && str[slen] == ch )
158 		str[slen--] = '\0';
159 
160 	return slen;
161 }
162 
163 
164 /*
165  * Skips leading blanks
166  */
skip_blanks(char * str)167 char *skip_blanks(char *str)
168 {
169 	if ( str != NULL )
170         	while( XBLANK( str ))
171             		str++;
172 	return str;
173 }
174 
175 
176 /*
177  * Skips trailing blanks
178  */
skip_blanksr(char * str)179 void skip_blanksr(char *str)
180 {
181 	char *r;
182 
183 	if ( str != NULL && *str ) {
184 		r = str + strlen( str ) - 1;
185 		while( r >= str && XBLANK( r )) {
186 			*r = '\0';
187 			r--;
188 		}
189 	}
190 }
191 
192 
193 /*
194  * Copy src to string dst of size siz.  At most siz-1 characters
195  * will be copied.  Always NULL terminates (unless siz == 0).
196  * Returns dst or NULL if dst is unallocated.
197  */
xstrcpy(char * dst,const char * src,size_t siz)198 char *xstrcpy(char *dst, const char *src, size_t siz)
199 {
200 	register char		*d = dst;
201 	register const char	*s = src;
202 	register size_t		n = siz;
203 
204 	if ( !src )
205         	return dst;
206 	if ( !dst )
207 		return NULL;
208 
209 	/* Copy as many bytes as will fit */
210 	if ( n != 0 && --n != 0 ) {
211 		do {
212 			if ((*d++ = *s++) == 0)
213 				break;
214 		} while (--n != 0);
215 	}
216 
217 	if (n == 0) {
218 		if (siz != 0)
219 			*d = '\0';
220 	}
221 
222 	return dst;
223 }
224 
225 
226 /*
227  * Appends src to string dst of size siz (unlike strncat, siz is the
228  * full size of dst, not space left).  At most siz-1 characters
229  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
230  * Returns dst or NULL if dst is unallocated.
231  */
xstrcat(char * dst,const char * src,size_t siz)232 char *xstrcat(char *dst, const char *src, size_t siz)
233 {
234 	register char		*d = dst;
235 	register const char	*s = src;
236 	register size_t		n = siz;
237 	size_t			dlen;
238 
239 	if ( !src )
240 		return dst;
241 	if ( !dst )
242 		return NULL;
243 
244 	/* Find the end of dst and adjust bytes left but don't go past end */
245 	while (n-- != 0 && *d != '\0')
246 		d++;
247 	dlen = d - dst;
248 	n = siz - dlen;
249 
250 	if (n > 0) {
251 		while (*s != '\0' && n > 1) {
252 			*d++ = *s++;
253 			n--;
254 		}
255 		*d = '\0';
256 	}
257 
258 	return dst;
259 }
260 
261 
xstrdup(const char * str)262 char *xstrdup(const char *str)
263 {
264 	char	*s;
265 	size_t	len;
266 
267 	if ( !str )
268 		return NULL;
269 
270 	len = strlen( str ) + 1;
271 	s = xmalloc( len );
272 	if ( s )
273 		return xstrcpy( s, str, len );
274 
275 	write_log( "!!! xstrdup(): could not duplicate string");
276 	abort();
277 }
278 
279 
restrcpy(char ** dst,const char * src)280 char *restrcpy(char **dst, const char *src)
281 {
282 	xfree( *dst );
283 
284 	if ( !src )
285         	return NULL;
286 
287 	return *dst = xstrdup( src );
288 }
289 
290 
restrcat(char ** dst,const char * src)291 char *restrcat(char **dst, const char *src)
292 {
293 	size_t	len;
294 
295 	if ( !src )
296 		return *dst;
297 	if ( !*dst )
298 		return *dst = xstrdup( src );
299 
300 	len = strlen( *dst ) + strlen( src ) + 1;
301 	*dst = xrealloc( *dst, len );
302 	return xstrcat( *dst, src, len );
303 }
304 
305 
bin2strhex(void * str,const void * binstr,size_t blen)306 void bin2strhex(void *str, const void *binstr, size_t blen)
307 {
308 	register unsigned char		*s = str;
309 	register const unsigned char	*b = binstr;
310 
311 	while( blen-- ) {
312 		*s++ = hexdigitslower[(*b >> 4) & 0x0f];
313 		*s++ = hexdigitslower[(*b++) & 0x0f];
314 	}
315 	*s = '\0';
316 }
317 
318 
strhex2bin(void * binstr,const void * str)319 int strhex2bin(void *binstr, const void *str)
320 {
321 	register unsigned char		*dest = binstr;
322 	register const unsigned char	*s = str;
323 	register const char		*p;
324 
325 	if ( str == NULL )
326 		return 0;
327 
328 	while( *s && *(s + 1)) {
329 		if (( p = strchr( hexdigitsall, *(s++)))) {
330 			*dest = (byte) ( p - hexdigitsall );
331 			if (( p = strchr( hexdigitsall, *(s++)))) {
332 				*dest <<= 4;
333 				*dest++ |= (byte) ( p - hexdigitsall );
334 			} else
335 				return 0;
336 		} else
337 			return 0;
338 	}
339 
340 	return ( dest - (unsigned char *) binstr );
341 }
342 
343 
gmtoff(time_t tt)344 time_t gmtoff(time_t tt)
345 {
346 	struct tm	gt;
347 	time_t		gmt;
348 
349 	memcpy( &gt, gmtime( &tt ), sizeof( struct tm ));
350 	gt.tm_isdst = 0;
351 	gmt = mktime( &gt );
352 	memcpy( &gt, localtime( &tt ), sizeof( struct tm ));
353 	gt.tm_isdst = 0;
354 	return mktime( &gt ) - gmt;
355 }
356 
357 
wktime_str(const char * flags)358 char *wktime_str(const char *flags)
359 {
360 	char		*p, *oflags, *optr;
361 	static char	res[80];
362 	time_t		tm = time( NULL );
363 	long		tz = gmtoff( tm ) / 3600;
364 
365 	optr = oflags = xstrdup( flags );
366 	res[0] = '\0';
367 	while(( p = strsep( &optr, "," ))) {
368 		if ( !strcmp( p, "CM" )) {
369 			xstrcpy( res, "00:00-24:00", 80 );
370 			break;
371 		}
372 		if ( p[0] == 'T' && strlen( p ) == 3 ) {
373 			snprintf( res, 79, "%02ld:%02d-%02ld:%02d",
374 				( toupper( p[1] ) - 'A' + tz ) % 24,
375 				islower((int) p[1] ) ? 30 : 0,
376 				( toupper( p[2] ) - 'A' + tz ) % 24,
377 				islower((int) p[2] ) ? 30 : 0 );
378 			break;
379 		}
380 	}
381 	xfree( oflags );
382 	return res[0] ? res : NULL;
383 }
384 
385 
386 
387 #ifndef HAVE_SETPROCTITLE
388 
389 #define MAXLINE	2048
390 /* return number of bytes left in a buffer */
391 #define SPACELEFT(buf, ptr)	(sizeof buf - ((ptr) - buf))
392 
393 /*
394 **  SETPROCTITLE -- set process title for ps
395 **
396 **	Parameters:
397 **		fmt -- a printf style format string.
398 **		a, b, c -- possible parameters to fmt.
399 **
400 **	Returns:
401 **		none.
402 **
403 **	Side Effects:
404 **		Clobbers argv of our main procedure so ps(1) will
405 **		display the title.
406 */
407 
408 #define SPT_NONE	0	/* don't use it at all */
409 #define SPT_REUSEARGV	1	/* cover argv with title information */
410 #define SPT_BUILTIN	2	/* use libc builtin */
411 #define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
412 #define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
413 #define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
414 #define SPT_SCO		6	/* write kernel u. area */
415 #define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
416 
417 #ifndef SPT_TYPE
418 # define SPT_TYPE	SPT_REUSEARGV
419 #endif /* ! SPT_TYPE */
420 
421 
422 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
423 
424 # if SPT_TYPE == SPT_PSTAT
425 #  include <sys/pstat.h>
426 # endif /* SPT_TYPE == SPT_PSTAT */
427 # if SPT_TYPE == SPT_PSSTRINGS
428 #  include <machine/vmparam.h>
429 #  include <sys/exec.h>
430 #  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
431 #   undef SPT_TYPE
432 #   define SPT_TYPE	SPT_REUSEARGV
433 #  else /* ! PS_STRINGS */
434 #   ifndef NKPDE			/* FreeBSD 2.0 */
435 #    define NKPDE 63
436 typedef unsigned int	*pt_entry_t;
437 #   endif /* ! NKPDE */
438 #  endif /* ! PS_STRINGS */
439 # endif /* SPT_TYPE == SPT_PSSTRINGS */
440 
441 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
442 #  define SETPROC_STATIC	static
443 # else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
444 #  define SETPROC_STATIC
445 # endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
446 
447 # if SPT_TYPE == SPT_SYSMIPS
448 #  include <sys/sysmips.h>
449 #  include <sys/sysnews.h>
450 # endif /* SPT_TYPE == SPT_SYSMIPS */
451 
452 # if SPT_TYPE == SPT_SCO
453 #  include <sys/immu.h>
454 #  include <sys/dir.h>
455 #  include <sys/user.h>
456 #  include <sys/fs/s5param.h>
457 #  if PSARGSZ > MAXLINE
458 #   define SPT_BUFSIZE	PSARGSZ
459 #  endif /* PSARGSZ > MAXLINE */
460 # endif /* SPT_TYPE == SPT_SCO */
461 
462 # ifndef SPT_PADCHAR
463 #  define SPT_PADCHAR	'\0'
464 # endif /* ! SPT_PADCHAR */
465 
466 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
467 
468 #ifndef SPT_BUFSIZE
469 # define SPT_BUFSIZE	MAXLINE
470 #endif /* ! SPT_BUFSIZE */
471 
472 /*
473 **  Pointers for setproctitle.
474 **	This allows "ps" listings to give more useful information.
475 */
476 
477 static char	**Argv = NULL;		/* pointer to argument vector */
478 static char	*LastArgv = NULL;	/* end of argv */
479 
480 void
initsetproctitle(argc,argv,envp)481 initsetproctitle(argc, argv, envp)
482 	int argc;
483 	char **argv;
484 	char **envp;
485 {
486 	register int i;
487 	extern char **environ;
488 
489 	/*
490 	**  Move the environment so setproctitle can use the space at
491 	**  the top of memory.
492 	*/
493 
494 	if (envp != NULL)
495 	{
496 		for (i = 0; envp[i] != NULL; i++)
497 			continue;
498 		environ = (char **) xmalloc(sizeof (char *) * (i + 1));
499 		for (i = 0; envp[i] != NULL; i++)
500 			environ[i] = xstrdup(envp[i]);
501 		environ[i] = NULL;
502 	}
503 
504 	/*
505 	**  Save start and extent of argv for setproctitle.
506 	*/
507 
508 	Argv = argv;
509 
510 	/*
511 	**  Determine how much space we can use for setproctitle.
512 	**  Use all contiguous argv and envp pointers starting at argv[0]
513 	*/
514 
515 	for (i = 0; i < argc; i++)
516 	{
517 		if (i == 0 || LastArgv + 1 == argv[i])
518 			LastArgv = argv[i] + strlen(argv[i]);
519 	}
520 	for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++)
521 	{
522 		if (LastArgv + 1 == envp[i])
523 			LastArgv = envp[i] + strlen(envp[i]);
524 	}
525 }
526 
527 #if SPT_TYPE != SPT_BUILTIN
528 
setproctitle(const char * fmt,...)529 void setproctitle(const char *fmt, ...)
530 {
531 # if SPT_TYPE != SPT_NONE
532 	register int i;
533 	register char *p;
534 	SETPROC_STATIC char buf[SPT_BUFSIZE];
535 	va_list ap;
536 #  if SPT_TYPE == SPT_PSTAT
537 	union pstun pst;
538 #  endif /* SPT_TYPE == SPT_PSTAT */
539 #  if SPT_TYPE == SPT_SCO
540 	int j;
541 	off_t seek_off;
542 	static int kmem = -1;
543 	static pid_t kmempid = -1;
544 	struct user u;
545 #  endif /* SPT_TYPE == SPT_SCO */
546 
547 	p = buf;
548 
549 	/* print `progname': heading for grep */
550 	snprintf( p, (size_t) SPACELEFT(buf, p), "%s: ", progname );
551 	p += strlen(p);
552 
553 	/* print the argument string */
554 	va_start( ap, fmt );
555 	(void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
556 	va_end( ap );
557 
558 	i = (int) strlen(buf);
559 	if (i < 0)
560 		return;
561 
562 #  if SPT_TYPE == SPT_PSTAT
563 	pst.pst_command = buf;
564 	pstat(PSTAT_SETCMD, pst, i, 0, 0);
565 #  endif /* SPT_TYPE == SPT_PSTAT */
566 #  if SPT_TYPE == SPT_PSSTRINGS
567 	PS_STRINGS->ps_nargvstr = 1;
568 	PS_STRINGS->ps_argvstr = buf;
569 #  endif /* SPT_TYPE == SPT_PSSTRINGS */
570 #  if SPT_TYPE == SPT_SYSMIPS
571 	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
572 #  endif /* SPT_TYPE == SPT_SYSMIPS */
573 #  if SPT_TYPE == SPT_SCO
574 	if (kmem < 0 || kmempid != CurrentPid)
575 	{
576 		if (kmem >= 0)
577 			(void) close(kmem);
578 		kmem = open(_PATH_KMEM, O_RDWR, 0);
579 		if (kmem < 0)
580 			return;
581 		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
582 		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
583 		{
584 			(void) close(kmem);
585 			kmem = -1;
586 			return;
587 		}
588 		kmempid = CurrentPid;
589 	}
590 	buf[PSARGSZ - 1] = '\0';
591 	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
592 	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
593 		(void) write(kmem, buf, PSARGSZ);
594 #  endif /* SPT_TYPE == SPT_SCO */
595 #  if SPT_TYPE == SPT_REUSEARGV
596 	if (LastArgv == NULL)
597 		return;
598 
599 	if (i > LastArgv - Argv[0] - 2)
600 	{
601 		i = LastArgv - Argv[0] - 2;
602 		buf[i] = '\0';
603 	}
604 	(void) xstrcpy(Argv[0], buf, i + 1);
605 	p = &Argv[0][i];
606 	while (p < LastArgv)
607 		*p++ = SPT_PADCHAR;
608 	Argv[1] = NULL;
609 #  endif /* SPT_TYPE == SPT_REUSEARGV */
610 #  if SPT_TYPE == SPT_CHANGEARGV
611 	Argv[0] = buf;
612 	Argv[1] = 0;
613 #  endif /* SPT_TYPE == SPT_CHANGEARGV */
614 # endif /* SPT_TYPE != SPT_NONE */
615 }
616 
617 #endif /* SPT_TYPE != SPT_BUILTIN */
618 
619 #if 0
620 void setargspace(int argc,char **argv,char **envp)
621 {
622     int i=0;
623     cmdstr=argv[0];
624     while(envp[i])i++;
625     environ=xmalloc(sizeof(char*)*(i+1));
626     i=0;
627     while(envp[i]) {
628         environ[i]=xstrdup(envp[i]);
629         i++;
630     }
631     environ[i]=NULL;
632     cmdstrend=argv[0]+strlen(argv[0]);
633     for(i=1;i<argc;i++)if(cmdstrend+1==argv[i])cmdstrend=argv[i]+strlen(argv[i]);
634     for(i=0;envp[i];i++)if(cmdstrend+1==envp[i])cmdstrend=envp[i]+strlen(envp[i]);
635 }
636 
637 
638 void setproctitle(char *str)
639 {
640     char *p;
641     if(!cmdstr)return;
642     for(p=cmdstr;p<cmdstrend&&*str;p++,str++)*p=*str;
643     *p++=0;while(p<cmdstrend)*p++=' ';
644 }
645 #endif /* 0 */
646 
647 #endif
648 
649 
u_vers(const char * progn)650 void u_vers(const char *progn)
651 {
652 	struct utsname uts;
653 
654 	printf( "%s v%s [%s]\n", progn, version, cvsdate );
655 
656 	if( !uname( &uts ))
657 		printf( "%s %s (%s), ", uts.sysname, uts.release, uts.machine );
658 	printf(
659 #ifdef __GNUC__
660 		"g"
661 #endif
662 		"cc: "
663 #ifdef __VERSION__
664 		__VERSION__
665 #else
666 		"unknown"
667 #endif
668 		"\n");
669 	exit( 0 );
670 }
671