haulm 发表于 2008-10-11 10:22:32

关于重写一个拔号器的MXD想法

声明: 个人习惯,此帖不需要某管理员移动到我管辖之外的技术区,请尊重我的意愿。

我最终还是想自己写一个拔号器,这样可以把多年综合掌握的知识点汇总起来,从一个用户、打包兼测试员的转向一个准程序员。
这是练习写的代码,大概重写rp-pppoe的gui界面应当从这个思路开始#include
#include
#include
int main(int argc,char *argv[])
{
uid_t uid;
uid=getuid();
int opt;
opt=getopt(argc,argv,"do");
if(opt!=-1)
{
switch(opt){
        case 'd':
                if(uid==0)
                {
                        system("/usr/sbin/adsl-stop");
                        }
                else
                {       
                        system("/usr/sbin/pppoe-wrapper stop haulm");
                        }
                break;
        case 'o':
                if(uid==0)
                {
                        system("/usr/sbin/adsl-start");
                        }
                else
                {       
                        system("/usr/sbin/pppoe-wrapper start haulm");
                        }
                break;
        }
}
        exit(0);
}界面我可能用Qt4来写,界面可能不会太复杂,一个用户框加密码框,对文件进行读写操作,拔号后直接退出程序,所有的连接状态我打包knetstats来显示,因为knetstats比较专业一些,有专门的人在维护。其它比如无线网络的拔号设置如果能整理出来,也会纳入新的MXD进行设置。大家有什么意见没有?

[ 本帖最后由 haulm 于 2008-10-19 08:13 编辑 ]

marry100 发表于 2008-10-12 10:45:10

我不会c语言,听楼主说的都不懂。不过支持了……
现在的拨号器在kde4.1里就不能用了,希望楼主测试的时候考虑这方面,
还有就是普通用户登录问题,呵呵。也许我说的都是废话了。
再一次强烈支持!

haulm 发表于 2008-10-12 11:20:01

原帖由 marry100 于 2008-10-12 10:45 发表 http://www.linuxfans.org/bbs/images/common/back.gif
我不会c语言,听楼主说的都不懂。不过支持了……
现在的拨号器在kde4.1里就不能用了,希望楼主测试的时候考虑这方面,
还有就是普通用户登录问题,呵呵。也许我说的都是废话了。
再一次强烈支持! ...
就是用Qt4写的,配置界面和配置写入还没实现,不过现在托盘菜单倒是好了,可以直接进行拔号,复杂的功用可能没有能力去实现,需要参照一下knetstart对网络状态的实现(原mxd并不能非常正确的分析网络状态)。

haulm 发表于 2008-10-15 08:16:19

完成了整个界面、配置、拔号、断开、提示功能,代码如下:
尚缺网络状态判断并显示的功能,正在查询方法。#include <QtGui>
#include "hello.h"
myclass::myclass()
{      
        uid=getuid();
        FILE *in=NULL;
        char sl;
        in=fopen("/etc/ppp/pap-secrets","r");
        if(in==NULL){printf("can't open the /etc/ppp/pap-secrets");}       
        while(fgets(sl,128,in))
        {
                if(strstr(sl,"mxd_connect"))
                {
                break;               
                        }
                                }
        char *a,*b;
        a=strtok(sl,"\t*");
        if(a!=NULL)
                {a=strtok(NULL,"\t*");}
        if(a!=NULL)
                {b=strtok(NULL,"\t*");}
        fclose(in);
        QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
      setMinimumSize(200,100);
        setMaximumSize(200,100);
        this->move(400,200);
        QString aText,bText;
      lee1=new QLineEdit(this);
        lee1->setContextMenuPolicy(Qt::NoContextMenu);
        lee1->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
        lee1->setGeometry(10,10,180,20);
        aText=a;
        lee1->setText(aText);
        lee2=new QLineEdit(this);
        lee2->setContextMenuPolicy(Qt::NoContextMenu);
        lee2->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
        lee2->setGeometry(10,40,180,20);
        bText=b;
        lee2->setText(bText);
        lee2->setEchoMode(QLineEdit::Password);
        b1=new QPushButton(tr("拔号"),this);
        b1->setGeometry(90,70,40,25);
        savebutton=new QPushButton(tr("保存"),this);
        savebutton->setGeometry(140,70,40,25);
        QIcon icon = QIcon("./images/status_error.png");
        setWindowIcon(icon);
      trayIcon = new QSystemTrayIcon(this);
      trayIcon->setIcon(icon);
      trayIcon->setToolTip(tr("Magic Linux 拔号器"));
        createActions();
        createTrayIcon();
      trayIcon->show();
      setWindowTitle(tr("Magic Linux 拔号器"));
        connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
connect(b1,SIGNAL(clicked()),this,SLOT(showM()));
connect(b1, SIGNAL(clicked()), this, SLOT(pppoeStart()));
connect(savebutton, SIGNAL(clicked()), this, SLOT(saveconf()));
}

