Beispiel #1
0
void Nhdc12832::refresh(void){
	Spi spi(spi_port);
	uint8_t buffer[MEM_ROWS];
	unsigned int i,j;
	unsigned char page = 0xB0;			//Page Address + 0xB0
	//cmd_out(0xAE);					//Display OFF
	cmd_out(0x40);					//Display start address + 0x40
	for(i=0;i<MEM_COLUMNS;i++){				//32pixel display / 8 pixels per page = 4 pages
		assert_cmd();
		buffer[0] = page;	//send page address
		buffer[1] = 0x10;	//column address upper 4 bits + 0x10
		buffer[2] = 0x00;	//column address lower 4 bits + 0x00
		assert_cs();
		spi.write(buffer, 3);
		deassert_cs();
		for(j=0;j<MEM_ROWS;j++){			//128 rows wide
			buffer[j] = nhd_mem[j][i];
		}
		assert_data();
		assert_cs();
		spi.write(buffer, MEM_ROWS);
		deassert_cs();
		page++;					//after 128 columns, go to next page
	}
	cmd_out(0xAF);					//Display ON
}
Beispiel #2
0
void cc_Ident (char * respons)
{
char to_do [] = {CMD_IDENT, 0, 0};

    cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E );

}
Beispiel #3
0
/* 获得硬盘参数信息 */
static void identify_disk(struct disk* hd) {
	char id_info[512];
	select_disk(hd);
	cmd_out(hd->my_channel, CMD_IDENTIFY);
	/* 向硬盘发送指令后便通过信号量阻塞自己,
	 * 待硬盘处理完成后,通过中断处理程序将自己唤醒 */
	sema_down(&hd->my_channel->disk_done);

	/* 醒来后开始执行下面代码*/
	if (!busy_wait(hd)) {     //  若失败
		char error[64];
		sprintf(error, "%s identify failed!!!!!!\n", hd->name);
		PANIC(error);
	}
	read_from_sector(hd, id_info, 1);

	char buf[64];
	uint8_t sn_start = 10 * 2, sn_len = 20, md_start = 27 * 2, md_len = 40;
	swap_pairs_bytes(&id_info[sn_start], buf, sn_len);
	printk("   disk %s info:\n      SN: %s\n", hd->name, buf);
	memset(buf, 0, sizeof(buf));
	swap_pairs_bytes(&id_info[md_start], buf, md_len);
	printk("      MODULE: %s\n", buf);
	uint32_t sectors = *(uint32_t*)&id_info[60 * 2];
	printk("      SECTORS: %d\n", sectors);
	printk("      CAPACITY: %dMB\n", sectors * 512 / 1024 / 1024);
}
Beispiel #4
0
void cc_Reset (void)
{
char to_do [] = {CMD_RESET, 0};
char dummy;

   cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
}
Beispiel #5
0
static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
{
unsigned char to_do[10];
unsigned char dummy;

                             
    switch (cmd)
    {
       case CDROMSTART:     /* Spin up the drive */
		/* Don't think we can do this.  Even if we could,
 		 * I think the drive times out and stops after a while
		 * anyway.  For now, ignore it.
		 */
            return 0;

       case CDROMRESUME:   /* keine Ahnung was das ist */
            return 0;


       case CDROMEJECT:
            cmd_status ();
            to_do[0] = CMD_TRAY_CTL;
            cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);

            return 0;

       default:
            return -EINVAL;
    }

}
Beispiel #6
0
void cc_SetSpeed (void)
{
char to_do [] = {CMD_SETSPEED, 0, 0};
char dummy;

    if ( speed > 0 )
    {
       to_do[1] = speed & 0x0F;
       cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
    }
}
Beispiel #7
0
void cmd_status (void)
{
char to_do [] = {CMD_STATUS, 0};
char dummy;

   cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);

