/*
 *
 * description of data file
 *
 * N max_grp max_mem
 * G num yomi kanji
 * M num grp secret yomi kanji phone
 * #, balnk line : comment
 * delimiter is TAB
 */
#include "config.h"

#ifdef DEBUG
/*
#define DPRI(args...) fprintf(stderr, ## args)
*/
#define DPRI(a) fprintf a
#define DPRI1(a) fprintf(stderr, a)
#define DPRI2(a,b) fprintf(stderr, a,b)
#define DPRI3(a,b,c) fprintf(stderr, a,b,c)
#define DPRI4(a,b,c,d) fprintf(stderr, a,b,c,d)
#else
/*
#define DPRI(args...)
*/
#define DPRI(a)
#define DPRI1(a)
#define DPRI2(a,b)
#define DPRI3(a,b,c)
#define DPRI4(a,b,c,d)
#endif

#define MSG1(a) if (verbose) fprintf(stderr, a)
#define MSG2(a,b) if (verbose) fprintf(stderr, a,b)
#define MSG3(a,b,c) if (verbose) fprintf(stderr, a,b,c)

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>

#if USE_TERMIO
#include <termio.h>
#define TERMIO struct termio
#endif

#if USE_TERMIOS
#include <termios.h>
#define TERMIO struct termios
#endif

#if HPUX
#include <sys/modem.h>
#endif

#ifdef HAVE_STDARG_H
# include <stdarg.h>
# define Va_start(a,b) va_start(a,b)
#else
# include <varargs.h>
# define Va_start(a,b) va_start(a)
#endif

#include "switchopt2.h"

#ifndef DEVICE
#define DEVICE "/dev/ttyS0"
#endif

#define BUFSIZE 2048
#define NUM_LEN 25

#define KIND_NUM 1
#define KIND_506G	1

typedef struct stkind {
   char *str;
   int num;
} kind_t;

kind_t cel_kind[] =
{
   {"506g", KIND_506G},
};
int kind = 0;

typedef struct stceldb {
    char *id, *desc;
    int yomilen, kanjilen;
    int ignoregroup;
    int kanjicode;
} cel_db_t;

cel_db_t cel_db[] =
    {
	{"NSHPBD", "SH821i", 10, 16, 0, 0},
	{"NSHPA", "SH811", 6, 12, 0, 0},
	{"NMAPA", "P811", 10, 0, 1, 0},
	{"NMACC", "P651i", 10, 0, 0, 0},
	{"DKW94", "J-K31", 16, 16, 0, 0},
	{"DSOP1", "J-SY01", 0, 0, 0, 0x02},
	{NULL, NULL, 0, 0, 0, 0}
    };

#define MAX_GRP 50
#define MAX_MEM 1000
#define STRLEN 40

#define ID_CELRW "CELRWK"

#define MAX_BYTE 255
#define LEN_MEM_YOMI  MAX_BYTE
#define LEN_MEM_KANJI MAX_BYTE
#define LEN_GRP_YOMI  MAX_BYTE
#define LEN_GRP_KANJI MAX_BYTE

#define MODE_READ 0
#define MODE_STORE 1

#define EOL -1

/* 8 bit */
/* even parity, stop bit = 1 */
/* 600 bps */
#define CLEAR_BITS ~(CSIZE | PARODD | CSTOPB)
#define SET_BITS   (CS8 | PARENB)

#define UCHAR unsigned char

#define ALARMW set_action(); alarm(timeout); if (setjmp(jump_env) == 0)
#define ALARMWT(x) set_action(); alarm(x); if (setjmp(jump_env) == 0)
#define ELSE else

int timeout = 1;
jmp_buf jump_env;

char rcv_num_tbl[] = {'D', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		 '0', '*', '#', 'A', 'B', 'C'};
char rev_num_tbl[] = {0x0a, 0x01, 0x02, 0x03, 0x04, 0x05,
		       0x06, 0x07, 0x08, 0x09};

#define NUM_BAUD 4
int valid_baud[] = {600, 2400, 4800, 9600};


TERMIO pmode;
#if HPUX
mflag mmode;
#endif

int mfd;
int baud;
int force_baud = 0;
char *device = DEVICE;

static UCHAR buf[BUFSIZE];
static char dummy[MAX_BYTE];

/* counter for send memory */
int n_grp = 0;
int n_mem = 0;

int nogroup = 0; /* 1: Group is not supported */

int max_grp, max_mem;
int file_grp_num[MAX_GRP];
UCHAR file_grp_yomi[MAX_GRP][STRLEN];
UCHAR file_grp_kanji[MAX_GRP][STRLEN];

int secret;
int file_mem_num[MAX_MEM];
int file_mem_grp[MAX_MEM];
int file_mem_secret[MAX_MEM];
UCHAR file_mem_yomi[MAX_MEM][STRLEN];
UCHAR file_mem_kanji[MAX_MEM][STRLEN];
UCHAR file_mem_phone[MAX_MEM][STRLEN];

int read_grp_num = 0, read_mem_num = 0;
int read_line;

int verbose = 1;

int yomi_len = 0;
int kanji_len = 0;
int ignore_group = 0;
int kanjicode = 0;

#if PORTWAIT
#include <sys/time.h>

void mwait(msec)
int msec;
{
   struct timeval tv_;
   struct timezone tz_;
   double d1,d2,d3;
   double w = msec * 1000.;

   (void) gettimeofday(&tv_,&tz_);
   d1 = tv_.tv_sec;
   d2 = tv_.tv_usec;

   do{
      (void) gettimeofday(&tv_,&tz_);
      d3 = (double) (tv_.tv_sec - d1) * 1000000.
	 + (double) (tv_.tv_usec - d2);
   }while ( d3 < w );
}
#endif /* PORTWAIT */

void Tcgeta(fd,tios)
     int fd;
     TERMIO *tios;
{
#if USE_TERMIO
   if (ioctl(fd, TCGETA, tios) < 0)
#endif
#if USE_TERMIOS
   if (tcgetattr(fd, tios) < 0)
#endif
      {
	 perror("TCGETA");
	 exit(-1);
      }
}

void Tcseta(fd,tios)
     int fd;
     TERMIO *tios;
{
#if USE_TERMIO
   if (ioctl(fd, TCSETAF, tios)< 0)
#endif
#if USE_TERMIOS
   if (tcsetattr(fd, TCSAFLUSH, tios) < 0)
#endif
      {
	 perror("TCSETAF");
	 exit(1);
      }
}

void Tcsetaw(fd,tios)
     int fd;
     TERMIO *tios;
{
#if USE_TERMIO
   if (ioctl(fd, TCSETAW, tios)< 0)
#endif
#if USE_TERMIOS
   if (tcsetattr(fd, TCSADRAIN, tios) < 0)
#endif
      {
	 perror("TCSETAW");
	 exit(1);
      }
}