void myclass::showM()
{
      QString titlec=tr("请稍候");
      QString textc=QString::fromLocal8Bit("正在尝试PPPOE拔号");
      trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
        this->hide();
      }
               
void myclass::saveconf()
{
QString titlec,textc;
if(uid==0)
{
        titlec=tr("请稍候");
      textc=QString::fromLocal8Bit("保存新的账号密码");
//配置1
        FILE *out=NULL;
        out=fopen("/etc/ppp/mxd-secrets","w+");
        if(out==NULL){printf("can't create the /etc/ppp/mxd-secrets");}
        char *a,*b;
        QString aText,bText;
        aText=lee1->text();
        a=aText.toLocal8Bit().data();
        bText=lee2->text();
        b=bText.toLocal8Bit().data();
        char c="mxd_connect\t*\t";
        strcat(c,a);
        strcat(c,"\t*\t");
        strcat(c,b);
        strcat(c,"\t*\n");
        fputs(c,out);
        strcpy(c,a);
        strcat(c,"\t*\t");
        strcat(c,b);
        strcat(c,"\t*\n");
        fputs(c,out);
        fclose(out);
        unlink("/etc/ppp/pap-secrets");
        rename("/etc/ppp/mxd-secrets","/etc/ppp/pap-secrets");
//配置2
out=fopen("/etc/ppp/rp-pppoe-gui/conf.mxd_connect","w+");
if(out==NULL){printf("can't create the conf.mxd_connect");}
strcpy(c,"USER=");
strcat(c,a);
fputs(c,out);
fputs("\nETH=eth0",out);
fputs("\nDNSTYPE=SERVER",out);
fputs("\nPEERDNS=yes",out);
fputs("\nDNS1=",out);
fputs("\nDNS2=",out);
fputs("\nNONROOT=OK",out);
fputs("\nSYNCHRONOUS=yes",out);
fputs("\nFIREWALL=STANDALONE",out);
fputs("\nSERVICENAME=",out);
fputs("\nACNAME=",out);
fputs("\nCONNECT_TIMEOUT=30",out);
fputs("\nCONNECT_POLL=1",out);
fputs("\nFORCEPING=\".\"",out);
fputs("\nPIDFILE=/var/run/pppoe-mxd.pid",out);
fputs("\nCLAMPMSS=1412",out);
fputs("\nLCP_INTERVAL=20",out);
fputs("\nLCP_FAILURE=3",out);
fputs("\nPPPOE_TIMEOUT=80",out);
fputs("\nLINUX_PLUGIN=",out);
fputs("\nDEMAND=no",out);
fputs("\nDEFAULTROUTE=yes\n",out);
fclose(out);
//配置3
out=fopen("/etc/ppp/rp-pppoe-gui/passwd","w+");
if(out==NULL){printf("can't create the conf.mxd_connect");}
strcpy(c,"\{ConnectionName mxd_connect Password ");
strcat(c,b);
strcat(c,"}\n");
fputs(c,out);
fclose(out);
}else
        {titlec=tr("非法操作");
       textc=QString::fromLocal8Bit("请用root账号进行保存");
                                                                }
trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
}
               