#ifdef GSCD_DEBUG
printk ("GSCD: Status: %d\n", disk_state );
#endif

}
Beispiel #8
0
static void
gscd_read_cmd (void)
{
long   block;
struct gscd_Play_msf gscdcmd;
char   cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */



        cmd_status ();
        if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) )
        {
           printk ( "GSCD: no disk or door open\n" );
           end_request (0);
        }
        else
        {
           if ( disk_state & ST_INVALID )
           {
              printk ( "GSCD: disk invalid\n" );
              end_request (0);
           }
           else
           {
              gscd_bn = -1;		/* purge our buffer */
              block = CURRENT -> sector / 4;
              gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */

              cmd[2] = gscdcmd.start.min;
              cmd[3] = gscdcmd.start.sec;
              cmd[4] = gscdcmd.start.frame;

#ifdef GSCD_DEBUG
              printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); 
#endif 
              cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 );
        
              gscd_bn = CURRENT -> sector / 4;
              gscd_transfer();
              end_request(1);
	   }
	}
	SET_TIMER(__do_gscd_request, 1);
}
Beispiel #9
0
//从硬盘读取sec_cnt个扇区到buf
void ide_read(struct disk* hd,uint32_t lba,void* buf,uint32_t sec_cnt){
	ASSERT(lba <= max_lba);
	ASSERT(sec_cnt > 0);
	lock_acquire(&hd->my_channel->lock);

	//1、先选择操作的硬盘
	select_disk(hd);

	uint32_t secs_op;				//每次操作的扇区数
	uint32_t secs_done = 0;			//已完成的扇区数
	while(secs_done < sec_cnt){
		if((secs_done + 256) <= sec_cnt){
			secs_op = 256;
		}else{
			secs_op = sec_cnt - secs_done;
		}

		//2、写入待读入的扇区数和起始扇区号
		select_sector(hd,lba + secs_done,secs_op);

		//3、执行的命令写入reg_cmd寄存器
		cmd_out(hd->my_channel,CMD_READ_SECTOR);		//准备开始读数据

		//------------ 阻塞自己的时机  --------------------
		//	在硬盘已经开始工作(开始在内部读数据或写数据)后才能阻塞自己,现在硬盘已经开始忙
		//	了,将自己阻塞,等待硬盘完成读操作后通过中断处理程序唤醒自己
		sema_down(&hd->my_channel->disk_done);
		//-------------------------------------------------

		//4、检测硬盘状态是否可读
		//醒来后开始执行下面代码
		if(!busy_wait(hd)){	//若失败
			char error[64];
			sprintf(error,"%s read sector %d failed!!!!\n",hd->name,lba);
			PANIC(error);
		}

		//5、把数据从硬盘的缓冲区中读出
		read_from_sector(hd,(void*)((uint32_t)buf + secs_done * 512),secs_op);
		secs_done += secs_op;
	}
	lock_release(&hd->my_channel->lock);
}
Beispiel #10
0
/* 从硬盘读取sec_cnt个扇区到buf */
void ide_read(struct disk* hd, uint32_t lba, void* buf, uint32_t sec_cnt) {   // 此处的sec_cnt为32位大小
    ASSERT(lba <= max_lba);
    ASSERT(sec_cnt > 0);
    lock_acquire (&hd->my_channel->lock);

    /* 1 先选择操作的硬盘 */
    select_disk(hd);

    uint32_t secs_op;		 // 每次操作的扇区数
    uint32_t secs_done = 0;	 // 已完成的扇区数
    while(secs_done < sec_cnt) {
        if ((secs_done + 256) <= sec_cnt) {
            secs_op = 256;
        } else {
            secs_op = sec_cnt - secs_done;
        }

        /* 2 写入待读入的扇区数和起始扇区号 */
        select_sector(hd, lba + secs_done, secs_op);

        /* 3 执行的命令写入reg_cmd寄存器 */
        cmd_out(hd->my_channel, CMD_READ_SECTOR);	      // 准备开始读数据

        /*********************   阻塞自己的时机  ***********************
          在硬盘已经开始工作(开始在内部读数据或写数据)后才能阻塞自己,现在硬盘已经开始忙了,
          将自己阻塞,等待硬盘完成读操作后通过中断处理程序唤醒自己*/
        sema_down(&hd->my_channel->disk_done);
        /*************************************************************/

        /* 4 检测硬盘状态是否可读 */
        /* 醒来后开始执行下面代码*/
        if (!busy_wait(hd)) {			      // 若失败
            char error[64];
            sprintf(error, "%s read sector %d failed!!!!!!\n", hd->name, lba);
            PANIC(error);
        }

        /* 5 把数据从硬盘的缓冲区中读出 */
        read_from_sector(hd, (void*)((uint32_t)buf + secs_done * 512), secs_op);
        secs_done += secs_op;
    }
    lock_release(&hd->my_channel->lock);
}
Beispiel #11
0
//将buf中sec_cnt扇区数据写入硬盘
void ide_write(struct disk* hd,uint32_t lba,void* buf,uint32_t sec_cnt){
	ASSERT(lba <= max_lba);
	ASSERT(sec_cnt > 0);
	lock_acquire(&hd->my_channel->lock);

	//1、先选择操作的硬盘
	select_disk(hd);

	uint32_t secs_op;				//每此操作的扇区数
	uint32_t secs_done = 0;			//以完成的扇区数
	while(secs_done < sec_cnt){
		if((secs_done + 256) <= sec_cnt){
			secs_op = 256;
		}else{
			secs_op = sec_cnt - secs_done;
		}

		//2、写入待写入的扇区数和起始扇区号
		select_sector(hd,lba + secs_done , secs_op);

		//3、执行的命令写入reg_cmd寄存器
		cmd_out(hd->my_channel,CMD_WRITE_SECTOR);		//准备开始写数据

		//4、检测硬盘状态是否可读
		if(!busy_wait(hd)){				//若失败
			char error[64];
			sprintf(error,"%s write sector %d failed !!!!\n",hd->name,lba);
			PANIC(error);
		}

		//5、将数据写入硬盘
		write2sector(hd,(void*)((uint32_t)buf + secs_done * 512),secs_op);

		//在硬盘响应期间阻塞自己
		sema_down(&hd->my_channel->disk_done);
		secs_done += secs_op;
	}

	//醒来后开始释放锁
	lock_release(&hd->my_channel->lock);
}
Beispiel #12
0
/* 将buf中sec_cnt扇区数据写入硬盘 */
void ide_write(struct disk* hd, uint32_t lba, void* buf, uint32_t sec_cnt) {
    ASSERT(lba <= max_lba);
    ASSERT(sec_cnt > 0);
    lock_acquire (&hd->my_channel->lock);

    /* 1 先选择操作的硬盘 */
    select_disk(hd);

    uint32_t secs_op;		 // 每次操作的扇区数
    uint32_t secs_done = 0;	 // 已完成的扇区数
    while(secs_done < sec_cnt) {
        if ((secs_done + 256) <= sec_cnt) {
            secs_op = 256;
        } else {
            secs_op = sec_cnt - secs_done;
        }

        /* 2 写入待写入的扇区数和起始扇区号 */
        select_sector(hd, lba + secs_done, secs_op);		      // 先将待读的块号lba地址和待读入的扇区数写入lba寄存器

        /* 3 执行的命令写入reg_cmd寄存器 */
        cmd_out(hd->my_channel, CMD_WRITE_SECTOR);	      // 准备开始写数据

        /* 4 检测硬盘状态是否可读 */
        if (!busy_wait(hd)) {			      // 若失败
            char error[64];
            sprintf(error, "%s write sector %d failed!!!!!!\n", hd->name, lba);
            PANIC(error);
        }

        /* 5 将数据写入硬盘 */
        write2sector(hd, (void*)((uint32_t)buf + secs_done * 512), secs_op);

        /* 在硬盘响应期间阻塞自己 */
        sema_down(&hd->my_channel->disk_done);
        secs_done += secs_op;
    }
    /* 醒来后开始释放锁*/
    lock_release(&hd->my_channel->lock);
}
Beispiel #13
0
int Nhdc12832::init(uint32_t spi_freq, uint8_t spi_pinassign){
	Pin cs(cs_port, cs_pin);
	Pin a0(a0_port, a0_pin);
	Spi spi(spi_port);
	//This is the startup sequence specified by the manufacturer
	const char start[] = {0xA0, 0xAE, 0xC0, 0xA2, 0x2F, 0x21, 0x81, 0x2F};


	cs.init(Pin::OUTPUT);
	cs = true;
	a0.init(Pin::OUTPUT);
	a0 = true;

	if( spi.init(spi_freq, spi_pinassign, SPI_ATTR_MODE0) < 0 ){
		return -1;
	}

	cmd_out(start, 8);
	clear();
	refresh();
	return 0;
}
Beispiel #14
0
int main(int argc, char ** argv)
{  int             c;
   int             fd;
   int             rc;
   int             i;
   int             fRun     = 0;
   int             fDaemon  = 0;
   int             fUpdate  = 0;
   int             fConvert = 0;
   int             fSQL     = 0;
   int             fDumpGates = 0;

   accbase_t       Accbase_temp;
   acc_t           new_acc;
   acc_t_old       old_acc; 

   char         ** row;

   res_coreinit();

   openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);

