pdial: la trasformazione di aswvdial - la potenza della GPL
Pubblicato da syscalo il 27/12/2002
Livello base

Introduzione

Da qualche tempo sono passato da Suse a Debian e tra i vari cambiamenti c'è anche quello riguardante la connessione a internet. Con la Suse utilizzavo wvdial mentre con la Debian sono passato a pon, poff & Co. Per wvdial è disponibile una dockapp (io uso window maker) per "controllarlo" e che mostra quando effettivamente è stato "tirato su" ppp0 e la durata della connessione.
"Purtroppo" mi sono affezionato a aswvdial ma volendo usare pon e poff l'unica soluzione è modificare adeguatamente aswvdial (di cui sono disponibili i sorgenti ed è anche distribuito con licenza GPL) per trasformarlo in pdial.

Programmi usati

Iniziamo

Analizzando il codice sorgente di aswvdial ho ricavato che funziona nel seguente modo:

A questo punto è chiaro che i punti in cui si deve intervenire sono: Fatte queste 3 semplici cose mi ritrovo con il mio pdial ;-)

Per quanto riguarda la configurazione ho deciso di mettere nel file /etc/pdial.conf i nomi dei vari account uno per riga. Questo perchè il comando pon accetta il nome dell'account come parametro. La funzione di lettura della configurazione si occupa solo di leggere ogni riga di questo file e di aggiungerla all'array già utilizzato da aswvdial per gestire i vari account.

Il comando di attivazione della connessione diventa ora "pon %s" in modo da passare il nome dell'account selezionato a pon.
Il comando di disconnessione diventa ora "poff".
Sostituiti i 2 comandi nelle system e ripulite le parti inutili il lavoro è fatto.

Dopo aver apportato le modifiche ho dato una ripulita ai sorgenti eliminando le variabili non più utilizzate; ho eliminato anche la gestione dei parametri dalla linea di comando e quindi la funzione che visualizza l'help in quanto il programma a mio modo di vedere va usato direttamente come dockapp avviata all'avvio di window maker.

Il nuovo programma pdial è disponibile, ovviamente con licenza GPL.
Di seguito c'è il listato del file pdial.c derivato da aswvdial.c:


#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>

#include "./wmgeneral/wmgeneral.h"
#include "./wmgeneral/misc.h"

#include "master.xpm"
#include "mask.xbm"


#define TRUE 1
#define FALSE 0

#define VERSION "1.1"

char wvdial_opt[30][30];
int maxentrys;
int connection=FALSE;
int entry=0;
time_t start_t=0;
double elapsed_t=0.0;

/*prototypes*/
void pressEvent(XButtonEvent *xbe);
int readproc(void);
int readconfig(void);
void timing(char *cmd);
void drawCHAR(char what[]);
void drawNUMBER(int x, int y, double what);

int main(int argc, char **argv)
{
    XEvent Event;

    if(!readconfig()) return 1;

    openXwindow(argc, argv, master_xpm, mask_bits, mask_width, mask_height);
    
    while(1)
    {
        while(XPending(display))
        {
            XNextEvent(display, &Event);
            switch(Event.type)
            {
            case Expose:
                RedrawWindow();
                break;
	    case ButtonPress:
		pressEvent(&Event.xbutton);
		break;
            case DestroyNotify:
	        XCloseDisplay(display);
	        exit(0);
	        break;
	    default:
		break;
	    }
	    
        } /*end of while XPending*/
	
	drawCHAR(wvdial_opt[entry]);
	if(readproc()==1)
	{
	    copyXPMArea(8,96,7,7,2,42);
	    timing("start");
	}
	else
	{
	    copyXPMArea(1,96,7,7,2,42);
	    timing("stop");
	}

	RedrawWindow();
	usleep(50000L);
    } /*end of while*/
    return 0;
}

