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

child.c

/*
 * acon a utility to facilitate the right to left writing
 * Copyright 1999 Ahmed Abdel-Hamid Mohamed <ahmedam@mail.usa.com>
 *
 * 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., 675 Mass
 * Ave, Cambridge, MA 02139, USA.
 *
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/vt.h>
#include <sys/time.h>
#include "acon.h"
#include "child.h"
#include <linux/kd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
#include "acon.h"
#include "arabicfont.h"
#include "render.h"
#include "menu.h"

int consoles[63],consolesn=0;
int needrefreshconsole=0,useunicode=0;

void refreshconsole()
{
      needrefreshconsole=1;
}

/*Carries data about each monitored console*/
struct {
      char *font;       /*font path, * at the start means exec*/
      char *keymap;     /*keymap path, * at the start means exec*/
      char *translation;      /*translation path*/
      int hendi;        /*hendi numbers type*/
      int direction;    /*general screen direction*/
      int unicode;      /*1=Enable UTF-8*/
}condata[63];

/*Chech if the console is in the list,then return entry number+1,else 0*/
int isinlist(int cnum)
{
      int i;
      for(i=0;i<consolesn;i++)
            if(consoles[i]==cnum)return i+1;
      return 0;
}

/*Add new console to the list of the consoles to be monitored*/
int addconsole(int cnum)
{
      if(isinlist(cnum))return -1;
      if(consolesn==63)return -2;
      memset(&condata[consolesn],0,sizeof(*condata));
      consoles[consolesn++]=cnum;
      
      return consolesn-1;
}

void removeconsole(int cnum)
{
      int i;
      setactive(cnum);
      cnum=getstructnum(cnum);
      for(i=cnum;i<consolesn-1;i++)
      {
            memcpy(&condata[i],&condata[i+1],sizeof(condata[0]));
            consoles[i]=consoles[i+1];
      }
      consolesn--;
}

void saveconfiguration(void)
{
      char tmp[300],*env;
      int i;
      FILE *fp;

      set_user_id();

      if(!(env=getenv("HOME")) || !env[0])
      {
            printf("Acon: can't know HOME directory\n");
            return;
      }
      sprintf(tmp,"%s/.acon.conf",env);
      if((fp=fopen(tmp,"w"))==NULL)
      {
            printf("Acon: can't save %s\n",tmp);
            return;
      }

      fprintf(fp,"# .acon.conf      generated by Acon\n"
            "# This file configure each console independebly\n"
            "# The console options are set first, then add it using 'add_console' command\n\n\n");
      for(i=0;i<consolesn;i++)
      {
            fprintf(fp,"hendinums %s   #never,always or context\n",
                  (!condata[i].hendi?"never"
                  :(condata[i].hendi==1?"always"
                  :"context")));
            fprintf(fp,"unicode %s     #disable or enable\n",
                  (!condata[i].unicode?"disable"
                  :"enable"));
            fprintf(fp,"direction %s   #LTR or RTL\n",
                  (!condata[i].direction?"LTR"
                  :"RTL"));
            fprintf(fp,"font %s\n",
                  (!condata[i].font?""
                  :condata[i].font));
            fprintf(fp,"keymap %s\n",
                  (!condata[i].keymap?""
                  :condata[i].keymap));
            fprintf(fp,"translation %s\n",
                  (!condata[i].translation?""
                  :condata[i].translation));
            fprintf(fp,"add_console %d\n\n\n",consoles[i]);
      }
      fprintf(fp,"# End of configuration");
      fclose(fp);
}

/*Set unimap table*/
/*void setuni(int tty)
{
      struct */
/*Set console properties*/
void setconsolefont(int cnum,char *font)
{
      cnum=getstructnum(cnum);
      if(condata[cnum].font)free(condata[cnum].font);
      condata[cnum].font=0;
      if(font && font[0])condata[cnum].font=malloc(strlen(font)+1);
      if(condata[cnum].font)strcpy(condata[cnum].font,font);
}
void setconsolekeymap(int cnum,char *keymap)
{
      cnum=getstructnum(cnum);
      if(condata[cnum].keymap)free(condata[cnum].keymap);
      condata[cnum].keymap=0;
      if(keymap && keymap[0])condata[cnum].keymap=malloc(strlen(keymap)+1);
      if(condata[cnum].keymap)strcpy(condata[cnum].keymap,keymap);
}
void setconsoletranslation(int cnum,char *translation)
{
      cnum=getstructnum(cnum);
      if(condata[cnum].translation)free(condata[cnum].translation);
      condata[cnum].translation=0;
      if(translation && translation[0])condata[cnum].translation=malloc(strlen(translation)+1);
      if(condata[cnum].translation)strcpy(condata[cnum].translation,translation);
}
void setconsoledirection(int cnum,int direction)
{
      cnum=getstructnum(cnum);
      condata[cnum].direction=direction;
}
void setconsolehendi(int cnum,int hendi)
{
      cnum=getstructnum(cnum);
      condata[cnum].hendi=hendi;
      usehendinums=hendi;
}
void setconsoleunicode(int cnum,int uni)
{
      cnum=getstructnum(cnum);
      useunicode=condata[cnum].unicode=uni;
}
void setconsole(int cnum,char *font,char *keymap,char *translation,int direction,int hendi,int unicode)
{
      setconsolefont(cnum,font);
      setconsolekeymap(cnum,keymap);
      setconsoletranslation(cnum,translation);  
      setconsoledirection(cnum,direction);
      setconsolehendi(cnum,hendi);
      setconsoleunicode(cnum,unicode);
}

