#include "../include/includes.h"
#include "../include/sms_msgtype.h"
#include "../include/iptrans.h"

extern long  timezone;
extern iconv_t  iconv_p,iconv_v;

void Terminate(int sign)
{
   int retv;

   usleep(10*1000);
   printf("Program unormally shutdown.\n");   
   exit(1);
}

void SetTerminate()
{
   struct termio ptermio;
   ioctl(0,TCGETA, &ptermio);
   ptermio.c_cc[VINTR]='\x03';
   ioctl(0,TCSETA, &ptermio);   
   signal(SIGINT , Terminate);
   signal(SIGTERM, Terminate);
}

void *ShmInit(int shm_id, key_t key, int size, int shmflg)
{
     void  *retp;
	 
     shm_id=shmget(key,size,shmflg);

     if(shm_id==-1){
       fprintf(stderr,"shmget(key %x) %s\n",key,strerror(errno));
       exit(1);
     }
     retp=shmat(shm_id,(char *)0,0);
     if(retp==(void *)-1){
       fprintf(stderr,"shmmat %s\n",strerror(errno));
       exit(1);
     }
     return retp;
}

int SemInit( key_t key, int sem_num, int sem_flg)
{
int           initarray[sem_num];
int           sem_id, retval, i;

    sem_id = semget(key, sem_num, sem_flg);
    if (sem_id == -1)
    { 
       fprintf(stderr,"Error in semget()\n");
       exit(1);
    }    
    for (i=0; i<sem_num; i++) {
        initarray[i] = 1;
  		retval = semctl(sem_id, i, SETVAL, initarray[i]);
    	if (retval == -1)
    	{
    	   fprintf(stderr,"Errro in semctl()\n");
        }
    }    
    return sem_id;
}

int SemLock(int sem_id, int sem_num, unsigned nsops, int sem_flg)
{
int               retval;
struct sembuf     lock = {0, -1, SEM_UNDO};

    lock.sem_num = sem_num;
    lock.sem_flg |= sem_flg;    
    retval = semop(sem_id, &lock, nsops);
    if (retval == -1) {
        fprintf(stderr,"Error in semop()\n");
        return 0;
    }

    return 1;
}

int SemUnlock(int sem_id, int sem_num, unsigned nsops, int sem_flg)
{
int               retval;
struct sembuf     unlock = {0, 1, SEM_UNDO};

    unlock.sem_num = sem_num;
    unlock.sem_flg |= sem_flg;
    retval = semop(sem_id, &unlock, nsops);
    if (retval == -1) {
        fprintf(stderr,"Error in semop()\n");
        return 0;
    }
    return 1;
}


int InitDaemon(void)
{
  pid_t  pid;
  if((pid=fork())<0)
     return  -1;
  else if(pid !=0)
      exit(0);
  setsid();
  chdir("/");
  umask(0);
  return 1;
}


int EncodeEnglish(char *str_In,BYTE *bcd_Out)
{
  int i,len,n,cur,index=0;
  unsigned char mid1,mid2;
  char tmpStr[2];
  char  strIn[180];
  
  n=0;
  strcpy(strIn,str_In);
  
  len=strlen(strIn);
  if(len>160) return 0;
  for(i=0;i<len;i++)
  {
   if(strIn[i] == 0x40)
    strIn[i] =0x00;
  }  
  
  for(i=0;i<len;i++)
   {
    if(i<len-1)
    {
     mid1=strIn[i];
     mid2=strIn[i+1];
     cur=(mid1>>n) |((mid2<<(7-n))&0xff);    
    }
    else
    {
     mid1=strIn[i];
     cur=(mid1>>n)&0xff;
    }
//    sprintf(tmpStr,"%2.2X", cur);
//    strcat(strOut,tmpStr);
    bcd_Out[index++]=cur;
    n=(n+1)%7;    
    if(n==0) i++;    
  }    
//  AsciiToBcd(bcd_Out,strOut,strlen(strOut));
//  bcd_Out[strlen(strOut)/2]='\0';
    bcd_Out[index]='\0';
  return 1;
}

