/* util.c	- ni idea what these are

    Tano Fotang, 1997/98

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License , or
    (at your option) any later version.
    see the file COPYING for details.

*/

#include <errno.h>
#include <sys/time.h>
#include <stdarg.h>
#include <pwd.h>
#include <ctype.h>
#include "aux.h"
#include "util.h"

Sigfunc *Signal(int signo, Sigfunc *func)
/* same as signal(2) but repeats interrupted system calls
   W.R.Stevens
 */
{
	struct sigaction act, oact;

	act.sa_handler=func;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	if(signo==SIGALRM){
#ifdef SA_INTERRUPT
		act.sa_flags|=SA_INTERRUPT; 
#endif
	}else{
#ifdef SA_RESTART
		act.sa_flags|=SA_RESTART;
#endif
	}
	if(sigaction(signo, &act, &oact)<0) return (SIG_ERR);
	return (oact.sa_handler);
}


int    delay(unsigned long microsecs)
{
	struct timeval tv;

	tv.tv_sec = 0;
	tv.tv_usec = microsecs;
	if(select(0, NULL, NULL, NULL, &tv)<0) return errno;
	return 0;
}
extern void new_str2args(char *buf, int *argc, char **args, size_t size){
	/* char *args[size] !!*/
	*argc=0;size--;
	while(*buf!='\0' && *argc<size){
		while( *buf==' '
		#if 1 
		|| *buf=='\t' || *buf=='\n'
		#endif
		) *buf++='\0';
		if(*buf) {*args++=buf; (*argc)++;}
		while( *buf!='\0' && *buf!=' ' && *buf!='\t' && *buf!='\n') buf++;
	}
	*args='\0';
}
extern char *
        expand_tilde(char *pname)
{
/* 
 * expand ~ ina pathname  */
	char   *fullpath;

	if (*pname != '~')
		return pname;
	if (*(pname + 1) == 0 || *++pname == '/') {
		char   *path;

		if (!(path = getenv("HOME")))
			return NULL;
		if (*(pname + 1) == 0)
			return path;
		fullpath = (char *) malloc(sizeof(char) * (
		strlen(path) + strlen(pname) + 8));
		if (!fullpath) 
			return NULL;
		sprintf(fullpath, "%s%s", path, pname);
		return fullpath;
	}
	else {
		struct passwd *pwd;

		if (!strchr(pname, '/')) {	/* ~tt */
			if (!(pwd = getpwnam(pname)))
				return NULL;
			return pwd->pw_dir;
		}
		else {		
				 /* ~tt/ttt  */
			pwd = getpwnam(strxstr(pname, "/"));
			if (!pwd)
				return NULL;
			fullpath = (char *) malloc(sizeof(char) * (strlen(pwd->pw_dir) +
						      strlen  (pname) + 8));
			if (!fullpath) 
				return NULL;
			sprintf(fullpath, "%s%s", pwd->pw_dir, strchr(pname, '/'));
			return fullpath;
		}
	}
}

char *unescape(char *str){
	char *p=str;
	while(isgraph(*p)) p++;
	*p='\0';
	return str;
}
void uncomment (char *s, int c)
{
/* squeeze out parts of s beginning with c */
  while (*s && *s != c)
    s++;
  *s = '\0';
}

extern char *
        strdup2(const char *str)
{
	char   *tmp = NULL;

	if (str == NULL || !(*str))
		return NULL;
	tmp = (char *) malloc(sizeof(char) * (strlen(str) + 1));

	if (tmp == NULL)
		return NULL;
	strcpy(tmp, str);
	return tmp;
}
extern char *getmemory(unsigned n){
	char *buf=(char *)malloc(sizeof(char)*n);
	if(buf==NULL)
		perror("Memory failure");
	return buf;
}
extern char *
        strcp(const char *s, size_t n)
{
/* 
 * return first n letters of s */

	if (!s)
		return NULL;
	if (n > strlen(s))
		return strdup(s);
	else {
		char   *buf = strdup(s);

		*(buf + n) = '\0';
		return buf;
	}
}
char   *
        strxstr(const char *s1, const char *s2)
/* 
 * return s1 up to and excluding s2 */
{
	char   *t;

	if (!s1 || !(t = strstr(s1, s2)))
		return NULL;
	else {
		char   *tmp = strdup(s1);

		tmp[strlen(s1) - strlen(t)] = '\0';
		return tmp;
	}
	return strdup(s1);
}

/* 
 * this is wrong..but already bein used somwhere. too late to correct! dont
 * correct;use strxstr() instead. 12.08.1998 -fotang */
char   *
        strnstr(const char *s1, const char *s2)