void Flush()
{
   Tcgeta(mfd, &pmode);
   Tcsetaw(mfd, &pmode);
}

void change_baud(b)
int b;
{
   Tcgeta(mfd,&pmode);

#if USE_TERMIO
   pmode.c_cflag &= ~CBAUD;
   pmode.c_cflag |= b;
#endif
#if USE_TERMIOS
   cfsetospeed(&pmode, b);
   cfsetispeed(&pmode, b);
#endif

   Tcseta(mfd, &pmode);
}

void OpenDevice()
{
   int temp;

#ifdef __OpenBSD__
   if ((mfd = open(device, O_RDWR)) < 0)
#else
   if ((mfd = open(device, O_RDWR | O_NDELAY)) < 0)
#endif
      {
	 perror("Can't open device");
	 exit(-1);
      }

#if HPUX
   if (ioctl(mfd, MCGETA, &mmode) == -1) {
      perror("MCGETA:");
      exit(1);
   }
   mmode |= (MDTR | MRTS);
   if (ioctl(mfd, MCSETAF, &mmode) == -1) {
      perror("MCSETAF:");
      exit(1);
   }
#endif

   Tcgeta(mfd, &pmode);

   pmode.c_cflag &= ~(HUPCL);
   pmode.c_cflag |= CLOCAL;
   pmode.c_iflag = IGNBRK ;
   pmode.c_oflag = pmode.c_lflag = 0;
   pmode.c_cc[VMIN] = 1;
   pmode.c_cc[VTIME] = 0;

   pmode.c_iflag &= ~(IXON | IXOFF | IXANY);
   /*
   pmode.c_iflag |= IXON | IXOFF | IXANY;
   */

   Tcseta(mfd, &pmode);

   temp = mfd;
#ifndef __OpenBSD__
   if ((mfd = open(device, O_RDWR)) < 0){
      perror("Can't open device part2 ");
      exit(-1);
   }
   close(temp);
#endif

   change_baud(B600);

   pmode.c_cflag &= CLEAR_BITS;
   pmode.c_cflag |= SET_BITS;

   Tcseta(mfd, &pmode);
}


void CloseDevice()
{
   Tcgeta(mfd, &pmode);

   pmode.c_cflag &= ~CLOCAL;
   pmode.c_cflag |= B0 | HUPCL;

   Tcseta(mfd, &pmode);

#if HPUX
   if (ioctl(mfd, MCGETA, &mmode) == -1) {
      perror("MCGETA:");
      exit(1);
   }
   mmode &= ~(MDTR | MRTS);
   if (ioctl(mfd, MCSETAF, &mmode) == -1) {
      perror("MCSETAF:");
      exit(1);
   }
#endif

   close(mfd);
}

void h_signal()
{
   signal(SIGINT, SIG_IGN);
   CloseDevice();
   (void) fprintf(stderr,"\n");
   exit(-1);
}


void change_baud_code(b)
int b;
{
   sleep(1);
   switch(b){
    case 7: /* 9600 */
    case 9600:
    case 5: /* 4800 */
    case 4800:
       DPRI1("** 9600 baud **\n");
       change_baud(B9600);
       break;
#if 0
       DPRI1("** 4800 baud **\n");
       change_baud(B4800);
       break;
#endif
    case 3: /* 2400 */
    case 2400:
       DPRI1("** 2400 baud **\n");
       change_baud(B2400);
       break;
    case 1: /* 600 */
    case 600:
       DPRI1("** 600 baud **\n");
       change_baud(B600);
       break;
    default: /* ??? */
       (void) fprintf(stderr,"code [%d] is unknown baud.\n",b);
       h_signal();
       break;
   }
}

int baud_code(b)
int b;
{
   int x;

   switch (baud) {
    case 600:
       x = 0x01;
       break;
    case 2400:
       x = 0x03;
       break;
    case 4800:
       x = 0x05;
       break;
    case 9600:
       x = 0x07;
       break;
   }
   return(x);
}

void error_line()
{
   (void) fprintf(stderr,"error: line %d.\n",read_line);
   exit(-1);
}

void file_get_token(fp,err)
FILE *fp;
int err;
{
   UCHAR *p,c;
   int done;

   /* skip TAB, comment, linefeed */
   done = 0;
   do {
      c = fgetc(fp);
      switch(c){
       case 0x09:
       case 0x0a:
       case 0x0d:
	  break;

#if 0
       case '#':
	  for(;fgetc(fp) != 0x0a && !feof(fp);) {
	     if (err && feof(fp)) {
		error_line();
	     }
	  }
	  break;
#endif

       default:
	  done = 1;
	  break;
      }
   } while(done == 0);

   p = buf;

   if (feof(fp)) {
      *p = '\0';
      return;
   }

   done = 0;
   /* get one token : delimiter=TAB, linefeed */
   do {
      *p++ = c;

      c = fgetc(fp);
      switch (c) {
       case 0x09:
	  done = 1;
	  break;

       case 0x0a:
       case 0x0d:
	  done = 1;
	  if (err == 1) {
	     error_line();
	  }
	  break;
      }

      if (err && feof(fp)) {
	 error_line();
      }
   } while(done == 0);

   *p = '\0';

   if(!strcmp((char *) buf,"*NONE*")){
      *buf = '\0';
   }
}

void read_file(fname)
char *fname;
{
   FILE *fp;

   if ((fp = fopen(fname,"r")) == NULL){
      (void) fprintf(stderr,"Can't open [%s].\n", fname);
      exit(1);
   }

   read_line = 0; /* line num */
   read_grp_num = 0;
   read_mem_num = 0;
   while (!feof(fp)){
      (void) file_get_token(fp,0); /* command , ignore error(EOF) */
      switch (buf[0]){
       case 'N': /* max nums */
	  file_get_token(fp,1); /* max group,with error */
	  (void) sscanf((char *) buf,"%d", &max_grp);
	  file_get_token(fp,2); /* max memory,with error */
	  (void) sscanf((char *) buf,"%d", &max_mem);
	  read_line++;
	  break;

       case 'G': /* group name */
	  file_get_token(fp,1); /* group num,with error */
	  (void) sscanf((char *) buf,"%d", &file_grp_num[read_grp_num]);
	  file_get_token(fp,1); /* yomi ,with error */
	  (void) strcpy((char *) file_grp_yomi[read_grp_num],(char *) buf);
	  file_get_token(fp,2); /* kanji ,with error */
	  (void) strcpy((char *) file_grp_kanji[read_grp_num],(char *) buf);

	  read_grp_num++;
	  read_line++;
	  break;

       case 'M': /* memory name */
	  file_get_token(fp,1); /* mamory num,with error */
	  (void) sscanf((char *) buf,"%d", &file_mem_num[read_mem_num]);
	  file_get_token(fp,1); /* group num,with error */
	  (void) sscanf((char *) buf,"%d", &file_mem_grp[read_mem_num]);
	  file_get_token(fp,1); /* secret */
	  (void) sscanf((char *) buf,"%d", &file_mem_secret[read_mem_num]);
	  file_get_token(fp,1); /* yomi ,with error */
	  (void) strcpy((char *) file_mem_yomi[read_mem_num],(char *) buf);
	  file_get_token(fp,1); /* kanji ,with error */
	  (void) strcpy((char *) file_mem_kanji[read_mem_num],(char *) buf);
	  file_get_token(fp,2); /* phone ,with error */
	  (void) strcpy((char *) file_mem_phone[read_mem_num], (char *) buf);

	  read_mem_num++;
	  read_line++;
	  break;
      }
   }

   (void) fclose(fp);
}