//   DumpQuery = 1;

/*
 A  1. Redefine service port
 u  2. Update access at start
 d  3. Run Daemon
 c  4. Run console
*/

   while ((c = getopt(argc, argv, OPTS)) != -1)
   {  switch (c)
      {
         case 'A':
            ForceService = strtol(optarg, NULL, 10);
            break;

         case '2':
            fSQL = 1;
            break;

         case 'v':   // verbose - show queries
            DumpQuery = 1;
            break;


         case 'f':
            Config_path = optarg;
            break;

         case 'c':
            ld->fStdio = 1;
            fRun       = 1;
            break;

         case 'd':
            fDaemon = 1;
            fRun    = 1;
            break;

         case 'u':
            fUpdate = 1;
            break;

         case 'o':
            fConvert = 1;
            break;

         case 't':
            proc_title = optarg;
            break;

         case 'Q':
            QueryFilename = optarg;
            break;

         case 'g':
            fDumpGates = 1;
            break;

         case 'q':
            QuietMode = 1;
            break;

         case 'h':
         case '?':
	    usage(0);

         default:
	    usage(-1);
      }
   }

// Load configuration
   if (QuietMode == 0) fprintf(stderr, "Loading base configuration ... ");

   rc = conf_load(Config_path);
   if (rc < 0)
   {  fprintf(stderr, "FAILURE\n");
      syslog(LOG_ERR, "FAILURE - Can't load configuration");
      exit(-1);
   }
   if (QuietMode == 0) fprintf(stderr, "OK.\n");

   if (fSQL)
   {
      if (QuietMode == 0) fprintf(stderr, "Loading SQL configuration ... ");
      rc = cfg_load(Config_path, &config);
      if (rc < 0)
      {  fprintf(stderr, "ERROR (Fatal, see syslog).\n");
         exit(-1);
      }

      if (QuietMode == 0) fprintf(stderr, "OK.\nLoading scripts ... ");

      rc = qlist_load(config.DBscripts);
      if (rc < 0)
      {  fprintf(stderr, "ERROR (fatal)\n");
         exit(-1);
      }
      if (QuietMode == 0) fprintf(stderr, "OK.\n");

   } // if fSQL