void setunimap(int tty)
{
      struct unimapdesc uni;
      struct unipair    entries[256];
      struct unimapinit unimapinit={0,0,1};
      unsigned int i;

      uni.entry_ct=256;
      uni.entries=entries;
      for(i=0;i<0xa0;i++)
            entries[i].unicode=entries[i].fontpos=i;
      for(i=0xa0;i<256;i++)
            entries[i].unicode=0x600+i-0xa0,entries[i].fontpos=i;
      
      set_acon_id();
      if(ioctl(tty,PIO_UNIMAPCLR,&unimapinit))
      {
            printf("Error PIO_UNIMAPCLR");
            set_user_id();
            return;
      }
      if(ioctl(tty,PIO_UNIMAP,&uni))
            printf("Error PIO_UNIMAP");
      set_user_id();
}
      
/*Turn off echo and send each character*/
int setfd(int fd)
{
      struct termios newt;
      tcgetattr(fd, &newt);

      newt.c_lflag &= ~ (ICANON | ECHO | ISIG);
      newt.c_iflag = 0;

      tcsetattr(fd, TCSAFLUSH, &newt);

      /*Set meta bit*/
      set_acon_id();
      if(ioctl(fd,KDSKBMETA,(long)K_METABIT))
            printf("Error setfd::KDSKBMETA\n");
      set_user_id();
      return 0;
}

/*Send one key or return 256*/
unsigned int getkey(int fd,int time/*in us**/)
{
      fd_set fdset;
      unsigned char chr;
      struct timeval tv;

      FD_ZERO(&fdset);
      FD_SET(fd,&fdset);

      tv.tv_sec=0;
      tv.tv_usec=/*50000*/time;

      if(!select(fd+1,&fdset,NULL,NULL,&tv))
            return 256;
      read(fd,&chr,1);
      return chr;
}

/*Get current active console*/
int getactive(void)
{
      static int consolefd=0;
      long ingraphics;
      struct {ushort active;ushort signal;ushort state;}argp;
      set_acon_id();
      if(!consolefd)
            if((consolefd=open("/dev/console",O_RDONLY))==-1){
                  printf("Cant't open /dev/console \n");
                  set_user_id();
                  return -1;
            }
      if(ioctl(consolefd,VT_GETSTATE,&argp))
      {
          printf("Error in child.c::getactive:VT_GETSTATE\n");/**/
            set_user_id();
          return -1;
      }
      if(ioctl(consolefd,KDGETMODE,&ingraphics))
      {
          printf("Error in child.c::getactive:KDGETMODE\n");
            set_user_id();
          return -1;
      }
      set_user_id();
      if(ingraphics)return -1;      /*in graphics mode*/
      return argp.active;
}
      
int acontty,childtty;
int aconvcsa,consolen,childvcsa,z;
int changed=1;

int getch(void)
{
      return getkey(acontty,50000);
}

int sendkey(unsigned int chr)
{
      set_acon_id();
      if (ioctl(childtty,TIOCSTI,&chr)) /*Send the key*/
      {
            char buf[200];
          /*Try to reopen acontty*/
            close(childvcsa);
            close(childtty);

            sprintf(buf,"/dev/tty%d",consolen);
            if((childtty=open(buf,O_RDWR))==-1)
            {
                printf("Error opening %s\n",buf);
                  set_user_id();
                return -1;
            }
            sprintf(buf,"/dev/vcsa%d",consolen);
            if((childvcsa=open(buf,O_RDWR))==-1)
            {
                printf("Error opening %s\n",buf);
                  set_user_id();
                return -1;
            }
      
            if(ioctl(childtty,TIOCSTI,&chr))
            {
            /*We faile so exit*/
                fprintf(stderr, "error=%d,sti: TIOCSTI ioctl failed\n",errno);
                  set_user_id();
                return (-1);
            }
            set_user_id();
      }
      return 0;
}

/*Get input and send it to the working console*/
int processkey(int time)
{
      unsigned int chr;
      if((chr=getkey(acontty,time))!=256)
      {
            changed=1;
            if(chr==0x86)setdirection((direction?0:1));     /*screen direction*/
            else if(chr==0x87)options(aconvcsa);      /*options*/
            else if(chr==0x88)setdirection(0);  /*screen direction LTR*/
            else if(chr==0x89)setdirection(1);  /*screen direction RTL*/
      
            else if(useunicode && chr>0xa0)
            {
                  int c;
                  c=chr-0xa0+0x600;

                  sendkey(0xc0 | (c>>6) );
                  sendkey(0x80 | (c & 0x3f));
            }
            else 
                  sendkey(chr);
      }
      return 0;
}

