home *** CD-ROM | disk | FTP | other *** search
- /*
- * Startppp
- *
- * Copyright (C) 1995 Matthias Ott
- * (msott@cip.informatik.uni-erlangen.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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 <string.h>
- #include "tk.h"
- #include <time.h>
- #include <unistd.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include "Modem.h"
-
-
- char dialerror[]="dialerror\n";
- char dialkill[]="dialkill\n";
- char dialup[]="dialup\n";
- char dialconnect[]="dialconnect\n";
- char dialend[]="dialend\n";
- int fd=-1;
- int childpid=0;
- int pipefd[2];
- int pipeterminalfd[2];
- int timeout;
- int timeouttime;
- int showtermint=0;
- Tcl_Interp *myinterp;
-
- /*
- ** Function name : alarm_handler
- **
- ** Description :
- ** Input :
- ** Output :
- */
- void alarm_handler(int x)
- {
- char dialtimeout[]="timeout -> closed line";
- write (pipefd[1], dialtimeout, strlen(dialtimeout));
- timeout=1;
- }
-
-
- /*
- ** Function name : modemdial
- **
- ** Description :
- ** Input : init number
- ** Output :
- */
- int modemdial(char *modeminit, char *modemconnect)
- {
- int len,i,ii;
- int number=0;
- char buf[60];
- char buf2[20];
- char action[200];
- int again = 1;
- struct sigaction sigalarm={
- alarm_handler,0,0};
-
- timeout=0;
-
- if (sigaction(SIGALRM, &sigalarm,NULL)!=0) {
- perror("SIGALRM: ");
- }
-
- i=0;
- ii=0;
- while (i < strlen (modeminit)) {
- if (modeminit[i]=='~') {
- sleep(1);
- ++i;
- continue;
- }
- ii=0;
- while ((modeminit[i]!='^') && (modeminit[i+1]!='M') && (i < strlen (modeminit))) {
- action[ii]=modeminit[i];
- ++i;
- ++ii;
- }
- i=i+2;
- action[ii]='\0';
- write (pipefd[1], action, strlen(action));
- strncat(action,"\r",1);
- write (fd, action, strlen(action));
- }
-
- /* magic sleep, should change it */
- sleep(2);
- write (pipefd[1], modemconnect, strlen(modemconnect));
- write (fd, modemconnect, strlen(modemconnect));
- modemwait(modemconnect);
-
- buf[0]='\0';
- alarm(timeouttime);
- do {
- number=0;
- do {
- number=read (fd, buf2,20);
- } while ((number == 0) && (again == 1) &&(timeout == 0));
- if ((number == -1) && (timeout == 0)) {
- alarm(0);
- printf("read error at modemdial\n");
- return 7;
- }
- if (timeout == 1) {
- sleep (1);
- write (pipefd[1], dialerror, strlen(dialerror));
- while(1) sleep (1000);
- }
- buf2[number]='\0';
- if (showtermint == 1) {
- write (pipeterminalfd[1], buf2, number);
- }
- strcat (buf,buf2);
-
- if (strstr(buf,"BUSY")!=NULL) {
- alarm(0);
- return 6;
- }
- if (strstr(buf,"NO ANSWER")!=NULL) {
- alarm(0);
- write (pipefd[1], "NO ANSWER", 9);
- sleep (1);
- return 7;
- }
- if (strstr(buf,"DELAYED")!=NULL) {
- alarm(0);
- write (pipefd[1], "DELAYED", 7);
- sleep (1);
- return 7;
- }
- if (strstr(buf,"NO DIALTONE")!=NULL) {
- alarm(0);
- write (pipefd[1], "NO DIALTONE", 11);
- sleep (1);
- return 7;
- }
- if (strstr(buf,"ERROR")!=NULL) {
- alarm(0);
- write (pipefd[1], "ERROR", 5);
- sleep (1);
- return 7;
- }
- if (strstr(buf,"NO CARRIER")!=NULL) {
- alarm(0);
- write (pipefd[1], "NO CARRIER", 10);
- sleep (1);
- return 7;
- }
- if (strstr(buf,"CARRIER")!=NULL) {
- alarm(0);
- return 0;
- }
- if (strstr(buf,"CONNECT")!=NULL) {
- alarm(0);
- return 0;
- }
- if (again >= 10) {
- alarm(0);
- write (pipefd[1], "ANY ERROR", 9);
- sleep (1);
- return 7;
- }
- ++again;
-
- } while (1);
- }
-
- /*
- ** Function name : ModemClose
- **
- ** Description :
- ** Input : modemdevicetail
- ** Output : UNLINK DENIED | CLOSED
- */
- int ModemClose(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
- {
- char buf[256];
- struct termios t;
- char *modemdevice;
- char *modemdevicetail;
- char *modemspeed;
- char *modemparity;
- char *modemstopbits;
- int result;
-
- if (argc != 2) {
- interp->result = "wrong # args";
- return TCL_ERROR;
- }
- if (fd==-1) {
- modemdevice=Tcl_GetVar(interp, "modemdevice", TCL_GLOBAL_ONLY);
- strcpy(modemdevicetail,argv[1]);
- modemspeed=Tcl_GetVar(interp, "modemspeed", TCL_GLOBAL_ONLY);
- modemparity=Tcl_GetVar(interp, "modemparity", TCL_GLOBAL_ONLY);
- modemstopbits=Tcl_GetVar(interp, "modemstopbits", TCL_GLOBAL_ONLY);
- result=modemopen(modemdevice,modemdevicetail,modemspeed,modemparity,modemstopbits);
- if (result==1) {
- interp->result = "can't open LCK.. for reading";
- return TCL_OK;
- }
- if (result==2) {
- interp->result = "LCK process active";
- return TCL_OK;
- }
- if (result==3) {
- interp->result = "can't delete LCK..";
- return TCL_OK;
- }
- if (result==4) {
- interp->result = "can't open LCK.. for writing";
- return TCL_OK;
- }
- if (result==5) {
- interp->result = "can't open modemdevice";
- return TCL_OK;
- }
- if (result==6) {
- interp->result = "tcget|setattr error";
- return TCL_OK;
- }
- }
-
- if (tcgetattr(fd,&t) < 0) {
- Tcl_SetVar(myinterp, "message", "tcsetattr is not working", TCL_GLOBAL_ONLY);
- } else {
- t.c_cflag=B0;
- if (tcsetattr(fd,TCSANOW,&t) < 0) {
- Tcl_SetVar(myinterp, "message", "tcgetattr is not working", TCL_GLOBAL_ONLY);
- }
- }
-
- close (fd);
- fd = -1;
- sprintf(buf,"/usr/spool/uucp/LCK..%s",argv[1]);
- if (unlink (buf) != 0) {
- interp->result = "unlink denied";
- return TCL_OK;
- }
- interp->result = "closed line";
- return TCL_OK;
- }
- /*
- ** Function name : modemtalk
- **
- ** Description :
- ** Input : file
- ** Output : 1 | 0
- */
- int modemtalk(char *expectfile)
- {
- char name[100];
- int len;
- FILE *fd2;
- char dialfile[]="no expectfile";
-
- fd2=fopen(expectfile,"r");
- if (fd2==NULL) {
- write (pipefd[1], dialfile, strlen(dialfile));
- return 1;
- }
- while (fgets(name,100,fd2)!=NULL) {
- len = strlen(name);
- name[len-1]='\0';
- modemwait (name);
- fgets(name,100,fd2);
- write (fd, name, strlen(name));
- }
- fclose (fd2);
-
- return 0;
- }
-
- /*
- ** Function name : modemwait
- **
- ** Description :
- ** Input :
- ** Output :
- */
- int modemwait(char *name)
- {
- int r;
- int i;
- int number=0;
- char buf[5000];
- char myname[100];
- struct sigaction sigalarm={
- alarm_handler,0,0};
- strcpy(myname,name);
- r=0;
-
- timeout=0;
- if (sigaction(SIGALRM, &sigalarm,NULL)!=0) {
- perror("SIGALRM: ");
- }
- alarm(timeouttime);
- do {
- number=0;
- while ((number == 0) && (timeout == 0)) {
- number=read (fd, &buf[r],1);
- }
-
- /*
- if ((number == -1) && (timeout == 0)) {
- alarm(0);
- printf("read error at modemwait\n");
- write (pipefd[1], dialerror, strlen(dialerror));
- while(1) sleep (1000);
- }
- */
- if (timeout == 1) {
- write (pipefd[1], dialerror, strlen(dialerror));
- while(1) sleep (1000);
- }
- buf[r+1]='\0';
-
- if (showtermint == 1) {
- write (pipeterminalfd[1], &buf[r], 1);
- }
- if (buf[r]=='\0') {
- buf[r]==' ';
- }
- r++;
- if (r >= 5000) {
- r = 0;
- }
- } while ((strstr(buf, myname)==NULL) && (timeout == 0));
- alarm(0);
- return 0;
- }
-
- /*
- ** Function name : modemopen
- **
- ** Description :
- ** Input : device lock
- ** Output :
- */
- int modemopen(char *modemdevice, char *modemdevicetail, char *modemspeed, char *modemparity, char *modemstopbits)
- {
- FILE *fp;
- char buf[256];
- int pid=0;
- struct termios t;
-
- sprintf(buf,"/usr/spool/uucp/LCK..%s",modemdevicetail);
- fp = fopen(buf, "r");
- if (fp == NULL) {
- if (errno != ENOENT) {
- return 1;
- }
- }
- else {
- fscanf(fp, "%d", &pid);
- fclose (fp);
- if (getpid()!=pid) {
- if (kill(pid,0)==0) {
- return 2;
- }
- }
- else {
- if (unlink (buf) != 0) {
- return 3;
- }
- }
- }
- fp = fopen(buf,"w");
- if (fp == NULL) {
- return 4;
- }
- fprintf(fp,"%d\n",getpid());
- fclose(fp);
-
- fd = open(modemdevice, O_RDWR | O_NDELAY);
- if (fd<0) {
- printf("MODEM open error\n");
- return 5;
- }
- fcntl(fd,F_SETFL,O_RDWR);
- if (tcgetattr(fd,&t)<0) {
- perror("tcgetattr not working");
- close(fd);
- fd = -1;
- return 6;
- }
- t.c_iflag=t.c_oflag=t.c_lflag=0;
- t.c_cc[VMIN]=1;
- t.c_cc[VTIME]=0;
-
- /* Setzen der Flags */
- if (strcmp(modemparity, "CS8")==0) t.c_cflag = CREAD | CS8;
- if (strcmp(modemparity, "CS8|PARENB ")==0) t.c_cflag = CREAD | CS8 | PARENB;
- if (strcmp(modemparity, "CS8|PARENB|PARODD")==0) t.c_cflag = CREAD | CS8 | PARENB | PARODD;
-
- if (strcmp(modemspeed, "38400")==0) t.c_cflag |= B38400;
- if (strcmp(modemspeed, "19200")==0) t.c_cflag |= B19200;
- if (strcmp(modemspeed, "9600")==0) t.c_cflag |= B9600;
- if (strcmp(modemspeed, "1200")==0) t.c_cflag |= B1200;
-
- if (strcmp(modemstopbits, "CSTOPB")==0) t.c_cflag |= CSTOPB;
- t.c_cflag |= HUPCL;
- /* t.c_cflag=CREAD | CS8 | B38400 | HUPCL;*/
- if (tcsetattr(fd,TCSANOW,&t)<0) {
- perror("tcsetattr not working");
- close(fd);
- fd = -1;
- return 6;
- }
- return 0;
-
- }
-
-
-
- /*
- ** Function name : TalkTerminal
- **
- ** Description :
- ** Input :
- ** Output :
- */
- void TalkTerminal(ClientData clientData, int mask)
- {
- int count,i;
- char input[1000];
- char order[1000];
- char order2[]=".sm.input.text yview -pickplace end\n";
-
- count=read(pipeterminalfd[0], input, 1000);
- if (count <=0) {
- printf("ERROR reading PIPE");
- return;
- }
- input[count]='\0';
- for (i=0;i<count;++i) {
- if (input[i]=='\r') {
- input[i]=' ';
- }
- }
- sprintf(order,".sm.input.text insert end {%s}",input);
- Tcl_Eval (myinterp, order);
- Tcl_Eval (myinterp, order2);
- }
-
- /*
- ** Function name : TalkProc
- **
- ** Description :
- ** Input :
- ** Output :
- */
- void TalkProc(ClientData clientData, int mask)
- {
- int i;
- int count;
- char *buf;
- int bufint;
- char up2[]="up2";
- char startonlinetime[]="startonlinetime";
- char input[100];
- char order [100];
- char *modemdevicetail;
- char *startcommand;
-
- count=read(pipefd[0], input, 100);
-
- if (count <=0) {
- printf("ERROR reading PIPE");
- return;
- }
- input[count]='\0';
-
- /* increase dialtry +1 */
- if (strstr(input, dialup)!=NULL) {
- buf=Tcl_GetVar(myinterp, "dialtry", TCL_GLOBAL_ONLY);
- Tcl_GetInt(myinterp, buf, &bufint);
- ++bufint;
- sprintf(buf,"%d",bufint);
- Tcl_SetVar(myinterp, "dialtry", buf, TCL_GLOBAL_ONLY);
- return;
- }
-
- /* error while dialing, close modemline */
- if (strstr(input, dialerror)!=NULL) {
- Tcl_SetVar(myinterp, "dialtry", "0", TCL_GLOBAL_ONLY);
- modemdevicetail=Tcl_GetVar(myinterp, "modemdevicetail", TCL_GLOBAL_ONLY);
- sprintf(order,"modemclose %s",modemdevicetail);
- Tcl_Eval (myinterp, order);
- pidkill();
- return;
- }
-
- /* error, only kill childprocess */
- if (strstr(input, dialkill)!=NULL) {
- Tcl_SetVar(myinterp, "dialtry", "0", TCL_GLOBAL_ONLY);
- pidkill();
- return;
- }
-
- /* got a connect, set LINE up, start onlinetime */
- if (strstr(input, dialconnect)!=NULL) {
- Tcl_SetVar(myinterp, "message", "connected", TCL_GLOBAL_ONLY);
- Tcl_SetVar(myinterp, "dialtry", "0", TCL_GLOBAL_ONLY);
- Tcl_SetVar(myinterp, "linestatus", "LINE up", TCL_GLOBAL_ONLY);
- Tcl_Eval (myinterp, startonlinetime);
- return;
- }
-
- /* sucessfull dialing, start <up2> */
- if (strstr(input, dialend)!=NULL) {
- Tcl_Eval (myinterp, up2);
- Tcl_SetVar(myinterp, "pid", "0", TCL_GLOBAL_ONLY);
- pidkill();
- return;
- }
-
- Tcl_SetVar(myinterp, "message", input, TCL_GLOBAL_ONLY);
- return;
- }
-
-
-
- /*
- ** Function name : DialProc
- **
- ** Description :
- ** Input :
- ** Output :
- */
- int DialProc(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
- {
- int pid;
- char *modemdevice;
- char *modemdevicetail;
- char *modemspeed;
- char *modemparity;
- char *modemstopbits;
- char *modemtimeout;
- char *showterminal;
- int result;
- if (childpid != 0) {
- interp->result="line already active";
- return TCL_OK;
- }
-
- modemdevice=Tcl_GetVar(interp, "modemdevice", TCL_GLOBAL_ONLY);
- modemdevicetail=Tcl_GetVar(interp, "modemdevicetail", TCL_GLOBAL_ONLY);
- modemspeed=Tcl_GetVar(interp, "modemspeed", TCL_GLOBAL_ONLY);
- modemparity=Tcl_GetVar(interp, "modemparity", TCL_GLOBAL_ONLY);
- modemstopbits=Tcl_GetVar(interp, "modemstopbits", TCL_GLOBAL_ONLY);
- modemtimeout=Tcl_GetVar(interp, "modemtimeout", TCL_GLOBAL_ONLY);
- showterminal=Tcl_GetVar(interp, "showterminal", TCL_GLOBAL_ONLY);
- Tcl_GetInt(interp, showterminal, &showtermint);
- Tcl_GetInt(interp, modemtimeout, &timeouttime);
-
- /* open the modemdevice */
- result=modemopen(modemdevice,modemdevicetail,modemspeed,modemparity,modemstopbits);
- if (result==1) {
- interp->result = "can't open LCK.. for reading";
- return TCL_OK;
- }
- if (result==2) {
- interp->result = "LCK process active";
- return TCL_OK;
- }
- if (result==3) {
- interp->result = "can't delete LCK..";
- return TCL_OK;
- }
- if (result==4) {
- interp->result = "can't open LCK.. for writing";
- return TCL_OK;
- }
- if (result==5) {
- interp->result = "can't open modemdevice";
- return TCL_OK;
- }
- if (result==6) {
- interp->result = "tcget|setattr error";
- return TCL_OK;
- }
-
- /* Pipes are initiated */
- if (pipe(pipefd) == -1) {
- interp->result="pipe error";
- return TCL_OK;
- }
- if (showtermint == 1) {
- if (pipe(pipeterminalfd) == -1) {
- interp->result="pipe error";
- return TCL_OK;
- }
- }
-
- /* forking */
- if ((pid = fork()) > 0) { /* parent process */
- myinterp=interp;
- Tk_CreateFileHandler(pipefd[0],TK_READABLE,TalkProc,(ClientData) NULL);
-
- /* show terminal */
- if (showtermint == 1) {
- Tk_CreateFileHandler(pipeterminalfd[0],TK_READABLE,TalkTerminal,(ClientData) NULL);
- }
-
- /* set childpid on pid */
- childpid=pid;
- sprintf(interp->result,"%d",childpid);
- return TCL_OK;
- }
- else {
- if (pid == 0) { /* child process */
-
- char *dialtype;
- char *modemnumber;
- char *modeminit;
- char modemconnect[30];
- char *expectfile;
- char *dialtry;
- char *repeatdelay;
- char dialbusy[]="line is busy";
- char dialerror2[]="error while dialing";
- int delay;
- int dialint;
-
- repeatdelay=Tcl_GetVar(interp, "repeatdelay", TCL_GLOBAL_ONLY);
- Tcl_GetInt(interp, repeatdelay, &delay);
- dialtype=Tcl_GetVar(interp, "dialtype", TCL_GLOBAL_ONLY);
- modemnumber=Tcl_GetVar(interp, "modemnumber", TCL_GLOBAL_ONLY);
- modeminit=Tcl_GetVar(interp, "modeminit", TCL_GLOBAL_ONLY);
- expectfile=Tcl_GetVar(interp, "expectfile", TCL_GLOBAL_ONLY);
-
- sprintf(modemconnect,"ATD%s%s\r",dialtype,modemnumber);
-
- while (1) {
- dialtry=Tcl_GetVar(interp, "dialtry", TCL_GLOBAL_ONLY);
- Tcl_GetInt(interp, dialtry, &dialint);
- ++dialint;
- sprintf(dialtry,"%d",dialint);
- write (pipefd[1], dialup, strlen(dialup));
-
- result=modemdial(modeminit, modemconnect);
- if (result == 0) {
- write (pipefd[1], dialconnect, strlen(dialconnect));
- if (modemtalk(expectfile)!=0) {
- write (pipefd[1], dialerror, strlen(dialerror));
- while(1) sleep (1000);
- }
- }
- if (result == 6) { /* BUSY */
- write (pipefd[1], dialbusy, strlen(dialbusy));
- sleep(delay);
- continue;
- }
- if (result == 7) { /* ERROR */
- write (pipefd[1], dialerror, strlen(dialerror));
- while(1) sleep (1000);
- }
- break;
- }
- write (pipefd[1], dialend, strlen(dialend));
- while(1) sleep (1000);
- }
- else { /* <fork> error */
- interp->result = "fork error";
- return TCL_OK;
- }
- }
- }
-
- /*
- ** Function name : KillPid
- **
- ** Description :
- ** Input :
- ** Output :
- */
- int KillPid(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
- {
- if (argc != 1) {
- interp->result = "wrong # args";
- return TCL_ERROR;
- }
-
- if (childpid==0) {
- interp->result = "child not active";
- return TCL_OK;
- }
- /* close the handler */
- Tk_DeleteFileHandler(pipefd[0]);
- close (pipefd[0]);
- close (pipefd[1]);
- if (showtermint == 1) {
- Tk_DeleteFileHandler(pipeterminalfd[0]);
- close (pipeterminalfd[0]);
- close (pipeterminalfd[1]);
- }
-
- /* kill child */
- if (kill (childpid, 2)==0) {
- waitpid (childpid,NULL,0);
- childpid=0;
- interp->result = "killed child process";
- return TCL_OK;
- }
- interp->result = "failed to kill child";
- return TCL_OK;
- }
-
- /*
- ** Function name : pidkill
- **
- ** Description :
- ** Input :
- ** Output :
- */
- void pidkill(void)
- {
- Tk_DeleteFileHandler(pipefd[0]);
- close (pipefd[0]);
- close (pipefd[1]);
- if (showtermint == 1) {
- Tk_DeleteFileHandler(pipeterminalfd[0]);
- close (pipeterminalfd[0]);
- close (pipeterminalfd[1]);
- }
- if(kill(childpid, 2)==0) {
- waitpid(childpid,NULL,0);
- childpid=0;
- }
- }
-
-