void myclass::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
   switch (reason) {
      case QSystemTrayIcon::DoubleClick:
        this->showNormal();
         break;
   default:
         ;
   }
}

void myclass::createActions()
{
   minimizeAction = new QAction(tr("隐藏 (&I)"), this);
   connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));

   conn1 = new QAction(tr("拔号 (&X)"), this);
   connect(conn1, SIGNAL(triggered()), this, SLOT(pppoeStart()));

   conn2 = new QAction(tr("断开 (&R)"), this);
   connect(conn2, SIGNAL(triggered()), this, SLOT(pppoeStop()));

   quitAction = new QAction(tr("退出 (&Q)"), this);
   connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void myclass::createTrayIcon()
{
   trayIconMenu = new QMenu(this);
   trayIconMenu->addAction(minimizeAction);
   trayIconMenu->addAction(conn1);
   trayIconMenu->addAction(conn2);
   trayIconMenu->addSeparator();
   trayIconMenu->addAction(quitAction);
   trayIcon->setContextMenu(trayIconMenu);
}

void myclass::pppoeStart()
{
        if(uid==0)
                {
                        system("/usr/sbin/adsl-start");
                        }
                else
                {       
                        system("/usr/sbin/pppoe-wrapper start mxd_connect");
                        }
        QIcon icon2 = QIcon("./images/status_both.png");
      trayIcon->setIcon(icon2);
        this->hide();
        }
void myclass::pppoeStop()
{
        if(uid==0)
                {
                        system("/usr/sbin/adsl-stop");
                        }
                else
                {       
                        system("/usr/sbin/pppoe-wrapper stop haulm");
                        }
        QIcon icon1 = QIcon("./images/status_error.png");
      trayIcon->setIcon(icon1);
}

int main(int argc,char **argv)
{
      QApplication testc(argc,argv);
      myclass newc;
      newc.show();
      return testc.exec();
}

stdio 发表于 2008-10-18 08:28:47

QT 那里用designer 就可以啊,很简单的。

写成KDE 程序或者applet也应该不成问题的。

我还会有后续意见的。

stdio 发表于 2008-10-18 09:15:45

system 那里最好独立成一个线程,

或者专门写一个类来实现系统调用

那样不会因为子进程没有响应而把主进程弄僵

网络状态分析参考一下 kde applet 那个就可以

haulm 发表于 2008-10-18 15:26:21

原帖由 stdio 于 2008-10-18 09:15 发表 http://www.linuxfans.org/bbs/images/common/back.gif
system 那里最好独立成一个线程,

或者专门写一个类来实现系统调用

那样不会因为子进程没有响应而把主进程弄僵

网络状态分析参考一下 kde applet 那个就可以 ...
在书上也是不建议使用system的,我在程序有进展后才会考虑使用其它方法的调用。

haulm 发表于 2008-10-19 08:08:15

昨天研究了半天的libpcap的应用,该库用于监听网络的,但很奇怪的是pcap_lookupnet函数经常返回空,昨晚偶而返回了网卡定义的IP和MASK值纯属于人品,今早又不行了只好注释掉。
pcap_next函数似乎不会马上返回,运行后如果没有接收到数据包就不会退出,这样对我来说还是有点麻烦,因为我不可能直接按pcap_next返回的值来判断是否在线,如果断开了,很可能陷入了长时间的等待。
这几天大量地搜索网络这方面的资料,有努力还是有收获,不过还是希望有能力的朋友指导和一起进步。
#include <pcap.h>
#include <stdio.h>