// Converting old account table
   if (fConvert != 0)
   {  fprintf(stderr, "Converting database ... ");

// Open old account file
      rc = acc_baseopen(&Accbase_temp, accbase_name_old);
      if (rc != SUCCESS)
      {  fprintf(stderr, "FAILURE - Can't open old account table\n");
         exit(-1);
      } 

// Open new account file
      rc = acc_baseopen(&Accbase, conf_accfile);
      if (rc != SUCCESS)
      {  rc = open(conf_accfile, O_RDONLY | O_CREAT | O_EXCL, 0600);
         if (rc < 0)
         {  fprintf(stderr, "FAILURE - Can't open/create new account table\n");
            exit(-1);
         }
         close(rc);
         rc = acc_baseopen(&Accbase, conf_accfile);
         if (rc != SUCCESS)
         {  fprintf(stderr, "FAILURE - Can't open created account table\n");
            exit(-1);
         }
      }

// Ensure, that new table is empty
      rc = acc_reccount(&Accbase);
      if (rc != 0)
      {  fprintf(stderr, "FAILURE - New account table must be empty !\n");
         exit(-1);
      }

// Copy accounts data
      memset(&new_acc, 0, sizeof(new_acc));
      for(i=0; 1; i++)
      {  rc = acci_get_old(&Accbase_temp, i, &old_acc);
         if (rc == IO_ERROR)
         {  fprintf(stderr, "FAILURE - I/O error on read, (%d accounts copied) !\n", i);
            exit(-1);
         }
         if (rc == NOT_FOUND) break;
         new_acc.tag     = old_acc.tag;
         new_acc.accno   = old_acc.accno;
         new_acc.balance = old_acc.balance;
         new_acc.start   = old_acc.start;
         new_acc.stop    = old_acc.stop;
         new_acc.tariff  = old_acc.reserv[0];

         rc = acc_add(&Accbase, &new_acc);
         if (rc == IO_ERROR)
         {  fprintf(stderr, "FAILURE - I/O error on write, (%d accounts copied) !\n", i);
            exit(-1);
         }

         if (rc != i)
         {  fprintf(stderr, "FAILURE - Accno sync error (%d accounts copied) !\n", i);
            exit(-1);
         }
      }
      acc_baseclose(&Accbase_temp);
      acc_baseclose(&Accbase);
      fprintf(stderr, "SUCCESS (%d accounts copied) !\n", i);
      exit(-1);
   }

   if (fDaemon != 0 && ld->fStdio != 0)
   {  fprintf(stderr, "Can't daemonize in console mode\n");
      fDaemon = 0;
   }