void pressEvent(XButtonEvent *xbe)
{
    int x=xbe->x;
    int y=xbe->y;
    char temp[50];
    
    if(xbe->button==Button1)
    {
	if(y>=50 && y<=64)
	/*mouse click on buttons*/
	{
	    if(x>=1 && x<=20 && !connection)
	    /*mouse click on left button*/
	    {
			if(entry==0) entry=maxentrys;
			else entry--;
	    }
	    if(x>=22 && x<=43)
	    /*mouse click on middle button*/
	    {
		if(!connection)
		{
		    copyXPMArea( 1,66,20,15,1,50);
		    copyXPMArea(22,66,22,15,22,50);
		    copyXPMArea(45,66,20,15,45,50);
		    connection=TRUE;
		    /*
		    sprintf(temp,"netup %s",wvdial_opt[entry]);
		    if(system(temp)==-1) printf("\nError: Cannot execute wvdial\n");
		    */
		    sprintf(temp,"pon %s",wvdial_opt[entry]);
		    if(system(temp)==-1) printf("\nError: Cannot execute pon\n");
		}
		else
		{
		    copyXPMArea( 1,81,20,15,1,50);
		    copyXPMArea(22,81,22,15,22,50);
		    copyXPMArea(45,81,20,15,45,50);		
		    /*
		    if(system("netdown")==-1) printf("\nError: Cannot close connection\n");
		    */
		    if(system("poff")==-1) printf("\nError: Cannot close connection\n");
		    connection=FALSE;		    
		}
	    }
	    if(x>=45 && x<=64 && !connection)
	    /*mouse click on right button*/
	    {
		if(entry==maxentrys) entry=0;
		else entry++;
	    }
	}
    }
}

int readconfig(void)
{
    FILE *config=NULL;
    char line[256];

    maxentrys=0;
    config=fopen("/etc/pdial.conf","r");
    if(config != 0)
    {
        while(fgets(line,256,config) != NULL)
        {
	    if(maxentrys<=29)
	    {
		strcpy(wvdial_opt[maxentrys++],line);
	    }
	}
	if(maxentrys!=0) maxentrys--;
	fclose(config);
    }
    else
    {
    	printf("\nError: cannot open /etc/pdial.conf\n");
	return 0;
    }
    return 1;
}

int readproc(void)
{
    FILE *fp=NULL;
    char line[256];
    int temp=0;

    fp=fopen("/proc/net/route","r");
    if(fp)
    {
        while(fgets(line,256,fp))
        {
	    if(strstr(line,"ppp0")) temp=1;
	}
    }
    else
    {
    	printf("\nError: cannot open /proc/net/route\n");
    }
    fclose(fp);    
    return temp;
}

void timing(char *cmd)
{
    double hours,minutes,seconds;				
    static int starttimer=TRUE;

    if(cmd=="start")
    {
        if(starttimer)
        {
	    starttimer=FALSE;
	    start_t=time(0);
	}
	elapsed_t=difftime(time(0),start_t);
    }
    else
    {
        if(!starttimer)
        {
	    starttimer=TRUE;
	    elapsed_t=difftime(time(0),start_t);
	}
    }

    minutes=modf(elapsed_t/3600,&hours);
    minutes=minutes*60;
    seconds=modf(minutes,&minutes);
    seconds=seconds*60;
    drawNUMBER( 1,23,hours);
    drawNUMBER(17,23,minutes);
    drawNUMBER(33,23,seconds);
}