int DecodeEnglish(char *strIn,char *strOut,int len0)
{
  int i,n,j;
  int len;
  unsigned char mid1,mid2,cur;
  char tmpStr[2];
  BYTE  strHex[1024];
  
//  len=strlen(strIn);
//  sprintf(strOut,"");
//
   
  n=0;j=0;
  len = len0 - len0/8;
  memcpy(strHex,strIn,len);    
  
  fprintf(stderr,"len0 :%d   len: %d\n",len0,len);
  
  for(i=0;i<len;i++)
  {
    if(i>0)
    {
      mid1=strHex[i];
      mid2=strHex[i-1];
      cur=((mid1<<n)&0x7f) |(mid2>>(8-n));      
    }
    else
    {
       mid1=strHex[i]&0x7f;
       cur=mid1;
    }
    strOut[j++] = cur;
    n =(n+1)%8;    
    if(n==0) i--;
  }  
  
  for(i=0;i<j;i++)
  {
    if(strOut[i] == 0x00)
    {
      strOut[i] = 0x40;  
    }  
  }
  
  strOut[len0] = 0;
}

int EncodeChinese(unsigned char *strIn, char *strOut)
{
   int i;
   int code; 
   int len = 0;
   unsigned char smsud[180];

   for(i=0;i<160;)
   {
   
    if(strIn[i] < 0x80)
    {
       if(strIn[i] == 0x00 )
        break;
       smsud[len++] = 0x00;
       smsud[len++] = strIn[i++];
    }
    else
    {
        smsud[len++] = strIn[i++];
        smsud[len++] = strIn[i++];
     }  
   }

   for(i=0;i<len/2;i++)  
   {  
     code = smsud[i*2]*256 + smsud[i*2+1];
     code = CP936_Array[smsud[i*2]*256+smsud[i*2+1]];
     strOut[i*2] = code >>8;
     strOut[i*2+1] = code;
   }
   
   strOut[len]=0;
   return len;
}

int DecodeChinese( unsigned char *strIn, char *strOut,int len)
{
   int i,code,count=0;
//   size_t size_in=8,size_out=0;   
//   len = iconv(iconv_p,&strIn,&size_in,&strOut,&size_out);  
   for(i=0;i<len/2;i++)
   {
      code = Unicode_Array[strIn[i*2]*256+strIn[i*2+1]];
      if(code<256)
      {       
        strOut[count++] = code;
      }
      else
      {
        strOut[count++] = code>>8;
        strOut[count++] = code;
      }  
   }
   strOut[count]=0;
   return len/2;
}

int StrToChar(char *strIn,char *strOut)
{
  int i,len;
  len=strlen(strIn);

  for(i=0;i<len;i++)
  {
    if(strIn[i]>=87) strIn[i] =strIn[i]-87;
    else if(strIn[i]>=65) strIn[i] =strIn[i]-55;
    else if(strIn[i]>=48) strIn[i] -=48;
  }
  for(i=0;i<len/2;i++)
    strOut[i] =strIn[i*2]*16+strIn[i*2+1];
  return 1;
}

int ReadCP936()
{
  FILE *fpRead;
  char strRead[81];
  int  i,j,len;
  int  startc,endc,startu,endu;
  char ucode[6],ccode[6];
  unsigned short  indexc,indexu,xcount;
  
  fpRead=fopen(CP936_NAME,"r");
  if(fpRead==NULL)
  {
    fprintf(stderr,"Can't open file CP936.TXT, PLEASE check the path\n");
	exit(1);
    return 0;
  }
  while(!feof(fpRead))
  {
    fgets(strRead,80,fpRead);
    len=strlen(strRead);
   
    for(j=0;j<len;j++)
    {       
      if(strRead[j]=='#') break;
    }
    len=j;
    if(len<4) continue;
    startc=endc=0;
    startu=endu=0;
    xcount=0;
    for(j=0;j<len;j++)
    {
      if(strRead[j]=='x' || strRead[j]=='X')
      {
        if(startc==0) startc=j+1;
        else if(startu==0) startu=j+1;
        xcount++;
      }   
      if(strRead[j]==0x09 && j>0)
      {
        if(endc==0) endc=j;
        else if(endu==0) endu=j;
      }    
    } 
    if(xcount>1){
       memcpy(ccode,&strRead[startc],endc-startc);
       memcpy(ucode,&strRead[startu],endu-startu);
       ccode[endc-startc]=0;
       ucode[endu-startu]=0;
       indexc=StrToInt(ccode);
       indexu=StrToInt(ucode);
       CP936_Array[indexc]=indexu;       
       Unicode_Array[indexu]=indexc;
    }       
   }
   return 1;
}