// Load gates table (check file integrity)
   rc = reslinks_load(LOCK_SH);
   if (rc != SUCCESS)
   {  syslog(LOG_ERR, "Can't load gates file");
      exit (-1);
   }

   if (fDumpGates)
   {
      printf("SET client_encoding = 'KOI8';\n\n");
      printf("TRUNCATE beegates;\n");
      printf("COPY beegates (res_id, rid, acc_id, ident) FROM stdin;\n");
      for (i=0; i < linktabsz; i++)
      {
         printf ("%d\t%d\t%d\t%s\n", 
                   linktab[i].res_id,
                   linktab[i].user_id,
                   linktab[i].accno,
                   linktab[i].username);
      }
      printf("\\.\n");
      
      rc = acc_baseopen(&Accbase, conf_accfile);
      if (rc < 0)
      {  syslog(LOG_ERR, "Can't open account database");
         exit (-1);
      }

      printf("TRUNCATE beeaccs;\n");
      printf("COPY beeaccs (id, tag_deleted, tag_broken, tag_frozen, tag_off, tag_unlim, tag_payman, tag_log, "
             "balance, tariff_id, inetin_summ, inetout_summ, money_summ, tcredit "
             ") FROM stdin;\n");

      c = acc_reccount(&Accbase);

      for (i=0; i < c; i++)
      {
         rc = acc_get(&Accbase, i, &new_acc);  
         if (rc < 0 && rc > ACC_BROKEN) continue;

         printf ("%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%g\t%d\t%lld\t%lld\t%g\t%g\n",
                   i, 
                   new_acc.tag & ATAG_DELETED ? "t":"f",
                   new_acc.tag & ATAG_BROKEN  ? "t":"f",
                   new_acc.tag & ATAG_FROZEN  ? "t":"f",
                   new_acc.tag & ATAG_OFF     ? "t":"f",
                   new_acc.tag & ATAG_UNLIMIT ? "t":"f",
                   new_acc.tag & ATAG_PAYMAN  ? "t":"f",
                   new_acc.tag & ATAG_LOG     ? "t":"f",
                   new_acc.balance,
                   new_acc.tariff,
                   new_acc.inet_summ_in,
                   new_acc.inet_summ_out,
                   new_acc.money_summ,
                   new_acc.tcredit);
      }
      printf("\\.\n");
       
      exit(0);
   }