int main()
    {
      pcap_t *handle;                        /* Session handle */
      char *dev;                              /* The device to sniff on */
      char errbuf; /* Error string */
      struct bpf_program filter;            /* The compiled filter */
      char filter_app[] = "";       /* The filter expression */
      bpf_u_int32 mask;                     /* Our netmask */
      bpf_u_int32 net;                        /* Our IP */
      struct pcap_pkthdr header;          /* The header that pcap gives us */
      const u_char *packet;               /* The actual packet */
      /* Define the device */
         if(!(dev = pcap_lookupdev(errbuf)))
    {
      perror(errbuf);
      exit(-1);
    }
      /* Find the properties for the device */
//      pcap_lookupnet(dev, &net, &mask, errbuf);
      /* Open the session in promiscuous mode */
      handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
if (handle == NULL)
                {perror(errbuf);
               exit(-1);}

      /* Compile and apply the filter */
      if(pcap_compile(handle, &filter, filter_app, 0, net)==-1)
        {fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(handle));
                exit(1);}
      if(pcap_setfilter(handle, &filter)==-1)
        {fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(handle));
                exit(1);}
      /* Grab a packet */

        packet = pcap_next(handle, &header);
                   /* Print its length */
      printf("Jacked a packet with length of [%d]\n",header.len);
      /* And close the session */

        struct pcap_stat {
      u_int ps_recv; /* number of packets received */
      u_int ps_drop; /* number of packets dropped */
      u_int ps_ifdrop; /* drops by interface XXX not yet supported */
};

        struct pcap_stat ps;
        pcap_stats (handle,&ps);
        printf("%d\n",ps.ps_recv);
      pcap_close(handle);
      return(0);
    }

haulm 发表于 2008-10-19 08:19:49

原帖由 stdio 于 2008-10-18 08:28 发表 http://www.linuxfans.org/bbs/images/common/back.gif
QT 那里用designer 就可以啊,很简单的。

写成KDE 程序或者applet也应该不成问题的。

我还会有后续意见的。
主要是我根本看不懂或很难看懂写的是什么,不少开源软件没有明显的注释,很难拿来主义或是下手修改。
另外这几天的C编程学习,总的感受是库函数也不是说没有毛病的,一些奇奇怪怪的事也会发生的。编译过程中出现最多的是段错误,以前打包编译程序时遇到过段错误,现在明白了该种错误是非常低级的错误,往往就是将函数返回值未经判断将NULL或-1值或完全不匹配的值应用到新的函数中去了。

jiangtao9999 发表于 2008-10-19 08:31:43

楼上。尝试 shell 编程吧……

haulm 发表于 2008-10-19 08:59:06

原帖由 jiangtao9999 于 2008-10-19 08:31 发表 http://www.linuxfans.org/bbs/images/common/back.gif
楼上。尝试 shell 编程吧……
兄台不会是想让我改用wxPython来写吧,晕倒。

haulm 发表于 2008-10-20 10:57:21

和kanker再次交流后放弃了用libpacp进行网络分析的想法,因为libpacp在抓包过程如果没有抓到包很可能就处于等待状态,直到你设置的超时时间过了才会返回,如果再加上线程,这个程序变得非常复杂。
/sys/class/net 目录下有着内核存放的网络状态分析文件,这里面提供非常详细的分析,所以重新去抓包分析网络就很可笑了,我现在只需要直接从这个目录中的各个文件中得到数据。

jiangtao9999 发表于 2008-10-20 17:19:43

原帖由 haulm 于 2008-10-19 08:59 AM 发表 http://www.linuxfans.org/bbs/images/common/back.gif

兄台不会是想让我改用wxPython来写吧,晕倒。
别晕,听说 php 也能 GTK 了……

haulm 发表于 2008-10-20 23:41:42

兄台孤陋寡闻了,PHP-GTK很早就有了,直到现在它的应用还是少的可怜。

hhf3498 发表于 2008-10-21 00:50:36

原帖由 haulm 于 2008-10-20 23:41 发表 http://www.linuxfans.org/bbs/images/common/back.gif
兄台孤陋寡闻了,PHP-GTK很早就有了,直到现在它的应用还是少的可怜。
pyqt
pygtk
wxpython
這些都可以
至少比你用c+qt來的快我覺得
页: [1] 2
查看完整版本: 关于重写一个拔号器的MXD想法