/* 
 * return s1 up to and excluding s2 */
{
	char   *t;

	if (!s1 || !(t = strstr(s1, s2)))
		return NULL;
	else {
		char   *tmp = strdup(s1);

		tmp[strlen(s1) - strlen(t) + 1] = '\0';
		return tmp;
	}
	return strdup(s1);
}

char   *strsstr(const char *s1, const char *s2)
/* 
 * return s1 as from and excluding s2 */
{
	char   *t;

	if (!s1 || !(*s1))
		return NULL;
	t = strstr(s1, s2);
	if (t)
		return strdup2(t + strlen(s2));
	else
		return NULL;
}

char   *
        clean(const char *s)
{
/* 
 * remove tabs n white spaces from start of s  */

	if (!s || !(*s))
		return NULL;
	else{

	char   *p = (char *)(s);
	while (*p == ' ' || *p == '\t')
		p++;
	return *p?strdup(p):NULL;
	}
}

char   *
        lowercase(const char *s)
/* 
 * convert string to lowercase..   */
{
	char   *t;
	char *p;

	if (!s || !(*s))
		return NULL;
       	t = (char *) malloc(sizeof(char) * (strlen(s) + 1));
	/*t= (char *)s;*/
	if (!t)
		return NULL; 
	p = t;
	while ((*p++ = isupper(*s) ? tolower(*s++) : *s++));
	return t;
}

char   *
        uppercase(const char *s)
/* 
 * convert string to lowercase..   */
{
	char   *t, *p;
	if (!s || !(*s))
		return NULL;
	t = (char *) malloc(sizeof(char) * (strlen(s) + 1));

	if (!t)
		return NULL;
	p = t;
	while ((*p++ = toupper(*s++)));
	return t;
}

char   *
        strdchr(const char *t, int c)
{
/* 
 * remove a ll c from t  */
	register unsigned short j = 0;

	char   *s;

	if (!t || !(*t))
		return NULL;
	s = (char *) malloc(sizeof(char) * (strlen(t) + 1));

	if (!s)
		return NULL;
	for (; *t; t++)
		if (*t != c)
			s[j++] = *t;
	s[j] = '\0';
	return s;
}
int find_pos(char *s, u_int n){
/* return start pos of (n)th word. white spaces are not counted
n=0 ->1st word
return value:
<0: s==nULL
strlen(s): if n>number of words in s 
>=0: start pos
 */
	int i=1, j=0;
	int ll;
	if(!(s && *s)) return -1;
	ll=strlen(s);
	while(*s && (*s==' ' || *s=='\t')){ j++; s++;}
	while(*s && i<n){
		while(*s && (*s!=' ' && *s!='\t')){j++;s++;}
		if(*s)	i++;
		while(*s && (*s==' ' || *s=='\t')){j++;s++;}
	}
	return (i<n)?ll:j;
}
int     rmstr(char **s, int n)
{
/* 
 * delete the nth word from a string. n=1 for 1st word  */
	char   *t, *ptr, *p, *z;
	int     i = 0;
	size_t  j = 0, k = 0;
	char   *buf;

	if (n < 1 || !(*s))
		return 0;
	if (!(t = strdup(*s))) {
		return errno;
	}
	if (!(z = strdup(*s))) {
		return errno;
	}
	ptr = z;
	p = t;
	while (*p && i < n) {
		while (*p && (*p == ' ' || *p == '\t')) {
			p++;
		}
		if (!(*p))
			break;
		j = 0;		/*
				 * length of next <word>
				 */
		while ((*ptr++ = *p) && (*p != ' ' && *p != '\t')) {
			p++;
			j++;
		}
		i++;
	}
	if (i < n)
		return 0;
	k = p - t - j;		/*
				 * lenght of 1st part of result
				 */
	p = *s;
	buf = t;
	while (k && (*buf++ = *p++))
		k--;
	p += j;			/*
				 * skip over what's to be <deleted> 
				 */
	while (*p == ' ' || *p == '\n')
		p++;		/*
				 * remove connecting blanks 
				 */
	while ((*buf = *p++))
		buf++;		/*
				 * add 2nd part of result string 
				 */
	while (*(--buf) == ' ' || *buf == '\t')
		*buf = '\0';	/*
				 * remove trailing blanks if u must
				 */
	*s = t;
	return 0;
}

char   *
        nextstr(const char *s, int n)
{
/* 
 * get nth word of a string  */
	char   *t, *ptr;
	int     i = 0;

	if(!(n>0 && s && *s)) return NULL;
	if (!(t = strdup2(s))) {
		return NULL;
	}
	ptr = strtok(t, " \t");
	while (ptr && ++i < n )
		ptr = strtok(NULL, " \t");
	if (i < n)
		return NULL;
	if(ptr)
		while (*ptr && (*ptr == ' ' || *ptr == '\t' /*|| *ptr=='\n'*/))
			ptr++;
	return *ptr?ptr:NULL;

}