// Open database (to check & update if needed)
   rc = acc_baseopen(&Accbase, conf_accfile);
   if (rc < 0)
   {  syslog(LOG_ERR, "Can't open account database");
      exit (-1);
   }   
   rc = log_baseopen(&Logbase, conf_logfile);
   if (rc < 0)
   {  syslog(LOG_ERR, "Can't open log database");
      exit (-1);
   }   
   rc = tariffs_load(conf_tariffile);
   if (rc < 0)
   {  syslog(LOG_ERR, "Can't open tariff database");
      exit (-1);
   }   

   if (fSQL)
   {
      fprintf(stderr, "SQL init ... ");

   // Initialize connection
      DBdata = db2_init(config.DBtype, config.DBhost, config.DBname);
      if (DBdata == NULL)
      {  fprintf(stderr, "FAULT. db_init() fails.\n");
         exit (-1);
      }
   // Open database
      rc = db2_open(DBdata, config.DBlogin, config.DBpass);
      if (rc < 0)
      {  fprintf(stderr, "FAULT. db_open() fails.\n");
         exit (-1);
      }

      fprintf(stderr, "OK.\n");

// Perform immediate query from file
      if (QueryFilename != NULL)
      {  fd = open(QueryFilename, O_RDONLY, 0);
         if (fd >= 0)
         {  c = 0;
            rc = ioctl(fd, FIONREAD, &c);
            if (rc >= 0 && c > 1)
            {  QueryBuffer = (char*)calloc(1, c + 1);
               if (QueryBuffer != NULL)
               {  rc = read(fd, QueryBuffer, c);
                  if (rc == c)
                  {  if (DumpQuery) printf("%s", QueryBuffer);
                     rc = db2_execute(DBdata, "%s", QueryBuffer);
                     if (rc < 0) fprintf(stderr, "QUERY: SQL error\n");
                     else fprintf(stderr, "QUERY: done.\n"); 
                  }
                  else fprintf(stderr, "QUERY: File read error\n");
                  free(QueryBuffer);
                  QueryBuffer = NULL;
               }
               else fprintf(stderr, "QUERY: Memory allocation error\n");
            }
            else fprintf(stderr, "QUERY: File size error\n");
            close(fd);
         }
         else fprintf(stderr, "QUERY: File access error - %s\n", strerror(errno));
      }

// Perform test query
      row = db2_search(DBdata, 0, "SELECT count(*) FROM accs");
      if (row == NULL)
      {  fprintf(stderr, "Test fails.\n");
         exit (-1);
      }
      else fprintf(stderr, "Test OK. (%s accounts).\n", *row);
  
   } // if fSQL

// Update resources permissions
   if (fUpdate != 0) access_update(); 

// Close database
   acc_baseclose(&Accbase);
   log_baseclose(&Logbase);
   tariffs_free();

// Close database
   if (fSQL)
   {
      rc = db2_close(DBdata);
      if (rc < 0)
      {  fprintf(stderr, "FATAL: db2_close() fails.\n\n");
         exit (-1);
      }
   } // if fSQL

