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( >, gmtime( &tt ), sizeof( struct tm ));
350 gt.tm_isdst = 0;
351 gmt = mktime( > );
352 memcpy( >, localtime( &tt ), sizeof( struct tm ));
353 gt.tm_isdst = 0;
354 return mktime( > ) - 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