#include "bbs.h"

char *gettime()
{
  TIME_T clock;
  static char str[ASCTIMESTRLEN];
  
  clock = time((TIME_T)0);
  strcpy(str,asctime(localtime(&clock)));
  str[24] = '\0';
  return str;
}


#ifndef NO_TV_USEC
double microtime(void)
{
  struct timeval tp;
  struct timezone tzp;
  
  gettimeofday(&tp,&tzp);
  return((double)(tp.tv_sec + 0.000001*tp.tv_usec));
}
#endif


int mklockfile(const char *pathname)
  /*
  legt ein Lockfile pathname an
  */
{
  int fd;
  
  if ((fd=open(pathname,O_RDWR|O_CREAT|O_EXCL,0644))<0) {
    bgerror("mklockfile","open %s: %m",pathname);
    return -1;
  }
  writen(fd,(void *)"LOCKED",(SIZE_T)7);
  close(fd);

  return 0;
}


int fgetnln(char str[], const int maxlen, FILE *datei)
  /*
  Liest eine Zeile aus einem File und kopiert maximal maxlen Zeichen
  in str.
  Rueckgabewerte: -1 bei EOF, maxlen+1 wenn die Zeile zu lang war
  */
{
  char c;
  int k;
  boolean ret;

  k = 0;
  do {
    c = fgetc( datei );
    if ( c != EOF )  str[k++] = c;
  } while ( k <= maxlen && c!= '\n' && c != '\0' && c != EOF );
  if ( c == '\n' ) {
    ret = TRUE;
    str[--k] = '\0';
  }
  else if ( c == '\0' ) {
    ret = FALSE;
    --k;
  }
  else if ( k > maxlen && c != '\n' && c != '\0' ) {
    ret = FALSE;
    str[k-1] = '\0';
  }
  else if ( c == EOF ) {
    ret = TRUE;
    str[k] = '\0';
    k = -1;
  }
  if ( ! ret ) {
    do{
        c = fgetc( datei );
    } while( c != '\n' && c != EOF );
    if ( c == EOF )  k = -1;
  }
  return k;
}


SSIZE_T readn(int fd, void *vptr, SIZE_T n)
{
  SIZE_T nleft;
  SSIZE_T nread;
  void *ptr;
  
  ptr = vptr;
  nleft = n;
  while (nleft > 0) {
    if ((nread=read(fd,ptr,nleft)) < 0) {
      return(nread);
    }
    else if (nread == 0) {
      break;
    }
    nleft -= (SIZE_T)nread;
    ptr = (char *)ptr + nread*sizeof(char);
  }
  return(SSIZE_T)(n-nleft);
}


SSIZE_T writen(int fd, const void *vptr, SIZE_T n)
{
  SIZE_T nleft;
  SSIZE_T nwritten;
  const void *ptr;
  
  ptr = vptr;
  nleft = n;
  while (nleft > 0) {
    if ((nwritten=write(fd,ptr,nleft)) <= 0) {
      return(nwritten);
    }
    nleft -= (SIZE_T)nwritten;
    ptr = (char *)ptr + nwritten*sizeof(char);
  }
  return(SSIZE_T)n;
}


SSIZE_T recvn(int s, void *buf, SIZE_T len, int flags)
{
  SIZE_T bytesleft;
  SSIZE_T n;
  void *ptr;

  ptr = buf;
  bytesleft = len;
  while (bytesleft > 0) {
    if ((n=recv(s,ptr,bytesleft,flags)) < 0) {
      return(n);
    }
    bytesleft -= (SIZE_T)n;
    ptr = (char *)ptr + n*sizeof(char);
  }
  return(SSIZE_T)(len-bytesleft);
}


