/* File: cid11.c * Desc: A simple caller-ID log util * Auth: Woody * Note: GPL */ #define USE_SAY 1 //#define DO_HTML 1 #define DO_XDIALOG 1 #include #include #include #include #include #include #include #include #include #include //#include #include #define BAUDRATE B115200 //#define MODEMDEVICE "/dev/ttyS1" #define LOGFILE "/var/log/phone.log" #define LOCKFILE "/var/lock/cid..lck" #define _POSIX_SOURCE 1 /* POSIX compliant source */ #define MAX(a,b) ((a>b)?a:b) #define deb(x) x #define BUFFSIZE 256 extern int errno; char *mytime (); static int modem_fd = 0; static int log_fd = 0; /*********************************************************************/ void cleanup(void) { int n; //printf("wms: cleanup().\n"); n = open (LOCKFILE, O_RDONLY); if (n > 0) { close(n); unlink(LOCKFILE); } if (modem_fd) { close(modem_fd); modem_fd = 0; } if (log_fd) { close(log_fd); log_fd = 0; } } /*********************************************************************/ void sighandler(int n) { //printf("wms: sig handler, n=%d..\n",n); cleanup(); exit (0); } /*********************************************************************/ int main (argc, argv) char **argv; { int i; struct termios oldtio, newtio; char buff[BUFFSIZE]; char modemdevice[16]; char modeminit[64]; int buff_wait; /* DATE=0704 TIME=1556 NAME=O NMBR=O MESG=06014C:= */ char cid_date[8]; char cid_time[8]; char cid_name[16]; char cid_num[16]; int xterm_flag = 0; int quiet_flag = 0; int say_flag = 0; strcpy(modeminit,"AT#CID=1\r"); strcpy(modemdevice,"/dev/ttyS1"); if (argc) { for (i=1; i 0) { read(i, buff, BUFFSIZE); pidstr = strchr(buff,'.'); if (pidstr > 0) *pidstr = 0; //printf("wms: buff=%s.\n",buff); pidstr = strchr(buff,'='); //printf("wms: pidstr=%s.\n",pidstr+1); rc = sscanf (pidstr+1, "%d", &oldpid); //printf("wms: rc=%d, oldpid=%d.\n",rc, oldpid); fprintf(stderr, "CID taking over from: %s\n", buff); if (rc == 1) { kill (oldpid, SIGTERM); } close(i); unlink(LOCKFILE); } i = open (LOCKFILE, O_WRONLY | O_CREAT | O_EXCL); } sprintf (buff, "%s: pid = %d, device = %s.\n", argv[0], getpid(), modemdevice); write (i, buff, strlen(buff)); close (i); /* open the device to be non-blocking (read will return immediatly) */ modem_fd = open (modemdevice, O_RDWR | O_NOCTTY | O_NONBLOCK); if (modem_fd < 0) { fprintf(stderr,"Error openinng serial connection on %s.",modemdevice); cleanup(); exit (1); } /* print text of incoming call msg if in interactive mode * and inside an xterm. set xterm name as well... */ if (!quiet_flag && isatty(0)) /* if in interactive mode == foreground... */ { const char *term_type; term_type = getenv("TERM"); if (!strcmp(term_type,"xterm")) { fprintf(stderr, "\033]0;CallerID\007"); xterm_flag = 1; /* print text in the xterm window */ } } log_fd = open (LOGFILE, O_WRONLY | O_CREAT); if (log_fd < 0) { perror ("Open log file"); cleanup(); exit (1); } i = lseek(log_fd,0,SEEK_END); /* seek to the end == append */ tcgetattr (modem_fd, &oldtio); /* save current port settings */ /* set new port settings for non-canonical input processing */ memset (&newtio, 0, sizeof (newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNBRK | INPCK | ICRNL; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VMIN] = 1; // wait for up to 32 chars newtio.c_cc[VTIME] = 1; // * 100 ms tcflush (modem_fd, TCIOFLUSH); tcsetattr (modem_fd, TCSANOW, &newtio); buff_wait = 0; // write(modem_fd, "AT#CID=1\r", 9); write(modem_fd, modeminit, strlen(modeminit)); while (1) { struct timeval to; int I_rc; int maxfd; fd_set readfds; to.tv_sec = 0; to.tv_usec = 400000; FD_ZERO (&readfds); FD_SET (modem_fd, &readfds); maxfd = modem_fd + 1; if ((I_rc = select (maxfd, &readfds, 0, 0, &to)) < 0) { if (errno == EINTR) continue; /* We were interrupted by a signal... continue james... */ perror ("select"); cleanup(); exit (1); } else if (!I_rc) //no data within to.tv_sec sec { dump_data_now: if(buff_wait) { char* p; char* q; //printf("cid11:buff_wait=%d.\n",buff_wait); buff[buff_wait]=0; cid_date[0] = cid_time[0] = cid_name[0] = cid_num[0] = 0; /* search for string 'DATE=', 'NAME=' and 'MESG=' */ for (i=0; i= ' ') *q++=*p++; *q = 0; } else if (buff[i]=='T' && buff[i+1]=='I' && buff[i+2]=='M' && buff[i+3]=='E' && buff[i+4]=='=') { p = &buff[i+5]; q = &cid_time[0]; while (*p >= ' ') *q++=*p++; *q = 0; } else if (buff[i]=='N' && buff[i+1]=='A' && buff[i+2]=='M' && buff[i+3]=='E' && buff[i+4]=='=') { p = &buff[i+5]; q = &cid_name[0]; while (*p >= ' ') *q++=*p++; *q = 0; } else if (buff[i]=='N' && buff[i+1]=='M' && buff[i+2]=='B' && buff[i+3]=='R' && buff[i+4]=='=') { p = &buff[i+5]; q = &cid_num[0]; while (*p >= ' ') *q++=*p++; *q = 0; } /* handle the long distance calls... */ /* DATE=0704 TIME=1556 NAME=O NMBR=O MESG=06014C:= */ else if (buff[i]=='M' && buff[i+1]=='E' && buff[i+2]=='S' && buff[i+3]=='G' && buff[i+4]=='=') { if (cid_name[0] == 'O') strcpy(cid_name,"Out of Area"); if (cid_num[0] == 'O') strcpy(cid_num,"???"); } } if (cid_date[0] && cid_time[0]) { sprintf(buff,"DATE=%s TIME=%s NAME=%s NMBR=%s\n", cid_date, cid_time, cid_name, cid_num); if (xterm_flag) printf("%s",buff); write(log_fd, buff, strlen(buff)); fsync(log_fd); /* flush buff */ #ifdef DO_HTML system("/etc/ppp/phoned.sh"); #endif #ifdef DO_XDIALOG if (cid_name[0]) { /* prepare the Xdialog app string... */ sprintf(buff, "/usr/bin/Xdialog --title 'Caller ID' --no-button --infobox 'Name=%s #%s' 5 38 15000", cid_name, cid_num ); //printf("xdialog: %s.\n", buff); system(buff); } #endif #ifdef USE_SAY if (cid_name[0] && say_flag) { /* convert to lower case for the say app */ p = &cid_name[0]; while (*p) { *p = tolower(*p); p++; } /* prepare the say app string... */ sprintf(buff, "/usr/local/bin/say '%s' > /dev/null", cid_name); //printf("cid9: %s.\n", buff); system(buff); } #endif } buff_wait = 0; } continue; } else if (FD_ISSET (modem_fd, &readfds)) { /* get COM data */ //deb(printf("read(fd=%X,buff=%p,cnt=%d.\n",modem_fd,buff+buff_wait,BUFFSIZE-buff_wait)); i = read (modem_fd, buff+buff_wait, BUFFSIZE-buff_wait); if (i < 0) { perror ("bad com data link"); cleanup(); exit (1); } //deb(printf("got(%d)=%s",i,buff)); buff_wait += i; //so much data waiting... if (buff_wait == BUFFSIZE) goto dump_data_now; continue; } else { printf("select() assert! failure"); cleanup(); exit (1); } } }