void RcvSwapNum(p, col, even)
UCHAR *p;
int col,even;
{
   UCHAR c1,c2;
   int i;

   DPRI1("RcvSwapNum:");
   for(i=0; i<col - 1; i++){
      if (read(mfd, &c1, 1) < 0) {
	 perror("RcvSwapNum:");
	 h_signal();
      }
      if (read(mfd, &c2, 1) < 0) {
	 perror("RcvSwapNum:");
	 h_signal();
      }
      DPRI3(" %02x %02x",c1,c2);
      *p++ = rcv_num_tbl[c2];
      *p++ = rcv_num_tbl[c1];
   }
   DPRI1("\n");
   *p = '\0';

   if (even) {
      --p;
      *p = '\0';
   }
}

void ReceiveMsg(n,d)
int n;
unsigned char d;
{
   unsigned char c = 0;
   int i=0;
   int ok = 0;

   DPRI1("recv:");
   while(ok == 0){
      if (read(mfd, &c, 1) < 0) {
	 perror("ReceiveMsg:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      (void) fflush(stdout);
      if (c == d) {
	 ok = 1;
      }
   }
   i++;

   while (i<n || n==0) {
      if (read(mfd, &c, 1) < 0) {
	 perror("ReceiveMsg:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      fflush(stdout);
      i++;
   }

   DPRI1("\n");
}

void RcvMsgMask(n,d,mask)
int n;
unsigned char d,mask;
{
   unsigned char c = 0;
   int i=0;
   int ok = 0;

   DPRI1("recv:");
   while(ok == 0){
      if (read(mfd, &c, 1) < 0) {
	 perror("ReceiveMsg:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      (void) fflush(stdout);
      if ((c & mask) == (d & mask)) {
	 ok = 1;
      }
   }
   i++;

   while (i<n || n==0) {
      if (read(mfd, &c, 1) < 0) {
	 perror("ReceiveMsg:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      fflush(stdout);
      i++;
   }

   DPRI1("\n");
}

void RcvBuf(n)
int n;
{
   UCHAR c = 0;
   int i=0;

   DPRI1("RcvBuf:");
   while ((i<n || n==0) && n < BUFSIZE) {
      if (read(mfd, &c, 1) < 0) {
	 perror("RcvBuf:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      buf[i] = c;
      i++;
   }
   DPRI1("\n");
}

void RcvBufVerify(n,d)
int n;
UCHAR d;
{
   UCHAR c = 0;
   int i=0;
   int ok = 0;

   DPRI1("RcvBufVerify:");
   while(ok == 0){
      if (read(mfd, &c, 1) < 0) {
	 perror("RcvBufVerify:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      (void) fflush(stdout);
      if (c == d) {
	 ok = 1;
      }
   }
   buf[i] = c;
   i++;

   while ((i<n || n==0) && n<BUFSIZE) {
      if (read(mfd, &c, 1) < 0) {
	 perror("RcvBufVerify:read");
	 h_signal();
      }
      DPRI2(" %02x",c);
      buf[i] = c;
      i++;
   }
   DPRI1("\n");
}

/*
 * received string = SJIS
 */
void RcvStr(n,str)
int n;
unsigned char *str;
{
   unsigned char c1 = 0, c2 = 0;
   unsigned char *p = str;
   int i=0;

   DPRI1("RecvStr:");

   while (i<n || n==0) {
      if (read(mfd, &c1, 1) < 0) {
	 perror("RcvStr:read");
	 h_signal();
      }
      if (read(mfd, &c2, 1) < 0) {
	 perror("RcvStr:read");
	 h_signal();
      }

      *p = (c1 << 4) | c2;
      i++;
      DPRI2("%02x ",*p);
      p++;
   }
   *p = '\0';

   DPRI1("\n");
}

int RcvShort()
{
   unsigned char c1 = 0, c2 = 0;
   int ret;

   if (read(mfd, &c1, 1) < 0) {
      perror("RcvShort:read");
      h_signal();
   }
   if (read(mfd, &c2, 1) < 0) {
      perror("RcvShort:read");
      h_signal();
   }

   DPRI3("RcvShort: %02x %02x\n",c1,c2);

   ret = (c1 << 8) + c2;

   return(ret);
}

int RcvByte()
{
   unsigned char c1 = 0, c2 = 0;
   int ret;

   if (read(mfd, &c1, 1) < 0) {
      perror("RcvByte:read");
      h_signal();
   }
   if (read(mfd, &c2, 1) < 0) {
      perror("RcvByte:read");
      h_signal();
   }

   DPRI3("RcvByte: %02x %02x\n",c1,c2);

   ret = (c1 << 4) + c2;

   return(ret);
}

int RcvNumber()
{
   unsigned char c1 = 0, c2 = 0;
   int ret;

   if (read(mfd, &c1, 1) < 0) {
      perror("RcvNumber:read");
      h_signal();
   }
   if (read(mfd, &c2, 1) < 0) {
      perror("RcvNumber:read");
      h_signal();
   }

   DPRI3("RcvNumber: %02x %02x\n",c1,c2);

   if (c1 == 0x08) {
      secret = 1;
   } else {
      secret = 0;
   }
   ret = c2 * 100 + RcvByte();

   return(ret);
}

int RcvStrLen(p)
UCHAR *p;
{
   int len;

   len = RcvByte();
   if (len) {
      RcvStr(len, p);
   } else {
#if 0
      *p = '\0';
#endif
      (void)strcpy((char *) p,"*NONE*");
   }

   return len;
}

void SendStrNum(s)
unsigned char *s;
{
   unsigned char *p;
   unsigned char c;

   DPRI1("sending ");
   p = s;
   while(*p != '\0') {
      if (*p < '0' && *p > '9') {
	 (void) fprintf(stderr, "SendStrNum:illegal char [%c]\n", *p);
	 h_signal();
      }
      c = rev_num_tbl[*p - '0'] + 0x90;
      if (write(mfd, &c , 1) < 0) {
	 perror("SendStrNum:write");
	 h_signal();
      }
      DPRI2("%02x ",c);
      p++;
   }
   DPRI1("\n");
}

void SendDial(s)
unsigned char *s;
{
   unsigned char c;

   SendStrNum(s);

   c = 0xaa;
   write(mfd, &c, 1);
   DPRI2("%02x : done\n",c);
}

void SendSwapNum(s,col)
UCHAR *s;
int col;
{
   UCHAR *p, *q;
   UCHAR c;
   int i;

   /* initialize */
   for(i=0; i<BUFSIZE; i++){
      buf[i] = 0;
   }

   /* swap */
   p = s;
   q = buf;
   while(*p != '\0') {
      *(q+1) = *p++;
      if (*p != '\0') {
	 *q = *p++;
      }
      q+=2;
   }

   DPRI1("sendSwapNum:");
   p = buf;
   i=0;
   for(i=0; i<col; i++){
      if (!((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'D') ||
	    (*p == '*') || (*p == '#') || (*p == '\0'))) {
	 (void) fprintf(stderr, "SendStrNum:illegal char [%c]\n", *p);
	 h_signal();
      }
      if (*p == '\0') {
	 c = 0;
      } else if (*p >= 'A' && *p <= 'C') {
	c = *p - 'A' + 0x0d;
      } else if (*p == 'D') {
	c = 0;
      } else if (*p == '#') {
	c = 0x0c;
      } else if (*p == '*') {
	c = 0x0b;
      } else {
	 c = rev_num_tbl[*p - '0'];
      }
      if (write(mfd, &c , 1) < 0) {
	 perror("SendSwapNum:write");
	 h_signal();
      }
      DPRI2("%02x ",c);
      p++;
   }
   DPRI1("\n");
}

void SendHex(h)
int h;
{
   unsigned char c;

   c = (unsigned char) h;

   if (write(mfd, &c , 1) < 0) {
      perror("SendHex:write");
      h_signal();
   }
   DPRI2("sendhex:%02x\n",c);
}

void SendShort(s)
unsigned short s;
{
   unsigned int i1, i2;
   unsigned char c1, c2;

   i1 = (s>>8) & 0xff;
   i2 = s & 0xff;
   c1 = (UCHAR) i1;
   c2 = (UCHAR) i2;

   if (write(mfd, &c1 , 1) < 0) {
      perror("SendShort:write");
      h_signal();
   }
   if (write(mfd, &c2 , 1) < 0) {
      perror("SendShort:write");
      h_signal();
   }
   DPRI3("SendShort :%02x %02x\n",c1,c2);
}

void SendByte(s)
UCHAR s;
{
   unsigned int i1, i2;
   unsigned char c1, c2;

   i1 = (s>>4) & 0xf;
   i2 = s & 0xf;
   c1 = (UCHAR) i1;
   c2 = (UCHAR) i2;

   if (write(mfd, &c1 , 1) < 0) {
      perror("SendByte:write");
      h_signal();
   }
   if (write(mfd, &c2 , 1) < 0) {
      perror("SendByte:write");
      h_signal();
   }
   DPRI3("SendByte :%02x %02x\n",c1,c2);
}

void SendNumber(n)
int n;
{
   int i1,i2;

   i1 = n / 100;
   i2 = n - i1*100;

   SendByte((UCHAR) i1);
   SendByte((UCHAR) i2);
}

void SendNumberSec(n,sec)
int n,sec;
{
   int i1,i2;

   i1 = n / 100;
   i2 = n - i1*100;

   SendHex((UCHAR) sec * 0x08);
   SendHex((UCHAR) i1);
   SendByte((UCHAR) i2);
}

void SendChar(c)
unsigned char c;
{
   unsigned char c1, c2;

   c1 = (c>>4) & 0xf;
   c2 = c & 0xf;

   if (write(mfd, &c1 , 1) < 0) {
      perror("SendChar:write");
      h_signal();
   }
   if (write(mfd, &c2 , 1) < 0) {
      perror("SendChar:write");
      h_signal();
   }
   DPRI3("SendChar :%02x %02x\n",c1,c2);
}

void SendStr(p)
unsigned char *p;
{
   SendByte(strlen((char *) p));

   while(*p != '\0'){
      SendChar(*p++);
   }
}

void SendStrN(p,len)
unsigned char *p;
int len;
{
    int n;

    if (len) {
	n = len;
    } else {
	n = strlen((char *) p);
    }
    DPRI3("SendStrN:%d,%d\n",len,n);
    SendByte(n);

    while(n--){
	SendChar(*p++);
    }
}

void SendStrNoLen(p)
unsigned char *p;
{
   /*
   SendByte(strlen((char *) p));
   */

   while(*p != '\0'){
      SendChar(*p++);
   }
}

#ifdef HAVE_STDARG_H
void VaSendHex(int h, ...)
#else
void VaSendHex(va_alist)
va_dcl
#endif
{
   va_list ap;
   unsigned char c;
#ifdef HAVE_STDARG_H
   Va_start(ap, h);
#else
   int h;
   Va_start(ap, h);
   h = (int) va_arg(ap, long);
#endif

   DPRI1("VaSendHex:");
   while (h != (int) EOL) {
      c = (unsigned char) h;

      if (write(mfd, &c , 1) < 0) {
	 perror("VaSendHex:write");
	 h_signal();
      }
      DPRI2(" %02x",c);

      h = (int) va_arg(ap, long);
   }

   va_end(ap);
   DPRI1("\n");
}

#ifdef HAVE_STDARG_H
int VaCompMsg(int n, ...)
#else
int VaCompMsg(va_alist)
va_dcl
#endif
{
   va_list ap;
   unsigned char c,d;
   int ret = 1;
   int i = 0;

#ifdef HAVE_STDARG_H
   Va_start(ap, n);
#else
   int n;
   Va_start(ap, n);
   n = (int) va_arg(ap, long);
#endif

   DPRI1("VaCompMsg:");

   while (i < n) {
      if (read(mfd, &c, 1) < 0) {
	 perror("VaCompMsg:read");
	 h_signal();
      }
      d = (unsigned char) va_arg(ap, long);
      DPRI3(" read[%02x]=%02x?", c, d);

      if (c != d) {
	 ret = 0;
      }
      i++;
   }

   va_end(ap);
   DPRI1("\n");

   return(ret);
}

void SendPasswdSuccess()
{
   VaSendHex(0x6c, 0x03, EOL);
}

void SendMaxGroup(cmd, max_mem, max_grp)
int cmd, max_mem, max_grp;
{
   DPRI1("SendMaxGroup\n");
   VaSendHex(cmd, 0x0d, 0x00, 0x02, EOL);
   /*
    * 00 00 : NO YOMI & KANJI
    * 00 01 : YOMI ONLY
    * 00 02 : KANJI ONLY
    * 00 03 : YOMI & KANJI
    */
   VaSendHex(0x00, 0x07, EOL);
   SendNumber(max_mem); /* max memory */

   VaSendHex(0x00, 0x07, EOL);   /* enable kanji */
   SendByte(LEN_MEM_YOMI);
   SendByte(LEN_MEM_KANJI);

   SendByte(max_grp); /* max group */
   SendByte(LEN_GRP_YOMI);
   SendByte(LEN_GRP_KANJI);

   SendStrNoLen(ID_CELRW);
   VaSendHex(0x00, 0x00, 0x00, 0x00, EOL);
}

void SendGroupName(num, yomi, kanji)
int num;
UCHAR *yomi, *kanji;
{
   MSG2("sending group #%d\n",num);

   VaSendHex(0x6c, 0x0a, EOL);
   SendByte(num);
   VaSendHex(0x00, 0x01, EOL);
   SendStr(yomi);

   VaSendHex(0x00, 0x03, EOL);
   SendStr(kanji);
}

void SendMemory(num, grp, sec, yomi, kanji, phone)
int num,grp,sec;
UCHAR *yomi, *kanji, *phone;
{
   int col;
   int i,j;

   MSG2("sending memory #%d\n",num);
   DPRI4("%s %s %s\n", yomi, kanji, phone);

   /*
    * send memory dial
    */
   if (*phone) {
      VaSendHex(0x6c, 0x06, EOL);
      SendNumberSec(num,sec);
      VaSendHex(0x00, 0x01, EOL);
      if (*yomi) {
	  DPRI3("yomi_len=%d len=%d\n", yomi_len, strlen(yomi));
	  if (yomi_len && (strlen(yomi)>yomi_len)) {
	      SendStrN(yomi,yomi_len);
	  } else {
	      SendStr(yomi);
	  }
      } else {
	 VaSendHex(0x00, 0x00, EOL);
      }

      col = strlen((char *) phone);
      i = (col + 1) / 2 +1;
      j = (i-1)*2 - col;
      SendShort((unsigned short)i);
      if (col) {
	 SendHex(j*8);
	 SendHex(0x00);

	 SendSwapNum(phone,(i-1)*2);
      }
      SendByte(grp);

      if (kanjicode) {
	  VaSendHex(0x00, kanjicode, EOL);
      } else {
	  VaSendHex(0x00, 0x03, EOL);
      }

      if (*kanji) {
	  if (kanji_len && (strlen(kanji) > kanji_len)) {
	      SendStrN(kanji, kanji_len);
	  } else {
	      SendStr(kanji);
	  }
      } else {
	 VaSendHex(0x00, 0x00, EOL);
      }
   }
}

void SendEndOfGroup()
{
   VaSendHex(0x6c, 0x0c, EOL);
}

int SendOneGroup()
{
   int ret = 0;

   /* skip no_data area */
   while(n_grp<read_grp_num &&
	 *file_grp_yomi[n_grp] == 0 &&
	 *file_grp_kanji[n_grp] == 0
	 ) {
      n_grp++;
   }
   if (n_grp < read_grp_num) {
      SendGroupName(file_grp_num[n_grp],file_grp_yomi[n_grp],file_grp_kanji[n_grp]);
      n_grp++;
   } else {
      SendEndOfGroup();
      ret = 1;
   }

   return ret;
}

#if 0
void SendMultiGroup()
{
   int i;

   DPRI1("***** send multiple group\n");

   for(i=0; i<read_grp_num; i++){
      SendGroupName(file_grp_num[i],file_grp_yomi[i],file_grp_kanji[i]);

      if (*file_grp_kanji[i]) {
	 /* recv 64 07 : more group*/
#if 0
	 ReceiveMsg(2, 0x64);
#endif
	 RcvBuf(2);
      }
   }
}

void SendMultiMem()
{
   int i;

   DPRI1("***** send multiple memory\n");

   for(i=0; i<read_mem_num; i++){
      SendMemory(file_mem_num[i],file_mem_grp[i],
		     file_mem_secret[i],
		     file_mem_yomi[i],file_mem_kanji[i],
		     file_mem_phone[i]);

      if (*file_mem_phone[i]) {
      /* recv 64 06 : more memory*/
      ReceiveMsg(2, 0x64);
      }
   }

   /*
    * send 6c 08 : finish copying
    */
   VaSendHex(0x6c, 0x08, EOL);
}
#endif

void SendEndOfMemory()
{
   VaSendHex(0x6c, 0x08, EOL);
}

int SendOneMemory()
{
   int ret = 0;

   /* skip no_data area */
   while(n_mem<read_mem_num &&
	 *file_mem_phone[n_mem] == 0) {
      n_mem++;
   }

   if (n_mem < read_mem_num) {
      SendMemory(file_mem_num[n_mem],file_mem_grp[n_mem],
		 file_mem_secret[n_mem],
		 file_mem_yomi[n_mem],file_mem_kanji[n_mem],
		 file_mem_phone[n_mem]);
      n_mem++;
   } else {
      SendEndOfMemory();
      ret = 1;
   }

   return ret;
}

#ifdef HAVE_STDARG_H
void SendAck(int h, ...)
#else
void SendAck(va_alist)
va_dcl
#endif
{
   va_list ap;
   unsigned char c;
   static UCHAR sendbuf[BUFSIZE];
   int i = 0, j , differ;
   UCHAR *p, *q;
#ifdef HAVE_STDARG_H
   Va_start(ap, h);
#else
   int h;
   Va_start(ap, h);
   h = (int) va_arg(ap, long);
#endif

   q = sendbuf;

   DPRI1("SendAck:");
   while (h != (int) EOL) {
      c = (unsigned char) h;
      *q++ = c;
      i++;

      if (write(mfd, &c , 1) < 0) {
	 perror("SendAck:write");
	 h_signal();
      }
      DPRI2(" %02x",c);

      h = (int) va_arg(ap, long);
   }

   va_end(ap);
   DPRI1("\n");

   RcvBuf(i);

   differ = 0;
   DPRI1("Verify :");
   for(j=1, p=buf+1, q=sendbuf+1; j<i; j++, p++, q++){
      DPRI2(" %02x",*p);
      if (*p != *q) {
	 differ = 1;
      }
   }
   DPRI1("\n");
   if (differ) {
      (void) fprintf(stderr,"Ack Error!\n");
      h_signal();
   }
}

void parse_id(id)
     char *id;
{
    cel_db_t *p;

    p = cel_db;
    while(p->id) {
	if (!strncmp(id, p->id, strlen(p->id))) {
	    DPRI2("Identified: %s\n", p->desc);
	    if (!yomi_len) {
		yomi_len = p->yomilen;
	    }
	    if (!kanji_len) {
		kanji_len = p->kanjilen;
	    }
	    if (!ignore_group) {
		ignore_group = p->ignoregroup;
	    }
	    kanjicode = p->kanjicode;
	}
	p++;
    }
}

void GetMaxNum(cmd,num,grp)
int cmd;
int *num, *grp;
{
   int flag;
   int len_yomi, len_kanji;

   DPRI1("GetMaxNum\n");
   ReceiveMsg(4,cmd);
   flag = RcvShort();
#ifdef DEBUG
   if (flag & 0x0001) {
      (void) fprintf(stderr,"YOMI enabled\n");
   }
   if (flag & 0x0002) {
      (void) fprintf(stderr,"KANJI enabled\n");
   }
#endif
   *num = RcvNumber();

   flag = RcvShort();
   len_yomi = RcvShort();
   len_kanji = RcvShort();
   DPRI3("mem: len #yomi=%d #kanji=%d\n", len_yomi, len_kanji);

   if (!yomi_len) {
       yomi_len = len_yomi;
   }

   if (!len_kanji) {
       kanji_len = len_kanji;
   }

   *grp = RcvByte();
   len_yomi = RcvShort();
   len_kanji = RcvShort();
   DPRI3("grp: len #yomi=%d #kanji=%d\n", len_yomi, len_kanji);

   RcvStr(6, dummy);
   RcvBuf(4);

   DPRI2("str=[%s]\n",
		  dummy);

   parse_id(dummy);
}


int GetGroup()
{
   static char kana[MAX_BYTE], kanji[MAX_BYTE];
   int grp_num;
   int len;

   /*
    * send 64 07 : get group
    * result
    * 6c 0a : group exists
    * 6c 0c : group end
    */
   VaSendHex(0x64, 0x07, EOL);

#if PORTWAIT
   mwait(400);
#endif
   if (VaCompMsg(2,0x6c,0x0c)) {
      DPRI1("***** group end.\n");
      return 0;
   }

   grp_num = RcvByte();
   DPRI2("* group number:%d\n",grp_num);
   MSG2("getting group #%d\n",grp_num);

   ReceiveMsg(2,0x00);
   len = RcvStrLen(kana);
   DPRI2("kana=[%s]\n",kana);

   ReceiveMsg(2,0x00);
   len += RcvStrLen(kanji);
   DPRI2("kanji=[%s]\n",kanji);

   if (len) {
      (void) printf("G\t%d\t%s\t%s\n",
		    grp_num, kana, kanji);
   }

   return 1;
}


int GetMemory()
{
   static char kana[MAX_BYTE], kanji[MAX_BYTE], phone[MAX_BYTE];
   int grp_num;
   int mem_num;
   int col,even;

   /*
    * send 64 06 : read memory dial
    */
   VaSendHex(0x64, 0x06, EOL);

#if PORTWAIT
   mwait(600);
#endif
   /*
    * 6c 06 : memory exists
    * 6c 08 : memory end
    */
   if (VaCompMsg(2,0x6c,0x08)) {
      DPRI1("***** memory end.\n");
      return 0;
   }

   mem_num = RcvNumber();
   DPRI3("* memory number:%d secret=%d\n",mem_num,secret);
   MSG2("getting memory #%d\n",mem_num);

   ReceiveMsg(2, 0x00);

   RcvStrLen(kana);
   DPRI2("furigana=[%s]\n",kana);

   col = RcvShort();
   if (col) {
      RcvBuf(2);
      even = buf[0];

      RcvSwapNum(phone, col, even);
      DPRI2("phone=[%s]\n",phone);
   } else {
      (void) strcpy(phone, "*NONE*");
   }

   if (!nogroup) {
      grp_num = RcvByte();
      DPRI2("group number:%d\n",grp_num);

      ReceiveMsg(2, 0x00);
      RcvStrLen(kanji);
      DPRI2("kanji=[%s]\n",kanji);
   } else {
       RcvBuf(2);
       (void) strcpy(kanji, "*NONE*");
   }

   if (col) {
      (void) printf("M\t%d\t%d\t%d\t%s\t%s\t%s\n",
		    mem_num,grp_num,secret, kana, kanji, phone);
   }

   return 1;
}

void RecvAck6c()
{
}

void RecvAck64()
{
   static UCHAR ackbuf[BUFSIZE];
   int i = 0;

   RcvBuf(1);
   switch(buf[0]){
    case 0x01:
       switch (kind) {
	case KIND_506G:
	   sleep(1);
	   break;
       }
       VaSendHex(0x6c, buf[0], EOL);
       break;

    case 0x02:
    case 0x0e:
       ackbuf[i++] = buf[0];
       RcvBuf(1);
       VaSendHex(0x6c, ackbuf[0], buf[0], EOL);
       break;
   }
}

void cb_timeout(sig)
int sig;
{
   /*
   signal(sig,SIG_IGN);
   */

   (void) fprintf(stderr,"alarm catch\n");

   longjmp(jump_env,1);
}

void set_action()
{
#ifdef HAVE_SIGACTION
   struct sigaction new_action;

   new_action.sa_handler = cb_timeout;
   sigemptyset (&new_action.sa_mask);
   new_action.sa_flags = SA_NODEFER;

   (void) sigaction(SIGALRM, &new_action, NULL);
#else
   signal(SIGALRM,cb_timeout);
#endif
}

void ign_action()
{
#ifdef HAVE_SIGACTIOON
   struct sigaction new_action;

   new_action.sa_handler = SIG_IGN;
   sigemptyset (&new_action.sa_mask);
   new_action.sa_flags = SA_NODEFER;

   (void) sigaction(SIGALRM, &new_action, NULL);
#else
   signal(SIGALRM,SIG_IGN);
#endif
}

void RecvAck()
{
   int done = 0;

   while(!done){
      RcvBuf(1);
      switch(buf[0]){
       case 0x6c: /* extend mode 1 */
	  RecvAck6c();
	  done=1;
	  break;
       case 0x64: /* extend mode 2 */
	  RecvAck64();
	  done=1;
	  break;
       case 0x60:
	  ign_action();
	  VaSendHex(0x61, EOL);
	  SendStrNoLen(ID_CELRW);
	  SendStrNoLen("          ");
	  RcvBuf(2); /* 64 08 */
	  VaSendHex(0x6c, 0x0b, 0x00, 0x00, EOL);
	  RcvBuf(4); /* 6c 0c 64 05 */
	  VaSendHex(0x6c, 0x05, 0x00, 0x03, 0x00, 0x00, EOL);

	  nogroup=1;
	  done=1;
	  break;
      }
   }
}

int SendMemoryAck(code)
     int code;
{
    int ret = 1;
    unsigned char c;

    if (read(mfd, &c, 1) < 0) {
	perror("SendMemoryAck:read");
	h_signal();
    }
    if (c != 0x64) {
	ret = 0;
    }
    DPRI((stderr, "required:64, received:%02x\n", c));

    if (read(mfd, &c, 1) < 0) {
	perror("SendMemoryAck:read");
	h_signal();
    }
    if (c != code && c != 0x0b && c != 0x00) { /* ok nor incomplete */
	ret = 0;
    }
    DPRI3("required:%02x, received:%02x\n", code, c);

    return(ret);
}

void StoreCellular()
{
   int temp_mem = 999, temp_grp = 99;
   int x;
   int eog;

   MSG1("establishing connection ...");
   /* make connection */
   SendHex(0xa8);
   sleep(2);
   SendHex(0xa8);

#if PORTWAIT
   mwait(200);
#endif
   /* recv 64 01 */
   /* send 6c 01 */
   RecvAck();
   MSG1("done\n");

   sleep(2);

#if 0
   /* recv a3: request passcode */
   switch (kind) {
    case KIND_506G:
       /* recv 64 01 */
       ReceiveMsg(2,0x64);
       break;
    default:
       RcvMsgMask(1,0xa3,0x7f);
       break;
   }
#else
   ALARMW {
       RcvMsgMask(1,0xa3,0x7f);
   }
#endif

   /* enter passcode on cellular */
   (void) fprintf(stderr,"Input your pass code into cellular\n");

   /*
   sleep(2);
   */
   /* recv 64 02 xx: set baud rate */
   /* send 6c 02 xx: set baud rate */
   RcvBufVerify(3,0x64);

   /* request speed */
   if (force_baud) {
      x = baud_code(baud);
   } else {
      x = buf[2];
   }
   VaSendHex(0x6c, 0x02, x, EOL);

   /* change baud */
   change_baud_code(x);

   /* any 4 digit */
   (void) fprintf(stderr,"Input any 4 digit into cellular\n");

   /* recv: 64 03 9a 9a 9a 9a 64 04 */
   RcvBuf(8);

   /* send: 6c 03 */
   SendPasswdSuccess();

   /* recv 64 0e 02 & ack*/
   /* send 6c 0e 02 */
   ALARMW {
       RecvAck();
   } ELSE {
       ALARMW {
	   /* for HD-50S */
	   VaSendHex(0x64, 0x0e, 0x03, 0x01, 0x00, EOL);
	   ReceiveMsg(5,0x6c);
       } ELSE {
	   /* for J-PE02 */
	   RecvAck();
       }
   }

   /* send max grp and num */

   if (!nogroup) {
   /* group num and memory num to send are identical with that of read */
   ALARMW {
      GetMaxNum(0x64, &temp_mem, &temp_grp);
      SendMaxGroup(0x6c, temp_mem, temp_grp);
   }
   ign_action();

   DPRI3("cel: grp=%d, mem=%d\n", temp_grp, temp_mem);

#if 0
   /* recv 64 07 */
   RcvBuf(2);
   /* send group name */
   SendMultiGroup();
   SendEndOfGroup();
#else
   if (!ignore_group) {
   /* send multiple group */
   eog = 0;
   while(eog == 0){
      /* 64 07 : get group */
      if (!SendMemoryAck(0x07)) {
	 eog=1;
      } else {
	 eog = SendOneGroup();
      }
   }
   } else {
   /* recv 64 07 */
   RcvBuf(2);
   SendEndOfGroup();
   }
#endif
   }

#if 0
   /* send memory */
   /* recv: 64 06 */
   RcvBuf(2);
   SendMultiMem();
#else
   /* send multiple memory */
   eog = 0;
   while(eog == 0){
      /* 64 06 : get memory */
      if (!SendMemoryAck(0x06)) {
	 eog=1;
      } else {
	 eog = SendOneMemory();
      }
   }
#endif

   sleep(2);
   /* memory copy done */
   VaSendHex(0xa8, EOL);

   (void) fprintf(stderr,"send memory done.\n");
}

void ReadCellular(passwd)
char *passwd;
{
   int x;

   /* establish connection */
   MSG1("establishing connection ...");
   SendHex(0xa8);
   sleep(2);
   SendHex(0xa8);

   /* recv 64 01 */
   ReceiveMsg(2,0x64);
   MSG1("done\n");

   /* send 6c 01 */
   VaSendHex(0x6c, 0x01, EOL);
   /*
   sleep(2);
   */
#if 0
   /* recv a3: request passcode */
   switch (kind) {
    case KIND_506G:
       /* recv 64 01 */
       ReceiveMsg(2,0x64);
       break;
    default:
       RcvMsgMask(1,0xa3,0x7f);
       break;
   }
#else
   ALARMW {
       RcvMsgMask(1,0xa3,0x7f);
   }
#endif

   sleep(2);


   /* request speed */
   /* send 64 02 xx */
   /* recv 6c 02 xx */

   x = baud_code(baud);
   VaSendHex(0x64, 0x02, x, EOL);
#if PORTWAIT
   mwait(200);
#endif
   RcvBufVerify(3,0x6c);

   /* change baud */
   change_baud_code(buf[2]);

   sleep(2);

   /* send passwd  */
   MSG1("sending password\n");
   VaSendHex(0x64, 0x03, EOL);
   SendStrNum(passwd);
   VaSendHex(0x64, 0x04, EOL);

#if PORTWAIT
   mwait(200);
#endif

   /*
    * recv 6c 03 => success
    * recv 6c 04 => fail
    */
   if (VaCompMsg(2,0x6c,0x03)) {
      (void) fprintf(stderr,"passwd OK\n");
   } else {
      (void) fprintf(stderr,"invalid passwd\n");
      h_signal();
   }


   /*
    * read group
    * send 64 0e 02
    * recv 6c 0e 02
    */
   VaSendHex(0x64, 0x0e, 0x02, EOL);
#if PORTWAIT
   mwait(200);
#endif
   /* for HD-50S hack */
   ALARMW {
      /* for HD-50S hack */
      /*
      ReceiveMsg(3,0x6c);
      */
      RcvBuf(1);
      switch(buf[0]){
       case 0x6c:
	  RcvBuf(2);
	  break;
       case 0x64:
	  /* for HD-50S */
	  RcvBuf(4);
	  VaSendHex(0x6c, buf[0], buf[1], buf[2], buf[3], EOL);
	  break;
      }
   } ELSE {
      /* DP144 */
      VaSendHex(0x60, EOL);
      RcvBuf(1);
      RcvStr(8, dummy);
      DPRI((stderr,"str=[%s]\n",dummy));
      ALARMW {
	  RcvStr(8, dummy);
	  DPRI((stderr,"additional str=[%s]\n",dummy));
      } ELSE {
      }
      VaSendHex(0x64, 0x08, EOL);
      RcvBuf(4); /* 6c 0b 00 00 */
      VaSendHex(0x6c, 0x0c, 0x64, 0x05, EOL);
      RcvBuf(6); /* 6c 05 00 03 00 00 */

      nogroup = 1;
   }

   /*
    * send max group num
    * send 64 0d
    */
   SendMaxGroup(0x64, 999, 99);
#if PORTWAIT
   mwait(1000);
#endif

   ALARMW {
      GetMaxNum(0x6c, &max_mem, &max_grp);
      DPRI3("max_mem=%d max_grp=%d\n",
	    max_mem, max_grp);
   } ELSE {
      max_mem = 999;
      max_grp = 99;
   }
   ign_action();
   (void) printf("N\t%d\t%d\n",
		 max_mem, max_grp);

   /* get groups */
   if (!nogroup) {
      while(GetGroup());
   }

   /* get memory */
   while(GetMemory());
}

UCHAR *input_passwd()
{
   TERMIO sg0, sg1;
   int i;
   UCHAR c;
   static UCHAR b[10];

   Tcgeta(0, &sg0);
   Tcgeta(0, &sg1);

   sg1.c_lflag &= ~(ECHO|ICANON);
   sg1.c_lflag |= ISIG;

   Tcseta(0, &sg1);

   (void) fprintf(stderr,"input passwd : ");
   (void) fflush(stderr);

   for(i=0; i<4; i++){
      c = (UCHAR) getchar();
      (void) fprintf(stderr,"*");
      (void) fflush(stderr);
      b[i] = c;
   }
   b[4] = '\0';
   (void) fprintf(stderr,"\n");

   Tcseta(0, &sg0);

   return(b);
}

void ListKind()
{
   int i;

   (void) fprintf(stderr,"Supported non-generic cellulars are:\n");
   for(i=0; i<KIND_NUM; i++){
      (void) fprintf(stderr,"\t%s\n",cel_kind[i].str);
   }
}

void Usage(name)
     char *name;
{
   (void) fprintf(stderr,"\n\
usage:\n\
%s [-s file][-b baud][-d dev][-k kind][-p][-num password][-v][-help]\n\
\n\
	-s file : store file data to cellular [default is read]\n\
        -b baud : baud rate (600,2400,9600) [default:9600 bps]\n\
        -d dev  : serial device [default: /dev/ttyS0]\n\
	-k kind : kind of cellular\n\
	-p      : use default password\n\
	-num pw : password for cellular [NOT RECOMMEND]\n\
	-yomilen len : restrict yomi length\n\
	-kanjilen len : restrict kanji length\n\
	-nogroup: don't write group data\n\
	-v	: display version\n\
	-V	: not verbose\n\
	-help	: display this message\n\
\n\
",name);

   ListKind();
}

void SwitchMode(mode,passwd)
     int mode;
     UCHAR *passwd;
{
   switch (mode) {
    case MODE_STORE:
       if (read_mem_num == 0) {
	  (void) fprintf(stderr, "You must read file.\n");
	  exit(-1);
       }
       StoreCellular();
       break;
    case MODE_READ:
       if (passwd == NULL) {
	  passwd = input_passwd();
       }
       ReadCellular(passwd);
       break;
   }
}

#ifndef EXP
#define EXP
#else
#include "exp.c"
#endif

int main(argc,argv)
int argc;
char **argv;
{
   int mode;
   UCHAR *passwd = NULL;
   char *appname = argv[0];
   int i;
   int valid;

   signal(SIGINT, h_signal);

   mode = MODE_READ;
   baud = 9600;

   /***** analyze command line *****/
   SWITCH_OPT
      EXP
   CASE_OPT("-s"){
      mode = MODE_STORE;
      ADVANCE_OPT;
      read_file(CURRENT_OPT);
   }
   CASE_OPT("-d"){
      ADVANCE_OPT;
      device = CURRENT_OPT;
   }
   CASE_OPT("-num"){
      ADVANCE_OPT;
      passwd = (UCHAR *) CURRENT_OPT;
   }
   CASE_OPT("-yomilen"){
      ADVANCE_OPT;
      (void) sscanf(CURRENT_OPT, "%d", &yomi_len);
   }
   CASE_OPT("-kanjilen"){
      ADVANCE_OPT;
      (void) sscanf(CURRENT_OPT, "%d", &kanji_len);
   }
   CASE_OPT("-nogroup"){
       ignore_group = 1;
   }
   CASE_OPT("-p"){
      passwd = (UCHAR *) PASSCODE;
   }
   CASE_OPT("-kanjicode"){
      ADVANCE_OPT;
      (void) sscanf(CURRENT_OPT, "%d", &kanjicode);
   }
   CASE_OPT("-k"){
      ADVANCE_OPT;
      for(i=0; i<KIND_NUM; i++){
	 if (!strcmp(CURRENT_OPT, cel_kind[i].str)){
	    kind = cel_kind[i].num;
	 }
      }
      if (kind == 0) {
	 (void) fprintf(stderr,"Unknown kind of cellular [%s].\n",
			CURRENT_OPT);
	 ListKind();
	 exit(-1);
      }
   }
   CASE_OPT("-b"){
      ADVANCE_OPT;
      (void) sscanf(CURRENT_OPT, "%d", &baud);
      force_baud = baud;
      valid = 0;
      for(i=0; i<NUM_BAUD; i++){
	 if (valid_baud[i] == baud) {
	    valid = 1;
	 }
      }
      if (!valid) {
	 (void) fprintf(stderr,"Invalid baud rate %d.\n", baud);
	 (void) fprintf(stderr,"Valid baud rates are\n");
	 for(i=0; i<NUM_BAUD; i++){
	    (void) fprintf(stderr,"%d, ", valid_baud[i]);
	 }
	 (void) fprintf(stderr,"\n");
	 exit(1);
      }
   }
   CASE_OPT("-v"){
      (void) fprintf(stderr,"%s version %s\n",
		     appname,VERSION);
      exit(0);
   }
   CASE_OPT("-V"){
      verbose = 0;
   }
   ELSE_OPT {
      Usage(appname);
      exit(1);
   }
   END_OPT;

   OpenDevice();

   SwitchMode(mode,passwd);

   /* reset DoCoMo */
   VaSendHex (0x1f, 0x07, 0x0d, EOL);

   CloseDevice();

   return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1