// Start server
   if (fRun)
   {  if (fDaemon)
      {  rc = daemon(0, 0);
         if (rc != SUCCESS)
         {  syslog(LOG_ERR, "Can't daemonize, closing");
            exit(-1);
         }
         if (proc_title == NULL) setproctitle("(daemon)");
         else setproctitle(proc_title);
      }
      if (setenv("HOME", "/root", 0) == (-1)) syslog(LOG_ERR, "setenv(): %m");
      rc = link_wait(ld, ForceService < 0 ? conf_coreport : ForceService);
      if (rc != -1)
      {  
         
         if (ld->fStdio == 0) setproctitle("(child)");
         else 
         {  if (proc_title == NULL) setproctitle("(console)");
            else setproctitle(proc_title);
         }

         cmd_out(RET_COMMENT, "Billing ver %d.%d.%d.%d", VER_VER, VER_SUBVER, VER_REV, VER_SUBREV);
         cmd_out(RET_COMMENT, "loading configuration ...");
         conf_free();
         rc = conf_load(Config_path);
         if (rc < 0)
         {  cmd_out(ERR_IOERROR, "failure");
            exit(-1);
         }
         cmd_out(RET_COMMENT, "loading gates ...");
// ReLoad linktable
         rc = reslinks_load(LOCK_SH);
         if (rc != SUCCESS)
         {  cmd_out(ERR_IOERROR, "failure: %s", strerror(errno));
            exit(-1);
         }
// Open database
         cmd_out(RET_COMMENT, "opening accounts ...");
         rc = acc_baseopen(&Accbase, conf_accfile);
         if (rc < 0)
         {  syslog(LOG_ERR, "Can't reopen account database");
            cmd_out(ERR_IOERROR, "failure: %s", strerror(errno));
            exit(-1);
         }
         cmd_out(RET_COMMENT, "opening log ...");
         rc = log_baseopen(&Logbase, conf_logfile);
         if (rc < 0)
         {  syslog(LOG_ERR, "Can't reopen log database");
            cmd_out(ERR_IOERROR, "failure: %s", strerror(errno));
            exit(-1);
         }
         cmd_out(RET_COMMENT, "loading tariffs ...");
         rc = tariffs_load(conf_tariffile);
         if (rc < 0)
         {  syslog(LOG_ERR, "Can't reopen tariff database");
            cmd_out(ERR_IOERROR, "failure");
            exit(-1);
         }

         if (fSQL)
         {
            cmd_out(RET_COMMENT, "connecting SQL ...");
            rc = db2_open(DBdata, config.DBlogin, config.DBpass);
            if (rc < 0)
            {  syslog(LOG_ERR, "Can't reopen SQL connection");
               cmd_out(ERR_IOERROR, "FAILURE");
               exit(-1);
            }

/*
            if (ld->fStdio)
            {  row = dbex_search(DBdata, 0, "log_session");
               if (row == NULL || row[0] == NULL)
               {  cmd_out(ERR_SYSTEM, "Session open failure");
                exit(-1);
               }
               SessionId = strtoll(row[0], NULL, 10);
               if (SessionId < 1)
               {  cmd_out(ERR_SYSTEM, "Session open failure (invalid id returned)");
                  exit(-1);
               }
               cmd_out(RET_COMMENT, "Log session (id: %lld)", SessionId);

               SessionPerm  = PERM_SUPERUSER;
               strlcpy(SessionLogin, "admin", sizeof(SessionLogin));
               UserId = 1;
               cmd_out(RET_COMMENT, "Root autologin ...");
            }
*/
         } // if fSQL
         cmd_out(RET_SUCCESS, "Ready");
         while(1)
         {  rc = link_gets(ld, sbuf, sizeof(sbuf));
            if (rc == LINK_DOWN) break;
            if (rc == SUCCESS) 
            {  rc = cmd_exec(sbuf, NULL);
               if (rc == LINK_DOWN || rc == CMD_EXIT) break;
            }
         }
      }
   }

// Close SQL connection
   if (fSQL) db2_close(DBdata);

   acc_baseclose(&Accbase);
   log_baseclose(&Logbase);

   return 0;
}