void drawCHAR(char what[])
{
    int i,x,y;

    x=y=1;
    for(i=0;i<18;i++,x=x+7)
    {
	if(i==9)
	{
	    x=1;
	    y=11;
	}
	switch(toupper(what[i]))
	{
	    case 'A':
		copyXPMArea(15,111,7,9,x,y);
	        break;
	    case 'B':
	        copyXPMArea(22,111,7,9,x,y);
	        break;
	    case 'C':
	        copyXPMArea(29,111,7,9,x,y);
	        break;
	    case 'D':
	        copyXPMArea(36,111,7,9,x,y);
	        break;
	    case 'E':
		copyXPMArea(43,111,7,9,x,y);
	        break;
	    case 'F':
	        copyXPMArea(50,111,7,9,x,y);
	        break;
	    case 'G':
	         copyXPMArea(57,111,7,9,x,y);
	         break;
	    case 'H':
	        copyXPMArea(1,120 ,7,9,x,y);
		break;
	    case 'I':
	        copyXPMArea(8,120,7,9,x,y);
	        break;
	    case 'J':
	        copyXPMArea(15,120,7,9,x,y);
	        break;
	    case 'K':
		copyXPMArea(22,120,7,9,x,y);
	        break;
	    case 'L':
	        copyXPMArea(29,120,7,9,x,y);
	        break;
	    case 'M':
	        copyXPMArea(36,120,7,9,x,y);
	        break;
	    case 'N':
	        copyXPMArea(43,120,7,9,x,y);
	        break;
	    case 'O':
		copyXPMArea(50,120,7,9,x,y);
	        break;
	    case 'P':
	        copyXPMArea(57,120,7,9,x,y);
	        break;
	    case 'Q':
	        copyXPMArea(1,129,7,9,x,y);
	        break;
	    case 'R':
	        copyXPMArea(8,129 ,7,9,x,y);
	        break;
	    case 'S':
	        copyXPMArea(15,129,7,9,x,y);
	        break;
	    case 'T':
	        copyXPMArea(22,129,7,9,x,y);
	        break;
	    case 'U':
		copyXPMArea(29,129,7,9,x,y);
	        break;
	    case 'V':
	        copyXPMArea(36,129,7,9,x,y);
	        break;
	    case 'W':
	        copyXPMArea(43,129,7,9,x,y);
	        break;
	    case 'X':
	        copyXPMArea(50,129,7,9,x,y);
	        break;
	    case 'Y':
		copyXPMArea(57,129,7,9,x,y);
	        break;
	    case 'Z':
	        copyXPMArea(1,138,7,9,x,y);
	        break;
	    case '0':
		copyXPMArea(1,102,7,9,x,y);
	        break;
	    case '1':
	        copyXPMArea(8,102,7,9,x,y);
	        break;
	    case '2':
	        copyXPMArea(15,102,7,9,x,y);
	        break;
	    case '3':
	        copyXPMArea(22,102,7,9,x,y);
	        break;
	    case '4':
		copyXPMArea(29,102,7,9,x,y);
	        break;
	    case '5':
	        copyXPMArea(36,102,7,9,x,y);
	        break;
	    case '6':
		copyXPMArea(43,102,7,9,x,y);
	        break;
	    case '7':
	        copyXPMArea(50,102,7,9,x,y);
		break;
	    case '8':
	        copyXPMArea(57,102,7,9,x,y);
	        break;
	    case '9':
	        copyXPMArea(1,111,7,9,x,y);
	        break;
	    default:
		copyXPMArea(8,111,7,9,x,y);
	        break;
	} /*end of switch*/
    } /*end of for*/
}

void drawNUMBER(int x, int y, double what)
{
    int i;
    double a,b;
    
    a=modf(what/10,&b);
    
    for(i=0;i<2;i++,x=x+7,a=modf(a*10,&b))
    {
        switch((int) b)
	{
        case 0:
	    copyXPMArea(1,102,7,9,x,y);
    	    break;
        case 1:
	    copyXPMArea(8,102,7,9,x,y);
    	    break;
        case 2:
	    copyXPMArea(15,102,7,9,x,y);
    	    break;
        case 3:
	    copyXPMArea(22,102,7,9,x,y);
    	    break;
        case 4:
	    copyXPMArea(29,102,7,9,x,y);
	    break;
        case 5:
	    copyXPMArea(36,102,7,9,x,y);
    	    break;
        case 6:
	    copyXPMArea(43,102,7,9,x,y);
            break;
	case 7:
    	    copyXPMArea(50,102,7,9,x,y);
	    break;
        case 8:
	    copyXPMArea(57,102,7,9,x,y);
    	    break;
        case 9:
	    copyXPMArea(1,111,7,9,x,y);
    	    break;
        default:
	    copyXPMArea(8,111,7,9,x,y);
    	    break;
        } /*end of switch*/
    } /*end of for*/
}

Conclusioni

Come avrete capito le modifiche apportate al programma originale sono molto semplici, ma spero anche che avrete capito che lo scopo del tutorial è di mostrare come con un po' di reversing dei sorgenti sia possibile far nascere nuovi programmi risparmiando un sacco di tempo: per dare un'idea, per ottenere pdial nella sua versione finale sono bastati 10 minuti, se avessi dovuto scrivere l'applicazione da zero tra la raccolta delle informazioni (su come si crea e gestisce una dockapp) e la realizzazione ci sarebbero volute almeno due giornate.
Per concludere, sfruttate il codice altrui il più possibile!!
bye syscalo