int StrToInt(char *strHex)
{
  int i,len;
  unsigned short intOut;
  len=strlen(strHex);
  for(i=0;i<len;i++)
  {
    if(strHex[i]>='a')      strHex[i] =strHex[i]-'a'+10;
    else if(strHex[i]>='A') strHex[i] =strHex[i]-'A'+10;
    else if(strHex[i]>='0') strHex[i] =strHex[i]-'0';
  }

  if(len==2)           intOut=(unsigned short)(strHex[0]*16+strHex[1]);
  else if(len==4)      intOut=(unsigned short)(strHex[0]*16+strHex[1])*256+(strHex[2]*16+strHex[3]);

  return intOut;
}

const char * Inet_ntoa(const long addr)
{
  struct sockaddr_in addr_in;
  addr_in.sin_addr.s_addr=addr;
  return ((char *)inet_ntoa(addr_in.sin_addr));
}

int msisdn_conv(BYTE* dst_buf,const char *src_buf,int req_len)
{
  BYTE tmp_buf[256];
  int  i,len;
  len = strlen(src_buf);
  memcpy(tmp_buf,src_buf,len);
  if(len%2)
  {
    tmp_buf[len] = 0x0F;
    len +=1;
  }
  AsciiToBcd_v(dst_buf,tmp_buf,len);    /* exchange position of the char */
  return 0;
}

int Datetime2SCTS(BYTE* scts, char* time_in)
{
  struct tm *tmnow=NULL;
  time_t timep;  
  char   tmpbuf[1024];
  
  timep      = time(NULL);    
  tmnow      = localtime(&timep);  

  tmpbuf[0]  = time_in[2];
  tmpbuf[1]  = time_in[3];
  tmpbuf[2]  = time_in[5];
  tmpbuf[3]  = time_in[6];
  tmpbuf[4]  = time_in[8];
  tmpbuf[5]  = time_in[9];
  tmpbuf[6]  = time_in[11];
  tmpbuf[7]  = time_in[12];
  tmpbuf[8]  = time_in[14];
  tmpbuf[9]  = time_in[15];
  tmpbuf[10] = time_in[17];
  tmpbuf[11] = time_in[18];
  if(timezone>0)
    tmpbuf[12] = 0;
  else
    tmpbuf[12] = 1;  
  tmpbuf[13] = timezone/3600;
  AsciiToBcd(scts,tmpbuf,14);
  return 0;
}


int AsciiToBcd(BYTE *bcd_buf, const char *ascii_buf, int len)
{
   int  i;
   char ch;

   for(i=0;i<len;i++)
   {
      ch =ascii_buf[i];
	  if(ch>='a')       ch -='a' -10;
	  else if(ch>='A')  ch -='A'-10;
	  else              ch -='0';
	  if(i &1) *(bcd_buf++) |=ch & 0x0f;
	  else     *(bcd_buf) =ch<<4;
    }
    
    return 0;
}

int AsciiToBcd_v(BYTE *bcd_buf, const char *ascii_buf, int len)
{
   int  i;
   char ch,tmp_buf[256];
   for(i=0;i<len;i++)
   {
      ch =ascii_buf[i];
	  if(ch>='a')       ch -= 'a' -10;
	  else if(ch>='A')  ch -= 'A'-10;
	  else              ch -= '0';
	  tmp_buf[i]            = ch;
    }
    for(i=0;i<len/2;i++)
    {
	*(bcd_buf++) =(tmp_buf[i*2+1]<<4) | ( tmp_buf[i*2] &0x0f);	
    }
    return 0;
}

const long Inet_pton(const char *sp)
{
  struct in_addr i_addr;
  inet_pton(AF_INET,sp,&i_addr);
  return i_addr.s_addr;
}

/* Convert data from left-aligned compact BCD form to ASCII form. */
void  BcdToAscii (char *ascii_buf, const BYTE *bcd_buf, int len)
{
    int   i;
    char  ch;

    for (i=0; i<len; i++) {
        if (i & 1)  ch = *(bcd_buf++) & 0x0f;
        else  ch = *bcd_buf >> 4;
        ascii_buf[i] = ch + ((ch > 9)? 'A'-10 : '0');
    }
    ascii_buf[i] = '\0';
}

void  DecodeAddress(char *addr_in,char *addrout)
{
   int i,len;
   char addrin[22];
   
   len = strlen(addr_in);
   BcdToAscii(addrin,addr_in,len*2);
   len = strlen(addrin);
   for(i=0;i<len/2-1;i++)
   {
     addrout[i*2] = addrin[i*2+1];
     addrout[i*2+1] = addrin[i*2];
   }
   if(addrin[len-2] =='f' || addrin[len-2] == 'F')
   {
     addrout[len-2] = addrin[len-1];
     addrout[len-1] = 0;
   }
   else
   {
     addrout[len-2] = addrin[len-1];
     addrout[len-1] = addrin[len-2];
     addrout[len] = 0;
   }
   
}