int getconsolenum(void)
{
      return consolen;
}

int getstructnum(int cons)
{
      return isinlist(cons)-1;
}

void setdirection(int dir)
{
      direction=dir;
      condata[getstructnum(getconsolenum())].direction=dir;
}

int setactive(int console)
{
      set_acon_id();
      if(ioctl(acontty,VT_ACTIVATE,console))
      {
          printf("Error VT_ACTIVATE");
            set_user_id();
          return -1;
      }
      set_user_id();
      return 0;
}

/*Switch to ttyn, set font, key map, font map, direction, hendi*/
int initconsole(int ttyn,int cons)
{
      loadfontmap(consolen);
      setunimap(childtty);

      cons=getstructnum(cons);

/*    if(condata[cons].keymap && condata[cons].keymap[0]=='*')
            system(condata[cons].keymap+1);
    else */
      loadkeys(acontty,condata[cons].keymap);
    loadfontmapping(acontty,condata[cons].translation);
    direction=condata[cons].direction;
    usehendinums=condata[cons].hendi;
    useunicode=condata[cons].unicode;

      if(condata[cons].unicode)
      {
            char code[]={27,'%','G'};
            write(childtty,code,3);
      }
      else
      {
            char code[]={27,'%','@'};
            write(childtty,code,3);
      }

      /*switch consoles*/
      setactive(ttyn);
      
/*    if(condata[cons].font && condata[cons].font[0]=='*')
            system(condata[cons].font+1);
    else*/
      loadfont(acontty,condata[cons].font);

      return 0;    
}

int aconttyn=-1;

void cleanup(void)
{
      restoreoldfont(acontty);

      /*switch consoles*/
      if(getactive()==aconttyn)
            setactive(consolen);
}

void terminate_sig(int sig)
{
      cleanup();
      printf("Acon is exited\n");
      exit(1);
}

/*The main loop*/
int runchild(int ttyn)
{
      char buf[100],fontrestored;
      int z=0;

/*open devices*/

      signal(SIGTERM,terminate_sig);
      signal(SIGHUP,terminate_sig);
      signal(SIGINT,terminate_sig);
      signal(SIGQUIT,terminate_sig);
      signal(SIGILL,terminate_sig);
      signal(SIGSEGV,terminate_sig);
      signal(SIGBUS,terminate_sig);
      
      sprintf(buf,"/dev/tty%d",ttyn);

      set_acon_id();
      if((acontty=open(buf,O_RDWR | O_NONBLOCK ))==-1)
      {
            printf("Error opening %s\n",buf);
            set_user_id();
            return -1;
      }
      sprintf(buf,"/dev/vcsa%d",ttyn);
      if((aconvcsa=open(buf,O_RDWR))==-1)
      {
            printf("Error opening %s\n",buf);
            set_user_id();
            return -1;
      }
      set_user_id();

      write(acontty,"\nA r a b i c   C O N s o l e\n\n     ",93);

      setfd(acontty);
      saveoldfont(acontty);
      tcsetpgrp(acontty,getpid());

      z=0;
      aconttyn=ttyn;
      
      while(consolesn)
      {
            fontrestored=0;
#if __DEBUG__
            printf("Waiting for a monitored console\n");
#endif
            while(!isinlist(getactive()))
            {
                  if(!fontrestored)
                        restoreoldfont(acontty),fontrestored=1;
                  sleep(1);
            }

            consolen=getactive();
#if __DEBUG__
            printf("Console %d is active\n",consolen);
#endif
            set_acon_id();
            
            sprintf(buf,"/dev/tty%d",consolen);
            if((childtty=open(buf,O_RDWR))==-1)
            {
                  printf("Error opening %s\n",buf);
                  set_user_id();
                  return -1;
            }
            sprintf(buf,"/dev/vcsa%d",consolen);
            if((childvcsa=open(buf,O_RDWR))==-1)
            {
                  printf("Error opening %s\n",buf);
                  set_user_id();
                  return -1;
            }
            set_user_id();

            initconsole(ttyn,consolen);   /*Switch console, set font,key map ... */
            
#if __DEBUG__
            printf("Switched to acon console %d\n",ttyn);
#endif
            while(consolesn && getactive()==ttyn)
            {
                  if((z++)%6==0 || changed)
                  {
                        if(needrefreshconsole)
                        {
                              initconsole(ttyn,consolen);
                              needrefreshconsole=0;
                        }
                        changed=0;
                        if(drawscrn(aconvcsa,childvcsa))
                              consolesn=0;
                  }
                  processkey(30000);
                  set_user_id();
            }
#if __DEBUG__
            printf("User switched to console %d\n",getactive());
#endif

      /*close devices*/
            close(childtty);
            close(childvcsa);
      }

      cleanup();
            
      close(aconvcsa);
      close(acontty);
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index