SSIZE_T sendn(int s, const void *buf, SIZE_T len, int flags)
{
  SIZE_T bytesleft;
  SSIZE_T n;
  const void *ptr;

  ptr = buf;
  bytesleft = len;
  while (bytesleft > 0) {
    if ((n=send(s,(const void *)ptr,bytesleft,flags)) < 0) {
      return(n);
    }
    if (n == 0) break;
    bytesleft -= (SIZE_T)n;
    ptr = (char *)ptr + n*sizeof(char);
  }
  return(SSIZE_T)len;
}


void (*setsighandler(int sig, void (*handler)(int)))(int)
{
  struct sigaction act, oact;
  
  act.sa_handler = handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  if (sig == SIGALRM) {
#ifdef SA_INTERRUPT
    act.sa_flags |= SA_INTERRUPT;
#endif    
  }
  else {
#ifdef SA_RESTART
    act.sa_flags |= SA_RESTART;
#endif
  }
  if (sigaction(sig,&act,&oact) < 0) {
    return(SIG_ERR);
  }
  return(oact.sa_handler);
}


void (*setsighandler2(int sig, SIGSET_T sigset, void (*handler)(int)))(int)
{
  struct sigaction act, oact;
  
  act.sa_handler = handler;
  act.sa_mask = sigset;
  act.sa_flags = 0;
  if (sig == SIGALRM) {
#ifdef SA_INTERRUPT
    act.sa_flags |= SA_INTERRUPT;
#endif    
  }
  else {
#ifdef SA_RESTART
    act.sa_flags |= SA_RESTART;
#endif
  }
  if (sigaction(sig,&act,&oact) < 0) {
    return(SIG_ERR);
  }
  return(oact.sa_handler);
}


#ifdef NO_VSYSLOG
void vsyslog(int priority, const char *message, va_list args)
{
  char str[PATH_MAX+1];
  
  vsprintf(str,message,args);
  syslog(priority,str);
  return;
}
#endif


int mdefenv(const char *env, const char *fmt, ...)
{
  va_list ap;
  int len;
  char *sp, str[PATH_MAX+1];
  
  va_start(ap, fmt);
  vsprintf(str, fmt, ap);
  va_end(ap);
  len = strlen(env) + strlen(str) + 2;
  if ((sp=(char *)malloc(len*sizeof(char))) == NULL) {
    bgerror("mdefenv","cannot malloc: %m");
    return(-1);
  }
  sprintf(sp,"%s=%s",env,str);
  return putenv(sp);
}


int mputenv(const char *str)
{
  char *sp;

  if ((sp=(char *)malloc((strlen(str)+1)*sizeof(char))) == NULL) {
    bgerror("mputenv","cannot malloc: %m");
    return(-1);
  }
  strcpy(sp,str);
  return putenv(sp);
}


#ifdef NO_PUTENV
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */

extern char **environ;

/* Put STRING, which is of the form "NAME=VALUE", in the environment.  */
int
putenv (string)
     const char *string;
{
  char *name_end = (char *)strchr (string, '=');
  register SIZE_T size;
  register char **ep;

  if (name_end == NULL)
    {
      /* Remove the variable from the environment.  */
      size = strlen (string);
      for (ep = environ; *ep != NULL; ++ep)
	if (!strncmp (*ep, string, size) && (*ep)[size] == '=')
	  {
	    while (ep[1] != NULL)
	      {
		ep[0] = ep[1];
		++ep;
	      }
	    *ep = NULL;
	    return 0;
	  }
    }

  size = 0;
  for (ep = environ; *ep != NULL; ++ep)
    if (!strncmp (*ep, string, name_end - string) &&
	(*ep)[name_end - string] == '=')
      break;
    else
      ++size;

  if (*ep == NULL)
    {
      static char **last_environ = NULL;
      char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
      if (new_environ == NULL)
	return -1;
      (void) bcopy ((char *) environ, (char *) new_environ, size * sizeof (char *));
      new_environ[size] = (char *) string;
      new_environ[size + 1] = NULL;
      if (last_environ != NULL)
	free ((char *) last_environ);
      last_environ = new_environ;
      environ = new_environ;
    }
  else
    *ep = (char *) string;

  return 0;
}
#endif