void DecodeMSISDN(unsigned char *msisdn, char *addrout)
{
   int i;
   char addrin[22];

   BcdToAscii(addrin,msisdn,16);

   for(i=0;i<8;i++)
   { 
       
     if(addrin[i*2] !='E' && addrin[i*2] !='e')     
     {
       addrout[i*2] = addrin[i*2+1];
       addrout[i*2+1] = addrin[i*2];
     }
     else if(addrin[i*2+1] == 'E' || addrin[i*2+1] =='e')
     {
       addrout[i*2] =0;
       break;
     }
     else     
     {
       addrout[i*2] = addrin[i*2+1];          
       addrout[i*2+1] = 0;
       break;
     }
   }
}

int msisdn2addr(char *msisdn, PSMS_ADDRESS sms_addr)
{
  int len,i;
  char addrin[22];

  BcdToAscii(addrin,msisdn,16);
  len =0;
  sms_addr->sms_addr_type = 0x81;
  for(i=0;i<8;i++)
  {
     if(addrin[i*2] !='E' && addrin[i*2] !='e')     
     {
       sms_addr->sms_addr[i] = msisdn[i];
       len = len+2;
     }
     else if(addrin[i*2+1] == 'E' || addrin[i*2+1] =='e')
     {       
       break;
     }
     else     
     {
       sms_addr->sms_addr[i] = 0xf0 | (msisdn[i] &0x0f);
       len = len+1;
       break;
     }
  }  
  sms_addr->sms_addr_len = len;

  return 1;
}

int addr2msisdn(SMS_ADDRESS sms_addr, unsigned char *msisdn)
{
  int i, len;
  char addrin[22];

  len = sms_addr.sms_addr_len;
  BcdToAscii(addrin,sms_addr.sms_addr,len%2 ==0 ? len:len+1);
  for(i=0;i<(len+1)/2;i++)
  {
    if(addrin[i*2] !='F' && addrin[i*2] !='f')     
     {
       msisdn[i] = sms_addr.sms_addr[i];
     }
     else     
     {
       msisdn[i] = 0xE0 | (sms_addr.sms_addr[i] &0x0f);
     }
  }
  for(i=(len+1)/2;i<8;i++)
   msisdn[i]=0xEE;  
  return 1;
}

int GetSCTS(long ltime, char *ch_time)
{
  struct tm *t ,tt;
  char   c_time[7];
  char   work[2]={""};
  char   tmp[20]={""};
  int    i;
  
  t = &tt;
  t = localtime(&ltime);
  
  c_time[0] = t->tm_year-100;
  c_time[1] = t->tm_mday;  
  c_time[2] = t->tm_mon+1;
  c_time[3] = t->tm_hour;
  c_time[4] = t->tm_min;
  c_time[5] = t->tm_sec;
  c_time[6] = timezone/3600;

  for(i=0;i<7;i++)
  {
   sprintf(work,"%02d",c_time[i]);
   strcat(tmp,work);
  } 

  AsciiToBcd_v(ch_time,tmp,14);
  
  return 1;
}

int str2msisdn(char *str_In, unsigned char *msisdn)
{
  int i,len;
  char strIn[22];
  strcpy(strIn,str_In);
  len = strlen(strIn);
  for(i=len;i<16;i++)
    strIn[i] = 'E';
  AsciiToBcd_v(msisdn,strIn,16);
  return 1;
}

int str2address(char *str_In, PSMS_ADDRESS addrout)
{
  int i,len;
  char  strIn[22];

  strcpy(strIn,str_In);
  len = strlen(strIn);
  
  addrout->sms_addr_len = len;
  addrout->sms_addr_type = 0x81;
  if(len%2 ==1)
  {
   strIn[len] ='F';
   len = len+1;
  } 
  AsciiToBcd_v(addrout->sms_addr,strIn,len );
  return 1;
}

int sms2str(char *strIn, char *strOut,int len)
{  
  BcdToAscii( strOut,strIn,len*2); 
  return 1;
}

int str2sms(char *strIn, char *strOut)
{
  int len;
  len = strlen(strIn);
  AsciiToBcd(strOut,strIn,len);
  return 1;
}

int GetDate(long ltime,char *ctime)
{
  struct tm *t ,tt;
 
  t = &tt;
  t = localtime(&ltime);
  
  ctime[0] = t->tm_year-100;
  ctime[1] = t->tm_mon+1;
  ctime[2] = t->tm_mday;    
  return 1;
}
