Logo Search packages:      
Sourcecode: dctc version File versions  Download package

status.c

/* DCTC - a Direct Connect text clone for Linux
 * Copyright (C) 2001 Eric Prevoteau
 *
 * status.c: Copyright (C) Eric Prevoteau <www@a2pb.gotdns.org>
 *
 * 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.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
/*
$Id: status.c,v 1.4 2003/12/28 08:12:38 uid68112 Exp $
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#include "var.h"
#include "display.h"
#include "status.h"

static long my_pos=-1;

#define NB_LONG_PER_ENTRY 32

void set_client_status(int status)
{
      int fd;
      pid_t my_pid;
      unsigned long entry[NB_LONG_PER_ENTRY];
      int i;
      
      fd=open(dctc_active_client_file->str,O_RDWR|O_CREAT,0644);
      if(fd==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","open",strerror(errno),NULL);
            return;
      }

      if(flock(fd,LOCK_EX)==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","flock",strerror(errno),NULL);
            close(fd);
            return;
      }

      my_pid=getpid();

      if(my_pos==-1)
      {     /* I still have no position, let's find one */
            int cur_pos=0;
            int ln;
            int empty_pos=-1;

            for(;;)
            {
                  ln=read(fd,entry,sizeof(entry));
                  if(ln==0)
                  {
                        if(empty_pos==-1)
                        {
                              /* end of file, append */
                              my_pos=cur_pos;
                        }
                        else
                              my_pos=empty_pos;
                        break;
                  }
                  else if(ln!=sizeof(entry))
                  {
                        if(empty_pos==-1)
                        {
                              /* end of file, truncated last entry, append on the next valid position */
                              my_pos=cur_pos+sizeof(entry);
                        }
                        else
                              my_pos=empty_pos;
                        break;
                  }
                  
                  if(entry[0]==my_pid)
                  {
                        my_pos=cur_pos;
                        break;
                  }

                  if((entry[0]==0)&&(empty_pos==-1))        /* find an empty entry at the same time */
                        empty_pos=cur_pos;

                  cur_pos+=sizeof(entry);
            }

            /* clear uninitialized fields */
            for(i=2;i<NB_LONG_PER_ENTRY;i++)
                  entry[i]=0;
      }
      else
      {
            lseek(fd,my_pos,SEEK_SET);
            read(fd,entry,sizeof(entry));
      }

      lseek(fd,my_pos,SEEK_SET);
      entry[0]=my_pid;
      entry[1]=status;
      if(write(fd,entry,sizeof(entry))!=sizeof(entry))
      {
            disp_msg(ERR_MSG,"set_client_status","write",strerror(errno),NULL);
      }

      flock(fd,LOCK_UN);
      close(fd);
}

/*************************************************************************************************/
/* set the given value (unsigned long) at the given position of the client entry in gstatus file */
/*************************************************************************************************/
void set_client_unsigned_long_number(GSTATUS_POSITION_ENUM position, unsigned long value)
{
      int fd;
      unsigned long entry[NB_LONG_PER_ENTRY];
      
      if(my_pos==-1)
            return;

      fd=open(dctc_active_client_file->str,O_RDWR|O_CREAT,0644);
      if(fd==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","open",strerror(errno),NULL);
            return;
      }

      if(flock(fd,LOCK_EX)==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","flock",strerror(errno),NULL);
            close(fd);
            return;
      }

      lseek(fd,my_pos,SEEK_SET);
      if(read(fd,entry,sizeof(entry))!=sizeof(entry))
      {
            disp_msg(ERR_MSG,"set_client_status","read",strerror(errno),NULL);
      }
      else
      {
            lseek(fd,my_pos,SEEK_SET);
            entry[position]=value;
            if(write(fd,entry,sizeof(entry))!=sizeof(entry))
            {
                  disp_msg(ERR_MSG,"set_client_status","write",strerror(errno),NULL);
            }
      }

      flock(fd,LOCK_UN);
      close(fd);
}

/*************************************************************************************************/
/* get the given value (unsigned long) at the given position of the client entry in gstatus file */
/* if the client has no entry on the gstatus file (this should never occurs), 0 is returned      */
/*************************************************************************************************/
unsigned long get_client_unsigned_long_number(GSTATUS_POSITION_ENUM position)
{
      int fd;
      unsigned long entry[NB_LONG_PER_ENTRY];
      
      if(my_pos==-1)
            return 0;

      fd=open(dctc_active_client_file->str,O_RDWR|O_CREAT,0644);
      if(fd==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","open",strerror(errno),NULL);
            return 0;
      }

      if(flock(fd,LOCK_SH)==-1)     /* we will only read, a shared lock is enough */
      {
            disp_msg(ERR_MSG,"set_client_status","flock",strerror(errno),NULL);
            close(fd);
            return 0;
      }

      lseek(fd,my_pos,SEEK_SET);
      if(read(fd,entry,sizeof(entry))!=sizeof(entry))
      {
            disp_msg(ERR_MSG,"set_client_status","read",strerror(errno),NULL);
            entry[position]=0;
      }

      flock(fd,LOCK_UN);
      close(fd);
      return entry[position];
}

/*****************************************************************************************/
/* set the given value (float) at the given position of the client entry in gstatus file */
/*****************************************************************************************/
void set_client_float_number(GSTATUS_POSITION_ENUM position, float value)
{
      int fd;
      unsigned long entry[NB_LONG_PER_ENTRY];
      
      if(my_pos==-1)
            return;

      fd=open(dctc_active_client_file->str,O_RDWR|O_CREAT,0644);
      if(fd==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","open",strerror(errno),NULL);
            return;
      }

      if(flock(fd,LOCK_EX)==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","flock",strerror(errno),NULL);
            close(fd);
            return;
      }

      lseek(fd,my_pos,SEEK_SET);
      if(read(fd,entry,sizeof(entry))!=sizeof(entry))
      {
            disp_msg(ERR_MSG,"set_client_status","read",strerror(errno),NULL);
      }
      else
      {
            lseek(fd,my_pos,SEEK_SET);
            *((float*)(&(entry[position])))=value;
            if(write(fd,entry,sizeof(entry))!=sizeof(entry))
            {
                  disp_msg(ERR_MSG,"set_client_status","write",strerror(errno),NULL);
            }
      }

      flock(fd,LOCK_UN);
      close(fd);
}


void del_client_status()
{
      int fd;
      unsigned long entry[NB_LONG_PER_ENTRY];
      int i;
      
      if(my_pos==-1)
            return;

      fd=open(dctc_active_client_file->str,O_RDWR|O_CREAT,0644);
      if(fd==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","open",strerror(errno),NULL);
            return;
      }

      if(flock(fd,LOCK_EX)==-1)
      {
            disp_msg(ERR_MSG,"set_client_status","flock",strerror(errno),NULL);
            close(fd);
            return;
      }

      lseek(fd,my_pos,SEEK_SET);
      for(i=0;i<NB_LONG_PER_ENTRY;i++)
            entry[i]=0;
      if(write(fd,entry,sizeof(entry))!=sizeof(entry))
      {
            disp_msg(ERR_MSG,"set_client_status","write",strerror(errno),NULL);
      }

      flock(fd,LOCK_UN);
      close(fd);
}

Generated by  Doxygen 1.6.0   Back to index