X-Git-Url: http://dolda2000.com/gitweb/?p=utils.git;a=blobdiff_plain;f=cidd.c;fp=cidd.c;h=be2e9e736f61c51ab958e7188b9607b3d642119e;hp=0000000000000000000000000000000000000000;hb=1c2fdcc245551183bbddfaa80bd9328062fc4ed1;hpb=5011fbe0143d3a9961cd31b8fe39783d9abe9714 diff --git a/cidd.c b/cidd.c new file mode 100644 index 0000000..be2e9e7 --- /dev/null +++ b/cidd.c @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODEM_DEV "/dev/modem" +#define PIDFILE "/var/run/cidd.pid" +#define PORT 5001 + +int mdm, sock; +int ibuflen = 0; +unsigned char ibuf[1024]; +unsigned char tmpbuf[1024]; +fd_set cfds; +int isdaemon; + +void write2(int fd, unsigned char *buf, int len) +{ + int ret; + + while(len) + { + ret = write(fd, buf, len); + if(ret < 0) + { + perror("write"); + exit(1); + } + buf += ret; + len -= ret; + } +} + +void sendcmd(unsigned char *cmd) +{ + unsigned char *lbuf; + + lbuf = strcpy(malloc(strlen(cmd) + 3), cmd); + strcat(lbuf, "\r\n"); + write2(mdm, lbuf, strlen(cmd) + 2); + free(lbuf); +} + +unsigned char *getline(int block) +{ + int i; + unsigned char *p; + int ret, len; + static unsigned char retbuf[1024]; + struct pollfd pf; + + while(1) + { + while((p = memchr(ibuf, '\r', ibuflen)) != NULL) + { + memcpy(retbuf, ibuf, len = (p - ibuf)); + retbuf[len] = 0; + memmove(ibuf, p + 1, ibuflen -= (len + 1)); + for(p = retbuf; *p; p++) + { + while(*p == '\n') + memmove(p, p + 1, len--); + } + if(len && (memcmp(retbuf, "AT", 2))) + return(retbuf); + } + if(!block) + { + pf.fd = mdm; + pf.events = POLLIN; + pf.revents = 0; + if(poll(&pf, 1, 0) == 0) + return(NULL); + } + ret = read(mdm, ibuf + ibuflen, 1024 - ibuflen); + if(ret < 0) + { + perror("read"); + exit(1); + } + ibuflen += ret; + } +} + +void broadcast(unsigned char *buf, ...) +{ + int i; + va_list args; + + va_start(args, buf); + vsprintf(tmpbuf, buf, args); + va_end(args); + strcat(tmpbuf, "\n"); + for(i = 0; i < FD_SETSIZE; i++) + { + if(FD_ISSET(i, &cfds) && (i != mdm) && (i != sock)) + write2(i, tmpbuf, strlen(tmpbuf)); + } +} + +void initmodem(void) +{ + sendcmd("ATZ"); + if(strcmp(getline(1), "OK")) + { + if(isdaemon) + syslog(LOG_CRIT, "Could not reset modem"); + else + fprintf(stderr, "Could not reset modem\n"); + exit(1); + } + sendcmd("AT#CID=1"); + if(strcmp(getline(1), "OK")) + { + if(isdaemon) + syslog(LOG_CRIT, "Could not activate called ID\n"); + else + fprintf(stderr, "Could not activate caller ID\n"); + exit(1); + } +} + +void sighandler(int sig) +{ + if(sig == SIGHUP) + { + initmodem(); + } +} + +int main(int argc, unsigned char **argv) +{ + int i; + unsigned char *p; + int nsock; + int ret; + struct sockaddr_in name; + struct termios tio; + fd_set rfds; + FILE *pidst; + + isdaemon = 0; + if((mdm = open(MODEM_DEV, O_RDWR)) < 0) + { + perror(MODEM_DEV); + return(1); + } + if(tcgetattr(mdm, &tio) < 0) + { + perror("tcgetattr"); + return(1); + } + cfmakeraw(&tio); + cfsetispeed(&tio, B0); + cfsetospeed(&tio, B38400); + if(tcsetattr(mdm, TCSANOW, &tio) < 0) + { + perror("tcsetattr"); + return(1); + } + if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) + { + perror("socket"); + return(1); + } + name.sin_family = AF_INET; + name.sin_port = htons(PORT); + name.sin_addr.s_addr = 0; + if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) + { + perror("bind"); + return(1); + } + if(listen(sock, 16) < 0) + { + perror("listen"); + return(1); + } + initmodem(); + signal(SIGHUP, sighandler); + if((pidst = fopen(PIDFILE, "w")) == NULL) + { + perror("open " PIDFILE); + exit(1); + } + daemon(0, 0); + fprintf(pidst, "%i\n", getpid()); + fclose(pidst); + openlog("cidd", LOG_PID, LOG_DAEMON); + isdaemon = 1; + FD_ZERO(&cfds); + FD_SET(mdm, &cfds); + FD_SET(sock, &cfds); + while(1) + { + rfds = cfds; + ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL); + if((ret < 0) && (errno != EINTR)) + { + syslog(LOG_CRIT, "select return %m"); + return(1); + } + if(ret > 0) + { + for(i = 0; i < FD_SETSIZE; i++) + { + if(FD_ISSET(i, &rfds)) + { + if(i == mdm) + { + while((p = getline(0)) != NULL) + { + if(!strcmp(p, "RING")) + broadcast("R"); + if(!memcmp(p, "NMBR = ", 7)) + { + p += 7; + broadcast("N%s", p); + } + } + } else if(i == sock) { + if((nsock = accept(sock, NULL, 0)) >= 0) + FD_SET(nsock, &cfds); + } else { + if(read(i, tmpbuf, 1024) == 0) + { + FD_CLR(i, &cfds); + close(i); + } + } + } + } + } + } +}