QT를 사용한 X윈도우용 네트워크 관리툴
박영선(youngsun@i-top.co.kr)
날짜: 1999.12.26
컴파일러: gcc
언어 : C++ (QT 1.44 Library 사용)
환경 : 알짜리눅스 6.1 XWindow환경
===============================================================
<들어가기전에...>
안녕하세요.
(주)아이탑에서 개발연구원으로 일하고 있는 박영선이라고 합니다.
우선, 간단하게 이 자료의 내용을 소개한 뒤 시작하기로 하죠.
제가 리눅스를 처음 접하고, 또 Gtk와 QT를 만나게 되면서, 실제 저
희회사 제품개발당시 힘들었던 점과 개발 후에 느꼈던 미비한 점등
을 참고해서 이 프로젝트를 계획하게 되었습니다.
이 프로젝트는 저희회사 개발원들이 개발했던 Topflash라는, 네
트워크, 프락시, 방화벽, 메신저등을 종합적으로 관리할 수 있는
통합인터넷솔루션중 제가 개발한 TopmanagerX를 기반으로 만들어졌
습니다.
이는 QT라이브러리와, ANSI-C기반의 file처리루틴을 라이브러리로
묶어 구현한 내용입니다.
사정상 이 중에서 네트워크관리를 QT를 사용하여 구현해보도록 하겠
습니다.
다음에는 Gtk를 이용한 버젼을 다른 처리 내용의 글로 올리겠습니다.
문의사항이나 개선점을 발견하신분들은 위의 E-mail주소로 꼭 연락
해주시기 바랍니다.
그리고 Gtk의 글이 끝나면 마지막으로 Kernel분석에 관한 자료를 만
들까 생각중입니다.
많은 관심과 격려 부탁드립니다.
===============================================================
<목차>
0. RedHat Linux 6.1의 System관리File에 관하여...
0.1. /etc디렉토리에 있는 file들
0.1.1. /etc/conf.modules
0.1.2. /etc/sysconfig/network-scripts/ifcfg-eth0
0.1.3. /etc/sysconfig/network
1. 이중연결리스트를 이용한 File처리 루틴에 관하여...
1.1. 이중연결리스트(Double LinkedList) 구현
1.2. file처리 라이브러리 구현
1.3. 개선되어야할 내용
2. QT 기본 다지기
2.1. QT의 Class계층정보
2.2. Widget이란?
2.2.1. 위젯(QWidget), 프레임(QFrame), 버튼(QButton)
2.2.2. Makefile 만들기
2.2.3. 라벨(QLabel)
2.2.4. 편집박스(QLineEdit)
2.2.4.1 QObject::connect, SIGNAL과 SLOT
2.2.5. 콤보박스(QComboBox)
2.2.6. 리스트(QListView)
2.2.7. 체크박스(QCheckBox), 라디오버튼(QRadioButton)
2.2.8. 메뉴(QMenu)
2.2.9. 툴바(QToolBar)와 메인윈도우(QMainWindow)
2.3. QT를 얻으려면?
< 한마디 >.
3. 기본 Format 작성하기
3.1. 메뉴 만들기
3.2. 툴바 집어넣기
3.3. Network관련 라이브러리 구현하기
3.4. Class만들기
3.4.1 일반네트워크관리
3.4.2 DNS관리
3.4.3 IP-Aliasing관리
< *** 전체 Source *** >
3.5. 개선되어야할 내용
4. 프로젝트를 마치고...
===============================================================
< 0. RedHat Linux 6.1의 System관리File에 관하여... >
0.1. /etc디렉토리에 있는 file들
0.1.1. /etc/conf.modules
이 file은 하드웨어에 새로운 디바이스가 추가되었을 때 해당 디바이스모
듈을 알기 쉬운 이름으로 속이는 역할을 한다.
예를들어 Lan Card의 Chipset이름이 3c59x라면 /etc/conf.modules에는 다
음과 같은 내용이 들어가야한다.
alias eth0 3c59x
여기서 3c59x는 엄밀히 말하자면 Chipset의 이름이 아니라 리눅스에서 제
공하는 Network Module의 이름이다. 리눅스의 제공 Network Module들은
각각 Chipset이름에 1:1 매치된다.(여기서의 Module이란 Windows에서의
드라이버개념과 비슷하다.)
Module file들은 *.o로 끝나며 이들에 대한 정보는
/lib/modules/2.2.12-20kr/net 디렉토리에 있다.
위의 "alias eth0 3c59x"의 의미는 3c59x모듈을 eth0로 aliasing해서 쓰겠
다는 뜻이다.
만약 Lan Card가 두장이상 시스템에 설치되어있다면 아래와 같은 정보가 추
가되어있을 것이다.
alias eth1 '모듈이름'
alias eth2 '모듈이름'
만약 카드가 ISA라면 이 file안에서 io와 irq번호를 수동으로 설정해주어야
한다. 원래 io, irq또한 설정하는 루틴도 같이 넣으려고 했지만, 요즈음
90% 이상 PCI카드를 사용하고 있으므로 이 설정은 뺐다.
0.1.2. /etc/sysconfig/network-scripts/ifcfg-eth0
위 작업을 마쳤다면 다음 file의 내용을 scan해보자.
cat /etc/sysconfig/network-scripts/ifcfg-eth0
다음과 같은 내용이 출력될 것이다.
DEVICE=eth0
BROADCAST=172.31.255.255
IPADDR=172.31.0.202
NETMASK=255.255.0.0
NETWORK=172.31.0.0
ONBOOT=yes
물론 IP, Netmask, Network, Broadcast등은 이렇게 되어있지는 않을 것이다.
맨 마지막줄의 "ONBOOT=yes"의 뜻은 시스템의 부팅시에 모듈을 올릴 것인지에
대한 옵션이다.
이 file이 없다면 에디터를 써서 file을 생성시키기 바란다.
이렇게 setting을 하고, 만약 Lan Card의 Chipset이 3c59x에 해당되는 모듈에
매치된다면 다음 명령어를 실행해보라.
/etc/rc.d/init.d/network restart
이 명령어를 실행하게 되면 모듈올리기에 성공하는지 실패하는지를 나타내준다.
만약 성공한다면 마지막으로 다음 명령어를 실행해본다.
ifconfig
이 명령어에 대한 필자의 시스템에서의 결과값은 다음과 같다.
eth0 Link encap:Ethernet HWaddr 00:90:27:A2:70:DE
inet addr:172.31.0.1 Bcast:172.31.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:88055 errors:0 dropped:0 overruns:0 frame:0
TX packets:119306 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
Interrupt:17 Base address:0xef00
eth1 Link encap:Ethernet HWaddr 00:90:27:57:17:27
inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
Interrupt:16 Base address:0xef40
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:3924 Metric:1
RX packets:146 errors:0 dropped:0 overruns:0 frame:0
TX packets:146 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
위의 결과값에서 볼 수 있듯이 필자의 IP(가상)은 "inet addr:172.31.0.1"에
명시되어 있고 나머지 Broadcast와 Netmask에 대한 정보 또한 나타나있다.
여기서 eth1에 대한 정보는 두번째 Lan Card를 장착했을 때, 또 그 Card를
OS에서 올바르게 인식했을 때 나타나는 정보이다. 설정 file들에 대한 정보는
eth0와 흡사하다.
출력결과중 세번째 단락의 "lo"는 localhost에 대한 정보이다. 이 결과값은
kernel에서 default로 setting하여주므로 별로 신경쓸 필요가 없다.
0.1.3. /etc/sysconfig/network
이 file은 호스트네임과 게이트웨이를 설정하는 file이다.
이 file을 cat해보자.
NETWORKING=yes
FORWARD_IPV4=false
HOSTNAME=superbug.i-top.co.kr
GATEWAY=172.31.0.200
위의 처음 두줄은 특별한 셋팅이 필요한 경우를 제외하고는 별로 설정값을
바꿀 일이 없으리라 생각한다.
레드헷 6.x이전 버젼까지는 이곳에 DOMAINNAME과 GATEWAYDEV항목이 들어있
었으나 6.x이후부터는 그 부분이 빠졌다. 이 항목들은 있어도 그만, 없어도
그만이므로 신경쓸 필요는 없다. DOMAINNAME항목은 HOSTNAME에 포함이 되었
고, GATEWAYDEV는 디폴트로 eth0를 셋팅하도록 되어있다.
< 1. 이중연결리스트를 이용한 File처리 루틴에 관하여... >
-> File처리루틴에 이중연결리스트를 이용한 목적:
File처리루틴은 이중연결리스트를 이용한 방법을 선택하였다.
연결리스트를 선택한 가장 중요한 이유는 확장성의 용이함때문이다.
가장 흔한 File처리방법은 DB(ISAM, Postgre sql, mysql기타등등)를
이용하는 방법이 있고, 혹은 File에서 한개의 문자씩 읽어들여 처리
하는 방법등 여러가지가 있다.
하지만 DB를 이용하는 방법은 대용량 데이터를 처리할 때, 그리고
데이터 포맷이 정형화되어있을 때 쓰는 방법이고, 한개의 문자씩 읽
어들여 처리하는 방법은 한두개정도의 File을 처리할 때나 유용한
방법이므로 범용적이지 못하다.
Linux의 Network 관련 File들은 각각의 정보가 모두 정형화되어있지도
않고 또한 자주 업그레이드되는 정보들이므로 범용적인 처리루틴이 필
요하다.
다른 좋은 방법들도 있겠지만, 그리고 문자처리방식을 확장시키는 방
법도 있겠지만, 손쉽게 File을 처리하기 위해, 메모리관리를 확실하게
하기위해 연결리스트를 사용했다. 여러분께서 더 좋은 방법이나 혹은
더 좋은 루틴을 가지고 계신분은 질타와 가르침을 주시기 바란다.
===============================================================
1.1. 이중연결리스트(Double LinkedList) 구현
이중연결리스트에 대한 source는 인터넷상에 널려있고,
학부과정에서도 지겹게 다루는 부분이므로 이 부분에 대
한 설명은 접어두기로 하고 file내용만 보여주도록 하겠다.
--- < source 1.1.1 Double LinkedList. Filename:procfile.h > ---
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
#endif
#endif
----------------------------------------------------------------
--- < source 1.1.2 Double LinkedList. Filename:procfile.c > ---
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
------------------------------------------------------------------------
1.2. file처리 라이브러리 구현
자, 이젠 이중연결리스트를 이용하여 File처리를 해보도록 하자.
가장 기본적인 algorithm은 다음과 같다.
< 연결리스트를 이용한 file처리 algorithm 1.2.1 >
1) file을 읽기모드로 열고
2) 한 라인을 읽어들인다.
3) 읽어들인 라인이 Search 조건에 맞는지 검사한다.
3-1) 조건에 맞으면 4)로 이동.
3-2) 맞지 않으면 연결리스트의 node에 삽입하고 2)로 이동
4) 조건에 따라 연결리스트의 node에 처리한(삽입 혹은 삭제, 변경등)
문자열을 삽입한다.
5) 처리가 다 끝나면 file을 닫는다.
6) file을 쓰기모드로 연다.
7) 메모리에 적재하고 있는 연결리스트의 각 노드들을 순서대로 file에
print한다.
8) file을 닫는다.
이렇게만 써놓으면 잘 이해가 가지 않을 것이다.
그러므로 이제부터 source와 그에 따른 algorithm을 토대로 설명하겠다.
우선 algorithm 1.2.1의 2)과정에 해당하는 함수를 만들어보자.
-------- < source 1.2.1 readOneLineSearchFile > -------------------
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp); /* file에서 한 문자를 읽어들인다. */
pszBuffer[i++] = c;
/* 실제 file처리함수에서 사용하게될 buffer에 읽 */
/* 어들인 문자를 삽입한다. */
if (c == EOF || c == '\n')
/* 문자가 file의 끝이거나 캐리지리턴값이면 */
break;
/* loop를 빠져나간다. 즉, 개행문자를 만나면 */
} while (1); /* 그때까지의 문자를 모두 버퍼에 저장하고 */
/* loop를 끝낸다. */
pszBuffer[i] = '\0'; /* 버퍼에 들어있는 개행문자나 EOF를 삭제한다. */
nLine++; /* file의 line수를 체크하기 위한 외부변수이다. */
/* 한 라인을 읽고나서 1씩 증가시킨다. */
return c; /* 개행문자'\n', 혹은 EOF가 return될 것이다. */
}
-------------------------------------------------------------------
다음으로 연결리스트의 내용을 file에 프린트하는 함수를 구현해보도록 하자.
연결리스트에 관한 함수들은 위에서 언급한 바와 같다.
간단하므로 이해하기도 쉬울 것이다.
--------------- < source 1.2.2 printToFileDL > -------------------
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next; /* node pPrint를 초기화한다. */
while (pPrint != dbltail) /* pPrint가 마지막이 될 때까지 반복해서 */
{
fprintf(fp, pPrint->pzKey); /* file에 프린트한다. */
pPrint = pPrint->next; /* node를 다음으로 이동 */
}
return pPrint->pzKey;
}
-------------------------------------------------------------------
아래 소개할 source 1.2.3이 바로 위에서 언급한 algorithm에 의한 루틴이다.
Code line 우측에 각각 해당하는 algorithm의 번호를 표시해놓겠다.
이 함수는 file(pszFileName)에서 특정 문자열(pszSearch)이 들어있는 라인
을 찾아 그 라인을 통째로 삽입할 문자열(pszInsert)로 바꾸는 함수이다.
만약 검색할 문자열이 발견되지 않으면 file은 아무 변화도 일어나지 않는다.
--------------- < source 1.2.3 insertStrToFile > -------------------
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
/* nMaxLine과 nMaxCol을 인자로 두는 이유는 메모리를 관리하기 */
/* 위해서이다. 즉 pszBuffer 이중포인터변수를 전역변수로 잡지 */
/* 않기 위해서인데, 만약 이 변수를 전역변수로 잡게되면 프로 */
/* 그램은 항상 nMaxLine*nMaxCol byte만큼의 메모리를 차지하게 */
/* 되므로 메모리의 막대한 낭비를 초래할 수 있는 문제점이 있다.*/
/* 이 루틴에서는 file의 최대 line수와 최대 coloum수를 인자로 */
/* 받아서 그 인자 만큼에 해당되는 메모리를 할당하여 준다. */
/* 이렇게 처리했을 때의 메모리의 사용량은, 이 루틴이 실행되었 */
/* 을 때만 nMaxLine*nMaxCol byte만큼 메모리에 할당이 되기때문 */
/* 에, 기본메모리가 큰 linux시스템에서는 별 무리 없이 사용할 */
/* 수 있다. */
nLine = 0;
fp = fopen(pszFileName, "r"); /* algor 1) file을 읽기모드로 연다. */
if (fp == NULL) /* file이 존재하지 않는다면 아무처리 없이 끝낸다. */
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL(); /* double linkedlist를 초기화한다. */
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
/* algor 2) file로부터 한라인(pszBuffer[i])씩 읽어들인다. */
{
/* algor 3-2) 읽어들인 라인(pszBuffer[i])이 검색할 문자열 */
/* (pszSearch)을 포함하고 있지 않다면 */
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
/* algor 3-2) node에 삽입한 후 for (i = 0; ~)로 이동해 다음라인 */
/* 을 읽어들인다.(algor 2) */
insertAsLastDL(pszBuffer[i]);
else /* algor 3-1) 검색할 문자열이 포함되어있다면 */
/* algor 4) 검색한 문자열이 포함된 line대신 삽입할 문자열을 연 */
/* 결리스트에 삽입한다. */
insertAsLastDL(pszInsert);
}
/* 만약 위 for 루틴에서 검색할 문자열이 발견되지 않는다면 연결리스트 */
/* 에는 file의 모든 라인을 가지고 있는 node들만이 있을 것이다. */
/* 이런 상태에서 바로 아래쪽의 printToFileDL함수를 호출하게 되면 */
/* file의 내용이 아무것도 변하지 않으면서 그 file자체에 내용을 복사 */
/* 하게 되는 것이다. */
fclose(fp); /* algor 5) file을 닫는다. */
fp = fopen(pszFileName, "w"); /* algor 6) file을 쓰기모드로 연다. */
printToFileDL(dblhead->next, fp); /* algor 7) 메모리에 적재하고 */
/* 있던 연결리스트의 모든 노드 */
/* 들을 순서대로 file에 print한다.*/
deletePerfectDL(); /* 연결리스트 초기화시 할당했던 메모리를 회수한다.*/
fclose(fp); /* algor 8) file을 닫는다. */
for (i = 0; i < nMaxLine; i++) /* 버퍼에 할당했던 메모리를 해제(회수)*/
free(pszBuffer[i]);
}
-------------------------------------------------------------------
이중연결리스트의 구조를 알고있다면 이해하기가 상당히 쉬울 것이다.
이 함수를 이해하지 못했다면 다음으로 넘어가지 못하므로 철저하게 이해하기
바란다. 이 함수의 쓰임새는 두가지가 있다.
첫번째, 특정문자열 바꾸기.
두번째, 특정문자열이 속한 라인 지우기.
여기서 두번째쓰임새의 내용을 보라. 특정문자열(pszSearch)이 속한 line을 지
우려면 어떻게 해야할까? 너무도 쉬운 내용이다.
인자 pszInsert에 "", 즉, 공백문자열을 넘겨주면 된다.
이 함수는 특정 file을 임시파일로 저장하는 과정 없이 바로 그 file을 갱신한
다. 임시파일로 저장하는 것과 메모리에 저장하는 것은 서로 장단점이 있는데
그에 대한 설명은 언급하지 않아도 잘 아시리라 믿는다.
strstr함수에 관한 내용은 man페이지를 참조하거나 library 메뉴얼을 참고하기
바란다.
다음으로 구현할 함수는 위의 함수와 거의 비슷하지만 약간 다르다. 위의 함수
에서는 검색문자열(pszSearch)이 없을 경우 아무일도 일어나지 않지만 이 함수
는 문자열이 검색되지 않으면 file의 맨 끝에 삽입할 문자열(pszInsert)을 끼
워넣게 된다.
검색할 문자열이 만약 검색된다면 바로 아무일을 하지 않고 루틴을 끝낸다.
대부분의 과정은 위에서 설명했으므로 새로운 주목해야할 부분만을 Comment
하겠다.
--------------- < source 1.2.4 insertStrToFileLast > -------------------
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else /* 검색할 문자열(pszSearch)이 검색 된다면 루틴을 끝낸다. */
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
/* 만약 문자열(pszSearch)이 검색되지 않았다면 이부분으로 넘어오게 */
/* 된다. 이 경우 바로 아래와 같이 삽입할 문자열을 연결리스트의 맨 */
/* 끝노드에 삽입을 시키고 file로 프린트한다. */
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
-------------------------------------------------------------------
이번에 설명할 함수는 file에서 특정문자열을 찾아 그 문자열을 원하는
문자열로 바꾸어주는 함수이다.
위에서 설명한 insertStrToFile함수와는 다른 역할을 한다.
즉, insertStrToFile함수는 line단위로 문자열을 삽입, 변경하는 반면
changeStrToOneLineToFile함수는 문자열단위로 변경하는 함수이다.
기본 algorithm은 < algorithm 1.2.1 >에 의거한다.
만약 위의 과정을 모두 이해했다면 이 함수도 별 어려움이 없을 것이다.
이 함수는 changeSearchStr이라는 함수를 call하는데, changeSearchStr
함수는 어떤 주어진 문자열(pszLine)에서 특정문자열(pszSearch)를 찾아
삽입할 문자열(pszIns)로 바꾸는 역할을 한다. 한 라인(pszLine)에 여러
개의 특정문자열(pszSearch)가 있을 수 있으므로 재귀호출(recursive
call)을 사용했다. 기본적인 C문법을 알고있다면 루틴 자체는 이해하기
쉬울 것이라 믿는다.
위와 마찬가지로 중복되는 Comment는 생략하겠다.
-------- < source 1.2.5 changeStrToOneLineToFile > -----------
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
/* 여기서 포인터 인자인 pszSave는 바뀐 라인을 저장할 공간이다. */
{
int i = 0;
char *pszPos;
int nPos;
/* 라인(pszLine)에서 검색문자열(pszSearch)의 위치를 계산하기 */
/* 위해 검색문자열의 pszLine에서의 포인터 위치를 저장해둔다. */
pszPos = (char *)strstr(pszLine, pszSearch);
/* 검색문자열의 위치를 계산한다. */
nPos = pszPos-pszLine;
/* 검색문자열의 위치(nPos)까지 pszSave에 pszLine의 내용을 복사 */
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
/* 저장할 변수(pszSave)에 바꿀 문자열(pszIns)를 붙힌다.*/
strcat(pszSave, pszIns);
/* 저장할 변수(pszSave)에 그 이후의 문자열을 붙힌다. */
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
/* 더이상 검색문자열(pszSearch)가 */
pszPos = (char *)strstr(pszSave, pszSearch);
/* 존재하지 않는다면 루틴을 끝낸다. */
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
/* 바뀐 라인(pszSave)를 원래 라인에 복사한다. */
strcpy(pszLine, pszSave);
/* 재귀호출을 위해 pszSave를 초기화한다. */
memset(pszSave, '\0', nMaxCol);
/* 첫번째 만나는 검색문자열을 바꾸었으므로 두번째, 세번째등등 */
/* 의 문자열을 바꾸기 위해 재귀호출을 한다. */
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
/* 이제 한 라인에 대한 문자열변경루틴은 끝냈으므로 위 함수에 실제 */
/* file에서 한 라인씩 읽어들여 인자로 넘겨주면 된다. */
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
/* pszLine은 바뀐 문자열을 저장할 공간이다. */
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
/* 한 라인씩 읽어들여서 */
{
/* 검색문자열(pszSearch)이 없다면 연결리스트에 삽입한다.*/
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
/* 검색문자열이 있다면 changeSearchStr함수를 이용해 검색문자열이 */
/* 포함된 라인을 수정하고 수정된 라인을 연결리스트에 삽입한다. */
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i], pszLine[j],
nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
/* file 쓰기 */
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
-------------------------------------------------------------------
예상외로 간단할 것이다. 특정 기능(예를들어, 삭제, 삽입, 변경등)에
대한 함수들의 구현은 위 방법과 구조가 항상 같다.
이는 연결리스트를 사용했을때의 장점이 유감없이 발휘된 특징중 하나
이다. 즉, 이해하기 쉽고 구현이 용이하고, 또 가장 중요한 범용성이
있다는 점이다.
이번엔 위의 source들의 구조를 약간 응용해서 구조화된 file의 처리
루틴을 작성해보기로 하자.
아래의 함수는 검색문자열(pszSearch)이 file(pszFileName)에 없다면
삽입할 문자열(pszInsert)을 라인으로 삽입하고 검색문자열이 존재한
다면 그 검색문자열을 포함한 라인을 삽입할 문자열로 바꾸는 함수이
다. 위의 함수들과 다른점이 있다면 이 함수에는 flag를 두었다는 점
이다. 이 flag는 file에 검색된 라인을 삽입문자열로 바꿀 것인지 아
니면 그냥 삽입문자열을 라인단위로 삽입할 것인지를 결정한다.
만약 문자열이 검색되지 않는다면 flag는 TRUE로 setting된다.
-------- < source 1.2.6 addOnNotExistChangeOnExist > -----------
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
/* 삽입할 지 혹은 변경할 지의 flag(flgAdd) */
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
/* 만약 검색문자열(pszSearch)이 검색된다면 */
else
{
/* 삽입문자열(pszIns)을 node에 삽입하고 */
insertAsLastDL(pszIns);
/* flag를 FALSE로 reset시킨다. */
flgAdd = FALSE;
}
}
fclose(fp);
/* flag가 TRUE라면 검색문자열이 발견되지 않았다는 것이므로 */
/* 링크리스트의 맨 끝node에 삽입문자열을 삽입한다. */
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
/* file 쓰기 */
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
-------------------------------------------------------------------
간단하게 몇줄만 추가 혹은 변경시켜 기능을 바꾸어놓았다.
앞으로 설명하게될 모든 file처리관련 함수들이 다 이런식이다.
이 routine을 응용하여 갖가지 source들을 재생성해보시기를...
이제부터는 위의 routine들은 물론 필자가 구현해놓은 모든 procedure들
을 한꺼번에 보여주기로 하겠다. 그리고 설명은 되도록 기능 위주로 하
겠다. 위 과정까지 모두 이해했다면 별다른 Comment없이도 이해할 수
있을 것이다.
-------- < source 1.2.7 total functions > -----------
/**************** proc_file.h *****************/
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine);
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine);
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine);
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol);
void *printToFileDL(DList *pPrint, FILE *fp);
int readOneLineSearchFile(char pszBuffer[], FILE *fp);
void insertStrToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol);
int countSearchLineToFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol);
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol);
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment,
char *pszFileName, int nMaxLine, int nMaxCol);
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExistWithoutComment(char *pszIns,
char *pszSearch, char cComment, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist2Search(char *pszIns,
char *pszFirstSearch, char *pszSecondSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void saveStrIdxToFileLine(char *pszSave, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol);
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol);
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol);
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol);
#endif
#endif
/**********************************************/
/**************** proc_file.c *****************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
/****** FILE procedure ******/
/* 한 라인에서 검색문자열(pszDel)을 지운다. */
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine)
{
char *pszPnt;
int i, nFirstLen;
if ((pszPnt = (char *)strstr(pszLine, pszDel)) == NULL)
return;
nFirstLen = pszPnt-pszLine;
for (i = 0; i < nFirstLen; i++)
pszSave[i] = pszLine[i];
for (i = nFirstLen; pszLine[i+strlen(pszDel)] != '\0'; i++)
pszSave[i] = pszLine[i+strlen(pszDel)];
pszSave[i] = '\0';
}
/* 한 라인에서 검색문자열(pszSearch)앞에 삽입문자열(pszInsert) */
/* 을 삽입한다. */
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine)
{
int i = 0;
int nLen;
char *pszPos;
if ((char *)strstr(pszLine, pszInsert) != NULL)
{
strcat(pszSave, pszTempLine);
return;
}
pszPos = (char *)strstr(pszLine, pszSearch);
nLen = pszPos-pszLine;
for (i = 0; i < nLen; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszInsert);
strcat(pszSave, strstr(pszLine, pszSearch));
}
/* 한 라인에서 검색문자열(pszIns)이 있다면 return하고 없다면 */
/* 라인 끝에 검색문자열을 삽입한다. */
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine)
{
int nFirstPos, nSecondPos;
if ((char *)strstr(pszLine, pszIns) != NULL)
return;
for (nFirstPos = 0; nFirstPos < strlen(pszLine); nFirstPos++)
pszSave[nFirstPos] = pszLine[nFirstPos];
for (nSecondPos = 0; nSecondPos < strlen(pszIns); nSecondPos++)
pszSave[nSecondPos+nFirstPos] = pszIns[nSecondPos];
pszSave[nSecondPos+nFirstPos] = '\0';
}
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
{
int i = 0;
char *pszPos;
int nPos;
pszPos = (char *)strstr(pszLine, pszSearch);
nPos = pszPos-pszLine;
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszIns);
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
pszPos = (char *)strstr(pszSave, pszSearch);
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
strcpy(pszLine, pszSave);
memset(pszSave, '\0', nMaxCol);
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
int nLine;
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
fprintf(fp, pPrint->pzKey);
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp);
pszBuffer[i++] = c;
if (c == EOF || c == '\n')
break;
} while (1);
pszBuffer[i] = '\0';
nLine++;
return c;
}
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
/* file의 라인수를 return한다. */
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (nCount = 0;
(readOneLineSearchFile(pszBuffer[nCount], fp) != EOF) &&
(nCount < nMaxLine); nCount++);
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
/* file에서 검색문자열(pszSearch)가 있는 line 수를 return한다. */
int countSearchLineToFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0;
int nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
nCount++;
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
/* file의 모든 라인을 이중포인터(pszSaveListStr)에 저장한다. */
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (j = 0; j < nMaxLine; j++)
{
pszBuffer[j] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[j], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
strcpy(pszSaveListStr[i], pszBuffer[i]);
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return i;
}
/* file에서 검색문자열(pszSearch)이 있는 line에 Comment(cComment)가 */
/* 없다면 이중포인터(pszSaveListStr)에 저장한다. */
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL &&
pszBuffer[i][0] != cComment)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
/* file에서 검색문자열(pszSearch)이 있는 line을 Comment(cComment)에 상 */
/* 관없이 이중포인터(pszSaveListStr)에 저장한다. */
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i],
pszLine[j], nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
/* 검색문자열(pszSearch)이 있는 라인에서 검색문자열 바로 */
/* 앞에 삽입문자열(pszIns)을 삽입한다. */
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertStrForeSearch(pszLine, pszIns, pszSearch, pszBuffer[i],
pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* file에서 검색문자열(pszSearch)을 찾아 그 문자열만 지워준다. */
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
deleteStrFromOneLine(pszLine, pszDel, pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
insertAsLastDL(pszInsert);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* file에서 검색문자열(pszSearch)이 있으면 TRUE, */
/* 없으면 FALSE를 return한다. */
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
fclose(fp);
return TRUE;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return FALSE;
}
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* Comment(cComment)가 없을 때, 검색문자열(pszSearch)이 */
/* 없으면 file 맨 끝에 삽입문자열(pszIns)를 라인으로 삽입 */
/* 하고, 있으면 검색문자열이 있는 라인을 삽입문자열로 바 */
/* 꾼다. */
void addOnNotExistChangeOnExistWithoutComment(char *pszIns,
char *pszSearch, char cComment,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL ||
pszBuffer[i][0] == cComment)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 두개의 검색문자열(pszFirstSearch, pszSecondSearch)이 모두 있으면 */
/* 그 라인을 삽입문자열(pszIns)로 바꾸고, 둘 중 하나라도 없으면 */
/* 삽입문자열을 file맨 끝에 라인으로 삽입한다. */
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszFirstSearch) != NULL &&
(char *)strstr(pszBuffer[i], pszSecondSearch) != NULL)
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
else
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그 라인의 바로 앞에 삽입 */
/* 문자열을 라인으로 삽입한다. */
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
insertAsLastDL(pszBuffer[i]);
fclose(fp);
insertDLAsKey(pszInsert, pszSearch);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)을 찾아 그 라인의 끝위치에 삽입문자열 */
/* (pszInsert)을 삽입한다. */
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][strlen(pszBuffer[i])-1] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nStartIdx)에서 */
/* 특정Coloum(nEndIdx)까지의 문자열을 Save(pszSave)한다. */
void saveStrIdxToFileLine(char *pszSave, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nStartIdx);
for (j = 0; j < nEndIdx-nStartIdx; j++)
pszSave[j] = pszEndBuffer[j];
}
}
fclose(fp);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nStartIdx)에서 */
/* 특정Coloum(nEndIdx)까지의 문자열을 삽입문자열(pszInsert)로 교체한다. */
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx,
int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nEndIdx);
pszBuffer[i][nStartIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
strcat(pszBuffer[i], pszEndBuffer);
pszBuffer[i][strlen(pszBuffer[i])] = '\0';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nIdx) 이후의 문자열 */
/* 을 모두 없애고, 삽입문자열(pszInsert)을 붙힌다. */
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][nIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 특정라인(nLineIdx)의 특정Coloum(nColIdx) 이후의 문자열 */
/* 을 모두 없애고, 삽입문자열(pszInsert)을 붙힌다. */
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if (i == nLineIdx-1)
{
pszBuffer[i][nColIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszStartLine)을 찾아 그 라인의 바로 다음라인에 */
/* 삽입문자열(pszInsert)을 라인으로 삽입한다. */
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
insertAsLastDL(pszInsert);
insertAsLastDL("\n");
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
insertAsLastDL(pszBuffer[j]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
/* 첫번째 검색문자열(pszStartLine)과 두번째 검색문자열(pszEndLine) */
/* 을 찾아 그 사이에 있는 line들을 저장(pszSaveLine)한다. */
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
{
if ((char *)strstr(pszBuffer[j], pszEndLine) == NULL)
strcpy(pszSaveLine[j-(i+1)], pszBuffer[j]);
else
break;
}
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return;
}
}
}
/* 첫번째 검색문자열(pszStartLine)과 두번째 검색문자열(pszEndLine) */
/* 을 찾아 그 사이에 있는 line들을 삽입문자열(pszInsert)로 대체 */
/* 시킨다. */
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
if ((char *)strstr(pszBuffer[j], pszEndLine) != NULL)
break;
for (k = 0; k < nInsertNum; k++)
insertAsLastDL(pszInsert[k]);
insertAsLastDL(pszBuffer[j]);
for (k = j+1;
readOneLineSearchFile(pszBuffer[k], fp) != EOF; k++)
insertAsLastDL(pszBuffer[k]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
-------------------------------------------------------
지금까지 링크리스트를 이용한 file처리에 관한 내용을 다루어보았다.
그런데, 왜 굳이 Simple LinkedList를 쓰지 않고, Double LinkedList
를 사용했는지 궁금할 것이다.
나는 후에라도 이 Source를 더욱 강화시키기위해 확장성이 좋은 이중
연결리스트를 사용한 것이다. 물론 단순연결리스트를 사용한다면 메
모리를 약간 절약할 수는 있겠지만 확장성에서는 훨씬 떨어진다.
따라서, Library를 후에 강화시킬 일이 있다면 이중연결리스트를 써
야한다고 생각한다.
1.3. 개선되어야할 내용
앞서 말했듯이 위의 Source는 특정 Routine이 수행될 때 순간적으로
Resource를 크게 차지할 수도 있는 단점이 있다.
이를 보완하려면 LinkList의 node에 key값을 삽입할 때 모든 file의
내용을 전부 LinkList에 삽입할 것이 아니라 조건에 맞을 때만 file
의 내용을 변경하도록 하는 것이 좋다.
이러한 개선점을 생각해 위의 Source들을 한번 수정해보시기를 바란
다.
===============================================================
< 2. QT 기본 다지기 >
-> 필자는 Ansi-C를 사용하는 원시 프로그래머였다.
주로 다뤘던 분야는 Network 관련 프로그램이었고 개발 환경또한
X-window가 아닌 text-mode에서였다. text-mode에서의 GUI구축에
온 힘을 쏟았고 그 결과로 Curses나 Slang보다도 더 좋다고 내세
울 수 있는 Library를 개발했다. 나는 내 자신이 상당한 수준에
올라와 있다고 착각하기 시작했고 점차 자만에 빠지게 되었다.
하지만 점차 Linux가 업그레이드 되면서 굉장한 수준의 그래픽환
경이 제공되면서 그 자만은 깨지기 시작했다. 그 충격이란 엄청
난 것이었다. 나와 비슷한 분들이 한분이라도 이 글을 읽는 분들
중에 계시다면 이 자료를 올린 보람이 있을 것이다.
기타등등의 이유로 C++에 대한 클래스 개념조차도 거의 모른 상태
에서 약 3개월 전부터 QT를 시작했다.
어떠한 자료도 없이 Alzza 리눅스에 포함되어있는 QT 1.44 의 예제
Source만으로 C++과 QT를 공부하자니 무척이나 힘이 들었다.
이렇게 힘들게 공부하면서 QT에 빨리 접근할 수 있는 방법을 저절
로 터득하게 되었는데 이 방법을 여러분께 가장 좋다고 생각하는
과정에 의거하여 글을 쓰겠다. 짧은 실력으로 글을 올리니 여러분
께 죄책감이 먼저 앞서지만 Source공유라는 차원에서 귀엽게 보아
주시기 바란다.
2.1. QT의 Class계층정보
우선 본격적인 QT 제공 Class들을 공부하기에 앞서 Class계층에
대해 눈으로 익혀두기 바란다. 이 계층정보는 상당히 중요하지만
외울 필요는 없다. 그냥 필요할 때 찾아보는 정도로 활용하기 바
란다. 아래의 표는 /usr/lib/qt/html/hierarchy.html 에서 발췌한
내용중 앞으로 쓰게될지도 모를 주요 클래스만을 정리한 것이다.
-------- < 표 2.1.1 QT Class 계층정보 > ---------
QBrush
QCollection
QGList
QList
QStrList
QStrIList
QColor
QColorGroup
QConnection
QCursor
QEvent
QChildEvent
QCloseEvent
QCustomEvent
QDragMoveEvent
QDropEvent
QFocusEvent
QKeyEvent
QMouseEvent
QMoveEvent
QPaintEvent
QResizeEvent
QTimerEvent
QFont
QFontInfo
QFontMetrics
QGArray
QArray
QByteArray
QString
QPointArray
QIconSet
QImage
QListBoxItem
QListBoxPixmap
QListBoxText
QListViewItem
QCheckListItem
QMenuData
QMenuBar
QPopupMenu
QMovie
QObject
QAccel
QApplication
QXtApplication
QDragObject
QImageDrag
QStoredDrag
QTextDrag
QUrlDrag
QLayout
QBoxLayout
QHBoxLayout
QVBoxLayout
QGridLayout
QSignal
QToolTipGroup
QValidator
QDoubleValidator
QIntValidator
QWidget
QButton
QCheckBox
QPushButton
QRadioButton
QToolButton
QComboBox
QDialog
QFileDialog
QMessageBox
QPrintDialog
QTabDialog
QFrame
QGroupBox
QButtonGroup
QLCDNumber
QLabel
QMenuBar
QProgressBar
QScrollView
QListView
QSpinBox
QSplitter
QTableView
QHeader
QListBox
QMultiLineEdit
QPopupMenu
QWidgetStack
QLineEdit
QMainWindow
QNPWidget
QScrollBar
QSemiModal
QProgressDialog
QSlider
QStatusBar
QTabBar
QToolBar
QWindow
QXtWidget
QPaintDevice
QPicture
QPixmap
QBitmap
QPrinter
QWidget
QPaintDeviceMetrics
QPainter
QPalette
QPen
QPixmapCache
QPoint
QRangeControl
QScrollBar
QSlider
QSpinBox
QRect
QSize
QTextStream
QTime
QToolTip
QWhatsThis
QWMatrix
-----------------------------------------
2.2. Widget(QWidget)이란?
-> 모든 사용자 인터페이스(User Interface)의 기본 Class이다.
위의 표와 같이 버튼, 프레임, 편집박스등 Graphic Interface를
주도하는 Class들중 최 상위에 위치해있다.
모든 Widget들에 대한 공부는 철저하게 예제위주로 하겠다.
2.2.1. 위젯(QWidget), 프레임(QFrame), 버튼(QButton)
---------- < source 2.2.1.1. testFrameButton.cpp > -----------
#include <qapplication.h> /* QApplication을 위한 header file */
#include <qwidget.h> /* QWidget을 위한 header file */
int main(int argc, char* argv[])
{
/* 이 부분은 QT 프로그램의 main함수에서 항상 써주어야 */
/* 하는 부분이다. */
QApplication myapp(argc, argv);
/* 인자가 없음에 주의 */
QWidget *wdgtTest = new QWidget();
/* setGeometry(x좌표, y좌표, 넓이, 높이) */
wdgtTest->setGeometry(100, 100, 200, 100);
/* application의 메인 윈도우를 wdgtTest로 정의 */
myapp.setMainWidget(wdgtTest);
/* wdgtTest를 보여준다. */
wdgtTest->show();
/* qt를 실행시킨다. 만약 이 부분이 없다면 윈도우가 뜨지 */
/* 않을 것이다. 항상 들어가야할 부분이다. */
return myapp.exec();
}
-----------------------------------------------------------
위의 Source에서 관심있게 보아야할 부분은 QWidget, QFrame,
QPushButton Class의 인자들이다.
우선 header file을 살펴보자. header file에 관한 정보는
/usr/lib/qt/include/ 에서 볼 수 있다.
public:
QWidget( QWidget *parent=0, const char *name=0, WFlags f=0 );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QWidget( const QWidget & );
QWidget &operator=( const QWidget & );
#endif
위 부분은 header file(/usr/lib/qt/include/qwidget.h)에 들어있
는 QWidget의 생성자 부분이다.
여기서 유심히 보아야할 부분은 인자들의 정의 부분이다. 즉,
QWidget *parent = 0, const char *name = 0, WFlags f = 0
이렇게 클래스정의부분에서 인자값까지도 정의할 수 있다는 것은
C++을 한번쯤 다뤄본 분이라면 모두 아실 것이다.
C에서 NULL값은 #define문으로 0으로 선언되어있다. 즉 parent,
name, f 모두 NULL로 정의를 했다는 뜻인데 그냥 초기화시켰다
는 의미로 받아들이자. 물론 이 부분은 class 생성자(constructor)
부분에서 직접 정의할 수도 있다.
이는 C++의 특권이라고 할 수 있겠다. 이런 방법은 여러곳에서 상
당히 유용하게 쓸 수 있는 기능이다. 자세한 예는 차차 이야기하
도록 하겠다.
이젠 인자들에 대해 살펴보자.
-> QWidget *parent: parent widget을 뜻한다.
위의 header file에 나타난 class선언에서도 보았
듯이 디폴트로 NULL(0)으로 설정되어있는데 이는
자신을 최상위 윈도우로 정하겠다는 뜻이다.
즉 parent가 정의되지 않은(인자가 없는) widget은
부모class가 없이 독립적인 윈도우 체제를 가진다.
parent인자에 만약 다른 widget값을 넘겨준다면
parent인자에 종속되게 된다. 자세한 내용은
source 2.2.1.2에서 다시 다루겠다.
-> const char *name:이것은 widget에 대한 식별자 역할을 한다.
이 식별자는 프로그래머가 거의 사용할 일이 없다.
library에서 자체적으로 compile시 debugging작업
을 할 때, 혹은 사용자가 debugging tool을 사용할
때 특정 부분에 대한 정보를 보고 싶을 때 name()
함수를 사용하여 정보를 추출할 수 있다.
필자는 거의 debugging tool을 사용하지 않으므로
이 인자에 대한 정의는 한번도 한적이 없다.
따라서 이 인자에 대한 설명은 생략하기로 하겠다.
-> WFlags f: 거의 사용할 일이 없으므로 디폴트값을 따르기로
하자. 설명도 생략하겠다. 자세한 정보는
/usr/lib/qt/html/qwidget.html file을 참조하기
바란다.
---------- < source 2.2.1.2. testFrameButton.cpp > -----------
#include <qapplication.h>
#include <qwidget.h>
#include <qframe.h> /* QFrame을 위한 header file */
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
QWidget *wdgtTest = new QWidget();
wdgtTest->setGeometry(100, 100, 200, 100);
/* parent 인자를 wdgtTest로 설정한다. */
QFrame *frTest = new QFrame(wdgtTest);
/* parent가 wdgtTest이므로 frTest에 대한 속성 */
/* 들(x좌표, y좌표)의 좌표값은 wdgtTest에 대한 */
/* 상대적인 좌표로 변환된다. */
frTest->setGeometry(10, 10, 150, 60);
/* frame의 형태를 정한다. */
frTest->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
myapp.setMainWidget(wdgtTest);
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
QFrame에 대한 class선언 정보는
/usr/lib/qt/include/qframe.h에 정의되어있다. 다음과 같이
public과 private양쪽에 선언되어있다.
public:
QFrame( QWidget *parent=0, const char *name=0, WFlags f=0,
bool allowLines=TRUE );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QFrame( const QFrame & );
QFrame &operator=( const QFrame & );
#endif
public member와 private member에 대해서는 굳이 언급하지 않아도 되
겠지만 참조범위에 대해 아주 간단하게 설명을 하겠다.
-> public member: 하위, 상위, 혹은 형제 class에서 이 member를 참조할
수 있다.
-> private member: 다른 어떤 class도 이 member를 참조할 수 없다.
인자에 대해 알아보도록 하자.
-> QWidget *parent: 위에서 언급한 QWidget의 parent인자와 같다.
-> const char *name: " "
-> WFlags f: " "
-> bool allowLines: 만약 FALSE로 setting된다면 수평라인과 수직라인
을 쓰지 않는다.
---------- < source 2.2.1.3. testFrameButton.cpp > -----------
#include <qapplication.h>
#include <qwidget.h>
#include <qframe.h>
#include <qpushbutton.h> /* QPushButton을 위한 header file */
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
QWidget *wdgtTest = new QWidget();
wdgtTest->setGeometry(100, 100, 200, 100);
QFrame *frTest = new QFrame(wdgtTest);
frTest->setGeometry(10, 10, 150, 60);
/* 형태에 주의하여 보자. */
frTest->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
/* text가 "테스트", parent가 frTest로 설정되어있다. */
QPushButton *bttnTest = new QPushButton("테스트", frTest);
/* frTest와 마찬가지로 bttnTest 또한 frTest에 대한 상대 */
/* 적인 좌표로 설정된다. */
bttnTest->setGeometry(20, 20, 100, 30);
// bttnTest->resize(100, 30);
myapp.setMainWidget(wdgtTest);
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
/usr/lib/qt/include/qframe.h에 보면 setFrameStyle에 대해 다음
과 같이 쓰여져 있다.
void setFrameStyle(int);
인자부분을 보면 integer형인데 이곳에 들어갈 수 있는 인자 또한
header file에 잘 나타나있다.
enum { NoFrame = 0, // no frame
Box = 0x0001, // rectangular box
Panel = 0x0002, // rectangular panel
WinPanel = 0x0003, // rectangular panel (Windows)
HLine = 0x0004, // horizontal line
VLine = 0x0005, // vertical line
MShape = 0x000f,
Plain = 0x0010, // plain line
Raised = 0x0020, // raised shadow effect
Sunken = 0x0030, // sunken shadow effect
MShadow = 0x00f0 };
enumeration 되어진 member들을 주의깊게 보면 숫자가 끊어져있는 것
을 알 수 있다. 즉 0x0001~0x0005, 0x000f, 0x0010, 0x0020, 0x0030,
0x00f0. 이 16진수들을 2진수로 풀어보자.
0x0001 => 0000 0000 0000 0001
0x0002 => 0000 0000 0000 0010
0x0003 => 0000 0000 0000 0011
0x0004 => 0000 0000 0000 0100
0x0005 => 0000 0000 0000 0101
0x000f => 0000 0000 0000 1111
0x0010 => 0000 0000 0001 0000
0x0020 => 0000 0000 0010 0000
0x0030 => 0000 0000 0011 0000
0x00f0 => 0000 0000 1111 0000
위의 2진수 값에서도 볼 수 있듯이 bit operation을 적당하게만 쓴
다면 여러 모양의 Frame Style을 나타낼 수 있는 조합이 나오게 된다.
예를 들어 [ Box | WinPanel | Sunken ]을 하게 되면 윈도우즈 스타
일의 움푹 들어간 입체 라인을 나타내준다.
/usr/lib/qt/include/qpushbutton.h에는 다음과 같이 class가 선
언되어있다.
public:
QPushButton( QWidget *parent=0, const char *name=0 );
QPushButton( const char *text, QWidget *parent=0,
const char *name=0 );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QPushButton( const QPushButton & );
QPushButton &operator=( const QPushButton & );
#endif
혹여 궁금하게 생각할 수도 있는 부분
QPushButton &operator=( const QPushButton & );
은 다음 보여드릴 source 2.2.1.4에서 설명하겠다.
보는 바와 같이 QPushButton의 인자에는 문자열 "테스트"와
frTest가 들어가있다. 종속성에 대한 설명은 위해서 이미 했
으므로 여기서는 생략하겠다. 각 widget들의 속성에 대한 설정은
setGeometry로 할 수도 있고, resize라는 함수로도 설정이 가능
하다. 이 두 함수는 설정값에서 약간의 차이가 있다.
setGeometry는 좌표와 크기에 대한 설정이 모두 들어가지만 resize
함수는 x좌표와 y좌표만이 인자로 들어간다. 이 두 함수는 widget
들에 대한 속성 설정이므로 QWidget의 하위 class들의 public함수
에 모두 선언이 되어있다. 물론 QWidget도 이들 함수를 포함하고 있다.
2.2.1.1. Class를 생성하여 만들기
이제부터는 위에서 설명한 source들을 사용하여 분할 컴파일하는 방
법을 알아보자. 우선 source들을 각 특성단위로 분리시켜야한다.
다음은 이렇게 분리된 source code들이다.
--------- < source 2.2.1.1.1 clssTestWidget.h > -----------
#include <qwidget.h> /* 아래쪽의 public QWidget 부분에 대한 header */
/* 아래쪽에 있는 frTest와 bttnTest를 선언하기 위한 class 선언. */
/* 일반함수 선언과 비슷함에 유의 */
class QFrame;
class QPushButton;
/* clssTestWidget class는 QWidget의 모든 public변수 혹은 class를 */
/* 공유할 수 있다. 즉 clssTestWidget class는 QWidget으로부터 '상속' */
/* 받은 class이다. */
class clssTestWidget : public QWidget
{
/* Qt library를 쓰는 class라면 항상 이렇게 선언해놓아야 한다. */
Q_OBJECT
public:
clssTestWidget(); /* 생성자 */
~clssTestWidget(); /* 소멸자 */
/* widget(bttnTest)의 특정 SIGNAL이 발생했을 때, event를 받아 */
/* 원하는 처리를 해줄 수 있는 slot function 선언 */
public slots:
void printMessage();
/* 후에 설명하겠다. 우선은 이런 format도 있다는 정도로 알아두자. */
protected:
private:
QFrame *frTest;
QPushButton *bttnTest;
};
-----------------------------------------------------------
--------- < source 2.2.1.1.2 clssTestWidget.cpp > ---------
#include <qframe.h> /* frTest를 위한 header 선언 */
#include <qpushbutton.h> /* bttnTest를 위해 */
#include <stdio.h>
#include "clssTestWidget.h"
clssTestWidget::clssTestWidget()
{
QFrame *frTest = new QFrame(this);
frTest->setGeometry(10, 10, 150, 60);
frTest->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
QPushButton *bttnTest = new QPushButton("테스트", frTest);
bttnTest->setGeometry(20, 20, 100, 30);
/* 버튼이 'clicked()'되었을 때 printMessage()함수를 호출하라는 */
/* 행동 지침 */
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(printMessage()));
}
clssTestWidget::~clssTestWidget()
{
}
/* 버튼이 눌렸을 때 처리되는 함수 */
void clssTestWidget::printMessage()
{
emit printf("버튼이 눌렸습니다.\n");
}
-----------------------------------------------------------
--------- < source 2.2.1.1.3 main_test1.cpp > ---------
#include <qapplication.h> /* QApplication을 위한 header file */
#include "clssTestWidget.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
/* class 생성 */
clssTestWidget *wdgtTest = new clssTestWidget();
/* class 속성정의 */
wdgtTest->setGeometry(100, 100, 200, 100);
/* main으로 쓸 widget 정의 */
myapp.setMainWidget(wdgtTest);
/* widget을 보여줌 */
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
이 source들에 앞서 설명한 source와의 차이점은, file들이 분리
되었고 class를 정의하여 그 class를 main에서 호출한다는 것
말고는 거의 없다. 따라서 더이상의 설명은 생략하고 다음으로
Maikfile에 대한 간단한 설명과 함께 이 분할 module들을 compile
하는 방법에 대해 알아보겠다.
2.2.2. Makefile 만들기
2.2.1.에서의 source들을 compile하는 방법에 대해서는 아직 언
급하지 않았다. Qt 2.0이상부터는 제법 GUI Tool이 괜찮아진 모
양이던데 필자도 한번은 사용을 해 보았지만 버그가 몇 가지 있
는 것 같아 지금은 전혀 사용하지 않고 있다. Makefile을 만드는
방법에 있어서도 요샌 tmake라는 GUI Tool을 사용한다고 들었다.
필자는 이 Tool도 사용하지 않는다. 이유는 간단하다. Makefile
을 마음대로 주무르기 위해서이다.
Makefile을 완전하게 이해하고 쉽게 쓸 수 있는 수준이라면 tmake
를 사용하는 것도 나쁘지는 않을 것이다.
아래의 code는 2.2.1.1의 source들을 분할 Compile하기 위한
Makefile이다.
---------------- < Makefile 2.2.2 > ---------------------
PROGS = main_test1 ### 보통 실행file의 이름을 적는다.
### X-window 환경에 관한 library들을 포함시킨다. (Qt 포함)
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
### Compiler를 정의한다.
CC = g++
GCC = gcc
### Header file들을 포함시킨다.
INCLUDE = -I/usr/lib/qt/include
### Compile option을 정의한다.
C_FLAG = -pipe -DNO_DEBUG -O2
### Header file에 대한 option과 Compile option을 합한다.
CFLAGS = $(INCLUDE) $(C_FLAG)
### 실행file생성을 위한 Linker를 정의한다. 여기서는 g++이 된다.
SYSCONF_LINK = $(CC)
### class를 분리시켜놓은 Header file을 .cpp source file과 연동
### 시키며 시스템에서 초기화된 graphic device에 관한 setting을
### 시키기 위한 특수한 cpp file인 moc file을 생성시키는 tool이
### 다. moc file에 대한 분석은 별로 필요없는 부분이므로 생략하
### 겠다.
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
### main함수가 들어있는 source file을 Link시킬 때 필요한 Object file
### 들을 후에 참조하기 편하도록 Label로 묶어놓는다.
MNU_OBJS = \
main_test1.o \
clssTestWidget_moc.o \
clssTestWidget.o
### 'make all'은 이 Makefile을 실행한다. (= make)
all: $(PROGS)
### 'make clean'은 make를 실행시켰을때 새로 생성되는 모든 file
### 을 지우는 역할을 한다. clean, all, 모두 사용자가 어떻게 정
### 의하는가에 따라 역할이 틀려지게 된다.
clean:
rm -f *.o
rm -f main_test1
rm -f *_moc.*
############# COMPILE #############
### main file을 컴파일한다.
main_test1.o: main_test1.cpp
$(CC) -c main_test1.cpp $(CFLAGS) -o $@
### Header file로부터 moc file을 만들어낸다.
clssTestWidget_moc.cpp: clssTestWidget.h
$(MOC) clssTestWidget.h -o clssTestWidget_moc.cpp
### 만들어진 moc file을 컴파일한다.
clssTestWidget_moc.o: clssTestWidget_moc.cpp
$(CC) -c clssTestWidget_moc.cpp $(CFLAGS) -o $@
### 새로 분리된 module file을 컴파일한다.
clssTestWidget.o: clssTestWidget.cpp
$(CC) -c clssTestWidget.cpp $(CFLAGS) -o $@
### 맨 윗부분의 PROG정의부에 있는 이름을 Label로 쓴다.
main_test1: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
------------------------------------------------------------
shell상에서 'make' 혹은 'make all' 을 실행시키면 자동적으로
compile 및 link를 시켜준다. make는 object file의 생성시간, 즉
compile된 시점을 기준으로 source에 변화가 생겼을 때 그 변화된
source module만을 compile함으로써 전체를 Compile하는 시간을 크
게 줄여주는 효과가 있다. 물론 source module이 두세개 정도로 작
다면 굳이 Makefile을 만들어줄 필요가 없다.
하지만 보통 실제 project들의 경우 상당한 수의 source module을
필요로 하기때문에 Makefile의 생성은 필수적이라 할 수 있다.
다음으로 소개하는 source들에 대해서는 모든 source의 Makefile
을 source바로 밑에 주석없이 소개하도록 하겠다. Makefile을 사용
하는데 있어 적게라도 도움이 되었으면 한다.
2.2.3. 라벨(QLabel)
이제부터 2.2.10까지의 모든 예제는 앞에서 사용한 분할 module compile
방법을 따르기로 하겠다. 물론 기존에 설명했던 부분들은 모두 생략한다.
우선 source를 보도록 하자.
-------------- < source 2.2.3.1 clssTestLabel.h > ---------------
#include <qwidget.h>
class QLabel;
class clssTestLabel : public QWidget
{
Q_OBJECT
public:
clssTestLabel();
~clssTestLabel();
public slots:
protected:
private:
QLabel *lblTest1;
QLabel *lblTest2;
QLabel *lblTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.3.2 clssTestLabel.cpp > ---------------
#include <qlabel.h>
#include <qframe.h>
#include "clssTestLabel.h"
clssTestLabel::clssTestLabel()
{
QLabel *lblTest1 = new QLabel(this);
lblTest1->setText("테스트 1");
lblTest1->setGeometry(20, 20, 100, 30);
/* QLabel에서 setFrameStyle함수를 호출했다는 것을 명심하자. */
lblTest1->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Raised);
QLabel *lblTest2 = new QLabel(this);
lblTest2->setText("테스트 2");
lblTest2->setGeometry(20, 60, 100, 30);
lblTest2->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Sunken);
QLabel *lblTest3 = new QLabel(this);
lblTest3->setText("테스트 3");
lblTest3->setGeometry(20, 100, 100, 30);
lblTest3->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Plain);
}
clssTestLabel::~clssTestLabel()
{
}
-------------------------------------------------------------------
위의 Source는 총 세가지 모양의 Label format을 나타내준다.
특이할 만한 점은 QLabel에서 setFrameStyle을 호출했다는 것인데
/usr/lib/qt/include/qlabel.h에서는 setFrameStyle함수가 선언되어있지
않다. qframe.h file에서만이 선언되어있는데 QLabel은 QFrame class에서
파생되어 나온 자식 class이므로 QFrame class에서 선언되어있는 모든
public함수들을 공유하여 쓸 수 있다. 물론 enumeration된 Box, Panel등
을 쓸 때는 QLabel의 member들이 아니므로 QFrame::과 같이 소속을 적어
주어야 Compiler가 알아들을 수 있다.
-------------- < source 2.2.3.3 main_test2.cpp > ---------------
#include <qapplication.h>
#include "clssTestLabel.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestLabel *clssTest = new clssTestLabel();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.3.1 > ----------------------
PROGS = main_test2
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test2.o \
clssTestLabel_moc.o \
clssTestLabel.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test2
rm -f *_moc.*
############# COMPILE #############
main_test2.o: main_test2.cpp
$(CC) -c main_test2.cpp $(CFLAGS) -o $@
clssTestLabel_moc.cpp: clssTestLabel.h
$(MOC) clssTestLabel.h -o clssTestLabel_moc.cpp
clssTestLabel_moc.o: clssTestLabel_moc.cpp
$(CC) -c clssTestLabel_moc.cpp $(CFLAGS) -o $@
clssTestLabel.o: clssTestLabel.cpp
$(CC) -c clssTestLabel.cpp $(CFLAGS) -o $@
main_test2: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.4. 편집박스(QLineEdit)
-------------- < source 2.2.4.1 clssTestLineEdit.h > ---------------
#include <qwidget.h>
class QLineEdit;
class QPushButton;
class clssTestLineEdit : public QWidget
{
Q_OBJECT
public:
clssTestLineEdit();
~clssTestLineEdit();
public slots:
void testClick();
protected:
private:
QLineEdit *leTest1;
QLineEdit *leTest2;
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.4.2 clssTestLineEdit.cpp > ---------------
#include <qlineedit.h>
#include <qpushbutton.h>
#include <stdio.h>
#include "clssTestLineEdit.h"
clssTestLineEdit::clssTestLineEdit()
{
leTest1 = new QLineEdit(this);
leTest1->setGeometry(20, 20, 100, 30);
leTest2 = new QLineEdit(this);
leTest2->setGeometry(20, 60, 100, 30);
leTest2->setText("환영!");
/* setEnabled는 편집을 할 수 있게 할 것인지 아닌지를 결정한다. */
/* true->편집가능, false->편집불가능 */
leTest2->setEnabled(false);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(20, 100, 100, 30);
/* 버튼(bttnTest)이 눌렸(clicked())을 때 testClick()함수를 실행하라 */
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(testClick()));
}
clssTestLineEdit::~clssTestLineEdit()
{
}
void clssTestLineEdit::testClick()
{
/* leTest1->text()는 현재 leTest1 편집박스안에 표시되어있는 */
/* text를 가져온다. */
emit printf("편집박스1의 텍스트는 < %s >입니다.\n",
leTest1->text());
emit printf("편집박스2의 텍스트는 < %s >입니다.\n",
leTest2->text());
}
-------------------------------------------------------------------
QLineEdit class는 윈도우즈의 edit box와 같은 기능을 하는 class이다.
특수키(예: 방향키, insert, delete, home, end등)들을 쓸 수 있으며
X-window와의 호환도 이루어진다. 즉 편집박스에 있는 문자열은 마우스
로 < copy and paste > 할 수 있다는 이야기다. 가장 자주 쓰이는 Widget
이니 꼭 기억해두자.
-------------- < source 2.2.4.3 main_test3.cpp > ---------------
#include <qapplication.h>
#include "clssTestLineEdit.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestLineEdit *clssTest = new clssTestLineEdit();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.4 > ----------------------
PROGS = main_test3
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test3.o \
clssTestLineEdit_moc.o \
clssTestLineEdit.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test3
rm -f *_moc.*
############# COMPILE #############
main_test3.o: main_test3.cpp
$(CC) -c main_test3.cpp $(CFLAGS) -o $@
clssTestLineEdit_moc.cpp: clssTestLineEdit.h
$(MOC) clssTestLineEdit.h -o clssTestLineEdit_moc.cpp
clssTestLineEdit_moc.o: clssTestLineEdit_moc.cpp
$(CC) -c clssTestLineEdit_moc.cpp $(CFLAGS) -o $@
clssTestLineEdit.o: clssTestLineEdit.cpp
$(CC) -c clssTestLineEdit.cpp $(CFLAGS) -o $@
main_test3: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.4.1 QObject::connect, SIGNAL과 SLOT
/usr/lib/qt/include/qobject.h에 선언되어있는 connect함수를 보자.
static bool connect( const QObject *sender, const char *signal,
const QObject *receiver, const char *member );
bool connect( const QObject *sender, const char *signal,
const char *member ) const;
위와 같이 두가지로 선언되어있는데 밑에 있는 bool type의 형태에서
빠져있는 const QObject *receiver 는 default로 < this >로 정해져있다.
즉 const char *member 는 this class 의 member라야한다.
마찬가지로 첫번째의 static bool type의 형태에서는 member가
< const QObject *receiver >의 member이어야 한다.
각 인자들을 보면 이 함수가 하는 기능이 무엇인지 알 수 있다.
const QObject *sender : signal을 보내줄 class 객체.
const char *signal : '사용자가 취한 행동'이다.
const QObject *receiver : signal을 받아서 처리할 class 객체.
const char *member : 보통 receiver class의 public member 함수를
쓴다.
const char *signal에 대해 좀더 자세히 알아보자.
예제 2.2.4.2의 Source중
QObject::connect(bttnTest, SIGNAL(clicked()), this, SLOT(testClick()));
부분에서 보면 const char *signal 부분을 SIGNAL(clicked())로 해놓았다.
QPushButton의 header file을 보면 다음과 같이 signal 함수들이 선언되어
있는 것을 알 수 있다.
signals:
void pressed();
void released();
void clicked();
void toggled( bool );
각각의 함수들은 함수 자체의 이름에 해당되는 사용자의 행동이 일어났을
때 부합하는 signal을 'this'라는 class에 전해주게 된다. 여기서 this는
class clssTestLineEdit를 말하며, 따라서 connect함수의 마지막 인자인
const char *member부분에는 clssTestLineEdit의 member함수인 testClick
함수가 오게 된 것이다.
< SLOT >이 하는 일은 차차 이야기 하겠다. 우선 그냥 이렇게 쓴다고 문법
처럼 생각을 해두자. member 인자부분은 만약 member 함수를 쓸 경우 반드
시 SLOT안에 member를 두어야하며 또한 이 member 함수는 public slots:
혹은 private slots: 에 선언되어있어야 한다.
2.2.5. 콤보박스(QComboBox)
-------------- < source 2.2.5.1 clssTestComboBox.h > ---------------
#include <qwidget.h>
class QComboBox;
class QPushButton;
class clssTestComboBox : public QWidget
{
Q_OBJECT
public:
clssTestComboBox();
~clssTestComboBox();
public slots:
void testClick();
protected:
private:
QComboBox *cbTest; /* 콤보박스에 대한 class */
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.5.2 clssTestComboBox.cpp > ---------------
#include <qcombobox.h>
#include <qpushbutton.h>
#include <stdio.h>
#include "clssTestComboBox.h"
clssTestComboBox::clssTestComboBox()
{
cbTest = new QComboBox(this);
cbTest->setGeometry(20, 20, 100, 30);
/* ComboBox에 item들을 넣는다. */
cbTest->insertItem("첫번째", 0);
cbTest->insertItem("두번째", 1);
cbTest->insertItem("세번째", 2);
cbTest->insertItem("네번째", 3);
cbTest->setCurrentItem(0);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(20, 100, 100, 30);
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(testClick()));
}
clssTestComboBox::~clssTestComboBox()
{
}
void clssTestComboBox::testClick()
{
/* cbTest->currentText()는 현재 ComboBox에서 보이는 */
/* text를 return한다. */
emit printf("콤보박스1의 텍스트는 < %s >입니다.\n",
cbTest->currentText());
}
-------------------------------------------------------------------
틀린부분이 거의 없으므로 QComboBox에 대해서만 설명하겠다.
/usr/lib/qt/include/qcombobox.h를 열어보자.(주의: 만약 당신이 Qt를
다운받아 다른 곳에 인스톨 시켰다면 path가 틀려질 것임.)
public:
QComboBox( QWidget *parent=0, const char *name=0 );
QComboBox( bool rw, QWidget *parent=0, const char *name=0 );
몇몇 특정 widget들을 제외하고는 거의 인자가 비슷하다. 인자들에 관
한 설명은 앞서 이야기했던 부분들과 같으므로 설명을 생략하겠다.
그러면 이번에는 < cbTest->insertItem("첫번째", 0); >부분을 보자.
header file에는 insertItem함수가 다음과 같이 선언되어있다.
이 함수는 콤보박스에 item을 추가할 때 사용하는 함수이다.
void insertItem( const char *text, int index=-1 );
void insertItem( const QPixmap &pixmap, int index=-1 );
첫번째 선언문을 보자.
const char *text는 콤보박스에 추가시킬 text이고 int index는 그 text
의 순번이다. index는 0번부터 시작한다. -1로 초기화되어있다는 것은
콤보박스에 아무 item도 들어있지 않다는 뜻이다. Compile해서 실행시켜
보기 바란다. 좀더 확실하게 이해가 될 것이다.
다음으로 cbTest->currentText()부분을 보자.
header file의 선언을 보면 다음과 같다.
const char *currentText() const;
이 함수는 현재 콤보박스에 나타나있는 text를 return한다.
콤보박스의 현재 text를 setting하는 함수는
void setCurrentItem( int index );
이다. 여기서의 index의 의미는 insertItem의 index의 의미와 동일하다.
< cbTest->setCurrentItem(0); >이 뜻하는 것은 첫번째 item을 현재 text
로 보여주겠다는 이야기다.
-------------- < source 2.2.5.3 main_test4.cpp > ---------------
#include <qapplication.h>
#include "clssTestComboBox.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestComboBox *clssTest = new clssTestComboBox();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.5 > ----------------------
PROGS = main_test4
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test4.o \
clssTestComboBox_moc.o \
clssTestComboBox.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test4
rm -f *_moc.*
############# COMPILE #############
main_test4.o: main_test4.cpp
$(CC) -c main_test4.cpp $(CFLAGS) -o $@
clssTestComboBox_moc.cpp: clssTestComboBox.h
$(MOC) clssTestComboBox.h -o clssTestComboBox_moc.cpp
clssTestComboBox_moc.o: clssTestComboBox_moc.cpp
$(CC) -c clssTestComboBox_moc.cpp $(CFLAGS) -o $@
clssTestComboBox.o: clssTestComboBox.cpp
$(CC) -c clssTestComboBox.cpp $(CFLAGS) -o $@
main_test4: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.6. 리스트(QListView)
-------------- < source 2.2.6.1 clssTestListView.h > ---------------
#include <qwidget.h>
class QListView;
class QListViewItem;
class QLabel;
class QFrame;
class clssTestListView : public QWidget
{
Q_OBJECT
public:
clssTestListView();
~clssTestListView();
public slots:
void appearItem();
protected:
private:
QFrame *frTest;
QListView *lvTest;
QListViewItem *lviTest[10];
QLabel *lblTest1;
QLabel *lblTest2;
QLabel *lblTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.6.2 clssTestListView.cpp > ---------------
#include <qlistview.h>
#include <qlabel.h>
#include <qframe.h>
#include <stdio.h>
#include "clssTestListView.h"
clssTestListView::clssTestListView()
{
int i;
char szTest1[50], szTest2[50], szTest3[50];
/* List의 가장자리선의 처리를 위해 frame을 그린다. */
frTest = new QFrame(this);
frTest->setGeometry(20, 20, 200, 200);
frTest->setFrameStyle(QFrame::Box | QFrame::Sunken |
QFrame::WinPanel);
lvTest = new QListView(frTest);
/* frame에서 약 3정도 사방으로 적은 크기가 가장 적당하다. */
lvTest->setGeometry(3, 3, 194, 194);
/* 각 field의 title을 정한다. */
lvTest->addColumn(" 첫번째 ");
lvTest->addColumn(" 두번째 ");
lvTest->addColumn(" 세번째 ");
/* tree장식을 할 것인지 아닌지를 결정한다. */
lvTest->setRootIsDecorated(true);
for (i = 0; i < 9; i++)
{
memset(szTest1, '\0', 50);
memset(szTest2, '\0', 50);
memset(szTest3, '\0', 50);
sprintf(szTest1, "환영 %d", i);
sprintf(szTest2, "리눅스 %d", i);
sprintf(szTest3, "만세 %d", i);
/* 첫번째 두번째 세번째*/
lviTest[i] = new QListViewItem(lvTest, szTest1, szTest2, szTest3);
}
/* List(lvTest)에서 item(lviTest[])이 선택(selectionChanged()) */
/* 되어질 때 this class(clssTestListView)의 member function */
/* (appearItem())을 수행해라. */
QObject::connect(lvTest, SIGNAL(selectionChanged()), this,
SLOT(appearItem()));
lblTest1 = new QLabel(this);
lblTest1->setGeometry(20, 230, 150, 20);
lblTest2 = new QLabel(this);
lblTest2->setGeometry(20, 260, 150, 20);
lblTest3 = new QLabel(this);
lblTest3->setGeometry(20, 290, 150, 20);
}
clssTestListView::~clssTestListView()
{
}
void clssTestListView::appearItem()
{
/* 선택된 item의 첫번째 field를 Label로 나타냄 */
lblTest1->setText(lvTest->currentItem()->text(0));
/* 선택된 item의 두번째 field를 Label로 나타냄 */
lblTest2->setText(lvTest->currentItem()->text(1));
/* 선택된 item의 세번째 field를 Label로 나타냄 */
lblTest3->setText(lvTest->currentItem()->text(2));
}
-------------------------------------------------------------------
/usr/lib/qt/include/qlistview.h file의 선언을 보자.
public:
QListView( QWidget * parent = 0, const char * name = 0 );
다른 widget들과 별 차이가 없으므로 설명은 생략한다.
virtual int addColumn( const char * label, int size = -1);
field의 제목(const char *label)을 지정한다.
size에 대해서는 값정의가 되어있으므로 써도 그만 안써도 그만이라는
이야기인데 흔히 field의 size를 임의로 정해서 해당 field의 값을 찾
아내는데 쓰이는 인자이다. 다시 이야기할 기회가 있을 지는 모르겠지
만 그렇게 중요한 인자는 아니므로 설명은 이쯤 해 두겠다.
virtual void setRootIsDecorated( bool );
만약 인자값을 false로 준다면 첫번째 field의 item들 앞에는 아무것
도 없게 된다.
현재 tree장식이 되어있는지 아닌지를 검사하고 싶다면 다음 함수를 써라.
bool rootIsDecorated() const;
이번에는 실제 item을 List에 삽입하는 방법에 대해 알아보자.
header file에는 다음과 같이 QListViewItem을 선언하고 있다.
public:
QListViewItem( QListView * parent );
QListViewItem( QListViewItem * parent );
QListViewItem( QListView * parent, QListViewItem * after );
QListViewItem( QListViewItem * parent, QListViewItem * after );
QListViewItem( QListView * parent,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListViewItem * parent,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListView * parent, QListViewItem * after,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListViewItem * parent, QListViewItem * after,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
약간 복잡하다고 생각할 지도 모르지만 상당히 간단한 선언이다.
우선 parent인자부터 살펴보자.
위에서 선언된 parent인자의 type은 < QListView * > 와 < QListViewItem * >
이 두가지이다.
< QListView * >를 parent인자로 받는다는 것은 현재 생성되어있는 List
에 < const char * > 형태의 text를 item으로 삽입한다는 뜻이다.
< QListViewItem * >를 parent인자로 받는다는 것은 List의 특정 item(parent)
을 root로 하는 tree구조로서 그 item의 자식 node를 삽입한다는 뜻이다.
언뜻 이해가 가지 않을 것이다. 위 source에서
< lviTest[i] = new QListViewItem(lvTest, szTest1, szTest2, szTest3); >
이 포함되어있는 for loop문을 다음과 같이 바꾼 후 Compile하여 실행시켜
보라.
lviTest[0] = new QListViewItem(lvTest,
"테스트1-1", "테스트1-2", "테스트1-3");
lviTest[1] = new QListViewItem(lviTest[0],
"테스트2-1", "테스트2-2", "테스트2-3");
실행시켜보면 위에서 필자가 이야기했던 부분들이 쉽게 이해가 갈 것이다.
다음은 List에서 삽입된 text를 얻는 방법에 대한 설명이다.
lblTest1->setText(lvTest->currentItem()->text(0));
QListViewItem의 text를 얻는 방법은 간단하다.
만약 QListViewItem type의 class가 lviTest1이라면, lviTest1의 첫번째
field의 text를 얻으려면 < lviTest1->text(0); >이라고 하면 될 것이다.
ComboBox와 비슷하지만 index가 의미하는 것이 틀리므로 유의하기 바란다.
위에서 lvTest->currentItem()이 의미하는 것은 현재 List에서 선택된
Item set을 말한다. header file에는 currentItem()함수가 다음과 같이
선언되어 있다.
QListViewItem * currentItem() const;
type을 보면 QListViewItem이다. 이는 currentItem()이 QListViewItem
class의 모든 member들을 참조할 수 있다는 이야기가 된다.
따라서 현재 List에서 선택된 Item의 두번째 field의 text를 알고 싶다면
다음과 같이 하면 된다.
lblTest1->setText(lvTest->currentItem()->text(1));
이번엔 QListView에서 발생가능한 Signal에 대해 알아보도록 하자.
header file을 보면 다음과 같이 총 6개의 signal함수가 있다.
signals:
void selectionChanged();
void selectionChanged( QListViewItem * );
void currentChanged( QListViewItem * );
void doubleClicked( QListViewItem * );
void returnPressed( QListViewItem * );
void rightButtonClicked( QListViewItem *, const QPoint&, int );
void rightButtonPressed( QListViewItem *, const QPoint&, int );
각 Signal들의 발생요인은 위함수의 제목과 동일하다.
-------------- < source 2.2.6.3 main_test5.cpp > ---------------
#include <qapplication.h>
#include "clssTestListView.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestListView *clssTest = new clssTestListView();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.6 > ----------------------
PROGS = main_test5
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test5.o \
clssTestListView_moc.o \
clssTestListView.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test5
rm -f *_moc.*
############# COMPILE #############
main_test5.o: main_test5.cpp
$(CC) -c main_test5.cpp $(CFLAGS) -o $@
clssTestListView_moc.cpp: clssTestListView.h
$(MOC) clssTestListView.h -o clssTestListView_moc.cpp
clssTestListView_moc.o: clssTestListView_moc.cpp
$(CC) -c clssTestListView_moc.cpp $(CFLAGS) -o $@
clssTestListView.o: clssTestListView.cpp
$(CC) -c clssTestListView.cpp $(CFLAGS) -o $@
main_test5: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.7. 체크박스(QCheckBox), 라디오버튼(QRadioButton)
-------------- < source 2.2.7.1 clssTestButton.h > ---------------
#include <qwidget.h>
class QButtonGroup;
class QRadioButton;
class QCheckBox;
class QPushButton;
class clssTestButton : public QWidget
{
Q_OBJECT
public:
clssTestButton();
~clssTestButton();
public slots:
void procButton();
protected:
private:
/* QRadioButton을 묶기 위한 Group class 선언 */
QButtonGroup *bgTest;
QRadioButton *rbTest1;
QRadioButton *rbTest2;
QCheckBox *chkbTest1;
QCheckBox *chkbTest2;
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.7.2 clssTestButton.cpp > ---------------
#include <qradiobutton.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qbuttongroup.h>
#include <stdio.h>
#include "clssTestButton.h"
clssTestButton::clssTestButton()
{
/* radio button은 어느 한 버튼이 활성화되면 다른 버튼들은 */
/* 비활성화되어야 한다. 이런 기능을 위해 QButtonGroup class */
/* 를 정의한다. */
bgTest = new QButtonGroup(this);
bgTest->setGeometry(20, 20, 300, 100);
/* radio button들을 bgTest에 종속시킨다. */
rbTest1 = new QRadioButton("리눅스 라디오", bgTest);
rbTest1->setGeometry(20, 20, 100, 20);
rbTest2 = new QRadioButton("만세 라디오", bgTest);
rbTest2->setGeometry(150, 20, 100, 20);
/* radio button들이 단지 하나의 버튼만이 선택되게 하기 위해 */
/* 마지막으로 QButtonGroup class변수에 삽입시킨다. */
bgTest->insert(rbTest1, 0);
bgTest->insert(rbTest2, 1);
/* 체크박스 정의 */
chkbTest1 = new QCheckBox("리눅스 체크", this);
chkbTest1->setGeometry(20, 160, 100, 20);
chkbTest2 = new QCheckBox("만세 체크", this);
chkbTest2->setGeometry(150, 160, 100, 20);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(60, 250, 100, 30);
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(procButton()));
}
clssTestButton::~clssTestButton()
{
}
void clssTestButton::procButton()
{
if (rbTest1->isChecked())
emit printf("리눅스 라디오 버튼이 체크되어 있습니다.\n");
else if (rbTest2->isChecked())
emit printf("만세 라디오 버튼이 체크되어 있습니다.\n");
else
emit printf("체크되어있는 라디오 버튼이 없습니다.\n");
if (chkbTest1->isChecked())
emit printf("리눅스 체크 박스가 체크되어 있습니다.\n");
if (chkbTest2->isChecked())
emit printf("만세 체크 박스가 체크되어 있습니다.\n");
if (chkbTest1->isChecked() == false &&
chkbTest2->isChecked() == false)
emit printf("체크되어있는 체크박스가 없습니다.\n");
}
-------------------------------------------------------------------
QButtonGroup부터 보도록하자. /usr/lib/qt/include/qbuttongroup.h에는
다음과 같이 선언되어있다.
public:
QButtonGroup( QWidget *parent=0, const char *name=0 );
QButtonGroup( const char *title, QWidget *parent=0,
const char *name=0 );
인자들에 대한 설명은 별로 필요없으리라 생각하므로 생략하겠다.
생성자부분보다는 insert하는 부분의 설명이 필요하리라 생각한다.
int insert( QButton *, int id=-1 );
int id 는 group에 포함되는 버튼들의 id를 지정해주는 역할을 한다.
순서에는 상관 없으나 값은 고유값을 가져야 한다.
다음으로 checkbox의 header file /usr/lib/qt/include/qradiobutton.h 에
나타난 생성자부분을 보도록 하자.
public:
QRadioButton( QWidget *parent=0, const char *name=0 );
QRadioButton( const char *text, QWidget *parent=0,
const char *name=0 );
QRadioButton의 < const char *text > 인자에 문자열을 넘겨주면 그 문자열이
이 radiobutton의 title이 된다. 체크가 되어있는지를 검사하는 함수는
isChecked()이다. 인위적으로 checking하는 함수는 header file에 이렇게 선
언되어있다.
void setChecked( bool check );
isChecked(), setChecked(bool check) 두 함수 모두 QRadioButton과
QCheckBox에 똑같이 선언되어있고 또한 기능도 같다.
-------------- < source 2.2.7.3 main_test6.cpp > ---------------
#include <qapplication.h>
#include "clssTestButton.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestButton *clssTest = new clssTestButton();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.7 > ----------------------
PROGS = main_test6
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test6.o \
clssTestButton_moc.o \
clssTestButton.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test6
rm -f *_moc.*
############# COMPILE #############
main_test6.o: main_test6.cpp
$(CC) -c main_test6.cpp $(CFLAGS) -o $@
clssTestButton_moc.cpp: clssTestButton.h
$(MOC) clssTestButton.h -o clssTestButton_moc.cpp
clssTestButton_moc.o: clssTestButton_moc.cpp
$(CC) -c clssTestButton_moc.cpp $(CFLAGS) -o $@
clssTestButton.o: clssTestButton.cpp
$(CC) -c clssTestButton.cpp $(CFLAGS) -o $@
main_test6: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.8. 메뉴(QMenu)
-------------- < source 2.2.8.1 clssTestMenu.h > ---------------
#include <qwidget.h>
class QMenuBar;
class QPopupMenu;
class clssTestMenu : public QWidget
{
Q_OBJECT
public:
clssTestMenu();
~clssTestMenu();
public slots:
void funcTest1();
void funcTest2();
void funcTest3();
void funcTest4();
void funcTest5();
void funcTest6();
protected:
private:
/* Pulldown 메뉴를 위한 메뉴바 */
QMenuBar *mnuMainBar;
/* Popup 메뉴를 위한 메뉴 */
QPopupMenu *mnuTest1;
QPopupMenu *mnuTest2;
QPopupMenu *mnuTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.8.2 clssTestMenu.cpp > ---------------
#include <qapplication.h>
/* hot key를 위한 header. 여기서는 hot key를 쓰지 않는다. */
/* 한 번 시험삼아 hot key기능까지 넣어보기 바란다. */
#include <qkeycode.h>
/* QMenuBar를 위한 header */
#include <qmenubar.h>
/* QPopupMenu를 위한 header */
#include <qpopupmenu.h>
#include <stdio.h>
#include "clssTestMenu.h"
clssTestMenu::clssTestMenu()
{
/* 전체적인 window의 형태를 Microsoft Windows의 형태로 맞춘다. */
qApp->setStyle(WindowsStyle);
mnuTest1 = new QPopupMenu;
/* Popup menu에 아이템을 넣는다. */
mnuTest1->insertItem("테스트1메뉴의 서브메뉴1", this,
SLOT(funcTest1()));
mnuTest1->insertItem("테스트1메뉴의 서브메뉴2", this,
SLOT(funcTest2()));
mnuTest1->insertItem("테스트1메뉴의 서브메뉴3", this,
SLOT(funcTest3()));
mnuTest2 = new QPopupMenu;
mnuTest2->insertItem("테스트2메뉴의 서브메뉴1", this,
SLOT(funcTest4()));
mnuTest2->insertItem("테스트2메뉴의 서브메뉴2", this,
SLOT(funcTest5()));
mnuTest3 = new QPopupMenu;
mnuTest3->insertItem("테스트3메뉴의 서브메뉴1", this,
SLOT(funcTest6()));
/* 각 popup menu들을 pulldown menu에 삽입시킨다. */
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 테스트1 ", mnuTest1);
mnuMainBar->insertItem(" 테스트2 ", mnuTest2);
mnuMainBar->insertItem(" 테스트3 ", mnuTest3);
}
clssTestMenu::~clssTestMenu()
{
}
void clssTestMenu::funcTest1()
{
emit printf("test1 메뉴\n");
}
void clssTestMenu::funcTest2()
{
emit printf("test2 메뉴\n");
}
void clssTestMenu::funcTest3()
{
emit printf("test3 메뉴\n");
}
void clssTestMenu::funcTest4()
{
emit printf("test4 메뉴\n");
}
void clssTestMenu::funcTest5()
{
emit printf("test5 메뉴\n");
}
void clssTestMenu::funcTest6()
{
emit printf("test6 메뉴\n");
}
-------------------------------------------------------------------
위의 결과치를 미리 나타내자면 다음과 같다.
---------------------------------------------------------
| 테스트1 | 테스트2 | 테스트3 |
|---------------------------------------------------------|
|| 테스트1메뉴의 서브메뉴1 | |
|| 테스트1메뉴의 서브메뉴2 | |
|| 테스트1메뉴의 서브메뉴3 | |
| ------------------------- |
| |
| |
| -------------------------- |
---------------- ---------------
뭐 그렇게 특별한 내용은 없다. 한번만 훑어보면 금방 이해가 갈 것이다.
/usr/lib/qt/include/qpopupmenu.h를 살펴보자.
public:
QPopupMenu( QWidget *parent=0, const char *name=0 );
별로 설명할 필요는 없으리라 생각한다. 중요한 것은 insertItem함수인데
header file을 찾아보면 알겠지만 이 함수가 member로 선언되어있지 않을
것이다. 그러면 어디에 선언이 되어 있을까?
QPopupMenu class의 선언부를 보자.
class Q_EXPORT QPopupMenu : public QTableView, public QMenuData
여기서 보면 QPopupMenu class는 QMenuData class로부터 상속을 받았다.
즉, QMenuData class의 public member들을 모두 QPopupMenu도 접근할 수
있다는 이야기다. 그러면 다시 /usr/lib/qt/include/pmenudata.h를 열어
보자. insertItem함수에 대한 선언이 다음과 같이 여러개가 선언되어있다.
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const QPixmap &pixmap,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const QPixmap &pixmap, const char *text,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const QPixmap &pixmap,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const QPixmap &pixmap, const char *text,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const char *text, int id=-1, int index=-1 );
int insertItem( const char *text, QPopupMenu *popup,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, QPopupMenu *popup,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, const char *text,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, const char *text,
QPopupMenu *popup,
int id=-1, int index=-1 );
이제는 밑도끝도 없이 insertItem이라는 함수가 어디서 튀어나왔는지 이
해가 될 것이다. 앞으로도 member function이 이런 식으로 호출되는 경우
가 가끔씩 있을 것이다. 당황하지 말고 차근차근 이해하기 바란다.
insertItem 함수에 대한 설명을 하자. 바로 위에 있는 모든 경우를 다 설
명할 필요는 없을 것 같다. source 2.2.8.2에서 쓰인 insertItem함수에
대한 설명만을 하겠다. 그 source에서 쓰인 함수는 바로 이 함수이다.
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel=0 );
각 인자에 대해 설명하겠다.
첫번째 인자 < const char *text >는 Popup menu에 들어갈 Item의 이름이다.
두번째 인자 < const QObject *receiver >는 Item의 이름이 삽입되는 class
이다.
세번째 인자 < const char *member >는 이 Item이 사용자에 의해 선택되어
click되었을 때 실행할 receiver의 member function이다.
네번째 인자 < int accel >은 header source 에서 잠깐 설명한 hot-key(혹
은 accel-key)를 말한다. accel-key에 대해 약간만 더 알아보자.
/usr/lib/qt/include/qkeycode.h에 보면 모든 key값들이 이런식으로 선언
혹은 정의되어있다.
.
.
.
const uint SHIFT = 0x00002000; // accelerator modifiers
const uint CTRL = 0x00004000;
const uint ALT = 0x00008000;
const uint ASCII_ACCEL = 0x10000000;
#define Key_Escape 0x1000 // misc keys
#define Key_Tab 0x1001
#define Key_Backtab 0x1002
#define Key_Backspace 0x1003
#define Key_Return 0x1004
#define Key_Enter 0x1005
#define Key_Insert 0x1006
#define Key_Delete 0x1007
#define Key_Pause 0x1008
#define Key_Print 0x1009
#define Key_SysReq 0x100a
#define Key_Home 0x1010 // cursor movement
#define Key_End 0x1011
#define Key_Left 0x1012
.
.
.
위에서 보면 SHIFT, CTRL, ALT, ASCII_ACCEL등은 4byte unsigned int
형태로 정의되어있고 나머지 key값들은 모두 2byte형태로 선언되어있
다. 이는 특수확장키인 SHIFT, CTRL, ALT key와 나머지 key들을 조합
하여 쓸수 있다는 이야기인데 예를 들어 다시 한번 설명하겠다.
만약 사용자가 < 테스트1메뉴의 서브메뉴1 >을 단축키 ALT+ENTER로
설정하고 싶다면 다음과 같이 하면 된다.
mnuTest1->insertItem("테스트1메뉴의 서브메뉴1", this,
SLOT(funcTest1()), ALT|ENTER);
이젠 QMenuBar에 대해 살펴보자.
/usr/lib/qt/include/qmenubar.h에는 다음과 같이 선언하고 있다.
class Q_EXPORT QMenuBar : public QFrame, public QMenuData
{
friend class QPopupMenu;
Q_OBJECT
public:
QMenuBar( QWidget *parent=0, const char *name=0 );
.
.
.
};
아무리 찾아보아도 insertItem함수를 찾을 수 없다. 하지만 QPopupMenu
의 경우와 마찬가지로 QMenuData의 모든 public member들을 상속받고
있다.
그러므로 이에 대한 설명은 더이상 하지 않아도 되리라 믿는다.
-------------- < source 2.2.8.3 main_test7.cpp > ---------------
#include <qapplication.h>
#include "clssTestMenu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestMenu *clssTest = new clssTestMenu();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.8 > ----------------------
PROGS = main_test7
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test7.o \
clssTestMenu_moc.o \
clssTestMenu.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test7
rm -f *_moc.*
############# COMPILE #############
main_test7.o: main_test7.cpp
$(CC) -c main_test7.cpp $(CFLAGS) -o $@
clssTestMenu_moc.cpp: clssTestMenu.h
$(MOC) clssTestMenu.h -o clssTestMenu_moc.cpp
clssTestMenu_moc.o: clssTestMenu_moc.cpp
$(CC) -c clssTestMenu_moc.cpp $(CFLAGS) -o $@
clssTestMenu.o: clssTestMenu.cpp
$(CC) -c clssTestMenu.cpp $(CFLAGS) -o $@
main_test7: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.9. 툴바(QToolBar), MainWindow(QMainWindow)
-------------- < source 2.2.9.1 clssTestToolBar.h > ---------------
#include <qmainwindow.h>
class QToolBar;
/* 이부분 < : public QMainWindow >을 주의 깊게 보기 바란다. */
class clssTestToolBar : public QMainWindow
{
Q_OBJECT
public:
clssTestToolBar();
~clssTestToolBar();
public slots:
void funcTest1();
void funcTest2();
void funcTest3();
protected:
private:
QToolBar *tbTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.9.2 clssTestToolBar.cpp > ---------------
#include <qapplication.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "clssTestToolBar.h"
#ifndef TEST1_TOOLTIP
/* ToolButton에 마우스를 갖다대었을 때 나올 풍선도움말을 선언한다. */
#define TEST1_TOOLTIP "첫번째 테스트"
#define TEST2_TOOLTIP "두번째 테스트"
#define TEST3_TOOLTIP "세번째 테스트"
#endif
clssTestToolBar::clssTestToolBar()
{
/* Icon를 저장할 QPixmap변수 선언 */
QPixmap iconTest1, iconTest2, iconTest3;
qApp->setStyle(WindowsStyle);
/* ToolBar에 들어갈 image들을 선언한 QPixmap변수에 Loading한다. */
iconTest1.load("./test1.gif");
iconTest2.load("./test2.gif");
iconTest3.load("./test3.gif");
tbTest = new QToolBar(this);
/* ToolBar의 방향은 수평이다. */
tbTest->setOrientation(tbTest->Horizontal);
/* ToolButton을 생성한다. */
QToolButton *tbttnTest1 = new QToolButton(iconTest1,
TEST1_TOOLTIP, 0, this, SLOT(funcTest1()),
tbTest, "test1");
QToolButton *tbttnTest2 = new QToolButton(iconTest2,
TEST2_TOOLTIP, 0, this, SLOT(funcTest2()),
tbTest, "test2");
QToolButton *tbttnTest3 = new QToolButton(iconTest3,
TEST3_TOOLTIP, 0, this, SLOT(funcTest3()),
tbTest, "test3");
}
clssTestToolBar::~clssTestToolBar()
{
}
void clssTestToolBar::funcTest1()
{
emit printf("첫번째 단축아이콘\n");
}
void clssTestToolBar::funcTest2()
{
emit printf("두번째 단축아이콘\n");
}
void clssTestToolBar::funcTest3()
{
emit printf("세번째 단축아이콘\n");
}
-------------------------------------------------------------------
/usr/lib/qt/include/qtoolbar.h를 살펴보자.
public:
QToolBar( const char * label,
QMainWindow *, QMainWindow::ToolBarDock = QMainWindow::Top,
bool newLine = FALSE, const char * name = 0 );
QToolBar( const char * label, QMainWindow *, QWidget *,
bool newLine = FALSE, const char * name = 0, WFlags f = 0 );
QToolBar( QMainWindow * parent = 0, const char * name = 0 );
여기서 주의깊게 보아야 할 부분이 한군데 있다. 바로 QMainWindow *parent
인자 부분이다. 이제까지 다뤘던 widget들은 parent 의 type이 모두 QWidget
이었다. 하지만 여기서는 QMainWindow이다. 그러면 계층정보를 좀 보자.
QMainWindow와 QToolBar 모두 QWidget의 하위 class로서 서로 형제간이다.
형제간에는 서로 종속될 수 있으므로 QToolBar의 parent를 QMainWindow로 정
의할 수 있다. QMenuBar또한 마찬가지이다. 이렇듯 class계층정보를 바탕으
로 상하관계를 설정해준다면 명확한 프로그래밍이 가능하게 된다.
/usr/lib/qt/include/qtoolbutton.h를 보자.
public:
QToolButton( QWidget * parent = 0, const char * name = 0 );
QToolButton( const QPixmap & pm, const char * textLabel,
const char * grouptext,
QObject * receiver, const char * slot,
QToolBar * parent, const char * name = 0 );
QToolButton( QIconSet s, const char * textLabel,
const char * grouptext,
QObject * receiver, const char * slot,
QToolBar * parent, const char * name = 0 );
source 2.2.9.2에서 쓰인 QToolButton 함수와 비교해서 설명하겠다.
QToolButton *tbttnTest1 = new QToolButton(iconTest1,
TEST1_TOOLTIP, 0, this, SLOT(funcTest1()),
tbTest, "test1");
이 함수는 header file에 선언된 세개의 함수중 두번째 함수가 쓰인
것이다.
두번째 함수의 첫번째 인자는 icon을 나타낸다. Qt에서는 여러가지
image file들 즉, bmp, gif, jpg, xpm 등등을 지원한다. 각 file들을
loading하는 방법은 약간씩 다르다. 이런 file들을 loading하는 방법
은 header file이나 혹은 Qt에서 제공하는 예제 프로그램들을 보면
금방 알 수 있을 것이다. gif와 jpg는 압축file이므로 먼저 Linux의
X-window에서 사용할 만한 format으로 변환시켜야한다. X-window에서
사용하는 file format은 xpm file인데 다음은 간단한 xpm file의 내
부를 vi로 열어본 것이다.
static char * Ant_xpm[] = {
"48 48 60 1",
" c None",
". c #492449244924",
"X c #618561856185",
"o c #9E799E799E79",
"O c #208120812081",
"+ c #514455555144",
"@ c #410341034103",
"# c #965896589658",
"$ c #082008200820",
"% c #8E388A288E38",
"& c #69A669A669A6",
"* c #71C675D671C6",
"= c #861782078617",
"- c #28A228A228A2",
"; c #104014511040",
": c #10400C300000",
"> c #410324921040",
", c #082004100000",
"< c #000000000000",
"1 c #71C63CF32081",
"2 c #8E38492428A2",
"3 c #208114511040",
"4 c #30C234D330C2",
"5 c #208110400820",
"6 c #492424921040",
"7 c #51442CB21861",
"8 c #38E320811040",
"9 c #104008200000",
"0 c #208114510820",
"q c #28A214510820",
"w c #79E741032081",
"e c #596530C21861",
"r c #10400C300820",
"t c #618534D32081",
"y c #30C218611040",
"u c #28A218610820",
"i c #79E7451428A2",
"p c #9658514430C2",
"a c #18610C300820",
"s c #186110400820",
"d c #30C21C711040",
"f c #49242CB21861",
"g c #104010400820",
"h c #59652CB21861",
"j c #492428A21861",
"k c #618538E32081",
"l c #30C21C710820",
"z c #69A634D32081",
"x c #20811C711861",
"c c #30C224921861",
"v c #30C22CB228A2",
"b c #186110401040",
"n c #410328A21861",
"m c #8617451428A2",
"M c #38E31C711040",
"N c #61855D755965",
"B c #69A638E32081",
"V c #410320811040",
"C c #51443CF330C2",
"Z c #514430C22081",
" . ",
" X. ",
" oOo ",
" +@ ",
" # $% ",
" %+ O ",
" &* =O ",
" O* =- ",
" o; =O ",
" &@ =-=X+= ",
" O. X:>,--# ",
" #<# *<12>3* = ",
" &4- ;56789<&$# ",
" o+$-= *0q<6,w,$;= o#",
" %;4* +8wq,ee<<<% *;%",
" %<O.#o #Xr8>tw<<<; o#.;+# ",
" %4% #+;<O% .9y<<u>,08<<<<<$-4# ",
" X;*$% &O<@5ipa<<<sd:O% ",
" +$% +$* *;fp8<,$$<<Xo ",
" @$% o$;o X4gh5<<7$#* %++-# ",
" #.$% oO. ;5jk9<<ld$ #X-;;.## ",
" #*.-<;;% o;.<2zu<<5y<* ;;+# ",
" .O.X=# =%=&X+6ia<,j4$;4# +- ",
" *@;<<$O+*x0<97yX=4<$#o=<= ",
" +;O4+&+O9<<<<ae0<= @<-.$O ",
" *$o %c8etd<<<vb<+ &<<$o ",
" %$* &nt2pe<<<$X@& &;+ ",
" o$- =07t2e<<5aOOX<@ %+ ",
" oO$o xt2qae,,79O<#X<+ ",
" @<= &>mtd<Mtjq<@< 4<* ",
" o&<+ NB7B<<<se<$+< o$;% ",
" +;4= :waa1,9jV5+X$ =<Oo ",
" #@$.# o9e9<d5j5,C -- @4 ",
"-<+# <7<,ue5<$% <& &$o ",
"o -5<8q:Z+o $ &;# ",
" o4$--&o +@ &$% ",
" o4$* <# ",
" =;O% %< ",
" o.<4o =4 ",
" o$<& ++ ",
" XO% -X ",
" ;o O# ",
" X@ $ ",
" ;= & ",
" &- ",
" -= ",
" %; ",
" %+ "};
약간 의외일 것이다. xpm file은 이처럼 C에서 바로 쓸 수 있는 char
형 pointer 변수인 것이다. 약간 감이 잡힐 것이다.
즉 압축 file인 gif를 QPixmap으로 Loading을 하게 되면 Loader는
이러한 char형 pointer로 변환을 해주고 그를 memory에 loading하게
된다. Windows System과 비슷하지 않은가? Windows에서도 이런 과정
을 거쳐 그림을 화면에 뿌려준다는 것은 웬만한 programmer라면 알
고 있을 것이다. 즉, gif나 jpg format을 Windows에서 접근 가능한
bmp로 변환시켜 memory에 loading한 다음 그를 화면에 나타낸다.
이런 bmp의 역할을 하는 것이 바로 Pixmap file인 xpm format file들
인 것이다. 이해가 됐을 지 모르겠다.
두번째 인자인 char 형 pointer인 textlabel은 Mouse Pointer가
ToolButton에 위치했을 때 나타낼 수 있는 Tooltip(풍선도움말)이다.
나머지 인자들은 지금까지 착실하게 source들을 이해했다면 설명할
필요가 없을 것 같아 생략하겠다.
-------------- < source 2.2.9.3 main_test8.cpp > ---------------
#include <qapplication.h>
#include "clssTestToolBar.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestToolBar *clssTest = new clssTestToolBar();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.9 > ----------------------
PROGS = main_test8
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test8.o \
clssTestToolBar_moc.o \
clssTestToolBar.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test8
rm -f *_moc.*
############# COMPILE #############
main_test8.o: main_test8.cpp
$(CC) -c main_test8.cpp $(CFLAGS) -o $@
clssTestToolBar_moc.cpp: clssTestToolBar.h
$(MOC) clssTestToolBar.h -o clssTestToolBar_moc.cpp
clssTestToolBar_moc.o: clssTestToolBar_moc.cpp
$(CC) -c clssTestToolBar_moc.cpp $(CFLAGS) -o $@
clssTestToolBar.o: clssTestToolBar.cpp
$(CC) -c clssTestToolBar.cpp $(CFLAGS) -o $@
main_test8: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.3. QT Library를 다운받으려면?
여러 Site가 있지만 가장 대표적인 Url은
< http://www.troll.no >
에서 다운받아 사용할 수 있다.
< 한마디 >.
지금까지 하나의 Project를 꾸미기 위해 그리 짧지만은 않은 과정을 거쳐왔습
니다.
기초 과정은 모두 끝난 것입니다. 아직 기초과정에 속한 network관련 Library
에 대한 설명의 화두도 나오지 않은 상태이지만 Project를 구현하기에는 충분한
실력을 쌓았다고 할 수 있겠죠. 기초 과정은 대략 설명이 끝났으므로 앞으로
나올 기초 부분에 연관된 code들에 대해서는 되도록이면 설명을 생략하도록 하
겠습니다.
===============================================================
< 3. 기본 Format 작성하기 >
이제부터 본격적으로 Project를 시작해보자.
Programming 순서는 여러분들도 잘 아시겠지만
< 입력->처리->출력 > 의 순서로 만들어야 한다. 이러한 과정은 여러분
들이 직접 Project를 개발할 때 유용한 방법이지 이렇게 발표혹은 세미
나형식의 대화에서는 별로 쓸모가 없다. 따라서 필자는 여러분이 가장
이해하기 쉬운 측면부터 파고들고자 한다.
우선 기본 format을 잡아보자.
기본 format은 Windows형태의 window가 가장 좋을 듯 하다.
요새는 리눅스 Application들도 Windows형태와 GUI가 비슷하다.
따라서 필자도 이 Format에 따르겠다.
--------------------------------------------------------
| 메뉴 영역 |
|--------------------------------------------------------|
| Icon 영역 |
|--------------------------------------------------------|
| |
| |
| |
| |
| 작업 영역 |
| |
| |
| ---------------- |
| ---- --------- |
|---- -----------------------|
3.1. 메뉴 만들기
메뉴는 다음과 같이 하나의 Popup Menu를 포함시키는 것으로 한다.
--------------------------------------------------------
| 네트워크관리 |
|--------------------------------------------------------|
| | 일반네트워크관리 | |
|-| DNS 관리 |-----------------------------------|
| | IP-Aliasing관리 | |
| |------------------| |
| |
| ------------------------- |
| ----------- ------- |
|---- ---------|
다음은 Source를 보기로 하자.
-------------- < Source 3.1.1 Network_menu.h > -----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
};
----------------------------------------------------------------
-------------- < Source 3.1.2 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <stdio.h>
#include "Network_menu.h"
clssNetwork::clssNetwork()
{
qApp->setStyle(WindowsStyle);
/* 메뉴를 만들고 그 메뉴에 해당하는 함수를 간단하게 */
/* 정의해 놓는다. */
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
---------------- < Source 3.1.3 main_menu.cpp > ----------------
#include <qapplication.h>
#include "Network_menu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
--------------------- < Makefile 3.1. > ------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
----------------------------------------------------------------
3.2. 툴바 집어넣기
ToolBar에 들어갈 ICON은 16*16크기정도의 gif file이 좋겠다.
Source를 보자.
-------------- < Source 3.2.1 Network_menu.h > -----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
};
----------------------------------------------------------------
-------------- < Source 3.2.2 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
/* icon에 대한 풍선도움말을 선언한다. */
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
/* 윈도우형태를 Windows스타일로 */
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
------------------ < Source 3.2.3 main_menu.cpp > --------------
#include <qapplication.h>
#include "Network_menu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
---------------------- < Makefile 3.2. > -----------------------
Makefile은 < Makefile 3.1. >과 같다.
----------------------------------------------------------------
3.3. Network관련 라이브러리 구현하기
메뉴와 툴바를 기본적으로 작성을 했으므로 이제부터는 Network관련
라이브러리를 구현하기로 하자. 이 라이브러리는 위쪽에서 구현했던
file처리루틴을 사용하기도 하고 gcc가 제공하는 network library를
사용하기도 한다. 마지막으로 이 부분만 잘 이해를 한다면 거의 어
려움 없이 끝까지 과정을 지나갈 수 있다.
우선 header file부터 보기로 하자.
--------------- < Source 3.3.1 network.h > ---------------------
#ifndef _NETWORK_H
#define _NETWORK_H
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef MAX_LINE
#define MAX_LINE 100
#define MAX_COL 1000
#endif
#ifndef NO_SETTING
#define NO_SETTING "셋팅되어있지 않습니다."
#endif
extern char pszNetConfHost[256];
extern char pszNetConfDomain[256];
extern char pszNetConfGateway[18];
extern char pszNetConfIPAddr[18];
extern char pszNetConfPrivate1IPAddr[18];
extern char pszNetConfPrivate2IPAddr[18];
extern char pszNetConfNetmask[18];
extern char pszNetConfPrivate1Netmask[18];
extern char pszNetConfPrivate2Netmask[18];
extern char pszNetconfBroadcast[18];
extern char pszNetconfPrivate1Broadcast[18];
extern char pszNetconfPrivate2Broadcast[18];
extern char pszNetConfNetwork[18];
extern char pszNetConfPrivate1Network[18];
extern char pszNetConfPrivate2Network[18];
extern char pszNetConfNetCard[3][30];
extern int nCountListStr;
extern char pszSaveNameServer[20][30];
extern int nCountNameServer;
extern int nCountClient;
extern int nAccountCount;
/* IP와 Netmask를 알아냈을 때 그에 해당하는 Network과 Broadcast */
/* 를 알아내기 위한 구조체 */
typedef struct tagNETMASKTAB {
char pszNetwork[18];
char pszBroadcast[18];
} NetTab;
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask);
/* IP에 대해 dot로 나누어진 4개의 번호를 얻기위해 쓰일 구조체 */
typedef struct tagSEPADDR {
char pszFirst[6];
char pszSecond[6];
char pszThird[6];
char pszFourth[6];
} S_Addr;
S_Addr separateAddress(char *pszAddr);
/* 현재 날짜를 계산한다. */
char *calculateDate(void);
/* 현재 첫번째 Network card에 대한 Netmask를 알아낸다. */
void getCurrentNetmask(char *pszNetmask);
/* 현재 첫번째 Network card에 대한 Gateway를 알아낸다. */
void getCurrentGateway(char *pszGateway);
/* 현재 첫번째 Network card에 대한 Hostname을 알아낸다. */
void getCurrentHostName(char *pszHostName, char *pszDomainName);
/* 현재 첫번째 Network card에 대한 IP를 알아낸다. */
void getCurrentIPAddr(char *pszIPAddr);
/* 현재 설정된 두번째 Network card에 대한 Netmask를 알아낸다. */
void getPrivate1Netmask(char *pszPrivateNetmask);
/* 현재 두번째 Network card에 대한 사설IP를 알아낸다. */
void getPrivate1IPAddr(char *pszPrivateIPAddr);
/* 현재 설정된 세번째 Network card에 대한 Netmask를 알아낸다. */
void getPrivate2Netmask(char *pszPrivateNetmask);
/* 현재 세번째 Network card에 대한 사설IP를 알아낸다. */
void getPrivate2IPAddr(char *pszPrivateIPAddr);
/* Network card가 ISA일 경우 Io number와 Irq number를 알아낸다. */
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nCardIdx);
/* 현재 DNS 서버의 설정값을 알아낸다. */
void getDNSServer(char *pszDNSServer[]);
/* 만약 IP가 Aliasing 되어있다면 Aliasing IP에 대한 Netmask를 알아낸다. */
void getAliasNetmask(char *pszNetmask, int nIdx);
/* Aliasing IP를 알아낸다. */
void getAliasIP(char *pszIPAddr, int nIdx);
/* Network카드의 정보를 알아낸다. */
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[]);
/* IP범위값을 알아낸다. 예: 172.31.0.0/24 -> 172.31.0.0~172.31.0.255 */
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth,
int nRange);
/* IP범위값을 받아 IP/number부분의 number값을 알아낸다. */
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange);
#endif
----------------------------------------------------------------
--------------- < Source 3.3.1 network.cpp > -------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include "network.h"
#include "proc_file.h"
/*************** Calculate Netmask table **************/
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask)
{
struct in_addr IP;
struct in_addr Mask;
struct in_addr pNetwork;
struct in_addr pBroadcast;
NetTab pNet;
memset(pNet.pszNetwork, '\0', 18);
memset(pNet.pszBroadcast, '\0', 18);
IP.s_addr = inet_addr(pszIPAddr);
Mask.s_addr = inet_addr(pszNetmask);
/* Network의 계산법은 IP & Netmask이다. */
pNetwork.s_addr = IP.s_addr & Mask.s_addr;
/* Network을 계산하여 pNet구조체의 network 변수에 전해준다. */
memcpy(pNet.pszNetwork, inet_ntoa(pNetwork), 18);
/* Broadcast의 계산법은 Network | Netmask이다. */
pBroadcast.s_addr = pNetwork.s_addr | ~Mask.s_addr;
/* Broadcast를 계산하여 pNet구조체의 broadcast 변수에 전해준다. */
memcpy(pNet.pszBroadcast, inet_ntoa(pBroadcast), 18);
return pNet;
}
/***************************************/
S_Addr separateAddress(char *pszAddr)
{
int i = 0, j = 0, k = 0;
S_Addr pAddr;
memset(pAddr.pszFirst, '\0', 6);
memset(pAddr.pszSecond, '\0', 6);
memset(pAddr.pszThird, '\0', 6);
memset(pAddr.pszFourth, '\0', 6);
/* 구조체의 각 member(pszFirst, pszSecond, pszThird, pszFourth) */
/* 에 해당하는 값을 나눠 복사하는 작업. 어렵지 않으므로 유심히 */
/* 보시길. */
for (k = 0; *(pszAddr+i) != '\0'; i++, k++)
{
if (*(pszAddr+i) == '.')
{
i++;
k = 0;
j++;
}
switch (j)
{
case 0:
pAddr.pszFirst[k] = *(pszAddr+i);
break;
case 1:
pAddr.pszSecond[k] = *(pszAddr+i);
break;
case 2:
pAddr.pszThird[k] = *(pszAddr+i);
break;
case 3:
pAddr.pszFourth[k] = *(pszAddr+i);
break;
default:
break;
}
}
return pAddr;
}
/* 실제 구현에서는 별로 쓸모없는 함수이지만 날짜를 얻어내는 함수정 */
/* 도는 있어야겠다 싶어 넣어놓았다. */
char pszDate[11];
char *calculateDate()
{
time_t tTime;
int i;
memset(pszDate, '\0', 11);
tTime = time(NULL);
for (i = 0; i < 4; i++)
pszDate[i] = *(ctime(&tTime)+20+i);
for (i = 0; i < 3; i++)
pszDate[i+4] = *(ctime(&tTime)+4+i);
for (i = 0; i < 2; i++)
pszDate[i+4+3] = *(ctime(&tTime)+8+i);
return pszDate;
}
void getCurrentNetmask(char *pszNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* Netmask를 얻어낼 때는 밑에있는 ifcfg-eth0 file에 있는 */
/* 정보를 사용하여 알아낸다. */
/* ifcfg-eth0 file을 열어보면 Redhat 6.0버젼까지는 이렇게 되어 */
/* 있다. */
/*
DEVICE=eth0
IPADDR=172.31.10.1
NETMASK=255.255.0.0
NETWORK=172.31.0.0
BROADCAST=172.31.255.255
ONBOOT=yes
*/
/* 이중에서 NETMASK= 뒷부분만을 읽어내는 것이다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "r")) ==
NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszNetmask[i] = pszSave[i+8];
pszNetmask[i-1] = '\0';
}
void getCurrentGateway(char *pszGateway)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* gateway를 알아낼 때는 network file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
/* GATEWAY=뒷부분을 저장한다. */
strcpy(pszSave, (char *)strstr(pszSaveFile, "GATEWAY="));
for (i = 0; pszSave[i+8] != 'G'; i++)
pszGateway[i] = pszSave[i+8];
pszGateway[i-1] = '\0';
}
void getPrivate1Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* ifcfg-eth1 file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) ==
NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate1IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) ==
NULL)
{
// strcpy(pszPrivateIPAddr, "172.31.0.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getPrivate2Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) ==
NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate2IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* ifcfg-eth2 file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) ==
NULL)
{
// strcpy(pszPrivateIPAddr, "192.168.1.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
/* network 구조체 utsname을 이용한다. */
/* utsname의 member인 nodename은 hostname.domainname의 형태 */
/* 로 들어가게 되어있다. */
void getCurrentHostName(char *pszHostName, char *pszDomainName)
{
struct utsname name;
int i, j;
uname(&name);
for (i = 0; name.nodename[i] != '.'; i++)
pszHostName[i] = name.nodename[i];
i++;
for (j = 0; name.nodename[i] != '\0'; i++, j++)
pszDomainName[j] = name.nodename[i];
}
void getCurrentIPAddr(char *pszIPAddr)
{
char *pszSaveListStr[20];
int i;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
/* ifcfg-eth0 file에서 IPADDR문자열을 찾아 그 라인을 저장한다. */
saveSearchLineToFile("IPADDR", pszSaveListStr,
"/etc/sysconfig/network-scripts/ifcfg-eth0", 20, 80);
/* IP 부분을 끄집어낸다. */
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* 요새는 Network card들 대부분이 PCI Card로밖에는 나오지 않는다. */
/* Io, Irq number를 수동으로 setting해야하는 Card는 ISA Card인데 */
/* ISA Card를 쓰는 사람은 1000명중 1명이나 될까? 따라서 이 루틴 */
/* 은 별로 필요가 없는 루틴이지만 필요할 지도 모른다는 생각에 집 */
/* 어넣었다. 이 루틴은 /etc/conf.modules file이 필요하다. */
/* conf.modules file에 io=0x230 irq=11 같은 형식으로 들어가기 때문 */
/* 에 이 부분에 대한 문자열 처리가 필요하다. 자세한 설명은 그만 */
/* 두겠다. */
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nNetCardIdx)
{
int i;
char *pszPosIo, *pszPosIrq;
int nIrqIdx, nIoIdx;
char *pszTmpStr = "options eth%d";
char pszOptionStr[30];
char *pszSaveListStr[3];
for (i = 0; i < 3; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("Memory allocation error!\n");
memset(pszSaveListStr[i], '\0', 200);
exit(1);
}
}
memset(pszOptionStr, '\0', 30);
sprintf(pszOptionStr, pszTmpStr, nNetCardIdx);
saveSearchLineToFile(pszOptionStr, pszSaveListStr,
"/etc/conf.modules", 200, 200);
pszPosIo = strstr(pszSaveListStr[0], "0x");
nIoIdx = pszPosIo-pszSaveListStr[0];
pszPosIrq = strstr(pszSaveListStr[0], "irq=");
nIrqIdx = pszPosIrq-pszSaveListStr[0];
for (i = nIoIdx-1; i < nIrqIdx-4; i++)
pszIo[i-nIoIdx+1] = pszSaveListStr[0][i+3];
for (i = nIrqIdx; pszSaveListStr[0][i+4] != '\n'; i++)
pszIrq[i-nIrqIdx] = pszSaveListStr[0][i+4];
for (i = 0; i < 3; i++)
free(pszSaveListStr[i]);
}
/* DNS Server는 /etc/resolv.conf file에 들어간다. */
/* resolv.conf file에 들어있는 IP는 순서대로 DNS Server 역할을 */
/* 한다. 즉 nameserver로서 별로 좋지않은 server IP가 첫줄에 있 */
/* 다면 그를 삭제하거나 뒤로 옮겨줄 수 있다. 이 함수는 단순히 */
/* setting되어있는 DNS Server IP만을 pszDNSServer에 저장한다. */
void getDNSServer(char *pszDNSServer[])
{
char *pszSaveListStr[50];
int i;
int nCntDNS;
for (i = 0; i < 50; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
saveSearchLineToFile("nameserver", pszSaveListStr,
"/etc/resolv.conf", 50, 200);
nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
nCntDNS--;
for (i = 0; i < nCntDNS; i++)
{
strcpy(pszDNSServer[i], pszSaveListStr[i]+11);
pszDNSServer[i][strlen(pszDNSServer[i])-1] = '\0';
}
for (i = 0; i < 50; i++)
free(pszSaveListStr[i]);
}
/* nIdx는 Aliasing되어있는 순번을 뜻한다. 즉 nIdx=1일때 */
/* 이것이 의미하는 것은 eth0:1이다. 번호는 순차적이다. */
/* 이 때 eth0:1 에 대한 정보는 ifcfg-eth0:1 file에 저장된다. */
void getAliasIP(char *pszIPAddr, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("IPADDR", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* 위와 마찬가지로 nIdx는 Aliasing되어있는 순번이다. */
void getAliasNetmask(char *pszNetmask, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("NETMASK", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+8] != '\n'; i++)
pszNetmask[i] = pszSaveListStr[0][i+8];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* Network card정보는 /proc/interrupts file에서 읽어들인다. */
/* interrupts file은 system의 여러가지 설정값들이 들어가는데 */
/* 이는 사용자가 절대 setting해서는 안되는 file이다. */
/* Network card가 설치되었을 때 두가지 file에 그 정보가 나타 */
/* 나는데 하나는 /etc/conf.modules file이고 나머지 하나는 */
/* interrupts file이다. setting을 할 때는 conf.modules file */
/* 을 사용하고 정보를 읽어들일 때는 interrupts file을 사용한다. */
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[])
{
FILE *fp;
int i, j, nIdx, nCount, nCardCount = 0;
char *pszSaveListStr[100];
char *pszSaveLine[4];
if ((fp = fopen("/proc/interrupts", "r")) == NULL)
{
printf("file open error!\n");
return;
}
fclose(fp);
for (i = 0; i < 4; i++)
{
if ((pszSaveLine[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveLine[i], '\0', 200);
}
for (i = 0; i < 100; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
nCount = saveAllLineToFile(pszSaveListStr, "/proc/interrupts",
100, 200);
for (i = 0, nIdx = 0; i < nCount; i++)
{
for (j = 0; j < 40; j++)
{
if (strstr(pszSaveListStr[i], pszCardInfo[j]) !=
(char *)NULL)
{
nCardCount++;
strcpy(pszSaveLine[nIdx++], pszSaveListStr[i]);
break;
}
}
}
if (nCardCount == 0)
{
strcpy(pszSaveNetCard[0], NO_SETTING);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 1)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 2)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], pszSaveLine[2]+33);
}
for (i = 0; i < 4; i++)
free(pszSaveLine[i]);
for (i = 0; i < 100; i++)
free(pszSaveListStr[i]);
}
/* 예를 들어 172.31.0.0/16 이라면 nRange의 값은 16이다. */
/* 그리고 pszStartIP는 172.31.0.0이되며 pszEndIP는 172.31.255.255 */
/* 가 된다. 이 값에 대한 정보는 이 자료의 맨 끝에 표로 설명을 하겠다. */
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth,
int nRange)
{
char pszSaveStartIP[4], pszSaveEndIP[4];
memset(pszSaveStartIP, '\0', 4);
memset(pszSaveEndIP, '\0', 4);
if (nIPFourth%nRange != 0)
{
sprintf(pszSaveStartIP, "%d", (nIPFourth/nRange)*nRange);
sprintf(pszSaveEndIP, "%d", (nIPFourth/nRange)*nRange+nRange-1);
}
else
{
sprintf(pszSaveStartIP, "%d", nIPFourth);
sprintf(pszSaveEndIP, "%d", nIPFourth+nRange-1);
}
strcat(pszStartIP, pszSaveStartIP);
strcat(pszEndIP, pszSaveEndIP);
}
/* 위와는 반대로 pszStartIP와 pszEndIP를 가지고 nRange값을 알아낸다. */
/* 알아낸 범위정보는 nRange변수에 저장되는데 저장을 위해 포인터를 */
/* 썼다. 이는 IP의 네번째 번호를 가지고 추출한다. 즉 A, B class */
/* 는 고려하지 않았다. */
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange)
{
S_Addr pAddr;
int i, nSaveRange;
int nStart, nEnd;
pAddr = separateAddress(pszStartIP);
nStart = atoi(pAddr.pszFourth);
pAddr = separateAddress(pszEndIP);
nEnd = atoi(pAddr.pszFourth);
nSaveRange = nEnd-nStart+1;
for (i = 0; nSaveRange > 0; i++)
nSaveRange /= 2;
*nRange = 32-(i-1);
}
----------------------------------------------------------------
3.4. Class만들기
3.4.1. 일반네트워크관리
이제부터는 본격적인 network 관리 구현에 들어가겠다.
지금부터 나오는 대부분의 Source 들은 위에서 이미 설명했던 부분들이다.
따라서 Source에 대한 설명은 가급적이면 생략하고 Source위주로 Project
를 이끌어 나가겠다.
일반네트워크관리메뉴에는 네트워크카드설정, IP및 Netmask,gateway설정등
일반적으로 리눅스에서 네트워크에 관한 설정을 할 때 가장 먼저 손을 보
아야 하는, 혹은 가장 자주 접하게 되는 부분들을 구현해보았다.
우선 Source를 컴파일 해서 직접 실행시켜보기 바란다. 이해가 빨라질 것
이다. Source는 앞서 설명했던 proc_file.c와 network.c부분이 상당부분
포함되어 있다. file 처리 루틴과 network 처리 루틴을 모두 이해했다면
어려움 없이 지금 이후의 부분들도 이해할 수 있으리라 생각한다.
---------------- < Source 3.4.1 clssGeneric.h > ----------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefGeneric : public QWidget
{
Q_OBJECT
public:
clssDefGeneric();
~clssDefGeneric();
private slots:
void setApply();
void setCancel();
void printLabelFormat(QLabel *lblBold);
private:
QLabel *lblGenericNetworkTitle;
QLabel *lblGateway;
QLineEdit *leGateway;
/* Eth0에 대한 member들 */
QLabel *lblEth0;
QLabel *lblEth0IPAddr;
QLineEdit *leEth0IPAddr;
QLabel *lblEth0Netmask;
QLineEdit *leEth0Netmask;
QLabel *lblEth0Network;
QLineEdit *leEth0Network;
QLabel *lblEth0Broadcast;
QLineEdit *leEth0Broadcast;
QLabel *lblEth0NetCard;
/* 네트워크 카드는 combobox로 설정하게 한다. */
QComboBox *cbEthNetCard[3]; /* to combobox */
/* Eth1에 대한 members */
QLabel *lblEth1;
QLineEdit *leEth1IPAddr;
QLineEdit *leEth1Netmask;
QLineEdit *leEth1Network;
QLineEdit *leEth1Broadcast;
QLabel *lblEth1NetCard;
/* Eth2에 대한 members */
QLabel *lblEth2;
QLineEdit *leEth2IPAddr;
QLineEdit *leEth2Netmask;
QLineEdit *leEth2Network;
QLineEdit *leEth2Broadcast;
QLabel *lblEth2NetCard;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frEthInfo;
QLabel *lblSeparator1;
QLabel *lblSeparator2;
};
----------------------------------------------------------------
--------------- < Source 3.4.2 clssGeneric.cpp > ---------------
#include <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qpalette.h>
#include <stdio.h>
#include <stdlib.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssGeneric.h"
clssDefGeneric::clssDefGeneric()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
int i, j, nCardIdx;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
/* Linux에서 제공하는 PCI type Network Card Modules */
/* 각 string의 끝에 있는 괄호안의 내용이 바로 module 이름이다. */
const char *pszNetCard[40] = {
" 3Com Vortex series (3c590, 3c592, 3c597, 3c595) (3c59x) ",
" 3Com Boomerang (3c900, 3c905, 3c575) (3c59x) ",
" 3Com Cyclone (3c905B) (3c59x) ",
" Intel EtherExpress Pro 100 (eepro100) ",
" HP J2585B, J2585A, J2970, J2973 (hp100) ",
" HP J2573 (hp100) ",
" Compex ReadyLink ENET100-VG4 (hp100) ",
" Compex FreedomLine 100/VG (hp100) ",
" IBM token ring (ibmtr) ",
" NE2000 (PCI) (ne2k-pci) ",
" AMD PCnet/PCI 79C970/PCnet32/PCnet/PCI II 79C970A (pcnet32) ",
" PCnet/PCI II 79C971A (pcnet32) ",
" Allied Telesyn AT2550 (rtl8139) ",
" Genius GF100TXR (RTL8139) (rtl8139) ",
" NDC Communications NE100TX-E (rtl8139) ",
" RealTek RTL8129/8139 Fast (rtl8139) ", //15
" SMC Ultra/SMC UltraEZ/SMC Ultra32 (smc-ultra) ",
" Compaq Netelligent 10 T PCI UTP (tlan) ",
" Compaq Netelligent 10/100 TX PCI UTP (tlan) ",
" Compaq Netelligent Integrated 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10/100 TX Embedded UTP (tlan) ",
" Compaq Netelligent 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10 T/2 PCI UTP/Coax (tlan) ",
" Accton EtherDuo PCI/Accton EN1207 (tulip) ",
" Adaptec ANA6901/C/Adaptec ANA6911/TX (tulip) ",
" C-NET CNE-935 (tulip) ",
" Cogent EM100/Cogent EM110/Cogent EM400 (tulip) ",
" Cogent EM960/Cogent EM964 Quartet (tulip) ",
" Danpex EN-9400P3 (tulip) ",
" D-Link DFE500-Tx/D-Link DE-530CT (tulip) ",
" Linksys EtherPCI (tulip) ",
" Kingston EtherX KNT40T/Kingston EtherX KNE100TX (tulip) ",
" Netgear FX310 TX 10/100 (tulip) ",
" SMC EtherPower/SMC 8432BT/ SMC Ether Power10/100 (tulip) ",
" Surecom EP-320X (tulip) ",
" Thomas Conrad TC5048 (tulip) ",
" Znyx ZX312 EtherAction/Znyx ZX314/ZX315 (tulip) ",
" Znyx ZX342/ZX344/ZX345/ZX346/ZX348 (tulip) ",
" Znyx ZX351 (tulip) ",
" 세팅되어있지 않습니다! (No Setting)"
};
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
/* 첫번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
/* 두번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
/* 세번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
/* gateway, IP, Netmask 등을 얻는다. */
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
/* network과 broadcast를 계산한다. */
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr,
pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr,
pszPrivate2Netmask);
/***********************/
lblGenericNetworkTitle =
new QLabel("Network Setting (일반적인 네트워크 설정)", this);
lblGenericNetworkTitle->setGeometry(20, 20, 400, 20);
// printLabelFormat(lblGenericNetworkTitle);
/***********************/
frEthInfo = new QFrame(this);
frEthInfo->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
frEthInfo->setGeometry(25, 50, 700, 362);
lblGateway = new QLabel("게이트웨이", frEthInfo);
lblGateway->setGeometry(10, 15, 80, 20);
leGateway = new QLineEdit(frEthInfo);
leGateway->setGeometry(90, 15, 150, 20);
/* getCurrentGateway함수를 이용하여 얻은 gateway를 편집박스 */
/* 에 삽입한다. */
leGateway->setText(pszGateway);
/* separator를 그린다. */
lblSeparator1 = new QLabel(frEthInfo);
lblSeparator1->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
lblSeparator1->setGeometry(20, 45, 630, 2);
/******** Ethernet Card 0 ********/
lblEth0 = new QLabel("첫번째 이더넷카드", frEthInfo);
lblEth0->setGeometry(90, 10+50, 100, 20);
lblEth0IPAddr = new QLabel("IP 주소 ", frEthInfo);
lblEth0IPAddr->setGeometry(10, 40+50, 80, 20);
leEth0IPAddr = new QLineEdit(frEthInfo);
leEth0IPAddr->setGeometry(90, 40+50, 150, 20);
leEth0IPAddr->setText(pszIPAddr);
/*** text -> proc ***/
lblEth0Netmask = new QLabel("Netmask ", frEthInfo);
lblEth0Netmask->setGeometry(10, 40+30+50, 80, 20);
leEth0Netmask = new QLineEdit(frEthInfo);
leEth0Netmask->setGeometry(90, 40+30+50, 150, 20);
leEth0Netmask->setText(pszNetmask);
lblEth0Network = new QLabel("Network ", frEthInfo);
lblEth0Network->setGeometry(10, 40+60+50, 80, 20);
leEth0Network = new QLineEdit(frEthInfo);
leEth0Network->setGeometry(90, 40+60+50, 150, 20);
/* Network은 IP와 Netmask의 값을 조합하여 나온 값이므로 이는 */
/* 따로 설정할 필요가 없는 부분이므로 편집박스를 edit할 수 */
/* 없도록 설정해둔다.(setEnabled(0)) */
leEth0Network->setEnabled(0);
/* pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);를 통하여 */
/* 얻어낸 pNet.pszNetwork값을 편집박스에 삽입. */
leEth0Network->setText(pNet.pszNetwork);
lblEth0Broadcast = new QLabel("Broadcast ", frEthInfo);
lblEth0Broadcast->setGeometry(10, 40+90+50, 80, 20);
leEth0Broadcast = new QLineEdit(frEthInfo);
leEth0Broadcast->setGeometry(90, 40+90+50, 150, 20);
leEth0Broadcast->setEnabled(0);
leEth0Broadcast->setText(pNet.pszBroadcast);
lblSeparator2 = new QLabel(frEthInfo);
lblSeparator2->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
lblSeparator2->setGeometry(20, 40+90+50+40, 630, 2);
/*** text -> proc ***/
/*********************************/
/******** Ethernet Card 1 ********/
lblEth1 = new QLabel("두번째 이더넷카드", frEthInfo);
lblEth1->setGeometry(300, 10+50, 100, 20);
leEth1IPAddr = new QLineEdit(frEthInfo);
leEth1IPAddr->setGeometry(300, 40+50, 150, 20);
leEth1IPAddr->setText(pszPrivate1IPAddr);
/*** text -> proc ***/
leEth1Netmask = new QLineEdit(frEthInfo);
leEth1Netmask->setGeometry(300, 40+30+50, 150, 20);
leEth1Netmask->setText(pszPrivate1Netmask);
/*** text -> proc ***/
leEth1Network = new QLineEdit(frEthInfo);
leEth1Network->setGeometry(300, 40+60+50, 150, 20);
leEth1Broadcast = new QLineEdit(frEthInfo);
leEth1Broadcast->setGeometry(300, 40+90+50, 150, 20);
leEth1Network->setEnabled(0);
leEth1Broadcast->setEnabled(0);
if (strlen(pszPrivate1IPAddr) >= 7)
{
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
}
/*********************************/
/******** Ethernet Card 2 ********/
lblEth2 = new QLabel("세번째 이더넷카드", frEthInfo);
lblEth2->setGeometry(520, 10+50, 100, 20);
leEth2IPAddr = new QLineEdit(frEthInfo);
leEth2IPAddr->setGeometry(520, 40+50, 150, 20);
leEth2IPAddr->setText(pszPrivate2IPAddr);
/*** text -> proc ***/
leEth2Netmask = new QLineEdit(frEthInfo);
leEth2Netmask->setGeometry(520, 40+30+50, 150, 20);
leEth2Netmask->setText(pszPrivate2Netmask);
/*** text -> proc ***/
leEth2Network = new QLineEdit(frEthInfo);
leEth2Network->setGeometry(520, 40+60+50, 150, 20);
leEth2Broadcast = new QLineEdit(frEthInfo);
leEth2Broadcast->setGeometry(520, 40+90+50, 150, 20);
leEth2Network->setEnabled(0);
leEth2Broadcast->setEnabled(0);
if (strlen(pszPrivate2IPAddr) >= 7)
{
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
}
/*********************************/
for (i = 0; i < 2; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*200);
memset(pszSaveListStr[i], '\0', 200);
}
/*********************************/
lblEth0NetCard = new QLabel("Ethernet 0 카드", frEthInfo);
lblEth0NetCard->setGeometry(10, 40+90+70+60, 90, 20);
cbEthNetCard[0] = new QComboBox(frEthInfo, "comboBox_Eth0");
cbEthNetCard[0]->setGeometry(110, 40+90+70+60, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[0]->insertItem(pszNetCard[i]);
cbEthNetCard[0]->setAutoResize(FALSE);
/* conf.modules file에서 Card정보를 찾아 외부변수인 */
/* pszNetConfNetCard에 저장한다. */
if (saveSearchLineToFile("alias eth0", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[0], pszSaveListStr[0]+11);
pszNetConfNetCard[0][strlen(pszNetConfNetCard[0])-1] = '\0';
}
/* 위에서 정의한 pszNetCard, 즉 Network Card Modules와 일 */
/* 치되는 Card가 conf.modules file에 있는지 검색하고 */
if (strlen(pszIPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[0]) !=
(char *)NULL)
break;
/* 만약 없다면 No Setting문자열을 combobox에 Setting한다. */
if (strlen(pszNetConfNetCard[0]) < 2)
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
/*********************************/
lblEth1NetCard = new QLabel("Ethernet 1 카드", frEthInfo);
lblEth1NetCard->setGeometry(10, 40+90+70+90, 90, 20);
cbEthNetCard[1] = new QComboBox(frEthInfo, "comboBox_Eth1");
cbEthNetCard[1]->setGeometry(110, 40+90+70+90, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[1]->insertItem(pszNetCard[i]);
cbEthNetCard[1]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth1", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[1], pszSaveListStr[0]+11);
pszNetConfNetCard[1][strlen(pszNetConfNetCard[1])-1] = '\0';
}
if (strlen(pszPrivate1IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[1]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[1]) < 2)
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
/**********************************/
lblEth2NetCard = new QLabel("Ethernet 2 카드", frEthInfo);
lblEth2NetCard->setGeometry(10, 40+90+70+120, 90, 20);
cbEthNetCard[2] = new QComboBox(frEthInfo, "comboBox_Eth2");
cbEthNetCard[2]->setGeometry(110, 40+90+70+120, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[2]->insertItem(pszNetCard[i]);
cbEthNetCard[2]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth2", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[2], pszSaveListStr[0]+11);
pszNetConfNetCard[2][strlen(pszNetConfNetCard[2])-1] = '\0';
}
if (strlen(pszPrivate2IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[2]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[2]) < 2)
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
cbEthNetCard[2]->setGeometry(110, 40+90+70+125, 470, 20);
/*************************************/
bttnApply = new QPushButton("적 용", this);
bttnApply->setGeometry(150, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this,
SLOT(setApply()));
bttnCancel = new QPushButton("취 소", this);
bttnCancel->setGeometry(450, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(setCancel()));
/************************************/
for (i = 0; i < 2; i++)
free(pszSaveListStr[i]);
free(pszIPAddr);
free(pszNetmask);
free(pszPrivate1IPAddr);
free(pszPrivate1Netmask);
free(pszPrivate2IPAddr);
free(pszPrivate2Netmask);
free(pszGateway);
}
clssDefGeneric::~clssDefGeneric()
{
int i;
delete lblEth0;
delete lblEth0IPAddr;
delete lblEth0Netmask;
delete lblEth0Network;
delete lblEth0Broadcast;
delete leEth0IPAddr;
delete leEth0Netmask;
delete leEth0Network;
delete leEth0Broadcast;
delete lblEth1;
delete leEth1IPAddr;
delete leEth1Netmask;
delete leEth1Network;
delete leEth1Broadcast;
delete lblEth2;
delete leEth2IPAddr;
delete leEth2Netmask;
delete leEth2Network;
delete leEth2Broadcast;
delete lblGateway;
delete leGateway;
delete lblSeparator1;
delete lblSeparator2;
for (i = 0; i < 3; i++)
delete cbEthNetCard[i];
delete lblEth0NetCard;
delete lblEth1NetCard;
delete lblEth2NetCard;
delete bttnCancel;
delete bttnApply;
delete lblGenericNetworkTitle;
delete frEthInfo;
}
/* Network에 관한 Setting이 위의 몇십줄로 끝나는 것은 아니다. */
/* Network 설정값이 변할 때 같이 변경되는 관련 file들도 다뤄주어 */
/* 야하기 때문이다. */
/* 이 함수는 설정값을 변경하고 적용버튼을 눌렀을 때, 그러한 관련 */
/* file들을 관리한다. */
void clssDefGeneric::setApply()
{
char *pszIfCfgEthFile = "DEVICE=%s\nIPADDR=%s\nNETMASK=%s\n\
NETWORK=%s\nBROADCAST=%s\nONBOOT=yes\n";
char *pszNetworkFile = "NETWORKING=yes\nFORWARD_IPV4=true\n\
HOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszOptions[95];
char *pszSaveCardLine[3], pszSaveHostName[256], pszSaveDomainName[256];
NetTab pNet, pNetPrivate1, pNetPrivate2;
FILE *fp;
S_Addr pAddr, pSaveAddr;
char pszTmpSearch[100];
char pszTmpInsert[100];
char pszSaveIP[18];
int i;
memset(pszSaveIP, '\0', 18);
getCurrentIPAddr(pszSaveIP);
pSaveAddr = separateAddress(pszSaveIP);
pNet = calculateNetMaskTab((char *)leEth0IPAddr->text(),
(char *)leEth0Netmask->text());
pNetPrivate1 = calculateNetMaskTab((char *)leEth1IPAddr->text(),
(char *)leEth1Netmask->text());
pNetPrivate2 = calculateNetMaskTab((char *)leEth2IPAddr->text(),
(char *)leEth2Netmask->text());
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
/* ifcfg-eth0, ifcfg-eth1, ifcfg-eth2 file들을 다룬다. */
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "w");
fprintf(fp, pszIfCfgEthFile,
"eth0", leEth0IPAddr->text(), leEth0Netmask->text(),
leEth0Network->text(), leEth0Broadcast->text());
fclose(fp);
if (strlen((char *)leEth1IPAddr->text()) >= 7)
{
char pszPrivate1IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "w");
fprintf(fp, pszIfCfgEthFile,
"eth1", leEth1IPAddr->text(), leEth1Netmask->text(),
leEth1Network->text(), leEth1Broadcast->text());
fclose(fp);
}
if (strlen((char *)leEth2IPAddr->text()) >= 7)
{
char pszPrivate2IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "w");
fprintf(fp, pszIfCfgEthFile,
"eth2", leEth2IPAddr->text(), leEth2Netmask->text(),
leEth2Network->text(), leEth2Broadcast->text());
fclose(fp);
}
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, pszSaveHostName, pszSaveDomainName,
pszSaveDomainName, leGateway->text());
fclose(fp);
for (i = 0; i < 3; i++)
{
if ((pszSaveCardLine[i] = (char *)malloc(sizeof(char)*50)) == NULL)
{
printf("pszSaveCardLine Memory Error!\n");
exit(1);
}
memset(pszSaveCardLine[i], '\0', 50);
}
for (i = 0; i < 3; i++)
{
sprintf(pszSaveCardLine[i], "alias eth%d ", i);
if (cbEthNetCard[i]->currentItem() >= 0 &&
cbEthNetCard[i]->currentItem() <= 2)
strcat(pszSaveCardLine[i], "3c59x");
else if (cbEthNetCard[i]->currentItem() == 3)
strcat(pszSaveCardLine[i], "eepro100");
else if (cbEthNetCard[i]->currentItem() >= 4 &&
cbEthNetCard[i]->currentItem() <= 7)
strcat(pszSaveCardLine[i], "hp100");
else if (cbEthNetCard[i]->currentItem() == 8)
strcat(pszSaveCardLine[i], "ibmtr");
else if (cbEthNetCard[i]->currentItem() == 9)
strcat(pszSaveCardLine[i], "ne2k-pci");
else if (cbEthNetCard[i]->currentItem() == 10 ||
cbEthNetCard[i]->currentItem() == 11)
strcat(pszSaveCardLine[i], "pcnet32");
else if (cbEthNetCard[i]->currentItem() >= 12 &&
cbEthNetCard[i]->currentItem() <= 15)
strcat(pszSaveCardLine[i], "rtl8139");
else if (cbEthNetCard[i]->currentItem() == 16)
strcat(pszSaveCardLine[i], "smc-ultra");
else if (cbEthNetCard[i]->currentItem() >= 17 ||
cbEthNetCard[i]->currentItem() <= 22)
strcat(pszSaveCardLine[i], "tlan");
else if (cbEthNetCard[i]->currentItem() >= 23 ||
cbEthNetCard[i]->currentItem() <= 38)
strcat(pszSaveCardLine[i], "tulip");
}
for (i = 0; i < 3; i++)
strcat(pszSaveCardLine[i], "\n");
/* conf.modules file을 변경한다. proc_file.c에서 설명한 바와 */
/* 같이 바로 아래함수가 의미하는 것은 */
/* conf.modules file에서 최대 200line, 100column 을 허용하여 */
/* alias eth0라는 문자열이 포함된 line을 찾아 Network Card */
/* 값인 pszSaveCardLine[0]을 대치시켜라 라는 뜻이다. */
addOnNotExistChangeOnExist(pszSaveCardLine[0], "alias eth0",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[1], "alias eth1",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[2], "alias eth2",
"/etc/conf.modules", 200, 100);
if (cbEthNetCard[0]->currentItem() == 39)
insertStrToFile("", "alias eth0", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[1]->currentItem() == 39)
insertStrToFile("", "alias eth1", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[2]->currentItem() == 39)
insertStrToFile("", "alias eth2", "/etc/conf.modules", 200, 100);
for (i = 0; i < 3; i++)
free(pszSaveCardLine[i]);
if (cbEthNetCard[0]->currentItem() == 39)
{
/* 만약 Eth0 Card가 Setting되어 있지 않다면 ifcfg-eth0 file */
/* 을 삭제하고 각 Network설정값들은 공백문자열로 놓는다. */
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth0");
leEth0IPAddr->setText("");
leEth0Netmask->setText("");
leEth0Network->setText("");
leEth0Broadcast->setText("");
}
if (cbEthNetCard[1]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth1");
leEth1IPAddr->setText("");
leEth1Netmask->setText("");
leEth1Network->setText("");
leEth1Broadcast->setText("");
}
if (cbEthNetCard[2]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth2");
leEth2IPAddr->setText("");
leEth2Netmask->setText("");
leEth2Network->setText("");
leEth2Broadcast->setText("");
}
/**************************************/
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth0 \
/etc/sysconfig/network-scripts/ifcfg-eth0.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth1 \
/etc/sysconfig/network-scripts/ifcfg-eth1.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth2 \
/etc/sysconfig/network-scripts/ifcfg-eth2.org\n");
system("cp -f /etc/sysconfig/network /etc/sysconfig/network.org\n");
system("cp -f /etc/conf.modules /etc/conf.modules.org\n");
system("cp -f /etc/resolv.conf /etc/resolv.conf.org\n");
system("/etc/rc.d/init.d/network \
stop;/etc/rc.d/init.d/network start\n");
}
/* 취소버튼을 눌렀을 때에는 설정했던 값들이 제자리를 찾아간다. */
/* 물론 적용버튼을 누르고 다시 취소버튼을 누르면 소용이 없다. */
void clssDefGeneric::setCancel()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char **pszHostName, *pszDomainName;
char *pszPrivate1IPAddr, *pszPrivate1Netmask;
char *pszPrivate2IPAddr, *pszPrivate2Netmask;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr,
pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr,
pszPrivate2Netmask);
/***** lineeditbox init: proc -> segmentation fault *****/
leGateway->setText(pszGateway);;
leEth0IPAddr->setText(pszIPAddr);
leEth0Netmask->setText(pszNetmask);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1IPAddr->setText(pszPrivate1IPAddr);
leEth1Netmask->setText(pszPrivate1Netmask);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2IPAddr->setText(pszPrivate2IPAddr);
leEth2Netmask->setText(pszPrivate2Netmask);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
}
/* Title을 나타내주는 부분이다. 별로 중요하지 않은 부분이므로 */
/* 설명은 생략하겠다. */
void clssDefGeneric::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(),
n.dark(), n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
/* 여기부터는 주메뉴, 즉 풀다운메뉴와 icon box등을 정의하는 부분 */
/* 이다. 이 부분들에 대한 설명은 2.2장에서 모두 설명했으므로 */
/* 설명을 생략하겠다. */
--------------- < Source 3.4.3 Network_menu.h > ----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
};
----------------------------------------------------------------
-------------- < Source 3.4.4 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
//#include "clssDNS.h"
//#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
--------------------- < Makefile 3.4. > ------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
OTHER_OBJS = \
network.o \
proc_file.o
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o \
clssGeneric.o \
clssGeneric_moc.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
network.o: network.c
$(CC) -c network.c -o $@
proc_file.o: proc_file.c
$(CC) -c proc_file.c -o $@
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
clssGeneric_moc.cpp: clssGeneric.h
$(MOC) clssGeneric.h -o clssGeneric_moc.cpp
clssGeneric_moc.o: clssGeneric_moc.cpp
$(CC) -c clssGeneric_moc.cpp $(CFLAGS) -o $@
clssGeneric.o: clssGeneric.cpp
$(CC) -c clssGeneric.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
----------------------------------------------------------------
3.4.2. DNS관리
이 장은 호스트 및 도메인 이름 설정, 그리고 DNS Server를 셋팅하는
방법에 대한 내용이다. 자세한 설명은 생략하겠다. Source가 별로 어
렵지 않으므로 이해하기 쉬우리라 생각한다.
-------------- < Source 3.4.2.1. clssDNS.h > -------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefDNS : public QWidget
{
Q_OBJECT
public:
clssDefDNS();
~clssDefDNS();
public slots:
void printLabelFormat(QLabel *lblDNSTitle);
void rebootSystem();
private slots:
void applySetting();
void cancelSetting();
void addDNS();
void delDNS();
private:
QLabel *lblHostName;
QLabel *lblDomainName;
QLineEdit *leHostName;
QLineEdit *leDomainName;
QLabel *lblDNSServer;
QComboBox *cbDNSServer;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frWorkArea;
QLabel *lblSeparator;
QPushButton *bttnAdd;
QPushButton *bttnDel;
QLabel *lblDNSTitle;
};
----------------------------------------------------------------
-------------- < Source 3.4.2.2. clssDNS.cpp > -----------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <stdio.h>
#include <stdlib.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssDNS.h"
clssDefDNS::clssDefDNS()
{
char *pszNetmask, *pszHostName, *pszDomainName;
int i, j;
NetTab pNet;
if (((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
/* Hostname과 Domainname을 얻는다. */
getCurrentHostName(pszHostName, pszDomainName);
/***********************/
lblDNSTitle = new QLabel("DNS Setting (DNS 설정)", this);
lblDNSTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblDNSTitle);
frWorkArea = new QFrame(this);
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
frWorkArea->setGeometry(30, 30, 330, 430);
/******** Ethernet Card 0 ********/
lblHostName = new QLabel("호스트명", frWorkArea);
lblHostName->setGeometry(20, 50, 80, 20);
leHostName = new QLineEdit(frWorkArea);
leHostName->setGeometry(100, 50, 180, 20);
leHostName->setText(pszHostName);
lblDomainName = new QLabel("도메인명", frWorkArea);
lblDomainName->setGeometry(20, 80, 80, 20);
leDomainName = new QLineEdit(frWorkArea);
leDomainName->setGeometry(100, 80, 180, 20);
leDomainName->setText(pszDomainName);
bttnApply = new QPushButton("적 용", frWorkArea);
bttnApply->setGeometry(50, 160, 80, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this,
SLOT(applySetting()));
bttnCancel = new QPushButton("취 소", frWorkArea);
bttnCancel->setGeometry(180, 160, 80, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(cancelSetting()));
/*************************************/
lblSeparator = new QLabel(frWorkArea);
lblSeparator->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
lblSeparator->setGeometry(20, 230, 290, 2);
lblDNSServer = new QLabel("DNS서버", frWorkArea);
lblDNSServer->setGeometry(20, 280, 80, 20);
cbDNSServer = new QComboBox(TRUE, frWorkArea, "comboBox_DNS");
cbDNSServer->setGeometry(100, 280, 150, 20);
char *pszDNSServer[50];
int nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
for (i = 0; i < 50; i++)
{
if ((pszDNSServer[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszDNSServer[i], '\0', 200);
}
/* DNSServer의 이름을 얻고 그들을 콤보박스에 삽입한다. */
getDNSServer(pszDNSServer);
for (i = 0; i < nCntDNS-1; i++)
cbDNSServer->insertItem(pszDNSServer[i]);
cbDNSServer->setAutoResize(FALSE);
for (i = 0; i < 50; i++)
free(pszDNSServer[i]);
bttnAdd = new QPushButton("추 가", frWorkArea);
bttnAdd->setGeometry(50, 350, 80, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addDNS()));
bttnDel = new QPushButton("삭 제", frWorkArea);
bttnDel->setGeometry(180, 350, 80, 30);
QObject::connect(bttnDel, SIGNAL(clicked()), this, SLOT(delDNS()));
/************************************/
free(pszHostName);
free(pszDomainName);
}
clssDefDNS::~clssDefDNS()
{
int i;
delete lblHostName;
delete lblDomainName;
delete leHostName;
delete leDomainName;
delete bttnCancel;
delete bttnApply;
delete lblDNSServer;
delete cbDNSServer;
delete bttnAdd;
delete bttnDel;
delete frWorkArea;
delete lblDNSTitle;
}
/* DNS의 추가 버튼을 눌렀을 때 실행되는 함수이다. */
/* 여기서는 resolv.conf file을 다룬다. */
void clssDefDNS::addDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
if (strcmp(cbDNSServer->text(cbDNSServer->currentItem()),
cbDNSServer->currentText()) != 0)
cbDNSServer->insertItem(cbDNSServer->currentText());
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
memset(pszTmpInsert, '\0', 100);
sprintf(pszTmpInsert, "nameserver %s\n",
cbDNSServer->currentText());
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->currentText());
/* 만약 resolv.conf에서 pszTempSearch에 저장되어있는 문 */
/* 자열을 찾지 못했다면 */
if (!searchStrInFile(pszTmpSearch,
"/etc/resolv.conf", 100, 100))
/* resolv.conf에서 pszTmpSearch문자열이 있다면 그 라 */
/* 인을 pszTmpInsert문자열로 바꾸고, 없다면 file */
/* 마지막 부분에 pszTmpInsert문자열을 라인단위로 */
/* 삽입하라. */
addOnNotExistChangeOnExist(pszTmpInsert, pszTmpSearch,
"/etc/resolv.conf", 100, 100);
}
}
/* DNS의 삭제버튼을 눌렀을 때 실행되는 함수이다. */
/* addDNS()와 비슷하다. */
void clssDefDNS::delDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->text(cbDNSServer->currentItem()));
if (!searchStrInFile(pszTmpSearch,
"/etc/resolve.conf", 100, 100))
/* pszTmpSearch문자열을 찾았다면 그 라인을 공백문자 */
/* 열로 바꾸어라. */
insertStrToFile("", pszTmpSearch, "/etc/resolv.conf",
100, 100);
cbDNSServer->removeItem(cbDNSServer->currentItem());
cbDNSServer->setCurrentItem(0);
}
}
/* Hostname 혹은 Domainname이 변경되었고 적용버튼을 눌렀을 경우 */
/* 실행되는 함수이다. */
/* Hostname 및 Domainname이 변경되었을 때는 재부팅을 해야만 변경 */
/* 된 내용을 적용시킬 수 있다. 따라서 여기서도 Hostname 혹은 */
/* Domainname을 바꿨을 경우 재부팅을 해준다. */
/* Source상 어려운 부분이 거의 없으므로 설명은 생략하겠다. */
void clssDefDNS::applySetting()
{
char *pszNetworkFile = "NETWORKING=yes\nFORWARD_IPV4=true\n\
HOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszGateway[18];
char pszOptions[95];
char *pszSaveCardLine[3];
FILE *fp;
S_Addr pAddr;
char pszTmpSearch[100], pszTmpInsert[100];
char pszSaveIP[18], pszSaveHostName[256], pszSaveDomainName[256];
int i;
char pszCommand[200];
memset(pszSaveIP, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentIPAddr(pszSaveIP);
getCurrentGateway(pszGateway);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, leHostName->text(), leDomainName->text(),
leDomainName->text(), pszGateway);
fclose(fp);
/**** update named daemon ****/
if (strlen(leHostName->text()) >= 1)
{
pAddr = separateAddress(pszSaveIP);
/*** HOSTNAME Host,Domain changed ***/
char pszTmpDomain[100];
char pszTmpHost[50];
memset(pszTmpInsert, '\0', 100);
memset(pszTmpHost, '\0', 50);
memset(pszTmpDomain, '\0', 100);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
sprintf(pszTmpInsert, "%s.%s\n", pszTmpHost, pszTmpDomain);
addOnNotExistChangeOnExist(pszTmpInsert, pszSaveHostName,
"/etc/HOSTNAME", 100, 100);
memset(pszTmpDomain, '\0', 100);
memset(pszTmpHost, '\0', 50);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
if (strcmp(pszSaveDomainName, pszTmpDomain) != 0 ||
strcmp(pszSaveHostName, pszTmpHost) != 0)
{
QWidget *wdgtRebooting = new QWidget();
wdgtRebooting->setGeometry(300, 300, 300, 150);
QLabel *lblRebooting = new QLabel(
"호스트이름 혹은 도메인 이름이 바뀌었으므로\n재부팅을 하겠습니다.",
wdgtRebooting);
lblRebooting->setGeometry(20, 20, 250, 50);
QPushButton *bttnRebooting = new QPushButton("재 부 팅",
wdgtRebooting);
bttnRebooting->setGeometry(120, 90, 120, 30);
QObject::connect(bttnRebooting, SIGNAL(clicked()), this,
SLOT(rebootSystem()));
wdgtRebooting->show();
}
}
system(
"/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network restart\n");
}
void clssDefDNS::cancelSetting()
{
char *pszHostName, *pszDomainName;
char *pszSaveListStr[2];
if (((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
leHostName->setText(pszHostName);
leDomainName->setText(pszDomainName);
}
void clssDefDNS::rebootSystem()
{
system("sync;sync;sync;sync;sync;init 6\n");
}
void clssDefDNS::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(),
n.dark(), n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
-------------- < Source 3.4.2.3. Network_menu.h > --------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
};
----------------------------------------------------------------
-------------- < Source 3.4.2.4. Network_menu.cpp > ------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
//#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
--------------------- < Makefile 3.4.2. > ----------------------
3.4.1의 Makefile과 마찬가지로 clssDNS_moc.cpp, clssDNS.cpp,
clssDNS.h등을 설정해준다.
----------------------------------------------------------------
3.4.3. IP-Aliasing관리
IP-Aliasing에 대해서는 3.3장에서 어느정도 설명은 했으므로 이곳에
서는 3.3장에서 설명되지 않은 부분들만을 주석처리하겠다.
-------------- < Source 3.4.3.1 clssAlias.h > ------------------
#include <qwidget.h>
class QLineEdit;
class QLabel;
class QLineEdit;
class QListView;
class QListViewItem;
class QFrame;
class QPushButton;
class clssDefAlias : public QWidget
{
Q_OBJECT
public:
clssDefAlias();
~clssDefAlias();
public slots:
void addSetting();
void deleteSetting();
void getAliasingItem();
void printLabelFormat(QLabel *lblAliasingTitle);
private slots:
private:
QFrame *frWorkArea;
QPushButton *bttnAdd;
QPushButton *bttnDelete;
QFrame *frAliasList;
QListView *lvAliasList;
QListViewItem *lviAlias[100];
QLabel *lblNetworkArea;
QLabel *lblIP;
QLineEdit *leIP;
QLabel *lblNetmask;
QLineEdit *leNetmask;
QLabel *lblNetwork;
QLineEdit *leNetwork;
QLabel *lblBroadcast;
QLineEdit *leBroadcast;
QLabel *lblAliasingTitle;
int nAliasCount;
};
----------------------------------------------------------------
-------------- < Source 3.4.3.2 clssAlias.cpp > ----------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <qframe.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlistview.h>
#include <stdio.h>
#include <stdlib.h>
#include "proc_file.h"
#include "network.h"
#include "clssAlias.h"
clssDefAlias::clssDefAlias()
{
int i;
char pszSaveFile[100];
char pszVirtualIP[18];
FILE *fp;
for (nAliasCount = 0; nAliasCount < 10; nAliasCount++)
{
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nAliasCount);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
break;
fclose(fp);
}
lblAliasingTitle = new QLabel("Virtual LAN (가상 네트워크 카드 설정)",
this);
lblAliasingTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblAliasingTitle);
frWorkArea = new QFrame(this, "IP Aliasing Area");
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
frWorkArea->setGeometry(40, 60, 670, 310);
lblNetworkArea = new QLabel("네트워크영역 선택", frWorkArea);
lblNetworkArea->setGeometry(30, 20, 120, 20);
frAliasList = new QFrame(frWorkArea, "Alias List Area");
frAliasList->setFrameStyle(QFrame::Box | QFrame::Sunken |
QFrame::WinPanel);
frAliasList->setGeometry(30, 60, 320, 220);
lvAliasList = new QListView(frAliasList);
lvAliasList->setGeometry(3, 3, 314, 214);
lvAliasList->addColumn(" 가상 네트워크 ");
lvAliasList->addColumn(" IP 주소 ");
lvAliasList->setRootIsDecorated(true);
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
/* Aliasing된 IP를 얻는다. i는 index이다. */
/* 3.3에서 설명한 바와 같이 만약 i에 2가 넘겨 */
/* 진다면 ifcfg-eth0:1에 관한, 즉, eth0:2 Card */
/* 에 대응하는 IP를 얻게 될 것이다. */
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
QObject::connect(lvAliasList, SIGNAL(selectionChanged()), this,
SLOT(getAliasingItem()));
lblIP = new QLabel("IP 주소", frWorkArea);
lblIP->setGeometry(400, 60, 70, 20);
leIP = new QLineEdit(frWorkArea);
leIP->setGeometry(480, 60, 130, 20);
lblNetmask = new QLabel("넷마스크", frWorkArea);
lblNetmask->setGeometry(400, 100, 70, 20);
leNetmask = new QLineEdit(frWorkArea);
leNetmask->setGeometry(480, 100, 130, 20);
leNetmask->setEnabled(false);
lblNetwork = new QLabel("네트워크", frWorkArea);
lblNetwork->setGeometry(400, 140, 70, 20);
leNetwork = new QLineEdit(frWorkArea);
leNetwork->setGeometry(480, 140, 130, 20);
leNetwork->setEnabled(false);
lblBroadcast = new QLabel("브로드캐스트", frWorkArea);
lblBroadcast->setGeometry(400, 180, 70, 20);
leBroadcast = new QLineEdit(frWorkArea);
leBroadcast->setGeometry(480, 180, 130, 20);
leBroadcast->setEnabled(false);
bttnAdd = new QPushButton("추가", this);
bttnAdd->setGeometry(100, 410, 150, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this,
SLOT(addSetting()));
bttnDelete = new QPushButton("삭제", this);
bttnDelete->setGeometry(480, 410, 150, 30);
QObject::connect(bttnDelete, SIGNAL(clicked()), this,
SLOT(deleteSetting()));
}
clssDefAlias::~clssDefAlias()
{
int i;
delete lblNetworkArea;
if (nAliasCount > 0)
for (i = 0; i < nAliasCount; i++)
lviAlias[i];
delete lvAliasList;
delete lblIP;
delete leIP;
delete lblNetmask;
delete leNetmask;
delete lblNetwork;
delete leNetwork;
delete lblBroadcast;
delete leBroadcast;
delete frAliasList;
delete frWorkArea;
delete bttnAdd;
delete bttnDelete;
delete lblAliasingTitle;
}
void clssDefAlias::getAliasingItem()
{
char pszNetmask[18];
NetTab pNet;
memset(pszNetmask, '\0', 18);
getCurrentNetmask(pszNetmask);
leIP->setText(lvAliasList->currentItem()->text(1));
pNet = calculateNetMaskTab((char *)leIP->text(), pszNetmask);
leNetmask->setText(pszNetmask);
leNetwork->setText(pNet.pszNetwork);
leBroadcast->setText(pNet.pszBroadcast);
}
void clssDefAlias::addSetting()
{
FILE *fp;
char pszVirtualCard[10], pszFile[100];
char pszCommand[150];
memset(pszVirtualCard, '\0', 10);
memset(pszFile, '\0', 100);
sprintf(pszVirtualCard, "eth0:%d", nAliasCount);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-%s",
pszVirtualCard);
lviAlias[nAliasCount] = new QListViewItem(lvAliasList,
pszVirtualCard, leIP->text());
if ((fp = fopen(pszFile, "w")) == NULL)
{
emit printf("file open error!\n");
exit(1);
}
fprintf(fp, "DEVICE=%s\nIPADDR=%s\nONBOOT=yes\n",
pszVirtualCard, leIP->text());
fclose(fp);
nAliasCount++;
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::deleteSetting()
{
int i, j;
char pszCommand[150], pszFile[100];
char pszVirtualIP[18];
FILE *fp;
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
lvAliasList->itemPos(lvAliasList->currentItem())/18);
if ((fp = fopen(pszFile, "r")) == NULL)
return;
fclose(fp);
nAliasCount--;
memset(pszCommand, '\0', 150);
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:*");
sprintf(pszCommand, "rm -f %s\n", pszFile);
system(pszCommand);
if (nAliasCount > 0)
{
for (i = 0, j = 0; i < nAliasCount+1; i++)
{
if (i != lvAliasList->itemPos(lvAliasList->currentItem())/18)
{
memset(pszFile, '\0', 100);
sprintf(pszFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", j);
if ((fp = fopen(pszFile, "w")) == NULL)
return;
fprintf(fp, "DEVICE=eth0:%d\nIPADDR=%s\nONBOOT=yes\n",
j, lviAlias[i]->text(1));
fclose(fp);
j++;
}
}
}
/* 여기서 clear시키게 되면 List에 있던 모든 항목들이 지워 */
/* 지게 된다. 그리고 나서 다시 필요한 항목을 삽입시키면 */
/* 마치 refresh하는 효과를 얻을 수 있다. 이렇게 함으로써 */
/* 특정 item의 삭제가 가능해진다. 물론 이러한 방법은 단점 */
/* 이 남는다. 만약 List에 있는 item의 개수가 몇개 안될 때 */
/* 는 clear했다가 다시 item들을 삽입시켜도 system이 충분히 */
/* 속도를 감당해낼 수 있지만 item의 개수가 수십, 수백, 수천 */
/* 개일 경우는 틀려진다. refresh되는 과정이 그대로 보이게 */
/* 되므로 약간 짜증이 날 수도 있다는 것이다. */
/* 따라서 이부분에 대한 수정을 권하고 싶다. Qt에서는 특 */
/* 정 item에 대한 삭제함수가 있다. 이 함수를 쓰기 바란다. */
/* 함수 사용법도 간단하므로 사용하기 쉬울 것이다. */
/* /usr/lib/qt/include/qlistview.h에 보면 QListViewItem */
/* class에 removeItem과 QListView class에 repaint함수가 있 */
/* 다 이들을 적절하게 이용하면 될 것이다. */
lvAliasList->clear();
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
-------------- < Source 3.4.3.3 Network_menu.h > ---------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssDefAlias;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
clssDefAlias *clssAlias;
};
----------------------------------------------------------------
------------ < Source 3.4.3.4 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
clssAlias = new clssDefAlias();
clssAlias->setGeometry(150, 150, 750, 500);
clssAlias->show();
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
------------ < Source 3.4.3.5 main_menu.cpp > ------------------
#include <qapplication.h>
#include "Network_menu.h"
char pszNetConfHost[256];
char pszNetConfDomain[256];
char pszNetConfGateway[18];
char pszNetConfIPAddr[18];
char pszNetConfPrivate1IPAddr[18];
char pszNetConfPrivate2IPAddr[18];
char pszNetConfNetmask[18];
char pszNetConfPrivate1Netmask[18];
char pszNetConfPrivate2Netmask[18];
char pszNetconfBroadcast[18];
char pszNetconfPrivate1Broadcast[18];
char pszNetconfPrivate2Broadcast[18];
char pszNetConfNetwork[18];
char pszNetConfPrivate1Network[18];
char pszNetConfPrivate2Network[18];
char pszNetConfNetCard[3][30];
int nCountListStr;
char pszSaveNameServer[20][30];
int nCountNameServer;
int nCountClient;
extern int nAccountCount;
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
--------------------- < Makefile 3.4.3. > ----------------------
3.4.1의 Makefile과 마찬가지로 clssAlias_moc.cpp, clssAlias.cpp,
clssAlias.h등을 설정해준다.
----------------------------------------------------------------
자. 이로서 모든 과정이 다 끝났다. 부족한 부분이야 수도 없이 많지만
더욱 완벽한 Source는 다음에 올리기로 하고 이쯤에서 Project에 대한
모든 설명은 이만 접기로 하겠다. 이 자료를 보시는 분들께 꼭 한마디 하
고 다음 전체 Source를 쓰기로 하겠다. 우선 이 자료를 Qt를 공부하기 위
해 보시는 분들이라면 제일 먼저 꼭 밑에 있는 전체 Source를 file로 저장
해 compile하고 실행시키시기 바란다. 보통 GUI에 대한 공부는 설명이 먼
저가 아니라 눈으로 보는것이 선행되어야한다.
꼭 먼저 이 Project를 눈으로 확인 해보시기 바란다.
------------------------------------------------------------------------
< *** 전체 Source *** >
// ------------------- < Source : network.h > ---------------------
#ifndef _NETWORK_H
#define _NETWORK_H
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef MAX_LINE
#define MAX_LINE 100
#define MAX_COL 1000
#endif
#ifndef NO_SETTING
#define NO_SETTING "셋팅되어있지 않습니다."
#endif
extern char pszNetConfHost[256];
extern char pszNetConfDomain[256];
extern char pszNetConfGateway[18];
extern char pszNetConfIPAddr[18];
extern char pszNetConfPrivate1IPAddr[18];
extern char pszNetConfPrivate2IPAddr[18];
extern char pszNetConfNetmask[18];
extern char pszNetConfPrivate1Netmask[18];
extern char pszNetConfPrivate2Netmask[18];
extern char pszNetconfBroadcast[18];
extern char pszNetconfPrivate1Broadcast[18];
extern char pszNetconfPrivate2Broadcast[18];
extern char pszNetConfNetwork[18];
extern char pszNetConfPrivate1Network[18];
extern char pszNetConfPrivate2Network[18];
extern char pszNetConfNetCard[3][30];
extern int nCountListStr;
extern char pszSaveNameServer[20][30];
extern int nCountNameServer;
extern int nCountClient;
extern int nAccountCount;
typedef struct tagNETMASKTAB {
char pszNetwork[18];
char pszBroadcast[18];
} NetTab;
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask);
typedef struct tagSEPADDR {
char pszFirst[6];
char pszSecond[6];
char pszThird[6];
char pszFourth[6];
} S_Addr;
S_Addr separateAddress(char *pszAddr);
char *calculateDate(void);
void getCurrentNetmask(char *pszNetmask);
void getCurrentGateway(char *pszGateway);
void getCurrentHostName(char *pszHostName, char *pszDomainName);
void getCurrentIPAddr(char *pszIPAddr);
void getPrivate1Netmask(char *pszPrivateNetmask);
void getPrivate1IPAddr(char *pszPrivateIPAddr);
void getPrivate2Netmask(char *pszPrivateNetmask);
void getPrivate2IPAddr(char *pszPrivateIPAddr);
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nCardIdx);
void getDNSServer(char *pszDNSServer[]);
void getAliasNetmask(char *pszNetmask, int nIdx);
void getAliasIP(char *pszIPAddr, int nIdx);
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[]);
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth, int nRange);
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange);
#endif
// ----------------------------------------------------------------
// ------------------- < Source : network.c > ---------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include "network.h"
#include "proc_file.h"
/*************** Calculate Netmask table **************/
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask)
{
struct in_addr IP;
struct in_addr Mask;
struct in_addr pNetwork;
struct in_addr pBroadcast;
NetTab pNet;
memset(pNet.pszNetwork, '\0', 18);
memset(pNet.pszBroadcast, '\0', 18);
IP.s_addr = inet_addr(pszIPAddr);
Mask.s_addr = inet_addr(pszNetmask);
pNetwork.s_addr = IP.s_addr & Mask.s_addr;
memcpy(pNet.pszNetwork, inet_ntoa(pNetwork), 18);
pBroadcast.s_addr = pNetwork.s_addr | ~Mask.s_addr;
memcpy(pNet.pszBroadcast, inet_ntoa(pBroadcast), 18);
return pNet;
}
/***************************************/
S_Addr separateAddress(char *pszAddr)
{
int i = 0, j = 0, k = 0;
S_Addr pAddr;
memset(pAddr.pszFirst, '\0', 6);
memset(pAddr.pszSecond, '\0', 6);
memset(pAddr.pszThird, '\0', 6);
memset(pAddr.pszFourth, '\0', 6);
for (k = 0; *(pszAddr+i) != '\0'; i++, k++)
{
if (*(pszAddr+i) == '.')
{
i++;
k = 0;
j++;
}
switch (j)
{
case 0:
pAddr.pszFirst[k] = *(pszAddr+i);
break;
case 1:
pAddr.pszSecond[k] = *(pszAddr+i);
break;
case 2:
pAddr.pszThird[k] = *(pszAddr+i);
break;
case 3:
pAddr.pszFourth[k] = *(pszAddr+i);
break;
default:
break;
}
}
return pAddr;
}
char pszDate[11];
char *calculateDate()
{
time_t tTime;
int i;
memset(pszDate, '\0', 11);
tTime = time(NULL);
for (i = 0; i < 4; i++)
pszDate[i] = *(ctime(&tTime)+20+i);
for (i = 0; i < 3; i++)
pszDate[i+4] = *(ctime(&tTime)+4+i);
for (i = 0; i < 2; i++)
pszDate[i+4+3] = *(ctime(&tTime)+8+i);
return pszDate;
}
void getCurrentNetmask(char *pszNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszNetmask[i] = pszSave[i+8];
pszNetmask[i-1] = '\0';
}
void getCurrentGateway(char *pszGateway)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "GATEWAY="));
for (i = 0; pszSave[i+8] != 'G'; i++)
pszGateway[i] = pszSave[i+8];
pszGateway[i-1] = '\0';
}
void getPrivate1Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) == NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate1IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) == NULL)
{
// strcpy(pszPrivateIPAddr, "172.31.0.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getPrivate2Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) == NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate2IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) == NULL)
{
// strcpy(pszPrivateIPAddr, "192.168.1.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getCurrentHostName(char *pszHostName, char *pszDomainName)
{
struct utsname name;
int i, j;
uname(&name);
for (i = 0; name.nodename[i] != '.'; i++)
pszHostName[i] = name.nodename[i];
i++;
for (j = 0; name.nodename[i] != '\0'; i++, j++)
pszDomainName[j] = name.nodename[i];
}
void getCurrentIPAddr(char *pszIPAddr)
{
char *pszSaveListStr[20];
int i;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
saveSearchLineToFile("IPADDR", pszSaveListStr,
"/etc/sysconfig/network-scripts/ifcfg-eth0", 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nNetCardIdx)
{
int i;
char *pszPosIo, *pszPosIrq;
int nIrqIdx, nIoIdx;
char *pszTmpStr = "options eth%d";
char pszOptionStr[30];
char *pszSaveListStr[3];
for (i = 0; i < 3; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
memset(pszSaveListStr[i], '\0', 200);
exit(1);
}
}
memset(pszOptionStr, '\0', 30);
sprintf(pszOptionStr, pszTmpStr, nNetCardIdx);
saveSearchLineToFile(pszOptionStr, pszSaveListStr, "/etc/conf.modules",
200, 200);
pszPosIo = strstr(pszSaveListStr[0], "0x");
nIoIdx = pszPosIo-pszSaveListStr[0];
pszPosIrq = strstr(pszSaveListStr[0], "irq=");
nIrqIdx = pszPosIrq-pszSaveListStr[0];
for (i = nIoIdx-1; i < nIrqIdx-4; i++)
pszIo[i-nIoIdx+1] = pszSaveListStr[0][i+3];
for (i = nIrqIdx; pszSaveListStr[0][i+4] != '\n'; i++)
pszIrq[i-nIrqIdx] = pszSaveListStr[0][i+4];
for (i = 0; i < 3; i++)
free(pszSaveListStr[i]);
}
void getDNSServer(char *pszDNSServer[])
{
char *pszSaveListStr[50];
int i;
int nCntDNS;
for (i = 0; i < 50; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
saveSearchLineToFile("nameserver", pszSaveListStr, "/etc/resolv.conf",
50, 200);
nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
nCntDNS--;
for (i = 0; i < nCntDNS; i++)
{
strcpy(pszDNSServer[i], pszSaveListStr[i]+11);
pszDNSServer[i][strlen(pszDNSServer[i])-1] = '\0';
}
for (i = 0; i < 50; i++)
free(pszSaveListStr[i]);
}
void getAliasIP(char *pszIPAddr, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("IPADDR", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getAliasNetmask(char *pszNetmask, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("NETMASK", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+8] != '\n'; i++)
pszNetmask[i] = pszSaveListStr[0][i+8];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[])
{
FILE *fp;
int i, j, nIdx, nCount, nCardCount = 0;
char *pszSaveListStr[100];
char *pszSaveLine[4];
if ((fp = fopen("/proc/interrupts", "r")) == NULL)
{
printf("file open error!\n");
return;
}
fclose(fp);
for (i = 0; i < 4; i++)
{
if ((pszSaveLine[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveLine[i], '\0', 200);
}
for (i = 0; i < 100; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
nCount = saveAllLineToFile(pszSaveListStr, "/proc/interrupts", 100, 200);
for (i = 0, nIdx = 0; i < nCount; i++)
{
for (j = 0; j < 40; j++)
{
if (strstr(pszSaveListStr[i], pszCardInfo[j]) != (char *)NULL)
{
nCardCount++;
strcpy(pszSaveLine[nIdx++], pszSaveListStr[i]);
break;
}
}
}
if (nCardCount == 0)
{
strcpy(pszSaveNetCard[0], NO_SETTING);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 1)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 2)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], pszSaveLine[2]+33);
}
for (i = 0; i < 4; i++)
free(pszSaveLine[i]);
for (i = 0; i < 100; i++)
free(pszSaveListStr[i]);
}
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth, int nRange)
{
char pszSaveStartIP[4], pszSaveEndIP[4];
memset(pszSaveStartIP, '\0', 4);
memset(pszSaveEndIP, '\0', 4);
if (nIPFourth%nRange != 0)
{
sprintf(pszSaveStartIP, "%d", (nIPFourth/nRange)*nRange);
sprintf(pszSaveEndIP, "%d", (nIPFourth/nRange)*nRange+nRange-1);
}
else
{
sprintf(pszSaveStartIP, "%d", nIPFourth);
sprintf(pszSaveEndIP, "%d", nIPFourth+nRange-1);
}
strcat(pszStartIP, pszSaveStartIP);
strcat(pszEndIP, pszSaveEndIP);
}
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange)
{
S_Addr pAddr;
int i, nSaveRange;
int nStart, nEnd;
pAddr = separateAddress(pszStartIP);
nStart = atoi(pAddr.pszFourth);
pAddr = separateAddress(pszEndIP);
nEnd = atoi(pAddr.pszFourth);
nSaveRange = nEnd-nStart+1;
for (i = 0; nSaveRange > 0; i++)
nSaveRange /= 2;
*nRange = 32-(i-1);
}
// ----------------------------------------------------------------
// ------------------- < Source : proc_file.h > -------------------
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef MAX_XXX_NUM
#define MAX_XXX_NUM 10000
#define BLACKLIST_INSERT 1
#define BLACKLIST_DELETE 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine);
void insertStrForeSearch(char *pszSave, char *pszInsert, char *pszSearch,
char *pszLine, char *pszTempLine);
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine);
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol);
void *printToFileDL(DList *pPrint, FILE *fp);
int readOneLineSearchFile(char pszBuffer[], FILE *fp);
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void insertStrToFileLast(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol);
int countSearchLineToFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol);
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol);
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol);
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment, char *pszFileName,
int nMaxLine, int nMaxCol);
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExistWithoutComment(char *pszIns, char *pszSearch,
char cComment, char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName, int nMaxLine, int nMaxCol);
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void saveStrIdxToFileLine(char *pszSave, char *pszSearch, char *pszFileName,
int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol);
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol);
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol);
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol);
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol);
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol);
void changeStrInFile(char *pszFile, char *pszSrc, char *pszDest,
int nStatus);
int getUserBlackList(char *pszXXXData[MAX_XXX_NUM], int nMode);
#endif
#endif
// ----------------------------------------------------------------
// ------------------- < Source : proc_file.c > -------------------
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
/****** Insert to FILE ******/
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine)
{
char *pszPnt;
int i, nFirstLen;
if ((pszPnt = (char *)strstr(pszLine, pszDel)) == NULL)
return;
nFirstLen = pszPnt-pszLine;
for (i = 0; i < nFirstLen; i++)
pszSave[i] = pszLine[i];
for (i = nFirstLen; pszLine[i+strlen(pszDel)] != '\0'; i++)
pszSave[i] = pszLine[i+strlen(pszDel)];
pszSave[i] = '\0';
}
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine)
{
int i = 0;
int nLen;
char *pszPos;
if ((char *)strstr(pszLine, pszInsert) != NULL)
{
strcat(pszSave, pszTempLine);
return;
}
pszPos = (char *)strstr(pszLine, pszSearch);
nLen = pszPos-pszLine;
for (i = 0; i < nLen; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszInsert);
strcat(pszSave, strstr(pszLine, pszSearch));
}
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine)
{
int nFirstPos, nSecondPos;
if ((char *)strstr(pszLine, pszIns) != NULL)
return;
for (nFirstPos = 0; nFirstPos < strlen(pszLine); nFirstPos++)
pszSave[nFirstPos] = pszLine[nFirstPos];
for (nSecondPos = 0; nSecondPos < strlen(pszIns); nSecondPos++)
pszSave[nSecondPos+nFirstPos] = pszIns[nSecondPos];
pszSave[nSecondPos+nFirstPos] = '\0';
}
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
{
int i = 0;
char *pszPos;
int nPos;
pszPos = (char *)strstr(pszLine, pszSearch);
nPos = pszPos-pszLine;
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszIns);
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
pszPos = (char *)strstr(pszSave, pszSearch);
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
strcpy(pszLine, pszSave);
memset(pszSave, '\0', nMaxCol);
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
int nLine;
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
fprintf(fp, pPrint->pzKey);
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp);
pszBuffer[i++] = c;
if (c == EOF || c == '\n')
break;
} while (1);
pszBuffer[i] = '\0';
nLine++;
return c;
}
void insertStrToFileLast(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (nCount = 0; (readOneLineSearchFile(pszBuffer[nCount], fp) != EOF) &&
(nCount < nMaxLine); nCount++);
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
int countSearchLineToFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0;
int nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
nCount++;
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName, int nMaxLine,
int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (j = 0; j < nMaxLine; j++)
{
pszBuffer[j] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[j], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
strcpy(pszSaveListStr[i], pszBuffer[i]);
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return i;
}
int saveSearchLineToFileWithoutComment(char *pszSearch, char *pszSaveListStr[],
char cComment, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL &&
pszBuffer[i][0] != cComment)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
void changeStrToOneLineToFile(char *pszIns, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i], pszLine[j],
nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
void insertStrToOneLineToFile(char *pszIns, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertStrForeSearch(pszLine, pszIns, pszSearch, pszBuffer[i],
pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
deleteStrFromOneLine(pszLine, pszDel, pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
insertAsLastDL(pszInsert);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
int searchStrInFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
fclose(fp);
return TRUE;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return FALSE;
}
/** if Search is true, change.. else add **/
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void addOnNotExistChangeOnExistWithoutComment(char *pszIns, char *pszSearch,
char cComment, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL ||
pszBuffer[i][0] == cComment)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszFirstSearch) != NULL &&
(char *)strstr(pszBuffer[i], pszSecondSearch) != NULL)
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
else
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
insertAsLastDL(pszBuffer[i]);
fclose(fp);
insertDLAsKey(pszInsert, pszSearch);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrToFileLine(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][strlen(pszBuffer[i])-1] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void saveStrIdxToFileLine(char *pszSave, char *pszSearch, char *pszFileName,
int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nStartIdx);
for (j = 0; j < nEndIdx-nStartIdx; j++)
pszSave[j] = pszEndBuffer[j];
}
}
fclose(fp);
}
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nEndIdx);
pszBuffer[i][nStartIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
strcat(pszBuffer[i], pszEndBuffer);
pszBuffer[i][strlen(pszBuffer[i])] = '\0';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][nIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName, int nLineIdx,
int nColIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if (i == nLineIdx-1)
{
pszBuffer[i][nColIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
insertAsLastDL(pszInsert);
insertAsLastDL("\n");
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
insertAsLastDL(pszBuffer[j]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
{
if ((char *)strstr(pszBuffer[j], pszEndLine) == NULL)
strcpy(pszSaveLine[j-(i+1)], pszBuffer[j]);
else
break;
}
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return;
}
}
}
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
if ((char *)strstr(pszBuffer[j], pszEndLine) != NULL)
break;
for (k = 0; k < nInsertNum; k++)
insertAsLastDL(pszInsert[k]);
insertAsLastDL(pszBuffer[j]);
for (k = j+1; readOneLineSearchFile(pszBuffer[k], fp) != EOF; k++)
insertAsLastDL(pszBuffer[k]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
// ----------------------------------------------------------------
// ---------------- < Source : clssGeneric.h > --------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefGeneric : public QWidget
{
Q_OBJECT
public:
clssDefGeneric();
~clssDefGeneric();
private slots:
void setApply();
void setCancel();
void printLabelFormat(QLabel *lblBold);
private:
QLabel *lblGenericNetworkTitle;
QLabel *lblGateway;
QLineEdit *leGateway;
QLabel *lblEth0;
QLabel *lblEth0IPAddr;
QLineEdit *leEth0IPAddr;
QLabel *lblEth0Netmask;
QLineEdit *leEth0Netmask;
QLabel *lblEth0Network;
QLineEdit *leEth0Network;
QLabel *lblEth0Broadcast;
QLineEdit *leEth0Broadcast;
QLabel *lblEth0NetCard;
QComboBox *cbEthNetCard[3]; /* to combobox */
QLabel *lblEth1;
QLineEdit *leEth1IPAddr;
QLineEdit *leEth1Netmask;
QLineEdit *leEth1Network;
QLineEdit *leEth1Broadcast;
QLabel *lblEth1NetCard;
QLabel *lblEth2;
QLineEdit *leEth2IPAddr;
QLineEdit *leEth2Netmask;
QLineEdit *leEth2Network;
QLineEdit *leEth2Broadcast;
QLabel *lblEth2NetCard;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frEthInfo;
QLabel *lblSeparator1;
QLabel *lblSeparator2;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssGeneric.cpp > ------------------
#include <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qpalette.h>
#include <stdio.h>
#include <stdlib.h>
/* test */
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include "network.h"
#include "proc_file.h"
#include "clssGeneric.h"
clssDefGeneric::clssDefGeneric()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
int i, j, nCardIdx;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
const char *pszNetCard[40] = {
" 3Com Vortex series (3c590, 3c592, 3c597, 3c595) (3c59x) ",
" 3Com Boomerang (3c900, 3c905, 3c575) (3c59x) ",
" 3Com Cyclone (3c905B) (3c59x) ",
" Intel EtherExpress Pro 100 (eepro100) ",
" HP J2585B, J2585A, J2970, J2973 (hp100) ",
" HP J2573 (hp100) ",
" Compex ReadyLink ENET100-VG4 (hp100) ",
" Compex FreedomLine 100/VG (hp100) ",
" IBM token ring (ibmtr) ",
" NE2000 (PCI) (ne2k-pci) ",
" AMD PCnet/PCI 79C970/PCnet32/PCnet/PCI II 79C970A (pcnet32) ",
" PCnet/PCI II 79C971A (pcnet32) ",
" Allied Telesyn AT2550 (rtl8139) ",
" Genius GF100TXR (RTL8139) (rtl8139) ",
" NDC Communications NE100TX-E (rtl8139) ",
" RealTek RTL8129/8139 Fast (rtl8139) ",
" SMC Ultra/SMC UltraEZ/SMC Ultra32 (smc-ultra) ",
" Compaq Netelligent 10 T PCI UTP (tlan) ",
" Compaq Netelligent 10/100 TX PCI UTP (tlan) ",
" Compaq Netelligent Integrated 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10/100 TX Embedded UTP (tlan) ",
" Compaq Netelligent 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10 T/2 PCI UTP/Coax (tlan) ",
" Accton EtherDuo PCI/Accton EN1207 (tulip) ",
" Adaptec ANA6901/C/Adaptec ANA6911/TX (tulip) ",
" C-NET CNE-935 (tulip) ",
" Cogent EM100/Cogent EM110/Cogent EM400 (tulip) ",
" Cogent EM960/Cogent EM964 Quartet (tulip) ",
" Danpex EN-9400P3 (tulip) ",
" D-Link DFE500-Tx/D-Link DE-530CT (tulip) ",
" Linksys EtherPCI (tulip) ",
" Kingston EtherX KNT40T/Kingston EtherX KNE100TX (tulip) ",
" Netgear FX310 TX 10/100 (tulip) ",
" SMC EtherPower/SMC 8432BT/ SMC Ether Power10/100 (tulip) ",
" Surecom EP-320X (tulip) ",
" Thomas Conrad TC5048 (tulip) ",
" Znyx ZX312 EtherAction/Znyx ZX314/ZX315 (tulip) ",
" Znyx ZX342/ZX344/ZX345/ZX346/ZX348 (tulip) ",
" Znyx ZX351 (tulip) ",
" 세팅되어있지 않습니다! (No Setting)"
};
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr, pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr, pszPrivate2Netmask);
/***********************/
lblGenericNetworkTitle = new QLabel(
"Network Setting (일반적인 네트워크 설정)", this);
lblGenericNetworkTitle->setGeometry(20, 20, 400, 20);
// printLabelFormat(lblGenericNetworkTitle);
/***********************/
frEthInfo = new QFrame(this);
frEthInfo->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frEthInfo->setGeometry(25, 50, 700, 362);
lblGateway = new QLabel("게이트웨이", frEthInfo);
lblGateway->setGeometry(10, 15, 80, 20);
leGateway = new QLineEdit(frEthInfo);
leGateway->setGeometry(90, 15, 150, 20);
leGateway->setText(pszGateway);
lblSeparator1 = new QLabel(frEthInfo);
lblSeparator1->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator1->setGeometry(20, 45, 630, 2);
/******** Ethernet Card 0 ********/
lblEth0 = new QLabel("첫번째 이더넷카드", frEthInfo);
lblEth0->setGeometry(90, 10+50, 100, 20);
lblEth0IPAddr = new QLabel("IP 주소 ", frEthInfo);
lblEth0IPAddr->setGeometry(10, 40+50, 80, 20);
leEth0IPAddr = new QLineEdit(frEthInfo);
leEth0IPAddr->setGeometry(90, 40+50, 150, 20);
leEth0IPAddr->setText(pszIPAddr);
/*** text -> proc ***/
lblEth0Netmask = new QLabel("Netmask ", frEthInfo);
lblEth0Netmask->setGeometry(10, 40+30+50, 80, 20);
leEth0Netmask = new QLineEdit(frEthInfo);
leEth0Netmask->setGeometry(90, 40+30+50, 150, 20);
leEth0Netmask->setText(pszNetmask);
lblEth0Network = new QLabel("Network ", frEthInfo);
lblEth0Network->setGeometry(10, 40+60+50, 80, 20);
leEth0Network = new QLineEdit(frEthInfo);
leEth0Network->setGeometry(90, 40+60+50, 150, 20);
leEth0Network->setEnabled(0);
leEth0Network->setText(pNet.pszNetwork);
lblEth0Broadcast = new QLabel("Broadcast ", frEthInfo);
lblEth0Broadcast->setGeometry(10, 40+90+50, 80, 20);
leEth0Broadcast = new QLineEdit(frEthInfo);
leEth0Broadcast->setGeometry(90, 40+90+50, 150, 20);
leEth0Broadcast->setEnabled(0);
leEth0Broadcast->setText(pNet.pszBroadcast);
lblSeparator2 = new QLabel(frEthInfo);
lblSeparator2->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator2->setGeometry(20, 40+90+50+40, 630, 2);
/*** text -> proc ***/
/*********************************/
/******** Ethernet Card 1 ********/
lblEth1 = new QLabel("두번째 이더넷카드", frEthInfo);
lblEth1->setGeometry(300, 10+50, 100, 20);
leEth1IPAddr = new QLineEdit(frEthInfo);
leEth1IPAddr->setGeometry(300, 40+50, 150, 20);
leEth1IPAddr->setText(pszPrivate1IPAddr);
/*** text -> proc ***/
leEth1Netmask = new QLineEdit(frEthInfo);
leEth1Netmask->setGeometry(300, 40+30+50, 150, 20);
leEth1Netmask->setText(pszPrivate1Netmask);
/*** text -> proc ***/
leEth1Network = new QLineEdit(frEthInfo);
leEth1Network->setGeometry(300, 40+60+50, 150, 20);
leEth1Broadcast = new QLineEdit(frEthInfo);
leEth1Broadcast->setGeometry(300, 40+90+50, 150, 20);
leEth1Network->setEnabled(0);
leEth1Broadcast->setEnabled(0);
if (strlen(pszPrivate1IPAddr) >= 7)
{
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
}
/*********************************/
/******** Ethernet Card 2 ********/
lblEth2 = new QLabel("세번째 이더넷카드", frEthInfo);
lblEth2->setGeometry(520, 10+50, 100, 20);
leEth2IPAddr = new QLineEdit(frEthInfo);
leEth2IPAddr->setGeometry(520, 40+50, 150, 20);
leEth2IPAddr->setText(pszPrivate2IPAddr);
/*** text -> proc ***/
leEth2Netmask = new QLineEdit(frEthInfo);
leEth2Netmask->setGeometry(520, 40+30+50, 150, 20);
leEth2Netmask->setText(pszPrivate2Netmask);
/*** text -> proc ***/
leEth2Network = new QLineEdit(frEthInfo);
leEth2Network->setGeometry(520, 40+60+50, 150, 20);
leEth2Broadcast = new QLineEdit(frEthInfo);
leEth2Broadcast->setGeometry(520, 40+90+50, 150, 20);
leEth2Network->setEnabled(0);
leEth2Broadcast->setEnabled(0);
if (strlen(pszPrivate2IPAddr) >= 7)
{
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
}
/*********************************/
for (i = 0; i < 2; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*200);
memset(pszSaveListStr[i], '\0', 200);
}
/*********************************/
lblEth0NetCard = new QLabel("Ethernet 0 카드", frEthInfo);
lblEth0NetCard->setGeometry(10, 40+90+70+60, 90, 20);
cbEthNetCard[0] = new QComboBox(frEthInfo, "comboBox_Eth0");
cbEthNetCard[0]->setGeometry(110, 40+90+70+60, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[0]->insertItem(pszNetCard[i]);
cbEthNetCard[0]->setAutoResize(FALSE);
if (saveSearchLineToFile("alias eth0", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[0], pszSaveListStr[0]+11);
pszNetConfNetCard[0][strlen(pszNetConfNetCard[0])-1] = '\0';
}
if (strlen(pszIPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[0]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[0]) < 2)
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
/*********************************/
lblEth1NetCard = new QLabel("Ethernet 1 카드", frEthInfo);
lblEth1NetCard->setGeometry(10, 40+90+70+90, 90, 20);
cbEthNetCard[1] = new QComboBox(frEthInfo, "comboBox_Eth1");
cbEthNetCard[1]->setGeometry(110, 40+90+70+90, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[1]->insertItem(pszNetCard[i]);
cbEthNetCard[1]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth1", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[1], pszSaveListStr[0]+11);
pszNetConfNetCard[1][strlen(pszNetConfNetCard[1])-1] = '\0';
}
if (strlen(pszPrivate1IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[1]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[1]) < 2)
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
/**********************************/
lblEth2NetCard = new QLabel("Ethernet 2 카드", frEthInfo);
lblEth2NetCard->setGeometry(10, 40+90+70+120, 90, 20);
cbEthNetCard[2] = new QComboBox(frEthInfo, "comboBox_Eth2");
cbEthNetCard[2]->setGeometry(110, 40+90+70+120, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[2]->insertItem(pszNetCard[i]);
cbEthNetCard[2]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth2", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[2], pszSaveListStr[0]+11);
pszNetConfNetCard[2][strlen(pszNetConfNetCard[2])-1] = '\0';
}
if (strlen(pszPrivate2IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[2]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[2]) < 2)
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
cbEthNetCard[2]->setGeometry(110, 40+90+70+125, 470, 20);
/*************************************/
bttnApply = new QPushButton("적 용", this);
bttnApply->setGeometry(150, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this, SLOT(setApply()));
bttnCancel = new QPushButton("취 소", this);
bttnCancel->setGeometry(450, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this, SLOT(setCancel()));
/************************************/
for (i = 0; i < 2; i++)
free(pszSaveListStr[i]);
free(pszIPAddr);
free(pszNetmask);
free(pszPrivate1IPAddr);
free(pszPrivate1Netmask);
free(pszPrivate2IPAddr);
free(pszPrivate2Netmask);
free(pszGateway);
}
clssDefGeneric::~clssDefGeneric()
{
int i;
delete lblEth0;
delete lblEth0IPAddr;
delete lblEth0Netmask;
delete lblEth0Network;
delete lblEth0Broadcast;
delete leEth0IPAddr;
delete leEth0Netmask;
delete leEth0Network;
delete leEth0Broadcast;
delete lblEth1;
delete leEth1IPAddr;
delete leEth1Netmask;
delete leEth1Network;
delete leEth1Broadcast;
delete lblEth2;
delete leEth2IPAddr;
delete leEth2Netmask;
delete leEth2Network;
delete leEth2Broadcast;
delete lblGateway;
delete leGateway;
delete lblSeparator1;
delete lblSeparator2;
for (i = 0; i < 3; i++)
delete cbEthNetCard[i];
delete lblEth0NetCard;
delete lblEth1NetCard;
delete lblEth2NetCard;
delete bttnCancel;
delete bttnApply;
delete lblGenericNetworkTitle;
delete frEthInfo;
}
void clssDefGeneric::setApply()
{
char *pszIfCfgEthFile =
"DEVICE=%s\nIPADDR=%s\nNETMASK=%s\nNETWORK=%s\nBROADCAST=%s\nONBOOT=yes\n";
char *pszNetworkFile =
"NETWORKING=yes\nFORWARD_IPV4=true\nHOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszOptions[95];
char *pszSaveCardLine[3], pszSaveHostName[256], pszSaveDomainName[256];
NetTab pNet, pNetPrivate1, pNetPrivate2;
FILE *fp;
S_Addr pAddr, pSaveAddr;
char pszTmpSearch[100];
char pszTmpInsert[100];
char pszSaveIP[18];
int i;
memset(pszSaveIP, '\0', 18);
getCurrentIPAddr(pszSaveIP);
pSaveAddr = separateAddress(pszSaveIP);
pNet = calculateNetMaskTab((char *)leEth0IPAddr->text(),
(char *)leEth0Netmask->text());
pNetPrivate1 = calculateNetMaskTab((char *)leEth1IPAddr->text(),
(char *)leEth1Netmask->text());
pNetPrivate2 = calculateNetMaskTab((char *)leEth2IPAddr->text(),
(char *)leEth2Netmask->text());
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "w");
fprintf(fp, pszIfCfgEthFile,
"eth0", leEth0IPAddr->text(), leEth0Netmask->text(),
leEth0Network->text(), leEth0Broadcast->text());
fclose(fp);
if (strlen((char *)leEth1IPAddr->text()) >= 7)
{
char pszPrivate1IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "w");
fprintf(fp, pszIfCfgEthFile,
"eth1", leEth1IPAddr->text(), leEth1Netmask->text(),
leEth1Network->text(), leEth1Broadcast->text());
fclose(fp);
memset(pszPrivate1IPAddr, '\0', 20);
memset(pszCommand, '\0', 150);
getPrivate1IPAddr(pszPrivate1IPAddr);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip del %s\n",
pszPrivate1IPAddr);
system(pszCommand);
memset(pszCommand, '\0', 150);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip add %s\n",
leEth1IPAddr->text());
system(pszCommand);
}
if (strlen((char *)leEth2IPAddr->text()) >= 7)
{
char pszPrivate2IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "w");
fprintf(fp, pszIfCfgEthFile,
"eth2", leEth2IPAddr->text(), leEth2Netmask->text(),
leEth2Network->text(), leEth2Broadcast->text());
fclose(fp);
memset(pszPrivate2IPAddr, '\0', 20);
memset(pszCommand, '\0', 150);
getPrivate2IPAddr(pszPrivate2IPAddr);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip del %s\n",
pszPrivate2IPAddr);
system(pszCommand);
memset(pszCommand, '\0', 150);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip add %s\n",
leEth2IPAddr->text());
system(pszCommand);
}
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, pszSaveHostName, pszSaveDomainName,
pszSaveDomainName, leGateway->text());
fclose(fp);
for (i = 0; i < 3; i++)
{
if ((pszSaveCardLine[i] = (char *)malloc(sizeof(char)*50)) == NULL)
{
printf("pszSaveCardLine Memory Error!\n");
exit(1);
}
memset(pszSaveCardLine[i], '\0', 50);
}
for (i = 0; i < 3; i++)
{
sprintf(pszSaveCardLine[i], "alias eth%d ", i);
if (cbEthNetCard[i]->currentItem() >= 0 &&
cbEthNetCard[i]->currentItem() <= 2)
strcat(pszSaveCardLine[i], "3c59x");
else if (cbEthNetCard[i]->currentItem() == 3)
strcat(pszSaveCardLine[i], "eepro100");
else if (cbEthNetCard[i]->currentItem() >= 4 &&
cbEthNetCard[i]->currentItem() <= 7)
strcat(pszSaveCardLine[i], "hp100");
else if (cbEthNetCard[i]->currentItem() == 8)
strcat(pszSaveCardLine[i], "ibmtr");
else if (cbEthNetCard[i]->currentItem() == 9)
strcat(pszSaveCardLine[i], "ne2k-pci");
else if (cbEthNetCard[i]->currentItem() == 10 ||
cbEthNetCard[i]->currentItem() == 11)
strcat(pszSaveCardLine[i], "pcnet32");
else if (cbEthNetCard[i]->currentItem() >= 12 &&
cbEthNetCard[i]->currentItem() <= 15)
strcat(pszSaveCardLine[i], "rtl8139");
else if (cbEthNetCard[i]->currentItem() == 16)
strcat(pszSaveCardLine[i], "smc-ultra");
else if (cbEthNetCard[i]->currentItem() >= 17 ||
cbEthNetCard[i]->currentItem() <= 22)
strcat(pszSaveCardLine[i], "tlan");
else if (cbEthNetCard[i]->currentItem() >= 23 ||
cbEthNetCard[i]->currentItem() <= 38)
strcat(pszSaveCardLine[i], "tulip");
}
for (i = 0; i < 3; i++)
strcat(pszSaveCardLine[i], "\n");
addOnNotExistChangeOnExist(pszSaveCardLine[0], "alias eth0",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[1], "alias eth1",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[2], "alias eth2",
"/etc/conf.modules", 200, 100);
if (cbEthNetCard[0]->currentItem() == 39)
insertStrToFile("", "alias eth0", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[1]->currentItem() == 39)
insertStrToFile("", "alias eth1", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[2]->currentItem() == 39)
insertStrToFile("", "alias eth2", "/etc/conf.modules", 200, 100);
for (i = 0; i < 3; i++)
free(pszSaveCardLine[i]);
if (cbEthNetCard[0]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth0");
leEth0IPAddr->setText("");
leEth0Netmask->setText("");
leEth0Network->setText("");
leEth0Broadcast->setText("");
}
if (cbEthNetCard[1]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth1");
leEth1IPAddr->setText("");
leEth1Netmask->setText("");
leEth1Network->setText("");
leEth1Broadcast->setText("");
}
if (cbEthNetCard[2]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth2");
leEth2IPAddr->setText("");
leEth2Netmask->setText("");
leEth2Network->setText("");
leEth2Broadcast->setText("");
}
/**************************************/
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth0 \
/etc/sysconfig/network-scripts/ifcfg-eth0.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth1 \
/etc/sysconfig/network-scripts/ifcfg-eth1.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth2 \
/etc/sysconfig/network-scripts/ifcfg-eth2.org\n");
system("cp -f /etc/sysconfig/network /etc/sysconfig/network.org\n");
system("cp -f /etc/conf.modules /etc/conf.modules.org\n");
system("cp -f /etc/resolv.conf /etc/resolv.conf.org\n");
system("/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network start\n");
}
void clssDefGeneric::setCancel()
{
char *pszIPAddr, *pszNetmask, *pszGateway, *pszHostName, *pszDomainName;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr, pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr, pszPrivate2Netmask);
/***** lineeditbox init: proc -> segmentation fault *****/
leGateway->setText(pszGateway);;
leEth0IPAddr->setText(pszIPAddr);
leEth0Netmask->setText(pszNetmask);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1IPAddr->setText(pszPrivate1IPAddr);
leEth1Netmask->setText(pszPrivate1Netmask);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2IPAddr->setText(pszPrivate2IPAddr);
leEth2Netmask->setText(pszPrivate2Netmask);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
}
void clssDefGeneric::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : clssDNS.h > ------------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefDNS : public QWidget
{
Q_OBJECT
public:
clssDefDNS();
~clssDefDNS();
public slots:
void printLabelFormat(QLabel *lblDNSTitle);
void rebootSystem();
private slots:
void applySetting();
void cancelSetting();
void addDNS();
void delDNS();
private:
QLabel *lblHostName;
QLabel *lblDomainName;
QLineEdit *leHostName;
QLineEdit *leDomainName;
QLabel *lblDNSServer;
QComboBox *cbDNSServer;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frWorkArea;
QLabel *lblSeparator;
QPushButton *bttnAdd;
QPushButton *bttnDel;
QLabel *lblDNSTitle;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssDNS.cpp > ----------------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <stdio.h>
#include <stdlib.h>
/* test */
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssDNS.h"
clssDefDNS::clssDefDNS()
{
char *pszNetmask, *pszHostName, *pszDomainName;
int i, j;
NetTab pNet;
if (((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
/***********************/
lblDNSTitle = new QLabel("DNS Setting (DNS 설정)", this);
lblDNSTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblDNSTitle);
frWorkArea = new QFrame(this);
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frWorkArea->setGeometry(30, 30, 330, 430);
/******** Ethernet Card 0 ********/
lblHostName = new QLabel("호스트명", frWorkArea);
lblHostName->setGeometry(20, 50, 80, 20);
leHostName = new QLineEdit(frWorkArea);
leHostName->setGeometry(100, 50, 180, 20);
leHostName->setText(pszHostName);
lblDomainName = new QLabel("도메인명", frWorkArea);
lblDomainName->setGeometry(20, 80, 80, 20);
leDomainName = new QLineEdit(frWorkArea);
leDomainName->setGeometry(100, 80, 180, 20);
leDomainName->setText(pszDomainName);
bttnApply = new QPushButton("적 용", frWorkArea);
bttnApply->setGeometry(50, 160, 80, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this, SLOT(applySetting()));
bttnCancel = new QPushButton("취 소", frWorkArea);
bttnCancel->setGeometry(180, 160, 80, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(cancelSetting()));
/*************************************/
lblSeparator = new QLabel(frWorkArea);
lblSeparator->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator->setGeometry(20, 230, 290, 2);
lblDNSServer = new QLabel("DNS서버", frWorkArea);
lblDNSServer->setGeometry(20, 280, 80, 20);
cbDNSServer = new QComboBox(TRUE, frWorkArea, "comboBox_DNS");
cbDNSServer->setGeometry(100, 280, 150, 20);
char *pszDNSServer[50];
int nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
for (i = 0; i < 50; i++)
{
if ((pszDNSServer[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszDNSServer[i], '\0', 200);
}
getDNSServer(pszDNSServer);
for (i = 0; i < nCntDNS-1; i++)
cbDNSServer->insertItem(pszDNSServer[i]);
cbDNSServer->setAutoResize(FALSE);
for (i = 0; i < 50; i++)
free(pszDNSServer[i]);
bttnAdd = new QPushButton("추 가", frWorkArea);
bttnAdd->setGeometry(50, 350, 80, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addDNS()));
bttnDel = new QPushButton("삭 제", frWorkArea);
bttnDel->setGeometry(180, 350, 80, 30);
QObject::connect(bttnDel, SIGNAL(clicked()), this, SLOT(delDNS()));
/************************************/
free(pszHostName);
free(pszDomainName);
}
clssDefDNS::~clssDefDNS()
{
int i;
delete lblHostName;
delete lblDomainName;
delete leHostName;
delete leDomainName;
delete bttnCancel;
delete bttnApply;
delete lblDNSServer;
delete cbDNSServer;
delete bttnAdd;
delete bttnDel;
delete frWorkArea;
delete lblDNSTitle;
}
void clssDefDNS::addDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
if (strcmp(cbDNSServer->text(cbDNSServer->currentItem()),
cbDNSServer->currentText()) != 0)
cbDNSServer->insertItem(cbDNSServer->currentText());
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
memset(pszTmpInsert, '\0', 100);
sprintf(pszTmpInsert, "nameserver %s\n", cbDNSServer->currentText());
sprintf(pszTmpSearch, "nameserver %s", cbDNSServer->currentText());
if (!searchStrInFile(pszTmpSearch, "/etc/resolve.conf", 100, 100))
addOnNotExistChangeOnExist(pszTmpInsert, pszTmpSearch,
"/etc/resolv.conf", 100, 100);
}
}
void clssDefDNS::delDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->text(cbDNSServer->currentItem()));
if (!searchStrInFile(pszTmpSearch, "/etc/resolve.conf", 100, 100))
insertStrToFile("", pszTmpSearch, "/etc/resolv.conf", 100, 100);
cbDNSServer->removeItem(cbDNSServer->currentItem());
cbDNSServer->setCurrentItem(0);
}
}
void clssDefDNS::applySetting()
{
char *pszNetworkFile =
"NETWORKING=yes\nFORWARD_IPV4=true\nHOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszGateway[18];
char pszOptions[95];
char *pszSaveCardLine[3];
FILE *fp;
S_Addr pAddr;
char pszTmpSearch[100], pszTmpInsert[100];
char pszSaveIP[18], pszSaveHostName[256], pszSaveDomainName[256];
int i;
char pszCommand[200];
memset(pszSaveIP, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentIPAddr(pszSaveIP);
getCurrentGateway(pszGateway);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, leHostName->text(), leDomainName->text(),
leDomainName->text(), pszGateway);
fclose(fp);
/**** update named daemon ****/
if (strlen(leHostName->text()) >= 1)
{
pAddr = separateAddress(pszSaveIP);
/*** HOSTNAME Host,Domain changed ***/
char pszTmpDomain[100];
char pszTmpHost[50];
memset(pszTmpInsert, '\0', 100);
memset(pszTmpHost, '\0', 50);
memset(pszTmpDomain, '\0', 100);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
sprintf(pszTmpInsert, "%s.%s\n", pszTmpHost, pszTmpDomain);
addOnNotExistChangeOnExist(pszTmpInsert, pszSaveHostName,
"/etc/HOSTNAME", 100, 100);
memset(pszTmpDomain, '\0', 100);
memset(pszTmpHost, '\0', 50);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
if (strcmp(pszSaveDomainName, pszTmpDomain) != 0 ||
strcmp(pszSaveHostName, pszTmpHost) != 0)
{
QWidget *wdgtRebooting = new QWidget();
wdgtRebooting->setGeometry(300, 300, 300, 150);
QLabel *lblRebooting = new QLabel(
"호스트이름 혹은 도메인 이름이 바뀌었으므로\n재부팅을 하겠습니다.",
wdgtRebooting);
lblRebooting->setGeometry(20, 20, 250, 50);
QPushButton *bttnRebooting = new QPushButton("재 부 팅",
wdgtRebooting);
bttnRebooting->setGeometry(120, 90, 120, 30);
QObject::connect(bttnRebooting, SIGNAL(clicked()), this,
SLOT(rebootSystem()));
wdgtRebooting->show();
}
}
system("/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network restart\n");
}
void clssDefDNS::cancelSetting()
{
char *pszHostName, *pszDomainName;
char *pszSaveListStr[2];
if (((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
leHostName->setText(pszHostName);
leDomainName->setText(pszDomainName);
}
void clssDefDNS::rebootSystem()
{
system("sync;sync;sync;sync;sync;sync;sync;sync;init 6\n");
}
void clssDefDNS::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : clssAlias.h > ----------------------
#include <qwidget.h>
class QLineEdit;
class QLabel;
class QLineEdit;
class QListView;
class QListViewItem;
class QFrame;
class QPushButton;
class clssDefAlias : public QWidget
{
Q_OBJECT
public:
clssDefAlias();
~clssDefAlias();
public slots:
void addSetting();
void deleteSetting();
void getAliasingItem();
void printLabelFormat(QLabel *lblAliasingTitle);
private slots:
private:
QFrame *frWorkArea;
QPushButton *bttnAdd;
QPushButton *bttnDelete;
QFrame *frAliasList;
QListView *lvAliasList;
QListViewItem *lviAlias[100];
QLabel *lblNetworkArea;
QLabel *lblIP;
QLineEdit *leIP;
QLabel *lblNetmask;
QLineEdit *leNetmask;
QLabel *lblNetwork;
QLineEdit *leNetwork;
QLabel *lblBroadcast;
QLineEdit *leBroadcast;
QLabel *lblAliasingTitle;
int nAliasCount;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssAlias.cpp > --------------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <qframe.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlistview.h>
#include <stdio.h>
#include <stdlib.h>
#include "proc_file.h"
#include "network.h"
#include "clssAlias.h"
clssDefAlias::clssDefAlias()
{
int i;
char pszSaveFile[100];
char pszVirtualIP[18];
FILE *fp;
for (nAliasCount = 0; nAliasCount < 10; nAliasCount++)
{
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nAliasCount);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
break;
fclose(fp);
}
lblAliasingTitle = new QLabel("Virtual LAN (가상 네트워크 카드 설정)",
this);
lblAliasingTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblAliasingTitle);
frWorkArea = new QFrame(this, "IP Aliasing Area");
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frWorkArea->setGeometry(40, 60, 670, 310);
lblNetworkArea = new QLabel("네트워크영역 선택", frWorkArea);
lblNetworkArea->setGeometry(30, 20, 120, 20);
frAliasList = new QFrame(frWorkArea, "Alias List Area");
frAliasList->setFrameStyle(QFrame::Box | QFrame::Sunken | QFrame::WinPanel);
frAliasList->setGeometry(30, 60, 320, 220);
lvAliasList = new QListView(frAliasList);
lvAliasList->setGeometry(3, 3, 314, 214);
lvAliasList->addColumn(" 가상 네트워크 ");
lvAliasList->addColumn(" IP 주소 ");
lvAliasList->setRootIsDecorated(true);
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
QObject::connect(lvAliasList, SIGNAL(selectionChanged()), this,
SLOT(getAliasingItem()));
lblIP = new QLabel("IP 주소", frWorkArea);
lblIP->setGeometry(400, 60, 70, 20);
leIP = new QLineEdit(frWorkArea);
leIP->setGeometry(480, 60, 130, 20);
lblNetmask = new QLabel("넷마스크", frWorkArea);
lblNetmask->setGeometry(400, 100, 70, 20);
leNetmask = new QLineEdit(frWorkArea);
leNetmask->setGeometry(480, 100, 130, 20);
leNetmask->setEnabled(false);
lblNetwork = new QLabel("네트워크", frWorkArea);
lblNetwork->setGeometry(400, 140, 70, 20);
leNetwork = new QLineEdit(frWorkArea);
leNetwork->setGeometry(480, 140, 130, 20);
leNetwork->setEnabled(false);
lblBroadcast = new QLabel("브로드캐스트", frWorkArea);
lblBroadcast->setGeometry(400, 180, 70, 20);
leBroadcast = new QLineEdit(frWorkArea);
leBroadcast->setGeometry(480, 180, 130, 20);
leBroadcast->setEnabled(false);
bttnAdd = new QPushButton("추가", this);
bttnAdd->setGeometry(100, 410, 150, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addSetting()));
bttnDelete = new QPushButton("삭제", this);
bttnDelete->setGeometry(480, 410, 150, 30);
QObject::connect(bttnDelete, SIGNAL(clicked()), this,
SLOT(deleteSetting()));
}
clssDefAlias::~clssDefAlias()
{
int i;
delete lblNetworkArea;
if (nAliasCount > 0)
for (i = 0; i < nAliasCount; i++)
lviAlias[i];
delete lvAliasList;
delete lblIP;
delete leIP;
delete lblNetmask;
delete leNetmask;
delete lblNetwork;
delete leNetwork;
delete lblBroadcast;
delete leBroadcast;
delete frAliasList;
delete frWorkArea;
delete bttnAdd;
delete bttnDelete;
delete lblAliasingTitle;
}
void clssDefAlias::getAliasingItem()
{
char pszNetmask[18];
NetTab pNet;
memset(pszNetmask, '\0', 18);
getCurrentNetmask(pszNetmask);
leIP->setText(lvAliasList->currentItem()->text(1));
pNet = calculateNetMaskTab((char *)leIP->text(), pszNetmask);
leNetmask->setText(pszNetmask);
leNetwork->setText(pNet.pszNetwork);
leBroadcast->setText(pNet.pszBroadcast);
}
void clssDefAlias::addSetting()
{
FILE *fp;
char pszVirtualCard[10], pszFile[100];
char pszCommand[150];
memset(pszVirtualCard, '\0', 10);
memset(pszFile, '\0', 100);
sprintf(pszVirtualCard, "eth0:%d", nAliasCount);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-%s", pszVirtualCard);
lviAlias[nAliasCount] = new QListViewItem(lvAliasList, pszVirtualCard,
leIP->text());
if ((fp = fopen(pszFile, "w")) == NULL)
{
emit printf("file open error!\n");
exit(1);
}
fprintf(fp, "DEVICE=%s\nIPADDR=%s\nONBOOT=yes\n",pszVirtualCard,
leIP->text());
fclose(fp);
nAliasCount++;
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::deleteSetting()
{
int i, j;
char pszCommand[150], pszFile[100];
char pszVirtualIP[18];
FILE *fp;
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
lvAliasList->itemPos(lvAliasList->currentItem())/18);
if ((fp = fopen(pszFile, "r")) == NULL)
return;
fclose(fp);
nAliasCount--;
memset(pszCommand, '\0', 150);
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:*");
sprintf(pszCommand, "rm -f %s\n", pszFile);
system(pszCommand);
if (nAliasCount > 0)
{
for (i = 0, j = 0; i < nAliasCount+1; i++)
{
if (i != lvAliasList->itemPos(lvAliasList->currentItem())/18)
{
memset(pszFile, '\0', 100);
sprintf(pszFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", j);
if ((fp = fopen(pszFile, "w")) == NULL)
return;
fprintf(fp, "DEVICE=eth0:%d\nIPADDR=%s\nONBOOT=yes\n", j,
lviAlias[i]->text(1));
fclose(fp);
j++;
}
}
}
lvAliasList->clear();
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : Network_menu.h > -------------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssDefAlias;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
clssDefAlias *clssAlias;
};
// ----------------------------------------------------------------
// ---------------- < Source : Network_menu.cpp > -----------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric, GENERIC_TOOLTIP,
0, this, SLOT(funcGenericNetwork()), tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0, this,
SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP, 0,
this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
clssAlias = new clssDefAlias();
clssAlias->setGeometry(150, 150, 750, 500);
clssAlias->show();
}
void clssNetwork::funcQuit()
{
exit(0);
}
// ----------------------------------------------------------------
// ------------------ < Source : main_menu.cpp > ------------------
#include <qapplication.h>
#include "Network_menu.h"
char pszNetConfHost[256];
char pszNetConfDomain[256];
char pszNetConfGateway[18];
char pszNetConfIPAddr[18];
char pszNetConfPrivate1IPAddr[18];
char pszNetConfPrivate2IPAddr[18];
char pszNetConfNetmask[18];
char pszNetConfPrivate1Netmask[18];
char pszNetConfPrivate2Netmask[18];
char pszNetconfBroadcast[18];
char pszNetconfPrivate1Broadcast[18];
char pszNetconfPrivate2Broadcast[18];
char pszNetConfNetwork[18];
char pszNetConfPrivate1Network[18];
char pszNetConfPrivate2Network[18];
char pszNetConfNetCard[3][30];
int nCountListStr;
char pszSaveNameServer[20][30];
int nCountNameServer;
int nCountClient;
extern int nAccountCount;
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
// ----------------------------------------------------------------
# ------------------------ < Makefile > --------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
OTHER_OBJS = \
network.o \
proc_file.o
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o \
clssGeneric.o \
clssGeneric_moc.o \
clssDNS.o \
clssDNS_moc.o \
clssAlias.o \
clssAlias_moc.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
network.o: network.c
$(CC) -c network.c -o $@
proc_file.o: proc_file.c
$(CC) -c proc_file.c -o $@
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
clssGeneric_moc.cpp: clssGeneric.h
$(MOC) clssGeneric.h -o clssGeneric_moc.cpp
clssGeneric_moc.o: clssGeneric_moc.cpp
$(CC) -c clssGeneric_moc.cpp $(CFLAGS) -o $@
clssGeneric.o: clssGeneric.cpp
$(CC) -c clssGeneric.cpp $(CFLAGS) -o $@
clssDNS_moc.cpp: clssDNS.h
$(MOC) clssDNS.h -o clssDNS_moc.cpp
clssDNS_moc.o: clssDNS_moc.cpp
$(CC) -c clssDNS_moc.cpp $(CFLAGS) -o $@
clssDNS.o: clssDNS.cpp
$(CC) -c clssDNS.cpp $(CFLAGS) -o $@
clssAlias_moc.cpp: clssAlias.h
$(MOC) clssAlias.h -o clssAlias_moc.cpp
clssAlias_moc.o: clssAlias_moc.cpp
$(CC) -c clssAlias_moc.cpp $(CFLAGS) -o $@
clssAlias.o: clssAlias.cpp
$(CC) -c clssAlias.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
# ----------------------------------------------------------------
3.5. 개선되어야할 내용
여러가지로 모자란 프로그램을 올린 것에 대해 이 글을 읽는 분들께 죄송
스러운 마음뿐이다.
Qt Library는 제공하는 Library만을 써서 그다지 문제될 것은 없겠지만,
파일처리루틴에 있어 모든 procedure들이 최적화되어있다고는 말씀드릴 수
없다. 즉, 이식성과 확장성문제를 고려한다 하더라도 메모리에 대한 완벽
한 최적화를 이루지는 못했다. 또한 네트워크처리루틴에 대해서도 일정한
패턴 혹은 일관성있는 처리를 해주어야 하는데 그렇게 하지 못했다. 즉,
리눅스 버젼이 업데이트될 때마다 네트워크 관련 파일들의 Format이 변할
지도 모르는 상황에서 이를 통합관리하는 파일의 생성없이 각 파일들을
직접 접근한다는 것은 여러모로 비합리적인 방법이다.
필자는 직장에서 개발했던 프로그램의 일부인 이 네트워크 처리부분을 사
정상 그대로 이곳에 올려놓지는 않았다. 이점 무척 죄송스럽게 생각한다.
위의 Source들은 필자가 (주)아이탑의 Topflash project개발 초기에 만든
최적화작업이 되지않은 Source들이다.
지금 학내망쪽에 공급되어 나가고 있는 상품이므로 최적화 되어있는
Source들은 굳이 싣지 못했음을 알려드리며 이점 다시한번 죄송스럽게 생
각한다.
이 Source들에서의 개선방향은 바로 위에서 말씀드린바와 같으며 이 프로
젝트에 대한 모든 이야기는 여기서 마치겠다.
4. 프로젝트를 마치고...
이 프로젝트는 초반에도 말씀드렸듯이 Qt 1.44를 사용한 Network 처리 프로
젝트입니다. 그리고 이는 제가 지금 몸담고 있는 (주)아이탑의 생산제품군
중 하나인 TopmanagerX의 일부분에 대한-초기 최적화되지 않은- 자료이기
도 합니다. Qt를 기반으로 어떤 프로젝트를 개발하고 그를 상품화시켜 판
매하기 위해서는 Gtk와는 다르게 trolltech와 License계약을 맺어야한다는
것은 모두들 아시리라 생각합니다.
그래서 저는 되도록이면 Qt보다는 Gtk기반의 Application개발을 권해드리고
싶습니다. 최근에 와서야 Qt가 약간씩 인기를 끌고 있지만 Open Source개념
의 노하우가 상당히 축적되어있는 Gtk보다는 발전 가능성이 적다고 감히 생
각합니다. Qt는, 물론 GUI에 대해서 Gtk보다 월등합니다만 Gtk의 Open Source
사상(?)은 조만간 Qt의 GUI를 앞설 것이라 생각합니다.
그리고 또 Borland사에서 Delphi를 리눅스에 포팅하고 있다는 사실은 여러
분들도 잘 아시리라 믿습니다. 이렇듯 리눅스용 개발 툴들이 상당히 많이
만들어지고 있으므로 GUI개발에서 획기적으로 두각을 나타낼 만한 개발툴이
머지않아 나올 것이라 생각합니다.
각설하고, 어쨌든 다음에 글을 올릴 때는 MailServer Setting과 WebServer
Setting에 대해 Gtk Library를 써서 구현한 Project를 올리겠습니다.
모자란 글 끝까지 읽어주셔서 진심으로 감사드립니다.
박영선(youngsun@i-top.co.kr)
날짜: 1999.12.26
컴파일러: gcc
언어 : C++ (QT 1.44 Library 사용)
환경 : 알짜리눅스 6.1 XWindow환경
===============================================================
<들어가기전에...>
안녕하세요.
(주)아이탑에서 개발연구원으로 일하고 있는 박영선이라고 합니다.
우선, 간단하게 이 자료의 내용을 소개한 뒤 시작하기로 하죠.
제가 리눅스를 처음 접하고, 또 Gtk와 QT를 만나게 되면서, 실제 저
희회사 제품개발당시 힘들었던 점과 개발 후에 느꼈던 미비한 점등
을 참고해서 이 프로젝트를 계획하게 되었습니다.
이 프로젝트는 저희회사 개발원들이 개발했던 Topflash라는, 네
트워크, 프락시, 방화벽, 메신저등을 종합적으로 관리할 수 있는
통합인터넷솔루션중 제가 개발한 TopmanagerX를 기반으로 만들어졌
습니다.
이는 QT라이브러리와, ANSI-C기반의 file처리루틴을 라이브러리로
묶어 구현한 내용입니다.
사정상 이 중에서 네트워크관리를 QT를 사용하여 구현해보도록 하겠
습니다.
다음에는 Gtk를 이용한 버젼을 다른 처리 내용의 글로 올리겠습니다.
문의사항이나 개선점을 발견하신분들은 위의 E-mail주소로 꼭 연락
해주시기 바랍니다.
그리고 Gtk의 글이 끝나면 마지막으로 Kernel분석에 관한 자료를 만
들까 생각중입니다.
많은 관심과 격려 부탁드립니다.
===============================================================
<목차>
0. RedHat Linux 6.1의 System관리File에 관하여...
0.1. /etc디렉토리에 있는 file들
0.1.1. /etc/conf.modules
0.1.2. /etc/sysconfig/network-scripts/ifcfg-eth0
0.1.3. /etc/sysconfig/network
1. 이중연결리스트를 이용한 File처리 루틴에 관하여...
1.1. 이중연결리스트(Double LinkedList) 구현
1.2. file처리 라이브러리 구현
1.3. 개선되어야할 내용
2. QT 기본 다지기
2.1. QT의 Class계층정보
2.2. Widget이란?
2.2.1. 위젯(QWidget), 프레임(QFrame), 버튼(QButton)
2.2.2. Makefile 만들기
2.2.3. 라벨(QLabel)
2.2.4. 편집박스(QLineEdit)
2.2.4.1 QObject::connect, SIGNAL과 SLOT
2.2.5. 콤보박스(QComboBox)
2.2.6. 리스트(QListView)
2.2.7. 체크박스(QCheckBox), 라디오버튼(QRadioButton)
2.2.8. 메뉴(QMenu)
2.2.9. 툴바(QToolBar)와 메인윈도우(QMainWindow)
2.3. QT를 얻으려면?
< 한마디 >.
3. 기본 Format 작성하기
3.1. 메뉴 만들기
3.2. 툴바 집어넣기
3.3. Network관련 라이브러리 구현하기
3.4. Class만들기
3.4.1 일반네트워크관리
3.4.2 DNS관리
3.4.3 IP-Aliasing관리
< *** 전체 Source *** >
3.5. 개선되어야할 내용
4. 프로젝트를 마치고...
===============================================================
< 0. RedHat Linux 6.1의 System관리File에 관하여... >
0.1. /etc디렉토리에 있는 file들
0.1.1. /etc/conf.modules
이 file은 하드웨어에 새로운 디바이스가 추가되었을 때 해당 디바이스모
듈을 알기 쉬운 이름으로 속이는 역할을 한다.
예를들어 Lan Card의 Chipset이름이 3c59x라면 /etc/conf.modules에는 다
음과 같은 내용이 들어가야한다.
alias eth0 3c59x
여기서 3c59x는 엄밀히 말하자면 Chipset의 이름이 아니라 리눅스에서 제
공하는 Network Module의 이름이다. 리눅스의 제공 Network Module들은
각각 Chipset이름에 1:1 매치된다.(여기서의 Module이란 Windows에서의
드라이버개념과 비슷하다.)
Module file들은 *.o로 끝나며 이들에 대한 정보는
/lib/modules/2.2.12-20kr/net 디렉토리에 있다.
위의 "alias eth0 3c59x"의 의미는 3c59x모듈을 eth0로 aliasing해서 쓰겠
다는 뜻이다.
만약 Lan Card가 두장이상 시스템에 설치되어있다면 아래와 같은 정보가 추
가되어있을 것이다.
alias eth1 '모듈이름'
alias eth2 '모듈이름'
만약 카드가 ISA라면 이 file안에서 io와 irq번호를 수동으로 설정해주어야
한다. 원래 io, irq또한 설정하는 루틴도 같이 넣으려고 했지만, 요즈음
90% 이상 PCI카드를 사용하고 있으므로 이 설정은 뺐다.
0.1.2. /etc/sysconfig/network-scripts/ifcfg-eth0
위 작업을 마쳤다면 다음 file의 내용을 scan해보자.
cat /etc/sysconfig/network-scripts/ifcfg-eth0
다음과 같은 내용이 출력될 것이다.
DEVICE=eth0
BROADCAST=172.31.255.255
IPADDR=172.31.0.202
NETMASK=255.255.0.0
NETWORK=172.31.0.0
ONBOOT=yes
물론 IP, Netmask, Network, Broadcast등은 이렇게 되어있지는 않을 것이다.
맨 마지막줄의 "ONBOOT=yes"의 뜻은 시스템의 부팅시에 모듈을 올릴 것인지에
대한 옵션이다.
이 file이 없다면 에디터를 써서 file을 생성시키기 바란다.
이렇게 setting을 하고, 만약 Lan Card의 Chipset이 3c59x에 해당되는 모듈에
매치된다면 다음 명령어를 실행해보라.
/etc/rc.d/init.d/network restart
이 명령어를 실행하게 되면 모듈올리기에 성공하는지 실패하는지를 나타내준다.
만약 성공한다면 마지막으로 다음 명령어를 실행해본다.
ifconfig
이 명령어에 대한 필자의 시스템에서의 결과값은 다음과 같다.
eth0 Link encap:Ethernet HWaddr 00:90:27:A2:70:DE
inet addr:172.31.0.1 Bcast:172.31.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:88055 errors:0 dropped:0 overruns:0 frame:0
TX packets:119306 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
Interrupt:17 Base address:0xef00
eth1 Link encap:Ethernet HWaddr 00:90:27:57:17:27
inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
Interrupt:16 Base address:0xef40
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:3924 Metric:1
RX packets:146 errors:0 dropped:0 overruns:0 frame:0
TX packets:146 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
위의 결과값에서 볼 수 있듯이 필자의 IP(가상)은 "inet addr:172.31.0.1"에
명시되어 있고 나머지 Broadcast와 Netmask에 대한 정보 또한 나타나있다.
여기서 eth1에 대한 정보는 두번째 Lan Card를 장착했을 때, 또 그 Card를
OS에서 올바르게 인식했을 때 나타나는 정보이다. 설정 file들에 대한 정보는
eth0와 흡사하다.
출력결과중 세번째 단락의 "lo"는 localhost에 대한 정보이다. 이 결과값은
kernel에서 default로 setting하여주므로 별로 신경쓸 필요가 없다.
0.1.3. /etc/sysconfig/network
이 file은 호스트네임과 게이트웨이를 설정하는 file이다.
이 file을 cat해보자.
NETWORKING=yes
FORWARD_IPV4=false
HOSTNAME=superbug.i-top.co.kr
GATEWAY=172.31.0.200
위의 처음 두줄은 특별한 셋팅이 필요한 경우를 제외하고는 별로 설정값을
바꿀 일이 없으리라 생각한다.
레드헷 6.x이전 버젼까지는 이곳에 DOMAINNAME과 GATEWAYDEV항목이 들어있
었으나 6.x이후부터는 그 부분이 빠졌다. 이 항목들은 있어도 그만, 없어도
그만이므로 신경쓸 필요는 없다. DOMAINNAME항목은 HOSTNAME에 포함이 되었
고, GATEWAYDEV는 디폴트로 eth0를 셋팅하도록 되어있다.
< 1. 이중연결리스트를 이용한 File처리 루틴에 관하여... >
-> File처리루틴에 이중연결리스트를 이용한 목적:
File처리루틴은 이중연결리스트를 이용한 방법을 선택하였다.
연결리스트를 선택한 가장 중요한 이유는 확장성의 용이함때문이다.
가장 흔한 File처리방법은 DB(ISAM, Postgre sql, mysql기타등등)를
이용하는 방법이 있고, 혹은 File에서 한개의 문자씩 읽어들여 처리
하는 방법등 여러가지가 있다.
하지만 DB를 이용하는 방법은 대용량 데이터를 처리할 때, 그리고
데이터 포맷이 정형화되어있을 때 쓰는 방법이고, 한개의 문자씩 읽
어들여 처리하는 방법은 한두개정도의 File을 처리할 때나 유용한
방법이므로 범용적이지 못하다.
Linux의 Network 관련 File들은 각각의 정보가 모두 정형화되어있지도
않고 또한 자주 업그레이드되는 정보들이므로 범용적인 처리루틴이 필
요하다.
다른 좋은 방법들도 있겠지만, 그리고 문자처리방식을 확장시키는 방
법도 있겠지만, 손쉽게 File을 처리하기 위해, 메모리관리를 확실하게
하기위해 연결리스트를 사용했다. 여러분께서 더 좋은 방법이나 혹은
더 좋은 루틴을 가지고 계신분은 질타와 가르침을 주시기 바란다.
===============================================================
1.1. 이중연결리스트(Double LinkedList) 구현
이중연결리스트에 대한 source는 인터넷상에 널려있고,
학부과정에서도 지겹게 다루는 부분이므로 이 부분에 대
한 설명은 접어두기로 하고 file내용만 보여주도록 하겠다.
--- < source 1.1.1 Double LinkedList. Filename:procfile.h > ---
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
#endif
#endif
----------------------------------------------------------------
--- < source 1.1.2 Double LinkedList. Filename:procfile.c > ---
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
------------------------------------------------------------------------
1.2. file처리 라이브러리 구현
자, 이젠 이중연결리스트를 이용하여 File처리를 해보도록 하자.
가장 기본적인 algorithm은 다음과 같다.
< 연결리스트를 이용한 file처리 algorithm 1.2.1 >
1) file을 읽기모드로 열고
2) 한 라인을 읽어들인다.
3) 읽어들인 라인이 Search 조건에 맞는지 검사한다.
3-1) 조건에 맞으면 4)로 이동.
3-2) 맞지 않으면 연결리스트의 node에 삽입하고 2)로 이동
4) 조건에 따라 연결리스트의 node에 처리한(삽입 혹은 삭제, 변경등)
문자열을 삽입한다.
5) 처리가 다 끝나면 file을 닫는다.
6) file을 쓰기모드로 연다.
7) 메모리에 적재하고 있는 연결리스트의 각 노드들을 순서대로 file에
print한다.
8) file을 닫는다.
이렇게만 써놓으면 잘 이해가 가지 않을 것이다.
그러므로 이제부터 source와 그에 따른 algorithm을 토대로 설명하겠다.
우선 algorithm 1.2.1의 2)과정에 해당하는 함수를 만들어보자.
-------- < source 1.2.1 readOneLineSearchFile > -------------------
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp); /* file에서 한 문자를 읽어들인다. */
pszBuffer[i++] = c;
/* 실제 file처리함수에서 사용하게될 buffer에 읽 */
/* 어들인 문자를 삽입한다. */
if (c == EOF || c == '\n')
/* 문자가 file의 끝이거나 캐리지리턴값이면 */
break;
/* loop를 빠져나간다. 즉, 개행문자를 만나면 */
} while (1); /* 그때까지의 문자를 모두 버퍼에 저장하고 */
/* loop를 끝낸다. */
pszBuffer[i] = '\0'; /* 버퍼에 들어있는 개행문자나 EOF를 삭제한다. */
nLine++; /* file의 line수를 체크하기 위한 외부변수이다. */
/* 한 라인을 읽고나서 1씩 증가시킨다. */
return c; /* 개행문자'\n', 혹은 EOF가 return될 것이다. */
}
-------------------------------------------------------------------
다음으로 연결리스트의 내용을 file에 프린트하는 함수를 구현해보도록 하자.
연결리스트에 관한 함수들은 위에서 언급한 바와 같다.
간단하므로 이해하기도 쉬울 것이다.
--------------- < source 1.2.2 printToFileDL > -------------------
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next; /* node pPrint를 초기화한다. */
while (pPrint != dbltail) /* pPrint가 마지막이 될 때까지 반복해서 */
{
fprintf(fp, pPrint->pzKey); /* file에 프린트한다. */
pPrint = pPrint->next; /* node를 다음으로 이동 */
}
return pPrint->pzKey;
}
-------------------------------------------------------------------
아래 소개할 source 1.2.3이 바로 위에서 언급한 algorithm에 의한 루틴이다.
Code line 우측에 각각 해당하는 algorithm의 번호를 표시해놓겠다.
이 함수는 file(pszFileName)에서 특정 문자열(pszSearch)이 들어있는 라인
을 찾아 그 라인을 통째로 삽입할 문자열(pszInsert)로 바꾸는 함수이다.
만약 검색할 문자열이 발견되지 않으면 file은 아무 변화도 일어나지 않는다.
--------------- < source 1.2.3 insertStrToFile > -------------------
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
/* nMaxLine과 nMaxCol을 인자로 두는 이유는 메모리를 관리하기 */
/* 위해서이다. 즉 pszBuffer 이중포인터변수를 전역변수로 잡지 */
/* 않기 위해서인데, 만약 이 변수를 전역변수로 잡게되면 프로 */
/* 그램은 항상 nMaxLine*nMaxCol byte만큼의 메모리를 차지하게 */
/* 되므로 메모리의 막대한 낭비를 초래할 수 있는 문제점이 있다.*/
/* 이 루틴에서는 file의 최대 line수와 최대 coloum수를 인자로 */
/* 받아서 그 인자 만큼에 해당되는 메모리를 할당하여 준다. */
/* 이렇게 처리했을 때의 메모리의 사용량은, 이 루틴이 실행되었 */
/* 을 때만 nMaxLine*nMaxCol byte만큼 메모리에 할당이 되기때문 */
/* 에, 기본메모리가 큰 linux시스템에서는 별 무리 없이 사용할 */
/* 수 있다. */
nLine = 0;
fp = fopen(pszFileName, "r"); /* algor 1) file을 읽기모드로 연다. */
if (fp == NULL) /* file이 존재하지 않는다면 아무처리 없이 끝낸다. */
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL(); /* double linkedlist를 초기화한다. */
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
/* algor 2) file로부터 한라인(pszBuffer[i])씩 읽어들인다. */
{
/* algor 3-2) 읽어들인 라인(pszBuffer[i])이 검색할 문자열 */
/* (pszSearch)을 포함하고 있지 않다면 */
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
/* algor 3-2) node에 삽입한 후 for (i = 0; ~)로 이동해 다음라인 */
/* 을 읽어들인다.(algor 2) */
insertAsLastDL(pszBuffer[i]);
else /* algor 3-1) 검색할 문자열이 포함되어있다면 */
/* algor 4) 검색한 문자열이 포함된 line대신 삽입할 문자열을 연 */
/* 결리스트에 삽입한다. */
insertAsLastDL(pszInsert);
}
/* 만약 위 for 루틴에서 검색할 문자열이 발견되지 않는다면 연결리스트 */
/* 에는 file의 모든 라인을 가지고 있는 node들만이 있을 것이다. */
/* 이런 상태에서 바로 아래쪽의 printToFileDL함수를 호출하게 되면 */
/* file의 내용이 아무것도 변하지 않으면서 그 file자체에 내용을 복사 */
/* 하게 되는 것이다. */
fclose(fp); /* algor 5) file을 닫는다. */
fp = fopen(pszFileName, "w"); /* algor 6) file을 쓰기모드로 연다. */
printToFileDL(dblhead->next, fp); /* algor 7) 메모리에 적재하고 */
/* 있던 연결리스트의 모든 노드 */
/* 들을 순서대로 file에 print한다.*/
deletePerfectDL(); /* 연결리스트 초기화시 할당했던 메모리를 회수한다.*/
fclose(fp); /* algor 8) file을 닫는다. */
for (i = 0; i < nMaxLine; i++) /* 버퍼에 할당했던 메모리를 해제(회수)*/
free(pszBuffer[i]);
}
-------------------------------------------------------------------
이중연결리스트의 구조를 알고있다면 이해하기가 상당히 쉬울 것이다.
이 함수를 이해하지 못했다면 다음으로 넘어가지 못하므로 철저하게 이해하기
바란다. 이 함수의 쓰임새는 두가지가 있다.
첫번째, 특정문자열 바꾸기.
두번째, 특정문자열이 속한 라인 지우기.
여기서 두번째쓰임새의 내용을 보라. 특정문자열(pszSearch)이 속한 line을 지
우려면 어떻게 해야할까? 너무도 쉬운 내용이다.
인자 pszInsert에 "", 즉, 공백문자열을 넘겨주면 된다.
이 함수는 특정 file을 임시파일로 저장하는 과정 없이 바로 그 file을 갱신한
다. 임시파일로 저장하는 것과 메모리에 저장하는 것은 서로 장단점이 있는데
그에 대한 설명은 언급하지 않아도 잘 아시리라 믿는다.
strstr함수에 관한 내용은 man페이지를 참조하거나 library 메뉴얼을 참고하기
바란다.
다음으로 구현할 함수는 위의 함수와 거의 비슷하지만 약간 다르다. 위의 함수
에서는 검색문자열(pszSearch)이 없을 경우 아무일도 일어나지 않지만 이 함수
는 문자열이 검색되지 않으면 file의 맨 끝에 삽입할 문자열(pszInsert)을 끼
워넣게 된다.
검색할 문자열이 만약 검색된다면 바로 아무일을 하지 않고 루틴을 끝낸다.
대부분의 과정은 위에서 설명했으므로 새로운 주목해야할 부분만을 Comment
하겠다.
--------------- < source 1.2.4 insertStrToFileLast > -------------------
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else /* 검색할 문자열(pszSearch)이 검색 된다면 루틴을 끝낸다. */
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
/* 만약 문자열(pszSearch)이 검색되지 않았다면 이부분으로 넘어오게 */
/* 된다. 이 경우 바로 아래와 같이 삽입할 문자열을 연결리스트의 맨 */
/* 끝노드에 삽입을 시키고 file로 프린트한다. */
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
-------------------------------------------------------------------
이번에 설명할 함수는 file에서 특정문자열을 찾아 그 문자열을 원하는
문자열로 바꾸어주는 함수이다.
위에서 설명한 insertStrToFile함수와는 다른 역할을 한다.
즉, insertStrToFile함수는 line단위로 문자열을 삽입, 변경하는 반면
changeStrToOneLineToFile함수는 문자열단위로 변경하는 함수이다.
기본 algorithm은 < algorithm 1.2.1 >에 의거한다.
만약 위의 과정을 모두 이해했다면 이 함수도 별 어려움이 없을 것이다.
이 함수는 changeSearchStr이라는 함수를 call하는데, changeSearchStr
함수는 어떤 주어진 문자열(pszLine)에서 특정문자열(pszSearch)를 찾아
삽입할 문자열(pszIns)로 바꾸는 역할을 한다. 한 라인(pszLine)에 여러
개의 특정문자열(pszSearch)가 있을 수 있으므로 재귀호출(recursive
call)을 사용했다. 기본적인 C문법을 알고있다면 루틴 자체는 이해하기
쉬울 것이라 믿는다.
위와 마찬가지로 중복되는 Comment는 생략하겠다.
-------- < source 1.2.5 changeStrToOneLineToFile > -----------
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
/* 여기서 포인터 인자인 pszSave는 바뀐 라인을 저장할 공간이다. */
{
int i = 0;
char *pszPos;
int nPos;
/* 라인(pszLine)에서 검색문자열(pszSearch)의 위치를 계산하기 */
/* 위해 검색문자열의 pszLine에서의 포인터 위치를 저장해둔다. */
pszPos = (char *)strstr(pszLine, pszSearch);
/* 검색문자열의 위치를 계산한다. */
nPos = pszPos-pszLine;
/* 검색문자열의 위치(nPos)까지 pszSave에 pszLine의 내용을 복사 */
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
/* 저장할 변수(pszSave)에 바꿀 문자열(pszIns)를 붙힌다.*/
strcat(pszSave, pszIns);
/* 저장할 변수(pszSave)에 그 이후의 문자열을 붙힌다. */
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
/* 더이상 검색문자열(pszSearch)가 */
pszPos = (char *)strstr(pszSave, pszSearch);
/* 존재하지 않는다면 루틴을 끝낸다. */
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
/* 바뀐 라인(pszSave)를 원래 라인에 복사한다. */
strcpy(pszLine, pszSave);
/* 재귀호출을 위해 pszSave를 초기화한다. */
memset(pszSave, '\0', nMaxCol);
/* 첫번째 만나는 검색문자열을 바꾸었으므로 두번째, 세번째등등 */
/* 의 문자열을 바꾸기 위해 재귀호출을 한다. */
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
/* 이제 한 라인에 대한 문자열변경루틴은 끝냈으므로 위 함수에 실제 */
/* file에서 한 라인씩 읽어들여 인자로 넘겨주면 된다. */
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
/* pszLine은 바뀐 문자열을 저장할 공간이다. */
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
/* 한 라인씩 읽어들여서 */
{
/* 검색문자열(pszSearch)이 없다면 연결리스트에 삽입한다.*/
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
/* 검색문자열이 있다면 changeSearchStr함수를 이용해 검색문자열이 */
/* 포함된 라인을 수정하고 수정된 라인을 연결리스트에 삽입한다. */
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i], pszLine[j],
nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
/* file 쓰기 */
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
-------------------------------------------------------------------
예상외로 간단할 것이다. 특정 기능(예를들어, 삭제, 삽입, 변경등)에
대한 함수들의 구현은 위 방법과 구조가 항상 같다.
이는 연결리스트를 사용했을때의 장점이 유감없이 발휘된 특징중 하나
이다. 즉, 이해하기 쉽고 구현이 용이하고, 또 가장 중요한 범용성이
있다는 점이다.
이번엔 위의 source들의 구조를 약간 응용해서 구조화된 file의 처리
루틴을 작성해보기로 하자.
아래의 함수는 검색문자열(pszSearch)이 file(pszFileName)에 없다면
삽입할 문자열(pszInsert)을 라인으로 삽입하고 검색문자열이 존재한
다면 그 검색문자열을 포함한 라인을 삽입할 문자열로 바꾸는 함수이
다. 위의 함수들과 다른점이 있다면 이 함수에는 flag를 두었다는 점
이다. 이 flag는 file에 검색된 라인을 삽입문자열로 바꿀 것인지 아
니면 그냥 삽입문자열을 라인단위로 삽입할 것인지를 결정한다.
만약 문자열이 검색되지 않는다면 flag는 TRUE로 setting된다.
-------- < source 1.2.6 addOnNotExistChangeOnExist > -----------
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
/* 삽입할 지 혹은 변경할 지의 flag(flgAdd) */
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
/* 만약 검색문자열(pszSearch)이 검색된다면 */
else
{
/* 삽입문자열(pszIns)을 node에 삽입하고 */
insertAsLastDL(pszIns);
/* flag를 FALSE로 reset시킨다. */
flgAdd = FALSE;
}
}
fclose(fp);
/* flag가 TRUE라면 검색문자열이 발견되지 않았다는 것이므로 */
/* 링크리스트의 맨 끝node에 삽입문자열을 삽입한다. */
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
/* file 쓰기 */
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
-------------------------------------------------------------------
간단하게 몇줄만 추가 혹은 변경시켜 기능을 바꾸어놓았다.
앞으로 설명하게될 모든 file처리관련 함수들이 다 이런식이다.
이 routine을 응용하여 갖가지 source들을 재생성해보시기를...
이제부터는 위의 routine들은 물론 필자가 구현해놓은 모든 procedure들
을 한꺼번에 보여주기로 하겠다. 그리고 설명은 되도록 기능 위주로 하
겠다. 위 과정까지 모두 이해했다면 별다른 Comment없이도 이해할 수
있을 것이다.
-------- < source 1.2.7 total functions > -----------
/**************** proc_file.h *****************/
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine);
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine);
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine);
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol);
void *printToFileDL(DList *pPrint, FILE *fp);
int readOneLineSearchFile(char pszBuffer[], FILE *fp);
void insertStrToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol);
int countSearchLineToFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol);
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol);
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment,
char *pszFileName, int nMaxLine, int nMaxCol);
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExistWithoutComment(char *pszIns,
char *pszSearch, char cComment, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist2Search(char *pszIns,
char *pszFirstSearch, char *pszSecondSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void saveStrIdxToFileLine(char *pszSave, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol);
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol);
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol);
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol);
#endif
#endif
/**********************************************/
/**************** proc_file.c *****************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
/****** FILE procedure ******/
/* 한 라인에서 검색문자열(pszDel)을 지운다. */
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine)
{
char *pszPnt;
int i, nFirstLen;
if ((pszPnt = (char *)strstr(pszLine, pszDel)) == NULL)
return;
nFirstLen = pszPnt-pszLine;
for (i = 0; i < nFirstLen; i++)
pszSave[i] = pszLine[i];
for (i = nFirstLen; pszLine[i+strlen(pszDel)] != '\0'; i++)
pszSave[i] = pszLine[i+strlen(pszDel)];
pszSave[i] = '\0';
}
/* 한 라인에서 검색문자열(pszSearch)앞에 삽입문자열(pszInsert) */
/* 을 삽입한다. */
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine)
{
int i = 0;
int nLen;
char *pszPos;
if ((char *)strstr(pszLine, pszInsert) != NULL)
{
strcat(pszSave, pszTempLine);
return;
}
pszPos = (char *)strstr(pszLine, pszSearch);
nLen = pszPos-pszLine;
for (i = 0; i < nLen; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszInsert);
strcat(pszSave, strstr(pszLine, pszSearch));
}
/* 한 라인에서 검색문자열(pszIns)이 있다면 return하고 없다면 */
/* 라인 끝에 검색문자열을 삽입한다. */
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine)
{
int nFirstPos, nSecondPos;
if ((char *)strstr(pszLine, pszIns) != NULL)
return;
for (nFirstPos = 0; nFirstPos < strlen(pszLine); nFirstPos++)
pszSave[nFirstPos] = pszLine[nFirstPos];
for (nSecondPos = 0; nSecondPos < strlen(pszIns); nSecondPos++)
pszSave[nSecondPos+nFirstPos] = pszIns[nSecondPos];
pszSave[nSecondPos+nFirstPos] = '\0';
}
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
{
int i = 0;
char *pszPos;
int nPos;
pszPos = (char *)strstr(pszLine, pszSearch);
nPos = pszPos-pszLine;
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszIns);
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
pszPos = (char *)strstr(pszSave, pszSearch);
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
strcpy(pszLine, pszSave);
memset(pszSave, '\0', nMaxCol);
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
int nLine;
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
fprintf(fp, pPrint->pzKey);
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp);
pszBuffer[i++] = c;
if (c == EOF || c == '\n')
break;
} while (1);
pszBuffer[i] = '\0';
nLine++;
return c;
}
void insertStrToFileLast(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
/* file의 라인수를 return한다. */
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (nCount = 0;
(readOneLineSearchFile(pszBuffer[nCount], fp) != EOF) &&
(nCount < nMaxLine); nCount++);
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
/* file에서 검색문자열(pszSearch)가 있는 line 수를 return한다. */
int countSearchLineToFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0;
int nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
nCount++;
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
/* file의 모든 라인을 이중포인터(pszSaveListStr)에 저장한다. */
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (j = 0; j < nMaxLine; j++)
{
pszBuffer[j] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[j], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
strcpy(pszSaveListStr[i], pszBuffer[i]);
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return i;
}
/* file에서 검색문자열(pszSearch)이 있는 line에 Comment(cComment)가 */
/* 없다면 이중포인터(pszSaveListStr)에 저장한다. */
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL &&
pszBuffer[i][0] != cComment)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
/* file에서 검색문자열(pszSearch)이 있는 line을 Comment(cComment)에 상 */
/* 관없이 이중포인터(pszSaveListStr)에 저장한다. */
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i],
pszLine[j], nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
/* 검색문자열(pszSearch)이 있는 라인에서 검색문자열 바로 */
/* 앞에 삽입문자열(pszIns)을 삽입한다. */
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertStrForeSearch(pszLine, pszIns, pszSearch, pszBuffer[i],
pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* file에서 검색문자열(pszSearch)을 찾아 그 문자열만 지워준다. */
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
deleteStrFromOneLine(pszLine, pszDel, pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
insertAsLastDL(pszInsert);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* file에서 검색문자열(pszSearch)이 있으면 TRUE, */
/* 없으면 FALSE를 return한다. */
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
fclose(fp);
return TRUE;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return FALSE;
}
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* Comment(cComment)가 없을 때, 검색문자열(pszSearch)이 */
/* 없으면 file 맨 끝에 삽입문자열(pszIns)를 라인으로 삽입 */
/* 하고, 있으면 검색문자열이 있는 라인을 삽입문자열로 바 */
/* 꾼다. */
void addOnNotExistChangeOnExistWithoutComment(char *pszIns,
char *pszSearch, char cComment,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL ||
pszBuffer[i][0] == cComment)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 두개의 검색문자열(pszFirstSearch, pszSecondSearch)이 모두 있으면 */
/* 그 라인을 삽입문자열(pszIns)로 바꾸고, 둘 중 하나라도 없으면 */
/* 삽입문자열을 file맨 끝에 라인으로 삽입한다. */
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszFirstSearch) != NULL &&
(char *)strstr(pszBuffer[i], pszSecondSearch) != NULL)
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
else
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그 라인의 바로 앞에 삽입 */
/* 문자열을 라인으로 삽입한다. */
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
insertAsLastDL(pszBuffer[i]);
fclose(fp);
insertDLAsKey(pszInsert, pszSearch);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)을 찾아 그 라인의 끝위치에 삽입문자열 */
/* (pszInsert)을 삽입한다. */
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][strlen(pszBuffer[i])-1] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nStartIdx)에서 */
/* 특정Coloum(nEndIdx)까지의 문자열을 Save(pszSave)한다. */
void saveStrIdxToFileLine(char *pszSave, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nStartIdx);
for (j = 0; j < nEndIdx-nStartIdx; j++)
pszSave[j] = pszEndBuffer[j];
}
}
fclose(fp);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nStartIdx)에서 */
/* 특정Coloum(nEndIdx)까지의 문자열을 삽입문자열(pszInsert)로 교체한다. */
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx,
int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nEndIdx);
pszBuffer[i][nStartIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
strcat(pszBuffer[i], pszEndBuffer);
pszBuffer[i][strlen(pszBuffer[i])] = '\0';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszSearch)를 찾아 그라인의 특정Coloum(nIdx) 이후의 문자열 */
/* 을 모두 없애고, 삽입문자열(pszInsert)을 붙힌다. */
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][nIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 특정라인(nLineIdx)의 특정Coloum(nColIdx) 이후의 문자열 */
/* 을 모두 없애고, 삽입문자열(pszInsert)을 붙힌다. */
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if (i == nLineIdx-1)
{
pszBuffer[i][nColIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
/* 검색문자열(pszStartLine)을 찾아 그 라인의 바로 다음라인에 */
/* 삽입문자열(pszInsert)을 라인으로 삽입한다. */
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
insertAsLastDL(pszInsert);
insertAsLastDL("\n");
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
insertAsLastDL(pszBuffer[j]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
/* 첫번째 검색문자열(pszStartLine)과 두번째 검색문자열(pszEndLine) */
/* 을 찾아 그 사이에 있는 line들을 저장(pszSaveLine)한다. */
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
{
if ((char *)strstr(pszBuffer[j], pszEndLine) == NULL)
strcpy(pszSaveLine[j-(i+1)], pszBuffer[j]);
else
break;
}
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return;
}
}
}
/* 첫번째 검색문자열(pszStartLine)과 두번째 검색문자열(pszEndLine) */
/* 을 찾아 그 사이에 있는 line들을 삽입문자열(pszInsert)로 대체 */
/* 시킨다. */
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1;
readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
if ((char *)strstr(pszBuffer[j], pszEndLine) != NULL)
break;
for (k = 0; k < nInsertNum; k++)
insertAsLastDL(pszInsert[k]);
insertAsLastDL(pszBuffer[j]);
for (k = j+1;
readOneLineSearchFile(pszBuffer[k], fp) != EOF; k++)
insertAsLastDL(pszBuffer[k]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
-------------------------------------------------------
지금까지 링크리스트를 이용한 file처리에 관한 내용을 다루어보았다.
그런데, 왜 굳이 Simple LinkedList를 쓰지 않고, Double LinkedList
를 사용했는지 궁금할 것이다.
나는 후에라도 이 Source를 더욱 강화시키기위해 확장성이 좋은 이중
연결리스트를 사용한 것이다. 물론 단순연결리스트를 사용한다면 메
모리를 약간 절약할 수는 있겠지만 확장성에서는 훨씬 떨어진다.
따라서, Library를 후에 강화시킬 일이 있다면 이중연결리스트를 써
야한다고 생각한다.
1.3. 개선되어야할 내용
앞서 말했듯이 위의 Source는 특정 Routine이 수행될 때 순간적으로
Resource를 크게 차지할 수도 있는 단점이 있다.
이를 보완하려면 LinkList의 node에 key값을 삽입할 때 모든 file의
내용을 전부 LinkList에 삽입할 것이 아니라 조건에 맞을 때만 file
의 내용을 변경하도록 하는 것이 좋다.
이러한 개선점을 생각해 위의 Source들을 한번 수정해보시기를 바란
다.
===============================================================
< 2. QT 기본 다지기 >
-> 필자는 Ansi-C를 사용하는 원시 프로그래머였다.
주로 다뤘던 분야는 Network 관련 프로그램이었고 개발 환경또한
X-window가 아닌 text-mode에서였다. text-mode에서의 GUI구축에
온 힘을 쏟았고 그 결과로 Curses나 Slang보다도 더 좋다고 내세
울 수 있는 Library를 개발했다. 나는 내 자신이 상당한 수준에
올라와 있다고 착각하기 시작했고 점차 자만에 빠지게 되었다.
하지만 점차 Linux가 업그레이드 되면서 굉장한 수준의 그래픽환
경이 제공되면서 그 자만은 깨지기 시작했다. 그 충격이란 엄청
난 것이었다. 나와 비슷한 분들이 한분이라도 이 글을 읽는 분들
중에 계시다면 이 자료를 올린 보람이 있을 것이다.
기타등등의 이유로 C++에 대한 클래스 개념조차도 거의 모른 상태
에서 약 3개월 전부터 QT를 시작했다.
어떠한 자료도 없이 Alzza 리눅스에 포함되어있는 QT 1.44 의 예제
Source만으로 C++과 QT를 공부하자니 무척이나 힘이 들었다.
이렇게 힘들게 공부하면서 QT에 빨리 접근할 수 있는 방법을 저절
로 터득하게 되었는데 이 방법을 여러분께 가장 좋다고 생각하는
과정에 의거하여 글을 쓰겠다. 짧은 실력으로 글을 올리니 여러분
께 죄책감이 먼저 앞서지만 Source공유라는 차원에서 귀엽게 보아
주시기 바란다.
2.1. QT의 Class계층정보
우선 본격적인 QT 제공 Class들을 공부하기에 앞서 Class계층에
대해 눈으로 익혀두기 바란다. 이 계층정보는 상당히 중요하지만
외울 필요는 없다. 그냥 필요할 때 찾아보는 정도로 활용하기 바
란다. 아래의 표는 /usr/lib/qt/html/hierarchy.html 에서 발췌한
내용중 앞으로 쓰게될지도 모를 주요 클래스만을 정리한 것이다.
-------- < 표 2.1.1 QT Class 계층정보 > ---------
QBrush
QCollection
QGList
QList
QStrList
QStrIList
QColor
QColorGroup
QConnection
QCursor
QEvent
QChildEvent
QCloseEvent
QCustomEvent
QDragMoveEvent
QDropEvent
QFocusEvent
QKeyEvent
QMouseEvent
QMoveEvent
QPaintEvent
QResizeEvent
QTimerEvent
QFont
QFontInfo
QFontMetrics
QGArray
QArray
QByteArray
QString
QPointArray
QIconSet
QImage
QListBoxItem
QListBoxPixmap
QListBoxText
QListViewItem
QCheckListItem
QMenuData
QMenuBar
QPopupMenu
QMovie
QObject
QAccel
QApplication
QXtApplication
QDragObject
QImageDrag
QStoredDrag
QTextDrag
QUrlDrag
QLayout
QBoxLayout
QHBoxLayout
QVBoxLayout
QGridLayout
QSignal
QToolTipGroup
QValidator
QDoubleValidator
QIntValidator
QWidget
QButton
QCheckBox
QPushButton
QRadioButton
QToolButton
QComboBox
QDialog
QFileDialog
QMessageBox
QPrintDialog
QTabDialog
QFrame
QGroupBox
QButtonGroup
QLCDNumber
QLabel
QMenuBar
QProgressBar
QScrollView
QListView
QSpinBox
QSplitter
QTableView
QHeader
QListBox
QMultiLineEdit
QPopupMenu
QWidgetStack
QLineEdit
QMainWindow
QNPWidget
QScrollBar
QSemiModal
QProgressDialog
QSlider
QStatusBar
QTabBar
QToolBar
QWindow
QXtWidget
QPaintDevice
QPicture
QPixmap
QBitmap
QPrinter
QWidget
QPaintDeviceMetrics
QPainter
QPalette
QPen
QPixmapCache
QPoint
QRangeControl
QScrollBar
QSlider
QSpinBox
QRect
QSize
QTextStream
QTime
QToolTip
QWhatsThis
QWMatrix
-----------------------------------------
2.2. Widget(QWidget)이란?
-> 모든 사용자 인터페이스(User Interface)의 기본 Class이다.
위의 표와 같이 버튼, 프레임, 편집박스등 Graphic Interface를
주도하는 Class들중 최 상위에 위치해있다.
모든 Widget들에 대한 공부는 철저하게 예제위주로 하겠다.
2.2.1. 위젯(QWidget), 프레임(QFrame), 버튼(QButton)
---------- < source 2.2.1.1. testFrameButton.cpp > -----------
#include <qapplication.h> /* QApplication을 위한 header file */
#include <qwidget.h> /* QWidget을 위한 header file */
int main(int argc, char* argv[])
{
/* 이 부분은 QT 프로그램의 main함수에서 항상 써주어야 */
/* 하는 부분이다. */
QApplication myapp(argc, argv);
/* 인자가 없음에 주의 */
QWidget *wdgtTest = new QWidget();
/* setGeometry(x좌표, y좌표, 넓이, 높이) */
wdgtTest->setGeometry(100, 100, 200, 100);
/* application의 메인 윈도우를 wdgtTest로 정의 */
myapp.setMainWidget(wdgtTest);
/* wdgtTest를 보여준다. */
wdgtTest->show();
/* qt를 실행시킨다. 만약 이 부분이 없다면 윈도우가 뜨지 */
/* 않을 것이다. 항상 들어가야할 부분이다. */
return myapp.exec();
}
-----------------------------------------------------------
위의 Source에서 관심있게 보아야할 부분은 QWidget, QFrame,
QPushButton Class의 인자들이다.
우선 header file을 살펴보자. header file에 관한 정보는
/usr/lib/qt/include/ 에서 볼 수 있다.
public:
QWidget( QWidget *parent=0, const char *name=0, WFlags f=0 );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QWidget( const QWidget & );
QWidget &operator=( const QWidget & );
#endif
위 부분은 header file(/usr/lib/qt/include/qwidget.h)에 들어있
는 QWidget의 생성자 부분이다.
여기서 유심히 보아야할 부분은 인자들의 정의 부분이다. 즉,
QWidget *parent = 0, const char *name = 0, WFlags f = 0
이렇게 클래스정의부분에서 인자값까지도 정의할 수 있다는 것은
C++을 한번쯤 다뤄본 분이라면 모두 아실 것이다.
C에서 NULL값은 #define문으로 0으로 선언되어있다. 즉 parent,
name, f 모두 NULL로 정의를 했다는 뜻인데 그냥 초기화시켰다
는 의미로 받아들이자. 물론 이 부분은 class 생성자(constructor)
부분에서 직접 정의할 수도 있다.
이는 C++의 특권이라고 할 수 있겠다. 이런 방법은 여러곳에서 상
당히 유용하게 쓸 수 있는 기능이다. 자세한 예는 차차 이야기하
도록 하겠다.
이젠 인자들에 대해 살펴보자.
-> QWidget *parent: parent widget을 뜻한다.
위의 header file에 나타난 class선언에서도 보았
듯이 디폴트로 NULL(0)으로 설정되어있는데 이는
자신을 최상위 윈도우로 정하겠다는 뜻이다.
즉 parent가 정의되지 않은(인자가 없는) widget은
부모class가 없이 독립적인 윈도우 체제를 가진다.
parent인자에 만약 다른 widget값을 넘겨준다면
parent인자에 종속되게 된다. 자세한 내용은
source 2.2.1.2에서 다시 다루겠다.
-> const char *name:이것은 widget에 대한 식별자 역할을 한다.
이 식별자는 프로그래머가 거의 사용할 일이 없다.
library에서 자체적으로 compile시 debugging작업
을 할 때, 혹은 사용자가 debugging tool을 사용할
때 특정 부분에 대한 정보를 보고 싶을 때 name()
함수를 사용하여 정보를 추출할 수 있다.
필자는 거의 debugging tool을 사용하지 않으므로
이 인자에 대한 정의는 한번도 한적이 없다.
따라서 이 인자에 대한 설명은 생략하기로 하겠다.
-> WFlags f: 거의 사용할 일이 없으므로 디폴트값을 따르기로
하자. 설명도 생략하겠다. 자세한 정보는
/usr/lib/qt/html/qwidget.html file을 참조하기
바란다.
---------- < source 2.2.1.2. testFrameButton.cpp > -----------
#include <qapplication.h>
#include <qwidget.h>
#include <qframe.h> /* QFrame을 위한 header file */
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
QWidget *wdgtTest = new QWidget();
wdgtTest->setGeometry(100, 100, 200, 100);
/* parent 인자를 wdgtTest로 설정한다. */
QFrame *frTest = new QFrame(wdgtTest);
/* parent가 wdgtTest이므로 frTest에 대한 속성 */
/* 들(x좌표, y좌표)의 좌표값은 wdgtTest에 대한 */
/* 상대적인 좌표로 변환된다. */
frTest->setGeometry(10, 10, 150, 60);
/* frame의 형태를 정한다. */
frTest->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
myapp.setMainWidget(wdgtTest);
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
QFrame에 대한 class선언 정보는
/usr/lib/qt/include/qframe.h에 정의되어있다. 다음과 같이
public과 private양쪽에 선언되어있다.
public:
QFrame( QWidget *parent=0, const char *name=0, WFlags f=0,
bool allowLines=TRUE );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QFrame( const QFrame & );
QFrame &operator=( const QFrame & );
#endif
public member와 private member에 대해서는 굳이 언급하지 않아도 되
겠지만 참조범위에 대해 아주 간단하게 설명을 하겠다.
-> public member: 하위, 상위, 혹은 형제 class에서 이 member를 참조할
수 있다.
-> private member: 다른 어떤 class도 이 member를 참조할 수 없다.
인자에 대해 알아보도록 하자.
-> QWidget *parent: 위에서 언급한 QWidget의 parent인자와 같다.
-> const char *name: " "
-> WFlags f: " "
-> bool allowLines: 만약 FALSE로 setting된다면 수평라인과 수직라인
을 쓰지 않는다.
---------- < source 2.2.1.3. testFrameButton.cpp > -----------
#include <qapplication.h>
#include <qwidget.h>
#include <qframe.h>
#include <qpushbutton.h> /* QPushButton을 위한 header file */
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
QWidget *wdgtTest = new QWidget();
wdgtTest->setGeometry(100, 100, 200, 100);
QFrame *frTest = new QFrame(wdgtTest);
frTest->setGeometry(10, 10, 150, 60);
/* 형태에 주의하여 보자. */
frTest->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
/* text가 "테스트", parent가 frTest로 설정되어있다. */
QPushButton *bttnTest = new QPushButton("테스트", frTest);
/* frTest와 마찬가지로 bttnTest 또한 frTest에 대한 상대 */
/* 적인 좌표로 설정된다. */
bttnTest->setGeometry(20, 20, 100, 30);
// bttnTest->resize(100, 30);
myapp.setMainWidget(wdgtTest);
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
/usr/lib/qt/include/qframe.h에 보면 setFrameStyle에 대해 다음
과 같이 쓰여져 있다.
void setFrameStyle(int);
인자부분을 보면 integer형인데 이곳에 들어갈 수 있는 인자 또한
header file에 잘 나타나있다.
enum { NoFrame = 0, // no frame
Box = 0x0001, // rectangular box
Panel = 0x0002, // rectangular panel
WinPanel = 0x0003, // rectangular panel (Windows)
HLine = 0x0004, // horizontal line
VLine = 0x0005, // vertical line
MShape = 0x000f,
Plain = 0x0010, // plain line
Raised = 0x0020, // raised shadow effect
Sunken = 0x0030, // sunken shadow effect
MShadow = 0x00f0 };
enumeration 되어진 member들을 주의깊게 보면 숫자가 끊어져있는 것
을 알 수 있다. 즉 0x0001~0x0005, 0x000f, 0x0010, 0x0020, 0x0030,
0x00f0. 이 16진수들을 2진수로 풀어보자.
0x0001 => 0000 0000 0000 0001
0x0002 => 0000 0000 0000 0010
0x0003 => 0000 0000 0000 0011
0x0004 => 0000 0000 0000 0100
0x0005 => 0000 0000 0000 0101
0x000f => 0000 0000 0000 1111
0x0010 => 0000 0000 0001 0000
0x0020 => 0000 0000 0010 0000
0x0030 => 0000 0000 0011 0000
0x00f0 => 0000 0000 1111 0000
위의 2진수 값에서도 볼 수 있듯이 bit operation을 적당하게만 쓴
다면 여러 모양의 Frame Style을 나타낼 수 있는 조합이 나오게 된다.
예를 들어 [ Box | WinPanel | Sunken ]을 하게 되면 윈도우즈 스타
일의 움푹 들어간 입체 라인을 나타내준다.
/usr/lib/qt/include/qpushbutton.h에는 다음과 같이 class가 선
언되어있다.
public:
QPushButton( QWidget *parent=0, const char *name=0 );
QPushButton( const char *text, QWidget *parent=0,
const char *name=0 );
private: // Disabled copy constructor and operator=
#if defined(Q_DISABLE_COPY)
QPushButton( const QPushButton & );
QPushButton &operator=( const QPushButton & );
#endif
혹여 궁금하게 생각할 수도 있는 부분
QPushButton &operator=( const QPushButton & );
은 다음 보여드릴 source 2.2.1.4에서 설명하겠다.
보는 바와 같이 QPushButton의 인자에는 문자열 "테스트"와
frTest가 들어가있다. 종속성에 대한 설명은 위해서 이미 했
으므로 여기서는 생략하겠다. 각 widget들의 속성에 대한 설정은
setGeometry로 할 수도 있고, resize라는 함수로도 설정이 가능
하다. 이 두 함수는 설정값에서 약간의 차이가 있다.
setGeometry는 좌표와 크기에 대한 설정이 모두 들어가지만 resize
함수는 x좌표와 y좌표만이 인자로 들어간다. 이 두 함수는 widget
들에 대한 속성 설정이므로 QWidget의 하위 class들의 public함수
에 모두 선언이 되어있다. 물론 QWidget도 이들 함수를 포함하고 있다.
2.2.1.1. Class를 생성하여 만들기
이제부터는 위에서 설명한 source들을 사용하여 분할 컴파일하는 방
법을 알아보자. 우선 source들을 각 특성단위로 분리시켜야한다.
다음은 이렇게 분리된 source code들이다.
--------- < source 2.2.1.1.1 clssTestWidget.h > -----------
#include <qwidget.h> /* 아래쪽의 public QWidget 부분에 대한 header */
/* 아래쪽에 있는 frTest와 bttnTest를 선언하기 위한 class 선언. */
/* 일반함수 선언과 비슷함에 유의 */
class QFrame;
class QPushButton;
/* clssTestWidget class는 QWidget의 모든 public변수 혹은 class를 */
/* 공유할 수 있다. 즉 clssTestWidget class는 QWidget으로부터 '상속' */
/* 받은 class이다. */
class clssTestWidget : public QWidget
{
/* Qt library를 쓰는 class라면 항상 이렇게 선언해놓아야 한다. */
Q_OBJECT
public:
clssTestWidget(); /* 생성자 */
~clssTestWidget(); /* 소멸자 */
/* widget(bttnTest)의 특정 SIGNAL이 발생했을 때, event를 받아 */
/* 원하는 처리를 해줄 수 있는 slot function 선언 */
public slots:
void printMessage();
/* 후에 설명하겠다. 우선은 이런 format도 있다는 정도로 알아두자. */
protected:
private:
QFrame *frTest;
QPushButton *bttnTest;
};
-----------------------------------------------------------
--------- < source 2.2.1.1.2 clssTestWidget.cpp > ---------
#include <qframe.h> /* frTest를 위한 header 선언 */
#include <qpushbutton.h> /* bttnTest를 위해 */
#include <stdio.h>
#include "clssTestWidget.h"
clssTestWidget::clssTestWidget()
{
QFrame *frTest = new QFrame(this);
frTest->setGeometry(10, 10, 150, 60);
frTest->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
QPushButton *bttnTest = new QPushButton("테스트", frTest);
bttnTest->setGeometry(20, 20, 100, 30);
/* 버튼이 'clicked()'되었을 때 printMessage()함수를 호출하라는 */
/* 행동 지침 */
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(printMessage()));
}
clssTestWidget::~clssTestWidget()
{
}
/* 버튼이 눌렸을 때 처리되는 함수 */
void clssTestWidget::printMessage()
{
emit printf("버튼이 눌렸습니다.\n");
}
-----------------------------------------------------------
--------- < source 2.2.1.1.3 main_test1.cpp > ---------
#include <qapplication.h> /* QApplication을 위한 header file */
#include "clssTestWidget.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
/* class 생성 */
clssTestWidget *wdgtTest = new clssTestWidget();
/* class 속성정의 */
wdgtTest->setGeometry(100, 100, 200, 100);
/* main으로 쓸 widget 정의 */
myapp.setMainWidget(wdgtTest);
/* widget을 보여줌 */
wdgtTest->show();
return myapp.exec();
}
-----------------------------------------------------------
이 source들에 앞서 설명한 source와의 차이점은, file들이 분리
되었고 class를 정의하여 그 class를 main에서 호출한다는 것
말고는 거의 없다. 따라서 더이상의 설명은 생략하고 다음으로
Maikfile에 대한 간단한 설명과 함께 이 분할 module들을 compile
하는 방법에 대해 알아보겠다.
2.2.2. Makefile 만들기
2.2.1.에서의 source들을 compile하는 방법에 대해서는 아직 언
급하지 않았다. Qt 2.0이상부터는 제법 GUI Tool이 괜찮아진 모
양이던데 필자도 한번은 사용을 해 보았지만 버그가 몇 가지 있
는 것 같아 지금은 전혀 사용하지 않고 있다. Makefile을 만드는
방법에 있어서도 요샌 tmake라는 GUI Tool을 사용한다고 들었다.
필자는 이 Tool도 사용하지 않는다. 이유는 간단하다. Makefile
을 마음대로 주무르기 위해서이다.
Makefile을 완전하게 이해하고 쉽게 쓸 수 있는 수준이라면 tmake
를 사용하는 것도 나쁘지는 않을 것이다.
아래의 code는 2.2.1.1의 source들을 분할 Compile하기 위한
Makefile이다.
---------------- < Makefile 2.2.2 > ---------------------
PROGS = main_test1 ### 보통 실행file의 이름을 적는다.
### X-window 환경에 관한 library들을 포함시킨다. (Qt 포함)
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
### Compiler를 정의한다.
CC = g++
GCC = gcc
### Header file들을 포함시킨다.
INCLUDE = -I/usr/lib/qt/include
### Compile option을 정의한다.
C_FLAG = -pipe -DNO_DEBUG -O2
### Header file에 대한 option과 Compile option을 합한다.
CFLAGS = $(INCLUDE) $(C_FLAG)
### 실행file생성을 위한 Linker를 정의한다. 여기서는 g++이 된다.
SYSCONF_LINK = $(CC)
### class를 분리시켜놓은 Header file을 .cpp source file과 연동
### 시키며 시스템에서 초기화된 graphic device에 관한 setting을
### 시키기 위한 특수한 cpp file인 moc file을 생성시키는 tool이
### 다. moc file에 대한 분석은 별로 필요없는 부분이므로 생략하
### 겠다.
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
### main함수가 들어있는 source file을 Link시킬 때 필요한 Object file
### 들을 후에 참조하기 편하도록 Label로 묶어놓는다.
MNU_OBJS = \
main_test1.o \
clssTestWidget_moc.o \
clssTestWidget.o
### 'make all'은 이 Makefile을 실행한다. (= make)
all: $(PROGS)
### 'make clean'은 make를 실행시켰을때 새로 생성되는 모든 file
### 을 지우는 역할을 한다. clean, all, 모두 사용자가 어떻게 정
### 의하는가에 따라 역할이 틀려지게 된다.
clean:
rm -f *.o
rm -f main_test1
rm -f *_moc.*
############# COMPILE #############
### main file을 컴파일한다.
main_test1.o: main_test1.cpp
$(CC) -c main_test1.cpp $(CFLAGS) -o $@
### Header file로부터 moc file을 만들어낸다.
clssTestWidget_moc.cpp: clssTestWidget.h
$(MOC) clssTestWidget.h -o clssTestWidget_moc.cpp
### 만들어진 moc file을 컴파일한다.
clssTestWidget_moc.o: clssTestWidget_moc.cpp
$(CC) -c clssTestWidget_moc.cpp $(CFLAGS) -o $@
### 새로 분리된 module file을 컴파일한다.
clssTestWidget.o: clssTestWidget.cpp
$(CC) -c clssTestWidget.cpp $(CFLAGS) -o $@
### 맨 윗부분의 PROG정의부에 있는 이름을 Label로 쓴다.
main_test1: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
------------------------------------------------------------
shell상에서 'make' 혹은 'make all' 을 실행시키면 자동적으로
compile 및 link를 시켜준다. make는 object file의 생성시간, 즉
compile된 시점을 기준으로 source에 변화가 생겼을 때 그 변화된
source module만을 compile함으로써 전체를 Compile하는 시간을 크
게 줄여주는 효과가 있다. 물론 source module이 두세개 정도로 작
다면 굳이 Makefile을 만들어줄 필요가 없다.
하지만 보통 실제 project들의 경우 상당한 수의 source module을
필요로 하기때문에 Makefile의 생성은 필수적이라 할 수 있다.
다음으로 소개하는 source들에 대해서는 모든 source의 Makefile
을 source바로 밑에 주석없이 소개하도록 하겠다. Makefile을 사용
하는데 있어 적게라도 도움이 되었으면 한다.
2.2.3. 라벨(QLabel)
이제부터 2.2.10까지의 모든 예제는 앞에서 사용한 분할 module compile
방법을 따르기로 하겠다. 물론 기존에 설명했던 부분들은 모두 생략한다.
우선 source를 보도록 하자.
-------------- < source 2.2.3.1 clssTestLabel.h > ---------------
#include <qwidget.h>
class QLabel;
class clssTestLabel : public QWidget
{
Q_OBJECT
public:
clssTestLabel();
~clssTestLabel();
public slots:
protected:
private:
QLabel *lblTest1;
QLabel *lblTest2;
QLabel *lblTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.3.2 clssTestLabel.cpp > ---------------
#include <qlabel.h>
#include <qframe.h>
#include "clssTestLabel.h"
clssTestLabel::clssTestLabel()
{
QLabel *lblTest1 = new QLabel(this);
lblTest1->setText("테스트 1");
lblTest1->setGeometry(20, 20, 100, 30);
/* QLabel에서 setFrameStyle함수를 호출했다는 것을 명심하자. */
lblTest1->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Raised);
QLabel *lblTest2 = new QLabel(this);
lblTest2->setText("테스트 2");
lblTest2->setGeometry(20, 60, 100, 30);
lblTest2->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Sunken);
QLabel *lblTest3 = new QLabel(this);
lblTest3->setText("테스트 3");
lblTest3->setGeometry(20, 100, 100, 30);
lblTest3->setFrameStyle(QFrame::Box | QFrame::Panel | QFrame::Plain);
}
clssTestLabel::~clssTestLabel()
{
}
-------------------------------------------------------------------
위의 Source는 총 세가지 모양의 Label format을 나타내준다.
특이할 만한 점은 QLabel에서 setFrameStyle을 호출했다는 것인데
/usr/lib/qt/include/qlabel.h에서는 setFrameStyle함수가 선언되어있지
않다. qframe.h file에서만이 선언되어있는데 QLabel은 QFrame class에서
파생되어 나온 자식 class이므로 QFrame class에서 선언되어있는 모든
public함수들을 공유하여 쓸 수 있다. 물론 enumeration된 Box, Panel등
을 쓸 때는 QLabel의 member들이 아니므로 QFrame::과 같이 소속을 적어
주어야 Compiler가 알아들을 수 있다.
-------------- < source 2.2.3.3 main_test2.cpp > ---------------
#include <qapplication.h>
#include "clssTestLabel.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestLabel *clssTest = new clssTestLabel();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.3.1 > ----------------------
PROGS = main_test2
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test2.o \
clssTestLabel_moc.o \
clssTestLabel.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test2
rm -f *_moc.*
############# COMPILE #############
main_test2.o: main_test2.cpp
$(CC) -c main_test2.cpp $(CFLAGS) -o $@
clssTestLabel_moc.cpp: clssTestLabel.h
$(MOC) clssTestLabel.h -o clssTestLabel_moc.cpp
clssTestLabel_moc.o: clssTestLabel_moc.cpp
$(CC) -c clssTestLabel_moc.cpp $(CFLAGS) -o $@
clssTestLabel.o: clssTestLabel.cpp
$(CC) -c clssTestLabel.cpp $(CFLAGS) -o $@
main_test2: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.4. 편집박스(QLineEdit)
-------------- < source 2.2.4.1 clssTestLineEdit.h > ---------------
#include <qwidget.h>
class QLineEdit;
class QPushButton;
class clssTestLineEdit : public QWidget
{
Q_OBJECT
public:
clssTestLineEdit();
~clssTestLineEdit();
public slots:
void testClick();
protected:
private:
QLineEdit *leTest1;
QLineEdit *leTest2;
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.4.2 clssTestLineEdit.cpp > ---------------
#include <qlineedit.h>
#include <qpushbutton.h>
#include <stdio.h>
#include "clssTestLineEdit.h"
clssTestLineEdit::clssTestLineEdit()
{
leTest1 = new QLineEdit(this);
leTest1->setGeometry(20, 20, 100, 30);
leTest2 = new QLineEdit(this);
leTest2->setGeometry(20, 60, 100, 30);
leTest2->setText("환영!");
/* setEnabled는 편집을 할 수 있게 할 것인지 아닌지를 결정한다. */
/* true->편집가능, false->편집불가능 */
leTest2->setEnabled(false);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(20, 100, 100, 30);
/* 버튼(bttnTest)이 눌렸(clicked())을 때 testClick()함수를 실행하라 */
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(testClick()));
}
clssTestLineEdit::~clssTestLineEdit()
{
}
void clssTestLineEdit::testClick()
{
/* leTest1->text()는 현재 leTest1 편집박스안에 표시되어있는 */
/* text를 가져온다. */
emit printf("편집박스1의 텍스트는 < %s >입니다.\n",
leTest1->text());
emit printf("편집박스2의 텍스트는 < %s >입니다.\n",
leTest2->text());
}
-------------------------------------------------------------------
QLineEdit class는 윈도우즈의 edit box와 같은 기능을 하는 class이다.
특수키(예: 방향키, insert, delete, home, end등)들을 쓸 수 있으며
X-window와의 호환도 이루어진다. 즉 편집박스에 있는 문자열은 마우스
로 < copy and paste > 할 수 있다는 이야기다. 가장 자주 쓰이는 Widget
이니 꼭 기억해두자.
-------------- < source 2.2.4.3 main_test3.cpp > ---------------
#include <qapplication.h>
#include "clssTestLineEdit.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestLineEdit *clssTest = new clssTestLineEdit();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.4 > ----------------------
PROGS = main_test3
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test3.o \
clssTestLineEdit_moc.o \
clssTestLineEdit.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test3
rm -f *_moc.*
############# COMPILE #############
main_test3.o: main_test3.cpp
$(CC) -c main_test3.cpp $(CFLAGS) -o $@
clssTestLineEdit_moc.cpp: clssTestLineEdit.h
$(MOC) clssTestLineEdit.h -o clssTestLineEdit_moc.cpp
clssTestLineEdit_moc.o: clssTestLineEdit_moc.cpp
$(CC) -c clssTestLineEdit_moc.cpp $(CFLAGS) -o $@
clssTestLineEdit.o: clssTestLineEdit.cpp
$(CC) -c clssTestLineEdit.cpp $(CFLAGS) -o $@
main_test3: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.4.1 QObject::connect, SIGNAL과 SLOT
/usr/lib/qt/include/qobject.h에 선언되어있는 connect함수를 보자.
static bool connect( const QObject *sender, const char *signal,
const QObject *receiver, const char *member );
bool connect( const QObject *sender, const char *signal,
const char *member ) const;
위와 같이 두가지로 선언되어있는데 밑에 있는 bool type의 형태에서
빠져있는 const QObject *receiver 는 default로 < this >로 정해져있다.
즉 const char *member 는 this class 의 member라야한다.
마찬가지로 첫번째의 static bool type의 형태에서는 member가
< const QObject *receiver >의 member이어야 한다.
각 인자들을 보면 이 함수가 하는 기능이 무엇인지 알 수 있다.
const QObject *sender : signal을 보내줄 class 객체.
const char *signal : '사용자가 취한 행동'이다.
const QObject *receiver : signal을 받아서 처리할 class 객체.
const char *member : 보통 receiver class의 public member 함수를
쓴다.
const char *signal에 대해 좀더 자세히 알아보자.
예제 2.2.4.2의 Source중
QObject::connect(bttnTest, SIGNAL(clicked()), this, SLOT(testClick()));
부분에서 보면 const char *signal 부분을 SIGNAL(clicked())로 해놓았다.
QPushButton의 header file을 보면 다음과 같이 signal 함수들이 선언되어
있는 것을 알 수 있다.
signals:
void pressed();
void released();
void clicked();
void toggled( bool );
각각의 함수들은 함수 자체의 이름에 해당되는 사용자의 행동이 일어났을
때 부합하는 signal을 'this'라는 class에 전해주게 된다. 여기서 this는
class clssTestLineEdit를 말하며, 따라서 connect함수의 마지막 인자인
const char *member부분에는 clssTestLineEdit의 member함수인 testClick
함수가 오게 된 것이다.
< SLOT >이 하는 일은 차차 이야기 하겠다. 우선 그냥 이렇게 쓴다고 문법
처럼 생각을 해두자. member 인자부분은 만약 member 함수를 쓸 경우 반드
시 SLOT안에 member를 두어야하며 또한 이 member 함수는 public slots:
혹은 private slots: 에 선언되어있어야 한다.
2.2.5. 콤보박스(QComboBox)
-------------- < source 2.2.5.1 clssTestComboBox.h > ---------------
#include <qwidget.h>
class QComboBox;
class QPushButton;
class clssTestComboBox : public QWidget
{
Q_OBJECT
public:
clssTestComboBox();
~clssTestComboBox();
public slots:
void testClick();
protected:
private:
QComboBox *cbTest; /* 콤보박스에 대한 class */
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.5.2 clssTestComboBox.cpp > ---------------
#include <qcombobox.h>
#include <qpushbutton.h>
#include <stdio.h>
#include "clssTestComboBox.h"
clssTestComboBox::clssTestComboBox()
{
cbTest = new QComboBox(this);
cbTest->setGeometry(20, 20, 100, 30);
/* ComboBox에 item들을 넣는다. */
cbTest->insertItem("첫번째", 0);
cbTest->insertItem("두번째", 1);
cbTest->insertItem("세번째", 2);
cbTest->insertItem("네번째", 3);
cbTest->setCurrentItem(0);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(20, 100, 100, 30);
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(testClick()));
}
clssTestComboBox::~clssTestComboBox()
{
}
void clssTestComboBox::testClick()
{
/* cbTest->currentText()는 현재 ComboBox에서 보이는 */
/* text를 return한다. */
emit printf("콤보박스1의 텍스트는 < %s >입니다.\n",
cbTest->currentText());
}
-------------------------------------------------------------------
틀린부분이 거의 없으므로 QComboBox에 대해서만 설명하겠다.
/usr/lib/qt/include/qcombobox.h를 열어보자.(주의: 만약 당신이 Qt를
다운받아 다른 곳에 인스톨 시켰다면 path가 틀려질 것임.)
public:
QComboBox( QWidget *parent=0, const char *name=0 );
QComboBox( bool rw, QWidget *parent=0, const char *name=0 );
몇몇 특정 widget들을 제외하고는 거의 인자가 비슷하다. 인자들에 관
한 설명은 앞서 이야기했던 부분들과 같으므로 설명을 생략하겠다.
그러면 이번에는 < cbTest->insertItem("첫번째", 0); >부분을 보자.
header file에는 insertItem함수가 다음과 같이 선언되어있다.
이 함수는 콤보박스에 item을 추가할 때 사용하는 함수이다.
void insertItem( const char *text, int index=-1 );
void insertItem( const QPixmap &pixmap, int index=-1 );
첫번째 선언문을 보자.
const char *text는 콤보박스에 추가시킬 text이고 int index는 그 text
의 순번이다. index는 0번부터 시작한다. -1로 초기화되어있다는 것은
콤보박스에 아무 item도 들어있지 않다는 뜻이다. Compile해서 실행시켜
보기 바란다. 좀더 확실하게 이해가 될 것이다.
다음으로 cbTest->currentText()부분을 보자.
header file의 선언을 보면 다음과 같다.
const char *currentText() const;
이 함수는 현재 콤보박스에 나타나있는 text를 return한다.
콤보박스의 현재 text를 setting하는 함수는
void setCurrentItem( int index );
이다. 여기서의 index의 의미는 insertItem의 index의 의미와 동일하다.
< cbTest->setCurrentItem(0); >이 뜻하는 것은 첫번째 item을 현재 text
로 보여주겠다는 이야기다.
-------------- < source 2.2.5.3 main_test4.cpp > ---------------
#include <qapplication.h>
#include "clssTestComboBox.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestComboBox *clssTest = new clssTestComboBox();
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.5 > ----------------------
PROGS = main_test4
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test4.o \
clssTestComboBox_moc.o \
clssTestComboBox.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test4
rm -f *_moc.*
############# COMPILE #############
main_test4.o: main_test4.cpp
$(CC) -c main_test4.cpp $(CFLAGS) -o $@
clssTestComboBox_moc.cpp: clssTestComboBox.h
$(MOC) clssTestComboBox.h -o clssTestComboBox_moc.cpp
clssTestComboBox_moc.o: clssTestComboBox_moc.cpp
$(CC) -c clssTestComboBox_moc.cpp $(CFLAGS) -o $@
clssTestComboBox.o: clssTestComboBox.cpp
$(CC) -c clssTestComboBox.cpp $(CFLAGS) -o $@
main_test4: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.6. 리스트(QListView)
-------------- < source 2.2.6.1 clssTestListView.h > ---------------
#include <qwidget.h>
class QListView;
class QListViewItem;
class QLabel;
class QFrame;
class clssTestListView : public QWidget
{
Q_OBJECT
public:
clssTestListView();
~clssTestListView();
public slots:
void appearItem();
protected:
private:
QFrame *frTest;
QListView *lvTest;
QListViewItem *lviTest[10];
QLabel *lblTest1;
QLabel *lblTest2;
QLabel *lblTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.6.2 clssTestListView.cpp > ---------------
#include <qlistview.h>
#include <qlabel.h>
#include <qframe.h>
#include <stdio.h>
#include "clssTestListView.h"
clssTestListView::clssTestListView()
{
int i;
char szTest1[50], szTest2[50], szTest3[50];
/* List의 가장자리선의 처리를 위해 frame을 그린다. */
frTest = new QFrame(this);
frTest->setGeometry(20, 20, 200, 200);
frTest->setFrameStyle(QFrame::Box | QFrame::Sunken |
QFrame::WinPanel);
lvTest = new QListView(frTest);
/* frame에서 약 3정도 사방으로 적은 크기가 가장 적당하다. */
lvTest->setGeometry(3, 3, 194, 194);
/* 각 field의 title을 정한다. */
lvTest->addColumn(" 첫번째 ");
lvTest->addColumn(" 두번째 ");
lvTest->addColumn(" 세번째 ");
/* tree장식을 할 것인지 아닌지를 결정한다. */
lvTest->setRootIsDecorated(true);
for (i = 0; i < 9; i++)
{
memset(szTest1, '\0', 50);
memset(szTest2, '\0', 50);
memset(szTest3, '\0', 50);
sprintf(szTest1, "환영 %d", i);
sprintf(szTest2, "리눅스 %d", i);
sprintf(szTest3, "만세 %d", i);
/* 첫번째 두번째 세번째*/
lviTest[i] = new QListViewItem(lvTest, szTest1, szTest2, szTest3);
}
/* List(lvTest)에서 item(lviTest[])이 선택(selectionChanged()) */
/* 되어질 때 this class(clssTestListView)의 member function */
/* (appearItem())을 수행해라. */
QObject::connect(lvTest, SIGNAL(selectionChanged()), this,
SLOT(appearItem()));
lblTest1 = new QLabel(this);
lblTest1->setGeometry(20, 230, 150, 20);
lblTest2 = new QLabel(this);
lblTest2->setGeometry(20, 260, 150, 20);
lblTest3 = new QLabel(this);
lblTest3->setGeometry(20, 290, 150, 20);
}
clssTestListView::~clssTestListView()
{
}
void clssTestListView::appearItem()
{
/* 선택된 item의 첫번째 field를 Label로 나타냄 */
lblTest1->setText(lvTest->currentItem()->text(0));
/* 선택된 item의 두번째 field를 Label로 나타냄 */
lblTest2->setText(lvTest->currentItem()->text(1));
/* 선택된 item의 세번째 field를 Label로 나타냄 */
lblTest3->setText(lvTest->currentItem()->text(2));
}
-------------------------------------------------------------------
/usr/lib/qt/include/qlistview.h file의 선언을 보자.
public:
QListView( QWidget * parent = 0, const char * name = 0 );
다른 widget들과 별 차이가 없으므로 설명은 생략한다.
virtual int addColumn( const char * label, int size = -1);
field의 제목(const char *label)을 지정한다.
size에 대해서는 값정의가 되어있으므로 써도 그만 안써도 그만이라는
이야기인데 흔히 field의 size를 임의로 정해서 해당 field의 값을 찾
아내는데 쓰이는 인자이다. 다시 이야기할 기회가 있을 지는 모르겠지
만 그렇게 중요한 인자는 아니므로 설명은 이쯤 해 두겠다.
virtual void setRootIsDecorated( bool );
만약 인자값을 false로 준다면 첫번째 field의 item들 앞에는 아무것
도 없게 된다.
현재 tree장식이 되어있는지 아닌지를 검사하고 싶다면 다음 함수를 써라.
bool rootIsDecorated() const;
이번에는 실제 item을 List에 삽입하는 방법에 대해 알아보자.
header file에는 다음과 같이 QListViewItem을 선언하고 있다.
public:
QListViewItem( QListView * parent );
QListViewItem( QListViewItem * parent );
QListViewItem( QListView * parent, QListViewItem * after );
QListViewItem( QListViewItem * parent, QListViewItem * after );
QListViewItem( QListView * parent,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListViewItem * parent,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListView * parent, QListViewItem * after,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
QListViewItem( QListViewItem * parent, QListViewItem * after,
const char *, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0,
const char * = 0, const char * = 0 );
약간 복잡하다고 생각할 지도 모르지만 상당히 간단한 선언이다.
우선 parent인자부터 살펴보자.
위에서 선언된 parent인자의 type은 < QListView * > 와 < QListViewItem * >
이 두가지이다.
< QListView * >를 parent인자로 받는다는 것은 현재 생성되어있는 List
에 < const char * > 형태의 text를 item으로 삽입한다는 뜻이다.
< QListViewItem * >를 parent인자로 받는다는 것은 List의 특정 item(parent)
을 root로 하는 tree구조로서 그 item의 자식 node를 삽입한다는 뜻이다.
언뜻 이해가 가지 않을 것이다. 위 source에서
< lviTest[i] = new QListViewItem(lvTest, szTest1, szTest2, szTest3); >
이 포함되어있는 for loop문을 다음과 같이 바꾼 후 Compile하여 실행시켜
보라.
lviTest[0] = new QListViewItem(lvTest,
"테스트1-1", "테스트1-2", "테스트1-3");
lviTest[1] = new QListViewItem(lviTest[0],
"테스트2-1", "테스트2-2", "테스트2-3");
실행시켜보면 위에서 필자가 이야기했던 부분들이 쉽게 이해가 갈 것이다.
다음은 List에서 삽입된 text를 얻는 방법에 대한 설명이다.
lblTest1->setText(lvTest->currentItem()->text(0));
QListViewItem의 text를 얻는 방법은 간단하다.
만약 QListViewItem type의 class가 lviTest1이라면, lviTest1의 첫번째
field의 text를 얻으려면 < lviTest1->text(0); >이라고 하면 될 것이다.
ComboBox와 비슷하지만 index가 의미하는 것이 틀리므로 유의하기 바란다.
위에서 lvTest->currentItem()이 의미하는 것은 현재 List에서 선택된
Item set을 말한다. header file에는 currentItem()함수가 다음과 같이
선언되어 있다.
QListViewItem * currentItem() const;
type을 보면 QListViewItem이다. 이는 currentItem()이 QListViewItem
class의 모든 member들을 참조할 수 있다는 이야기가 된다.
따라서 현재 List에서 선택된 Item의 두번째 field의 text를 알고 싶다면
다음과 같이 하면 된다.
lblTest1->setText(lvTest->currentItem()->text(1));
이번엔 QListView에서 발생가능한 Signal에 대해 알아보도록 하자.
header file을 보면 다음과 같이 총 6개의 signal함수가 있다.
signals:
void selectionChanged();
void selectionChanged( QListViewItem * );
void currentChanged( QListViewItem * );
void doubleClicked( QListViewItem * );
void returnPressed( QListViewItem * );
void rightButtonClicked( QListViewItem *, const QPoint&, int );
void rightButtonPressed( QListViewItem *, const QPoint&, int );
각 Signal들의 발생요인은 위함수의 제목과 동일하다.
-------------- < source 2.2.6.3 main_test5.cpp > ---------------
#include <qapplication.h>
#include "clssTestListView.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestListView *clssTest = new clssTestListView();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.6 > ----------------------
PROGS = main_test5
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test5.o \
clssTestListView_moc.o \
clssTestListView.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test5
rm -f *_moc.*
############# COMPILE #############
main_test5.o: main_test5.cpp
$(CC) -c main_test5.cpp $(CFLAGS) -o $@
clssTestListView_moc.cpp: clssTestListView.h
$(MOC) clssTestListView.h -o clssTestListView_moc.cpp
clssTestListView_moc.o: clssTestListView_moc.cpp
$(CC) -c clssTestListView_moc.cpp $(CFLAGS) -o $@
clssTestListView.o: clssTestListView.cpp
$(CC) -c clssTestListView.cpp $(CFLAGS) -o $@
main_test5: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.7. 체크박스(QCheckBox), 라디오버튼(QRadioButton)
-------------- < source 2.2.7.1 clssTestButton.h > ---------------
#include <qwidget.h>
class QButtonGroup;
class QRadioButton;
class QCheckBox;
class QPushButton;
class clssTestButton : public QWidget
{
Q_OBJECT
public:
clssTestButton();
~clssTestButton();
public slots:
void procButton();
protected:
private:
/* QRadioButton을 묶기 위한 Group class 선언 */
QButtonGroup *bgTest;
QRadioButton *rbTest1;
QRadioButton *rbTest2;
QCheckBox *chkbTest1;
QCheckBox *chkbTest2;
QPushButton *bttnTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.7.2 clssTestButton.cpp > ---------------
#include <qradiobutton.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qbuttongroup.h>
#include <stdio.h>
#include "clssTestButton.h"
clssTestButton::clssTestButton()
{
/* radio button은 어느 한 버튼이 활성화되면 다른 버튼들은 */
/* 비활성화되어야 한다. 이런 기능을 위해 QButtonGroup class */
/* 를 정의한다. */
bgTest = new QButtonGroup(this);
bgTest->setGeometry(20, 20, 300, 100);
/* radio button들을 bgTest에 종속시킨다. */
rbTest1 = new QRadioButton("리눅스 라디오", bgTest);
rbTest1->setGeometry(20, 20, 100, 20);
rbTest2 = new QRadioButton("만세 라디오", bgTest);
rbTest2->setGeometry(150, 20, 100, 20);
/* radio button들이 단지 하나의 버튼만이 선택되게 하기 위해 */
/* 마지막으로 QButtonGroup class변수에 삽입시킨다. */
bgTest->insert(rbTest1, 0);
bgTest->insert(rbTest2, 1);
/* 체크박스 정의 */
chkbTest1 = new QCheckBox("리눅스 체크", this);
chkbTest1->setGeometry(20, 160, 100, 20);
chkbTest2 = new QCheckBox("만세 체크", this);
chkbTest2->setGeometry(150, 160, 100, 20);
bttnTest = new QPushButton("확 인", this);
bttnTest->setGeometry(60, 250, 100, 30);
QObject::connect(bttnTest, SIGNAL(clicked()), this,
SLOT(procButton()));
}
clssTestButton::~clssTestButton()
{
}
void clssTestButton::procButton()
{
if (rbTest1->isChecked())
emit printf("리눅스 라디오 버튼이 체크되어 있습니다.\n");
else if (rbTest2->isChecked())
emit printf("만세 라디오 버튼이 체크되어 있습니다.\n");
else
emit printf("체크되어있는 라디오 버튼이 없습니다.\n");
if (chkbTest1->isChecked())
emit printf("리눅스 체크 박스가 체크되어 있습니다.\n");
if (chkbTest2->isChecked())
emit printf("만세 체크 박스가 체크되어 있습니다.\n");
if (chkbTest1->isChecked() == false &&
chkbTest2->isChecked() == false)
emit printf("체크되어있는 체크박스가 없습니다.\n");
}
-------------------------------------------------------------------
QButtonGroup부터 보도록하자. /usr/lib/qt/include/qbuttongroup.h에는
다음과 같이 선언되어있다.
public:
QButtonGroup( QWidget *parent=0, const char *name=0 );
QButtonGroup( const char *title, QWidget *parent=0,
const char *name=0 );
인자들에 대한 설명은 별로 필요없으리라 생각하므로 생략하겠다.
생성자부분보다는 insert하는 부분의 설명이 필요하리라 생각한다.
int insert( QButton *, int id=-1 );
int id 는 group에 포함되는 버튼들의 id를 지정해주는 역할을 한다.
순서에는 상관 없으나 값은 고유값을 가져야 한다.
다음으로 checkbox의 header file /usr/lib/qt/include/qradiobutton.h 에
나타난 생성자부분을 보도록 하자.
public:
QRadioButton( QWidget *parent=0, const char *name=0 );
QRadioButton( const char *text, QWidget *parent=0,
const char *name=0 );
QRadioButton의 < const char *text > 인자에 문자열을 넘겨주면 그 문자열이
이 radiobutton의 title이 된다. 체크가 되어있는지를 검사하는 함수는
isChecked()이다. 인위적으로 checking하는 함수는 header file에 이렇게 선
언되어있다.
void setChecked( bool check );
isChecked(), setChecked(bool check) 두 함수 모두 QRadioButton과
QCheckBox에 똑같이 선언되어있고 또한 기능도 같다.
-------------- < source 2.2.7.3 main_test6.cpp > ---------------
#include <qapplication.h>
#include "clssTestButton.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestButton *clssTest = new clssTestButton();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.7 > ----------------------
PROGS = main_test6
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test6.o \
clssTestButton_moc.o \
clssTestButton.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test6
rm -f *_moc.*
############# COMPILE #############
main_test6.o: main_test6.cpp
$(CC) -c main_test6.cpp $(CFLAGS) -o $@
clssTestButton_moc.cpp: clssTestButton.h
$(MOC) clssTestButton.h -o clssTestButton_moc.cpp
clssTestButton_moc.o: clssTestButton_moc.cpp
$(CC) -c clssTestButton_moc.cpp $(CFLAGS) -o $@
clssTestButton.o: clssTestButton.cpp
$(CC) -c clssTestButton.cpp $(CFLAGS) -o $@
main_test6: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.8. 메뉴(QMenu)
-------------- < source 2.2.8.1 clssTestMenu.h > ---------------
#include <qwidget.h>
class QMenuBar;
class QPopupMenu;
class clssTestMenu : public QWidget
{
Q_OBJECT
public:
clssTestMenu();
~clssTestMenu();
public slots:
void funcTest1();
void funcTest2();
void funcTest3();
void funcTest4();
void funcTest5();
void funcTest6();
protected:
private:
/* Pulldown 메뉴를 위한 메뉴바 */
QMenuBar *mnuMainBar;
/* Popup 메뉴를 위한 메뉴 */
QPopupMenu *mnuTest1;
QPopupMenu *mnuTest2;
QPopupMenu *mnuTest3;
};
-------------------------------------------------------------------
-------------- < source 2.2.8.2 clssTestMenu.cpp > ---------------
#include <qapplication.h>
/* hot key를 위한 header. 여기서는 hot key를 쓰지 않는다. */
/* 한 번 시험삼아 hot key기능까지 넣어보기 바란다. */
#include <qkeycode.h>
/* QMenuBar를 위한 header */
#include <qmenubar.h>
/* QPopupMenu를 위한 header */
#include <qpopupmenu.h>
#include <stdio.h>
#include "clssTestMenu.h"
clssTestMenu::clssTestMenu()
{
/* 전체적인 window의 형태를 Microsoft Windows의 형태로 맞춘다. */
qApp->setStyle(WindowsStyle);
mnuTest1 = new QPopupMenu;
/* Popup menu에 아이템을 넣는다. */
mnuTest1->insertItem("테스트1메뉴의 서브메뉴1", this,
SLOT(funcTest1()));
mnuTest1->insertItem("테스트1메뉴의 서브메뉴2", this,
SLOT(funcTest2()));
mnuTest1->insertItem("테스트1메뉴의 서브메뉴3", this,
SLOT(funcTest3()));
mnuTest2 = new QPopupMenu;
mnuTest2->insertItem("테스트2메뉴의 서브메뉴1", this,
SLOT(funcTest4()));
mnuTest2->insertItem("테스트2메뉴의 서브메뉴2", this,
SLOT(funcTest5()));
mnuTest3 = new QPopupMenu;
mnuTest3->insertItem("테스트3메뉴의 서브메뉴1", this,
SLOT(funcTest6()));
/* 각 popup menu들을 pulldown menu에 삽입시킨다. */
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 테스트1 ", mnuTest1);
mnuMainBar->insertItem(" 테스트2 ", mnuTest2);
mnuMainBar->insertItem(" 테스트3 ", mnuTest3);
}
clssTestMenu::~clssTestMenu()
{
}
void clssTestMenu::funcTest1()
{
emit printf("test1 메뉴\n");
}
void clssTestMenu::funcTest2()
{
emit printf("test2 메뉴\n");
}
void clssTestMenu::funcTest3()
{
emit printf("test3 메뉴\n");
}
void clssTestMenu::funcTest4()
{
emit printf("test4 메뉴\n");
}
void clssTestMenu::funcTest5()
{
emit printf("test5 메뉴\n");
}
void clssTestMenu::funcTest6()
{
emit printf("test6 메뉴\n");
}
-------------------------------------------------------------------
위의 결과치를 미리 나타내자면 다음과 같다.
---------------------------------------------------------
| 테스트1 | 테스트2 | 테스트3 |
|---------------------------------------------------------|
|| 테스트1메뉴의 서브메뉴1 | |
|| 테스트1메뉴의 서브메뉴2 | |
|| 테스트1메뉴의 서브메뉴3 | |
| ------------------------- |
| |
| |
| -------------------------- |
---------------- ---------------
뭐 그렇게 특별한 내용은 없다. 한번만 훑어보면 금방 이해가 갈 것이다.
/usr/lib/qt/include/qpopupmenu.h를 살펴보자.
public:
QPopupMenu( QWidget *parent=0, const char *name=0 );
별로 설명할 필요는 없으리라 생각한다. 중요한 것은 insertItem함수인데
header file을 찾아보면 알겠지만 이 함수가 member로 선언되어있지 않을
것이다. 그러면 어디에 선언이 되어 있을까?
QPopupMenu class의 선언부를 보자.
class Q_EXPORT QPopupMenu : public QTableView, public QMenuData
여기서 보면 QPopupMenu class는 QMenuData class로부터 상속을 받았다.
즉, QMenuData class의 public member들을 모두 QPopupMenu도 접근할 수
있다는 이야기다. 그러면 다시 /usr/lib/qt/include/pmenudata.h를 열어
보자. insertItem함수에 대한 선언이 다음과 같이 여러개가 선언되어있다.
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const QPixmap &pixmap,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const QPixmap &pixmap, const char *text,
const QObject *receiver, const char *member,
int accel=0 );
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const QPixmap &pixmap,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const QPixmap &pixmap, const char *text,
const QObject *receiver, const char *member,
int accel, int id, int index = -1 );
int insertItem( const char *text, int id=-1, int index=-1 );
int insertItem( const char *text, QPopupMenu *popup,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, QPopupMenu *popup,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, const char *text,
int id=-1, int index=-1 );
int insertItem( const QPixmap &pixmap, const char *text,
QPopupMenu *popup,
int id=-1, int index=-1 );
이제는 밑도끝도 없이 insertItem이라는 함수가 어디서 튀어나왔는지 이
해가 될 것이다. 앞으로도 member function이 이런 식으로 호출되는 경우
가 가끔씩 있을 것이다. 당황하지 말고 차근차근 이해하기 바란다.
insertItem 함수에 대한 설명을 하자. 바로 위에 있는 모든 경우를 다 설
명할 필요는 없을 것 같다. source 2.2.8.2에서 쓰인 insertItem함수에
대한 설명만을 하겠다. 그 source에서 쓰인 함수는 바로 이 함수이다.
int insertItem( const char *text,
const QObject *receiver, const char *member,
int accel=0 );
각 인자에 대해 설명하겠다.
첫번째 인자 < const char *text >는 Popup menu에 들어갈 Item의 이름이다.
두번째 인자 < const QObject *receiver >는 Item의 이름이 삽입되는 class
이다.
세번째 인자 < const char *member >는 이 Item이 사용자에 의해 선택되어
click되었을 때 실행할 receiver의 member function이다.
네번째 인자 < int accel >은 header source 에서 잠깐 설명한 hot-key(혹
은 accel-key)를 말한다. accel-key에 대해 약간만 더 알아보자.
/usr/lib/qt/include/qkeycode.h에 보면 모든 key값들이 이런식으로 선언
혹은 정의되어있다.
.
.
.
const uint SHIFT = 0x00002000; // accelerator modifiers
const uint CTRL = 0x00004000;
const uint ALT = 0x00008000;
const uint ASCII_ACCEL = 0x10000000;
#define Key_Escape 0x1000 // misc keys
#define Key_Tab 0x1001
#define Key_Backtab 0x1002
#define Key_Backspace 0x1003
#define Key_Return 0x1004
#define Key_Enter 0x1005
#define Key_Insert 0x1006
#define Key_Delete 0x1007
#define Key_Pause 0x1008
#define Key_Print 0x1009
#define Key_SysReq 0x100a
#define Key_Home 0x1010 // cursor movement
#define Key_End 0x1011
#define Key_Left 0x1012
.
.
.
위에서 보면 SHIFT, CTRL, ALT, ASCII_ACCEL등은 4byte unsigned int
형태로 정의되어있고 나머지 key값들은 모두 2byte형태로 선언되어있
다. 이는 특수확장키인 SHIFT, CTRL, ALT key와 나머지 key들을 조합
하여 쓸수 있다는 이야기인데 예를 들어 다시 한번 설명하겠다.
만약 사용자가 < 테스트1메뉴의 서브메뉴1 >을 단축키 ALT+ENTER로
설정하고 싶다면 다음과 같이 하면 된다.
mnuTest1->insertItem("테스트1메뉴의 서브메뉴1", this,
SLOT(funcTest1()), ALT|ENTER);
이젠 QMenuBar에 대해 살펴보자.
/usr/lib/qt/include/qmenubar.h에는 다음과 같이 선언하고 있다.
class Q_EXPORT QMenuBar : public QFrame, public QMenuData
{
friend class QPopupMenu;
Q_OBJECT
public:
QMenuBar( QWidget *parent=0, const char *name=0 );
.
.
.
};
아무리 찾아보아도 insertItem함수를 찾을 수 없다. 하지만 QPopupMenu
의 경우와 마찬가지로 QMenuData의 모든 public member들을 상속받고
있다.
그러므로 이에 대한 설명은 더이상 하지 않아도 되리라 믿는다.
-------------- < source 2.2.8.3 main_test7.cpp > ---------------
#include <qapplication.h>
#include "clssTestMenu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestMenu *clssTest = new clssTestMenu();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.8 > ----------------------
PROGS = main_test7
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test7.o \
clssTestMenu_moc.o \
clssTestMenu.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test7
rm -f *_moc.*
############# COMPILE #############
main_test7.o: main_test7.cpp
$(CC) -c main_test7.cpp $(CFLAGS) -o $@
clssTestMenu_moc.cpp: clssTestMenu.h
$(MOC) clssTestMenu.h -o clssTestMenu_moc.cpp
clssTestMenu_moc.o: clssTestMenu_moc.cpp
$(CC) -c clssTestMenu_moc.cpp $(CFLAGS) -o $@
clssTestMenu.o: clssTestMenu.cpp
$(CC) -c clssTestMenu.cpp $(CFLAGS) -o $@
main_test7: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.2.9. 툴바(QToolBar), MainWindow(QMainWindow)
-------------- < source 2.2.9.1 clssTestToolBar.h > ---------------
#include <qmainwindow.h>
class QToolBar;
/* 이부분 < : public QMainWindow >을 주의 깊게 보기 바란다. */
class clssTestToolBar : public QMainWindow
{
Q_OBJECT
public:
clssTestToolBar();
~clssTestToolBar();
public slots:
void funcTest1();
void funcTest2();
void funcTest3();
protected:
private:
QToolBar *tbTest;
};
-------------------------------------------------------------------
-------------- < source 2.2.9.2 clssTestToolBar.cpp > ---------------
#include <qapplication.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "clssTestToolBar.h"
#ifndef TEST1_TOOLTIP
/* ToolButton에 마우스를 갖다대었을 때 나올 풍선도움말을 선언한다. */
#define TEST1_TOOLTIP "첫번째 테스트"
#define TEST2_TOOLTIP "두번째 테스트"
#define TEST3_TOOLTIP "세번째 테스트"
#endif
clssTestToolBar::clssTestToolBar()
{
/* Icon를 저장할 QPixmap변수 선언 */
QPixmap iconTest1, iconTest2, iconTest3;
qApp->setStyle(WindowsStyle);
/* ToolBar에 들어갈 image들을 선언한 QPixmap변수에 Loading한다. */
iconTest1.load("./test1.gif");
iconTest2.load("./test2.gif");
iconTest3.load("./test3.gif");
tbTest = new QToolBar(this);
/* ToolBar의 방향은 수평이다. */
tbTest->setOrientation(tbTest->Horizontal);
/* ToolButton을 생성한다. */
QToolButton *tbttnTest1 = new QToolButton(iconTest1,
TEST1_TOOLTIP, 0, this, SLOT(funcTest1()),
tbTest, "test1");
QToolButton *tbttnTest2 = new QToolButton(iconTest2,
TEST2_TOOLTIP, 0, this, SLOT(funcTest2()),
tbTest, "test2");
QToolButton *tbttnTest3 = new QToolButton(iconTest3,
TEST3_TOOLTIP, 0, this, SLOT(funcTest3()),
tbTest, "test3");
}
clssTestToolBar::~clssTestToolBar()
{
}
void clssTestToolBar::funcTest1()
{
emit printf("첫번째 단축아이콘\n");
}
void clssTestToolBar::funcTest2()
{
emit printf("두번째 단축아이콘\n");
}
void clssTestToolBar::funcTest3()
{
emit printf("세번째 단축아이콘\n");
}
-------------------------------------------------------------------
/usr/lib/qt/include/qtoolbar.h를 살펴보자.
public:
QToolBar( const char * label,
QMainWindow *, QMainWindow::ToolBarDock = QMainWindow::Top,
bool newLine = FALSE, const char * name = 0 );
QToolBar( const char * label, QMainWindow *, QWidget *,
bool newLine = FALSE, const char * name = 0, WFlags f = 0 );
QToolBar( QMainWindow * parent = 0, const char * name = 0 );
여기서 주의깊게 보아야 할 부분이 한군데 있다. 바로 QMainWindow *parent
인자 부분이다. 이제까지 다뤘던 widget들은 parent 의 type이 모두 QWidget
이었다. 하지만 여기서는 QMainWindow이다. 그러면 계층정보를 좀 보자.
QMainWindow와 QToolBar 모두 QWidget의 하위 class로서 서로 형제간이다.
형제간에는 서로 종속될 수 있으므로 QToolBar의 parent를 QMainWindow로 정
의할 수 있다. QMenuBar또한 마찬가지이다. 이렇듯 class계층정보를 바탕으
로 상하관계를 설정해준다면 명확한 프로그래밍이 가능하게 된다.
/usr/lib/qt/include/qtoolbutton.h를 보자.
public:
QToolButton( QWidget * parent = 0, const char * name = 0 );
QToolButton( const QPixmap & pm, const char * textLabel,
const char * grouptext,
QObject * receiver, const char * slot,
QToolBar * parent, const char * name = 0 );
QToolButton( QIconSet s, const char * textLabel,
const char * grouptext,
QObject * receiver, const char * slot,
QToolBar * parent, const char * name = 0 );
source 2.2.9.2에서 쓰인 QToolButton 함수와 비교해서 설명하겠다.
QToolButton *tbttnTest1 = new QToolButton(iconTest1,
TEST1_TOOLTIP, 0, this, SLOT(funcTest1()),
tbTest, "test1");
이 함수는 header file에 선언된 세개의 함수중 두번째 함수가 쓰인
것이다.
두번째 함수의 첫번째 인자는 icon을 나타낸다. Qt에서는 여러가지
image file들 즉, bmp, gif, jpg, xpm 등등을 지원한다. 각 file들을
loading하는 방법은 약간씩 다르다. 이런 file들을 loading하는 방법
은 header file이나 혹은 Qt에서 제공하는 예제 프로그램들을 보면
금방 알 수 있을 것이다. gif와 jpg는 압축file이므로 먼저 Linux의
X-window에서 사용할 만한 format으로 변환시켜야한다. X-window에서
사용하는 file format은 xpm file인데 다음은 간단한 xpm file의 내
부를 vi로 열어본 것이다.
static char * Ant_xpm[] = {
"48 48 60 1",
" c None",
". c #492449244924",
"X c #618561856185",
"o c #9E799E799E79",
"O c #208120812081",
"+ c #514455555144",
"@ c #410341034103",
"# c #965896589658",
"$ c #082008200820",
"% c #8E388A288E38",
"& c #69A669A669A6",
"* c #71C675D671C6",
"= c #861782078617",
"- c #28A228A228A2",
"; c #104014511040",
": c #10400C300000",
"> c #410324921040",
", c #082004100000",
"< c #000000000000",
"1 c #71C63CF32081",
"2 c #8E38492428A2",
"3 c #208114511040",
"4 c #30C234D330C2",
"5 c #208110400820",
"6 c #492424921040",
"7 c #51442CB21861",
"8 c #38E320811040",
"9 c #104008200000",
"0 c #208114510820",
"q c #28A214510820",
"w c #79E741032081",
"e c #596530C21861",
"r c #10400C300820",
"t c #618534D32081",
"y c #30C218611040",
"u c #28A218610820",
"i c #79E7451428A2",
"p c #9658514430C2",
"a c #18610C300820",
"s c #186110400820",
"d c #30C21C711040",
"f c #49242CB21861",
"g c #104010400820",
"h c #59652CB21861",
"j c #492428A21861",
"k c #618538E32081",
"l c #30C21C710820",
"z c #69A634D32081",
"x c #20811C711861",
"c c #30C224921861",
"v c #30C22CB228A2",
"b c #186110401040",
"n c #410328A21861",
"m c #8617451428A2",
"M c #38E31C711040",
"N c #61855D755965",
"B c #69A638E32081",
"V c #410320811040",
"C c #51443CF330C2",
"Z c #514430C22081",
" . ",
" X. ",
" oOo ",
" +@ ",
" # $% ",
" %+ O ",
" &* =O ",
" O* =- ",
" o; =O ",
" &@ =-=X+= ",
" O. X:>,--# ",
" #<# *<12>3* = ",
" &4- ;56789<&$# ",
" o+$-= *0q<6,w,$;= o#",
" %;4* +8wq,ee<<<% *;%",
" %<O.#o #Xr8>tw<<<; o#.;+# ",
" %4% #+;<O% .9y<<u>,08<<<<<$-4# ",
" X;*$% &O<@5ipa<<<sd:O% ",
" +$% +$* *;fp8<,$$<<Xo ",
" @$% o$;o X4gh5<<7$#* %++-# ",
" #.$% oO. ;5jk9<<ld$ #X-;;.## ",
" #*.-<;;% o;.<2zu<<5y<* ;;+# ",
" .O.X=# =%=&X+6ia<,j4$;4# +- ",
" *@;<<$O+*x0<97yX=4<$#o=<= ",
" +;O4+&+O9<<<<ae0<= @<-.$O ",
" *$o %c8etd<<<vb<+ &<<$o ",
" %$* &nt2pe<<<$X@& &;+ ",
" o$- =07t2e<<5aOOX<@ %+ ",
" oO$o xt2qae,,79O<#X<+ ",
" @<= &>mtd<Mtjq<@< 4<* ",
" o&<+ NB7B<<<se<$+< o$;% ",
" +;4= :waa1,9jV5+X$ =<Oo ",
" #@$.# o9e9<d5j5,C -- @4 ",
"-<+# <7<,ue5<$% <& &$o ",
"o -5<8q:Z+o $ &;# ",
" o4$--&o +@ &$% ",
" o4$* <# ",
" =;O% %< ",
" o.<4o =4 ",
" o$<& ++ ",
" XO% -X ",
" ;o O# ",
" X@ $ ",
" ;= & ",
" &- ",
" -= ",
" %; ",
" %+ "};
약간 의외일 것이다. xpm file은 이처럼 C에서 바로 쓸 수 있는 char
형 pointer 변수인 것이다. 약간 감이 잡힐 것이다.
즉 압축 file인 gif를 QPixmap으로 Loading을 하게 되면 Loader는
이러한 char형 pointer로 변환을 해주고 그를 memory에 loading하게
된다. Windows System과 비슷하지 않은가? Windows에서도 이런 과정
을 거쳐 그림을 화면에 뿌려준다는 것은 웬만한 programmer라면 알
고 있을 것이다. 즉, gif나 jpg format을 Windows에서 접근 가능한
bmp로 변환시켜 memory에 loading한 다음 그를 화면에 나타낸다.
이런 bmp의 역할을 하는 것이 바로 Pixmap file인 xpm format file들
인 것이다. 이해가 됐을 지 모르겠다.
두번째 인자인 char 형 pointer인 textlabel은 Mouse Pointer가
ToolButton에 위치했을 때 나타낼 수 있는 Tooltip(풍선도움말)이다.
나머지 인자들은 지금까지 착실하게 source들을 이해했다면 설명할
필요가 없을 것 같아 생략하겠다.
-------------- < source 2.2.9.3 main_test8.cpp > ---------------
#include <qapplication.h>
#include "clssTestToolBar.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssTestToolBar *clssTest = new clssTestToolBar();
clssTest->setGeometry(100, 100, 500, 350);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
-------------------------------------------------------------------
---------------------- < Makefile 2.2.9 > ----------------------
PROGS = main_test8
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_test8.o \
clssTestToolBar_moc.o \
clssTestToolBar.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_test8
rm -f *_moc.*
############# COMPILE #############
main_test8.o: main_test8.cpp
$(CC) -c main_test8.cpp $(CFLAGS) -o $@
clssTestToolBar_moc.cpp: clssTestToolBar.h
$(MOC) clssTestToolBar.h -o clssTestToolBar_moc.cpp
clssTestToolBar_moc.o: clssTestToolBar_moc.cpp
$(CC) -c clssTestToolBar_moc.cpp $(CFLAGS) -o $@
clssTestToolBar.o: clssTestToolBar.cpp
$(CC) -c clssTestToolBar.cpp $(CFLAGS) -o $@
main_test8: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
-------------------------------------------------------------------
2.3. QT Library를 다운받으려면?
여러 Site가 있지만 가장 대표적인 Url은
< http://www.troll.no >
에서 다운받아 사용할 수 있다.
< 한마디 >.
지금까지 하나의 Project를 꾸미기 위해 그리 짧지만은 않은 과정을 거쳐왔습
니다.
기초 과정은 모두 끝난 것입니다. 아직 기초과정에 속한 network관련 Library
에 대한 설명의 화두도 나오지 않은 상태이지만 Project를 구현하기에는 충분한
실력을 쌓았다고 할 수 있겠죠. 기초 과정은 대략 설명이 끝났으므로 앞으로
나올 기초 부분에 연관된 code들에 대해서는 되도록이면 설명을 생략하도록 하
겠습니다.
===============================================================
< 3. 기본 Format 작성하기 >
이제부터 본격적으로 Project를 시작해보자.
Programming 순서는 여러분들도 잘 아시겠지만
< 입력->처리->출력 > 의 순서로 만들어야 한다. 이러한 과정은 여러분
들이 직접 Project를 개발할 때 유용한 방법이지 이렇게 발표혹은 세미
나형식의 대화에서는 별로 쓸모가 없다. 따라서 필자는 여러분이 가장
이해하기 쉬운 측면부터 파고들고자 한다.
우선 기본 format을 잡아보자.
기본 format은 Windows형태의 window가 가장 좋을 듯 하다.
요새는 리눅스 Application들도 Windows형태와 GUI가 비슷하다.
따라서 필자도 이 Format에 따르겠다.
--------------------------------------------------------
| 메뉴 영역 |
|--------------------------------------------------------|
| Icon 영역 |
|--------------------------------------------------------|
| |
| |
| |
| |
| 작업 영역 |
| |
| |
| ---------------- |
| ---- --------- |
|---- -----------------------|
3.1. 메뉴 만들기
메뉴는 다음과 같이 하나의 Popup Menu를 포함시키는 것으로 한다.
--------------------------------------------------------
| 네트워크관리 |
|--------------------------------------------------------|
| | 일반네트워크관리 | |
|-| DNS 관리 |-----------------------------------|
| | IP-Aliasing관리 | |
| |------------------| |
| |
| ------------------------- |
| ----------- ------- |
|---- ---------|
다음은 Source를 보기로 하자.
-------------- < Source 3.1.1 Network_menu.h > -----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
};
----------------------------------------------------------------
-------------- < Source 3.1.2 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <stdio.h>
#include "Network_menu.h"
clssNetwork::clssNetwork()
{
qApp->setStyle(WindowsStyle);
/* 메뉴를 만들고 그 메뉴에 해당하는 함수를 간단하게 */
/* 정의해 놓는다. */
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
---------------- < Source 3.1.3 main_menu.cpp > ----------------
#include <qapplication.h>
#include "Network_menu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
--------------------- < Makefile 3.1. > ------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
----------------------------------------------------------------
3.2. 툴바 집어넣기
ToolBar에 들어갈 ICON은 16*16크기정도의 gif file이 좋겠다.
Source를 보자.
-------------- < Source 3.2.1 Network_menu.h > -----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
};
----------------------------------------------------------------
-------------- < Source 3.2.2 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
/* icon에 대한 풍선도움말을 선언한다. */
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
/* 윈도우형태를 Windows스타일로 */
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
------------------ < Source 3.2.3 main_menu.cpp > --------------
#include <qapplication.h>
#include "Network_menu.h"
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
---------------------- < Makefile 3.2. > -----------------------
Makefile은 < Makefile 3.1. >과 같다.
----------------------------------------------------------------
3.3. Network관련 라이브러리 구현하기
메뉴와 툴바를 기본적으로 작성을 했으므로 이제부터는 Network관련
라이브러리를 구현하기로 하자. 이 라이브러리는 위쪽에서 구현했던
file처리루틴을 사용하기도 하고 gcc가 제공하는 network library를
사용하기도 한다. 마지막으로 이 부분만 잘 이해를 한다면 거의 어
려움 없이 끝까지 과정을 지나갈 수 있다.
우선 header file부터 보기로 하자.
--------------- < Source 3.3.1 network.h > ---------------------
#ifndef _NETWORK_H
#define _NETWORK_H
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef MAX_LINE
#define MAX_LINE 100
#define MAX_COL 1000
#endif
#ifndef NO_SETTING
#define NO_SETTING "셋팅되어있지 않습니다."
#endif
extern char pszNetConfHost[256];
extern char pszNetConfDomain[256];
extern char pszNetConfGateway[18];
extern char pszNetConfIPAddr[18];
extern char pszNetConfPrivate1IPAddr[18];
extern char pszNetConfPrivate2IPAddr[18];
extern char pszNetConfNetmask[18];
extern char pszNetConfPrivate1Netmask[18];
extern char pszNetConfPrivate2Netmask[18];
extern char pszNetconfBroadcast[18];
extern char pszNetconfPrivate1Broadcast[18];
extern char pszNetconfPrivate2Broadcast[18];
extern char pszNetConfNetwork[18];
extern char pszNetConfPrivate1Network[18];
extern char pszNetConfPrivate2Network[18];
extern char pszNetConfNetCard[3][30];
extern int nCountListStr;
extern char pszSaveNameServer[20][30];
extern int nCountNameServer;
extern int nCountClient;
extern int nAccountCount;
/* IP와 Netmask를 알아냈을 때 그에 해당하는 Network과 Broadcast */
/* 를 알아내기 위한 구조체 */
typedef struct tagNETMASKTAB {
char pszNetwork[18];
char pszBroadcast[18];
} NetTab;
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask);
/* IP에 대해 dot로 나누어진 4개의 번호를 얻기위해 쓰일 구조체 */
typedef struct tagSEPADDR {
char pszFirst[6];
char pszSecond[6];
char pszThird[6];
char pszFourth[6];
} S_Addr;
S_Addr separateAddress(char *pszAddr);
/* 현재 날짜를 계산한다. */
char *calculateDate(void);
/* 현재 첫번째 Network card에 대한 Netmask를 알아낸다. */
void getCurrentNetmask(char *pszNetmask);
/* 현재 첫번째 Network card에 대한 Gateway를 알아낸다. */
void getCurrentGateway(char *pszGateway);
/* 현재 첫번째 Network card에 대한 Hostname을 알아낸다. */
void getCurrentHostName(char *pszHostName, char *pszDomainName);
/* 현재 첫번째 Network card에 대한 IP를 알아낸다. */
void getCurrentIPAddr(char *pszIPAddr);
/* 현재 설정된 두번째 Network card에 대한 Netmask를 알아낸다. */
void getPrivate1Netmask(char *pszPrivateNetmask);
/* 현재 두번째 Network card에 대한 사설IP를 알아낸다. */
void getPrivate1IPAddr(char *pszPrivateIPAddr);
/* 현재 설정된 세번째 Network card에 대한 Netmask를 알아낸다. */
void getPrivate2Netmask(char *pszPrivateNetmask);
/* 현재 세번째 Network card에 대한 사설IP를 알아낸다. */
void getPrivate2IPAddr(char *pszPrivateIPAddr);
/* Network card가 ISA일 경우 Io number와 Irq number를 알아낸다. */
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nCardIdx);
/* 현재 DNS 서버의 설정값을 알아낸다. */
void getDNSServer(char *pszDNSServer[]);
/* 만약 IP가 Aliasing 되어있다면 Aliasing IP에 대한 Netmask를 알아낸다. */
void getAliasNetmask(char *pszNetmask, int nIdx);
/* Aliasing IP를 알아낸다. */
void getAliasIP(char *pszIPAddr, int nIdx);
/* Network카드의 정보를 알아낸다. */
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[]);
/* IP범위값을 알아낸다. 예: 172.31.0.0/24 -> 172.31.0.0~172.31.0.255 */
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth,
int nRange);
/* IP범위값을 받아 IP/number부분의 number값을 알아낸다. */
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange);
#endif
----------------------------------------------------------------
--------------- < Source 3.3.1 network.cpp > -------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include "network.h"
#include "proc_file.h"
/*************** Calculate Netmask table **************/
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask)
{
struct in_addr IP;
struct in_addr Mask;
struct in_addr pNetwork;
struct in_addr pBroadcast;
NetTab pNet;
memset(pNet.pszNetwork, '\0', 18);
memset(pNet.pszBroadcast, '\0', 18);
IP.s_addr = inet_addr(pszIPAddr);
Mask.s_addr = inet_addr(pszNetmask);
/* Network의 계산법은 IP & Netmask이다. */
pNetwork.s_addr = IP.s_addr & Mask.s_addr;
/* Network을 계산하여 pNet구조체의 network 변수에 전해준다. */
memcpy(pNet.pszNetwork, inet_ntoa(pNetwork), 18);
/* Broadcast의 계산법은 Network | Netmask이다. */
pBroadcast.s_addr = pNetwork.s_addr | ~Mask.s_addr;
/* Broadcast를 계산하여 pNet구조체의 broadcast 변수에 전해준다. */
memcpy(pNet.pszBroadcast, inet_ntoa(pBroadcast), 18);
return pNet;
}
/***************************************/
S_Addr separateAddress(char *pszAddr)
{
int i = 0, j = 0, k = 0;
S_Addr pAddr;
memset(pAddr.pszFirst, '\0', 6);
memset(pAddr.pszSecond, '\0', 6);
memset(pAddr.pszThird, '\0', 6);
memset(pAddr.pszFourth, '\0', 6);
/* 구조체의 각 member(pszFirst, pszSecond, pszThird, pszFourth) */
/* 에 해당하는 값을 나눠 복사하는 작업. 어렵지 않으므로 유심히 */
/* 보시길. */
for (k = 0; *(pszAddr+i) != '\0'; i++, k++)
{
if (*(pszAddr+i) == '.')
{
i++;
k = 0;
j++;
}
switch (j)
{
case 0:
pAddr.pszFirst[k] = *(pszAddr+i);
break;
case 1:
pAddr.pszSecond[k] = *(pszAddr+i);
break;
case 2:
pAddr.pszThird[k] = *(pszAddr+i);
break;
case 3:
pAddr.pszFourth[k] = *(pszAddr+i);
break;
default:
break;
}
}
return pAddr;
}
/* 실제 구현에서는 별로 쓸모없는 함수이지만 날짜를 얻어내는 함수정 */
/* 도는 있어야겠다 싶어 넣어놓았다. */
char pszDate[11];
char *calculateDate()
{
time_t tTime;
int i;
memset(pszDate, '\0', 11);
tTime = time(NULL);
for (i = 0; i < 4; i++)
pszDate[i] = *(ctime(&tTime)+20+i);
for (i = 0; i < 3; i++)
pszDate[i+4] = *(ctime(&tTime)+4+i);
for (i = 0; i < 2; i++)
pszDate[i+4+3] = *(ctime(&tTime)+8+i);
return pszDate;
}
void getCurrentNetmask(char *pszNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* Netmask를 얻어낼 때는 밑에있는 ifcfg-eth0 file에 있는 */
/* 정보를 사용하여 알아낸다. */
/* ifcfg-eth0 file을 열어보면 Redhat 6.0버젼까지는 이렇게 되어 */
/* 있다. */
/*
DEVICE=eth0
IPADDR=172.31.10.1
NETMASK=255.255.0.0
NETWORK=172.31.0.0
BROADCAST=172.31.255.255
ONBOOT=yes
*/
/* 이중에서 NETMASK= 뒷부분만을 읽어내는 것이다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "r")) ==
NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszNetmask[i] = pszSave[i+8];
pszNetmask[i-1] = '\0';
}
void getCurrentGateway(char *pszGateway)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* gateway를 알아낼 때는 network file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
/* GATEWAY=뒷부분을 저장한다. */
strcpy(pszSave, (char *)strstr(pszSaveFile, "GATEWAY="));
for (i = 0; pszSave[i+8] != 'G'; i++)
pszGateway[i] = pszSave[i+8];
pszGateway[i-1] = '\0';
}
void getPrivate1Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* ifcfg-eth1 file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) ==
NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate1IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) ==
NULL)
{
// strcpy(pszPrivateIPAddr, "172.31.0.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getPrivate2Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) ==
NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate2IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
/* ifcfg-eth2 file을 이용한다. */
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) ==
NULL)
{
// strcpy(pszPrivateIPAddr, "192.168.1.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
/* network 구조체 utsname을 이용한다. */
/* utsname의 member인 nodename은 hostname.domainname의 형태 */
/* 로 들어가게 되어있다. */
void getCurrentHostName(char *pszHostName, char *pszDomainName)
{
struct utsname name;
int i, j;
uname(&name);
for (i = 0; name.nodename[i] != '.'; i++)
pszHostName[i] = name.nodename[i];
i++;
for (j = 0; name.nodename[i] != '\0'; i++, j++)
pszDomainName[j] = name.nodename[i];
}
void getCurrentIPAddr(char *pszIPAddr)
{
char *pszSaveListStr[20];
int i;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
/* ifcfg-eth0 file에서 IPADDR문자열을 찾아 그 라인을 저장한다. */
saveSearchLineToFile("IPADDR", pszSaveListStr,
"/etc/sysconfig/network-scripts/ifcfg-eth0", 20, 80);
/* IP 부분을 끄집어낸다. */
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* 요새는 Network card들 대부분이 PCI Card로밖에는 나오지 않는다. */
/* Io, Irq number를 수동으로 setting해야하는 Card는 ISA Card인데 */
/* ISA Card를 쓰는 사람은 1000명중 1명이나 될까? 따라서 이 루틴 */
/* 은 별로 필요가 없는 루틴이지만 필요할 지도 모른다는 생각에 집 */
/* 어넣었다. 이 루틴은 /etc/conf.modules file이 필요하다. */
/* conf.modules file에 io=0x230 irq=11 같은 형식으로 들어가기 때문 */
/* 에 이 부분에 대한 문자열 처리가 필요하다. 자세한 설명은 그만 */
/* 두겠다. */
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nNetCardIdx)
{
int i;
char *pszPosIo, *pszPosIrq;
int nIrqIdx, nIoIdx;
char *pszTmpStr = "options eth%d";
char pszOptionStr[30];
char *pszSaveListStr[3];
for (i = 0; i < 3; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("Memory allocation error!\n");
memset(pszSaveListStr[i], '\0', 200);
exit(1);
}
}
memset(pszOptionStr, '\0', 30);
sprintf(pszOptionStr, pszTmpStr, nNetCardIdx);
saveSearchLineToFile(pszOptionStr, pszSaveListStr,
"/etc/conf.modules", 200, 200);
pszPosIo = strstr(pszSaveListStr[0], "0x");
nIoIdx = pszPosIo-pszSaveListStr[0];
pszPosIrq = strstr(pszSaveListStr[0], "irq=");
nIrqIdx = pszPosIrq-pszSaveListStr[0];
for (i = nIoIdx-1; i < nIrqIdx-4; i++)
pszIo[i-nIoIdx+1] = pszSaveListStr[0][i+3];
for (i = nIrqIdx; pszSaveListStr[0][i+4] != '\n'; i++)
pszIrq[i-nIrqIdx] = pszSaveListStr[0][i+4];
for (i = 0; i < 3; i++)
free(pszSaveListStr[i]);
}
/* DNS Server는 /etc/resolv.conf file에 들어간다. */
/* resolv.conf file에 들어있는 IP는 순서대로 DNS Server 역할을 */
/* 한다. 즉 nameserver로서 별로 좋지않은 server IP가 첫줄에 있 */
/* 다면 그를 삭제하거나 뒤로 옮겨줄 수 있다. 이 함수는 단순히 */
/* setting되어있는 DNS Server IP만을 pszDNSServer에 저장한다. */
void getDNSServer(char *pszDNSServer[])
{
char *pszSaveListStr[50];
int i;
int nCntDNS;
for (i = 0; i < 50; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
saveSearchLineToFile("nameserver", pszSaveListStr,
"/etc/resolv.conf", 50, 200);
nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
nCntDNS--;
for (i = 0; i < nCntDNS; i++)
{
strcpy(pszDNSServer[i], pszSaveListStr[i]+11);
pszDNSServer[i][strlen(pszDNSServer[i])-1] = '\0';
}
for (i = 0; i < 50; i++)
free(pszSaveListStr[i]);
}
/* nIdx는 Aliasing되어있는 순번을 뜻한다. 즉 nIdx=1일때 */
/* 이것이 의미하는 것은 eth0:1이다. 번호는 순차적이다. */
/* 이 때 eth0:1 에 대한 정보는 ifcfg-eth0:1 file에 저장된다. */
void getAliasIP(char *pszIPAddr, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("IPADDR", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* 위와 마찬가지로 nIdx는 Aliasing되어있는 순번이다. */
void getAliasNetmask(char *pszNetmask, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("NETMASK", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+8] != '\n'; i++)
pszNetmask[i] = pszSaveListStr[0][i+8];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
/* Network card정보는 /proc/interrupts file에서 읽어들인다. */
/* interrupts file은 system의 여러가지 설정값들이 들어가는데 */
/* 이는 사용자가 절대 setting해서는 안되는 file이다. */
/* Network card가 설치되었을 때 두가지 file에 그 정보가 나타 */
/* 나는데 하나는 /etc/conf.modules file이고 나머지 하나는 */
/* interrupts file이다. setting을 할 때는 conf.modules file */
/* 을 사용하고 정보를 읽어들일 때는 interrupts file을 사용한다. */
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[])
{
FILE *fp;
int i, j, nIdx, nCount, nCardCount = 0;
char *pszSaveListStr[100];
char *pszSaveLine[4];
if ((fp = fopen("/proc/interrupts", "r")) == NULL)
{
printf("file open error!\n");
return;
}
fclose(fp);
for (i = 0; i < 4; i++)
{
if ((pszSaveLine[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveLine[i], '\0', 200);
}
for (i = 0; i < 100; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) ==
NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
nCount = saveAllLineToFile(pszSaveListStr, "/proc/interrupts",
100, 200);
for (i = 0, nIdx = 0; i < nCount; i++)
{
for (j = 0; j < 40; j++)
{
if (strstr(pszSaveListStr[i], pszCardInfo[j]) !=
(char *)NULL)
{
nCardCount++;
strcpy(pszSaveLine[nIdx++], pszSaveListStr[i]);
break;
}
}
}
if (nCardCount == 0)
{
strcpy(pszSaveNetCard[0], NO_SETTING);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 1)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 2)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], pszSaveLine[2]+33);
}
for (i = 0; i < 4; i++)
free(pszSaveLine[i]);
for (i = 0; i < 100; i++)
free(pszSaveListStr[i]);
}
/* 예를 들어 172.31.0.0/16 이라면 nRange의 값은 16이다. */
/* 그리고 pszStartIP는 172.31.0.0이되며 pszEndIP는 172.31.255.255 */
/* 가 된다. 이 값에 대한 정보는 이 자료의 맨 끝에 표로 설명을 하겠다. */
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth,
int nRange)
{
char pszSaveStartIP[4], pszSaveEndIP[4];
memset(pszSaveStartIP, '\0', 4);
memset(pszSaveEndIP, '\0', 4);
if (nIPFourth%nRange != 0)
{
sprintf(pszSaveStartIP, "%d", (nIPFourth/nRange)*nRange);
sprintf(pszSaveEndIP, "%d", (nIPFourth/nRange)*nRange+nRange-1);
}
else
{
sprintf(pszSaveStartIP, "%d", nIPFourth);
sprintf(pszSaveEndIP, "%d", nIPFourth+nRange-1);
}
strcat(pszStartIP, pszSaveStartIP);
strcat(pszEndIP, pszSaveEndIP);
}
/* 위와는 반대로 pszStartIP와 pszEndIP를 가지고 nRange값을 알아낸다. */
/* 알아낸 범위정보는 nRange변수에 저장되는데 저장을 위해 포인터를 */
/* 썼다. 이는 IP의 네번째 번호를 가지고 추출한다. 즉 A, B class */
/* 는 고려하지 않았다. */
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange)
{
S_Addr pAddr;
int i, nSaveRange;
int nStart, nEnd;
pAddr = separateAddress(pszStartIP);
nStart = atoi(pAddr.pszFourth);
pAddr = separateAddress(pszEndIP);
nEnd = atoi(pAddr.pszFourth);
nSaveRange = nEnd-nStart+1;
for (i = 0; nSaveRange > 0; i++)
nSaveRange /= 2;
*nRange = 32-(i-1);
}
----------------------------------------------------------------
3.4. Class만들기
3.4.1. 일반네트워크관리
이제부터는 본격적인 network 관리 구현에 들어가겠다.
지금부터 나오는 대부분의 Source 들은 위에서 이미 설명했던 부분들이다.
따라서 Source에 대한 설명은 가급적이면 생략하고 Source위주로 Project
를 이끌어 나가겠다.
일반네트워크관리메뉴에는 네트워크카드설정, IP및 Netmask,gateway설정등
일반적으로 리눅스에서 네트워크에 관한 설정을 할 때 가장 먼저 손을 보
아야 하는, 혹은 가장 자주 접하게 되는 부분들을 구현해보았다.
우선 Source를 컴파일 해서 직접 실행시켜보기 바란다. 이해가 빨라질 것
이다. Source는 앞서 설명했던 proc_file.c와 network.c부분이 상당부분
포함되어 있다. file 처리 루틴과 network 처리 루틴을 모두 이해했다면
어려움 없이 지금 이후의 부분들도 이해할 수 있으리라 생각한다.
---------------- < Source 3.4.1 clssGeneric.h > ----------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefGeneric : public QWidget
{
Q_OBJECT
public:
clssDefGeneric();
~clssDefGeneric();
private slots:
void setApply();
void setCancel();
void printLabelFormat(QLabel *lblBold);
private:
QLabel *lblGenericNetworkTitle;
QLabel *lblGateway;
QLineEdit *leGateway;
/* Eth0에 대한 member들 */
QLabel *lblEth0;
QLabel *lblEth0IPAddr;
QLineEdit *leEth0IPAddr;
QLabel *lblEth0Netmask;
QLineEdit *leEth0Netmask;
QLabel *lblEth0Network;
QLineEdit *leEth0Network;
QLabel *lblEth0Broadcast;
QLineEdit *leEth0Broadcast;
QLabel *lblEth0NetCard;
/* 네트워크 카드는 combobox로 설정하게 한다. */
QComboBox *cbEthNetCard[3]; /* to combobox */
/* Eth1에 대한 members */
QLabel *lblEth1;
QLineEdit *leEth1IPAddr;
QLineEdit *leEth1Netmask;
QLineEdit *leEth1Network;
QLineEdit *leEth1Broadcast;
QLabel *lblEth1NetCard;
/* Eth2에 대한 members */
QLabel *lblEth2;
QLineEdit *leEth2IPAddr;
QLineEdit *leEth2Netmask;
QLineEdit *leEth2Network;
QLineEdit *leEth2Broadcast;
QLabel *lblEth2NetCard;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frEthInfo;
QLabel *lblSeparator1;
QLabel *lblSeparator2;
};
----------------------------------------------------------------
--------------- < Source 3.4.2 clssGeneric.cpp > ---------------
#include <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qpalette.h>
#include <stdio.h>
#include <stdlib.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssGeneric.h"
clssDefGeneric::clssDefGeneric()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
int i, j, nCardIdx;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
/* Linux에서 제공하는 PCI type Network Card Modules */
/* 각 string의 끝에 있는 괄호안의 내용이 바로 module 이름이다. */
const char *pszNetCard[40] = {
" 3Com Vortex series (3c590, 3c592, 3c597, 3c595) (3c59x) ",
" 3Com Boomerang (3c900, 3c905, 3c575) (3c59x) ",
" 3Com Cyclone (3c905B) (3c59x) ",
" Intel EtherExpress Pro 100 (eepro100) ",
" HP J2585B, J2585A, J2970, J2973 (hp100) ",
" HP J2573 (hp100) ",
" Compex ReadyLink ENET100-VG4 (hp100) ",
" Compex FreedomLine 100/VG (hp100) ",
" IBM token ring (ibmtr) ",
" NE2000 (PCI) (ne2k-pci) ",
" AMD PCnet/PCI 79C970/PCnet32/PCnet/PCI II 79C970A (pcnet32) ",
" PCnet/PCI II 79C971A (pcnet32) ",
" Allied Telesyn AT2550 (rtl8139) ",
" Genius GF100TXR (RTL8139) (rtl8139) ",
" NDC Communications NE100TX-E (rtl8139) ",
" RealTek RTL8129/8139 Fast (rtl8139) ", //15
" SMC Ultra/SMC UltraEZ/SMC Ultra32 (smc-ultra) ",
" Compaq Netelligent 10 T PCI UTP (tlan) ",
" Compaq Netelligent 10/100 TX PCI UTP (tlan) ",
" Compaq Netelligent Integrated 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10/100 TX Embedded UTP (tlan) ",
" Compaq Netelligent 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10 T/2 PCI UTP/Coax (tlan) ",
" Accton EtherDuo PCI/Accton EN1207 (tulip) ",
" Adaptec ANA6901/C/Adaptec ANA6911/TX (tulip) ",
" C-NET CNE-935 (tulip) ",
" Cogent EM100/Cogent EM110/Cogent EM400 (tulip) ",
" Cogent EM960/Cogent EM964 Quartet (tulip) ",
" Danpex EN-9400P3 (tulip) ",
" D-Link DFE500-Tx/D-Link DE-530CT (tulip) ",
" Linksys EtherPCI (tulip) ",
" Kingston EtherX KNT40T/Kingston EtherX KNE100TX (tulip) ",
" Netgear FX310 TX 10/100 (tulip) ",
" SMC EtherPower/SMC 8432BT/ SMC Ether Power10/100 (tulip) ",
" Surecom EP-320X (tulip) ",
" Thomas Conrad TC5048 (tulip) ",
" Znyx ZX312 EtherAction/Znyx ZX314/ZX315 (tulip) ",
" Znyx ZX342/ZX344/ZX345/ZX346/ZX348 (tulip) ",
" Znyx ZX351 (tulip) ",
" 세팅되어있지 않습니다! (No Setting)"
};
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
/* 첫번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
/* 두번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
/* 세번째 네트워크 카드의 속성(IP, Netmask)를 저장할 변수 초기화 */
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
/* gateway, IP, Netmask 등을 얻는다. */
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
/* network과 broadcast를 계산한다. */
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr,
pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr,
pszPrivate2Netmask);
/***********************/
lblGenericNetworkTitle =
new QLabel("Network Setting (일반적인 네트워크 설정)", this);
lblGenericNetworkTitle->setGeometry(20, 20, 400, 20);
// printLabelFormat(lblGenericNetworkTitle);
/***********************/
frEthInfo = new QFrame(this);
frEthInfo->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
frEthInfo->setGeometry(25, 50, 700, 362);
lblGateway = new QLabel("게이트웨이", frEthInfo);
lblGateway->setGeometry(10, 15, 80, 20);
leGateway = new QLineEdit(frEthInfo);
leGateway->setGeometry(90, 15, 150, 20);
/* getCurrentGateway함수를 이용하여 얻은 gateway를 편집박스 */
/* 에 삽입한다. */
leGateway->setText(pszGateway);
/* separator를 그린다. */
lblSeparator1 = new QLabel(frEthInfo);
lblSeparator1->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
lblSeparator1->setGeometry(20, 45, 630, 2);
/******** Ethernet Card 0 ********/
lblEth0 = new QLabel("첫번째 이더넷카드", frEthInfo);
lblEth0->setGeometry(90, 10+50, 100, 20);
lblEth0IPAddr = new QLabel("IP 주소 ", frEthInfo);
lblEth0IPAddr->setGeometry(10, 40+50, 80, 20);
leEth0IPAddr = new QLineEdit(frEthInfo);
leEth0IPAddr->setGeometry(90, 40+50, 150, 20);
leEth0IPAddr->setText(pszIPAddr);
/*** text -> proc ***/
lblEth0Netmask = new QLabel("Netmask ", frEthInfo);
lblEth0Netmask->setGeometry(10, 40+30+50, 80, 20);
leEth0Netmask = new QLineEdit(frEthInfo);
leEth0Netmask->setGeometry(90, 40+30+50, 150, 20);
leEth0Netmask->setText(pszNetmask);
lblEth0Network = new QLabel("Network ", frEthInfo);
lblEth0Network->setGeometry(10, 40+60+50, 80, 20);
leEth0Network = new QLineEdit(frEthInfo);
leEth0Network->setGeometry(90, 40+60+50, 150, 20);
/* Network은 IP와 Netmask의 값을 조합하여 나온 값이므로 이는 */
/* 따로 설정할 필요가 없는 부분이므로 편집박스를 edit할 수 */
/* 없도록 설정해둔다.(setEnabled(0)) */
leEth0Network->setEnabled(0);
/* pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);를 통하여 */
/* 얻어낸 pNet.pszNetwork값을 편집박스에 삽입. */
leEth0Network->setText(pNet.pszNetwork);
lblEth0Broadcast = new QLabel("Broadcast ", frEthInfo);
lblEth0Broadcast->setGeometry(10, 40+90+50, 80, 20);
leEth0Broadcast = new QLineEdit(frEthInfo);
leEth0Broadcast->setGeometry(90, 40+90+50, 150, 20);
leEth0Broadcast->setEnabled(0);
leEth0Broadcast->setText(pNet.pszBroadcast);
lblSeparator2 = new QLabel(frEthInfo);
lblSeparator2->setFrameStyle(QFrame::Box |
QFrame::Raised | QFrame::Plain);
lblSeparator2->setGeometry(20, 40+90+50+40, 630, 2);
/*** text -> proc ***/
/*********************************/
/******** Ethernet Card 1 ********/
lblEth1 = new QLabel("두번째 이더넷카드", frEthInfo);
lblEth1->setGeometry(300, 10+50, 100, 20);
leEth1IPAddr = new QLineEdit(frEthInfo);
leEth1IPAddr->setGeometry(300, 40+50, 150, 20);
leEth1IPAddr->setText(pszPrivate1IPAddr);
/*** text -> proc ***/
leEth1Netmask = new QLineEdit(frEthInfo);
leEth1Netmask->setGeometry(300, 40+30+50, 150, 20);
leEth1Netmask->setText(pszPrivate1Netmask);
/*** text -> proc ***/
leEth1Network = new QLineEdit(frEthInfo);
leEth1Network->setGeometry(300, 40+60+50, 150, 20);
leEth1Broadcast = new QLineEdit(frEthInfo);
leEth1Broadcast->setGeometry(300, 40+90+50, 150, 20);
leEth1Network->setEnabled(0);
leEth1Broadcast->setEnabled(0);
if (strlen(pszPrivate1IPAddr) >= 7)
{
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
}
/*********************************/
/******** Ethernet Card 2 ********/
lblEth2 = new QLabel("세번째 이더넷카드", frEthInfo);
lblEth2->setGeometry(520, 10+50, 100, 20);
leEth2IPAddr = new QLineEdit(frEthInfo);
leEth2IPAddr->setGeometry(520, 40+50, 150, 20);
leEth2IPAddr->setText(pszPrivate2IPAddr);
/*** text -> proc ***/
leEth2Netmask = new QLineEdit(frEthInfo);
leEth2Netmask->setGeometry(520, 40+30+50, 150, 20);
leEth2Netmask->setText(pszPrivate2Netmask);
/*** text -> proc ***/
leEth2Network = new QLineEdit(frEthInfo);
leEth2Network->setGeometry(520, 40+60+50, 150, 20);
leEth2Broadcast = new QLineEdit(frEthInfo);
leEth2Broadcast->setGeometry(520, 40+90+50, 150, 20);
leEth2Network->setEnabled(0);
leEth2Broadcast->setEnabled(0);
if (strlen(pszPrivate2IPAddr) >= 7)
{
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
}
/*********************************/
for (i = 0; i < 2; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*200);
memset(pszSaveListStr[i], '\0', 200);
}
/*********************************/
lblEth0NetCard = new QLabel("Ethernet 0 카드", frEthInfo);
lblEth0NetCard->setGeometry(10, 40+90+70+60, 90, 20);
cbEthNetCard[0] = new QComboBox(frEthInfo, "comboBox_Eth0");
cbEthNetCard[0]->setGeometry(110, 40+90+70+60, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[0]->insertItem(pszNetCard[i]);
cbEthNetCard[0]->setAutoResize(FALSE);
/* conf.modules file에서 Card정보를 찾아 외부변수인 */
/* pszNetConfNetCard에 저장한다. */
if (saveSearchLineToFile("alias eth0", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[0], pszSaveListStr[0]+11);
pszNetConfNetCard[0][strlen(pszNetConfNetCard[0])-1] = '\0';
}
/* 위에서 정의한 pszNetCard, 즉 Network Card Modules와 일 */
/* 치되는 Card가 conf.modules file에 있는지 검색하고 */
if (strlen(pszIPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[0]) !=
(char *)NULL)
break;
/* 만약 없다면 No Setting문자열을 combobox에 Setting한다. */
if (strlen(pszNetConfNetCard[0]) < 2)
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
/*********************************/
lblEth1NetCard = new QLabel("Ethernet 1 카드", frEthInfo);
lblEth1NetCard->setGeometry(10, 40+90+70+90, 90, 20);
cbEthNetCard[1] = new QComboBox(frEthInfo, "comboBox_Eth1");
cbEthNetCard[1]->setGeometry(110, 40+90+70+90, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[1]->insertItem(pszNetCard[i]);
cbEthNetCard[1]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth1", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[1], pszSaveListStr[0]+11);
pszNetConfNetCard[1][strlen(pszNetConfNetCard[1])-1] = '\0';
}
if (strlen(pszPrivate1IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[1]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[1]) < 2)
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
/**********************************/
lblEth2NetCard = new QLabel("Ethernet 2 카드", frEthInfo);
lblEth2NetCard->setGeometry(10, 40+90+70+120, 90, 20);
cbEthNetCard[2] = new QComboBox(frEthInfo, "comboBox_Eth2");
cbEthNetCard[2]->setGeometry(110, 40+90+70+120, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[2]->insertItem(pszNetCard[i]);
cbEthNetCard[2]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth2", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[2], pszSaveListStr[0]+11);
pszNetConfNetCard[2][strlen(pszNetConfNetCard[2])-1] = '\0';
}
if (strlen(pszPrivate2IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[2]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[2]) < 2)
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
cbEthNetCard[2]->setGeometry(110, 40+90+70+125, 470, 20);
/*************************************/
bttnApply = new QPushButton("적 용", this);
bttnApply->setGeometry(150, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this,
SLOT(setApply()));
bttnCancel = new QPushButton("취 소", this);
bttnCancel->setGeometry(450, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(setCancel()));
/************************************/
for (i = 0; i < 2; i++)
free(pszSaveListStr[i]);
free(pszIPAddr);
free(pszNetmask);
free(pszPrivate1IPAddr);
free(pszPrivate1Netmask);
free(pszPrivate2IPAddr);
free(pszPrivate2Netmask);
free(pszGateway);
}
clssDefGeneric::~clssDefGeneric()
{
int i;
delete lblEth0;
delete lblEth0IPAddr;
delete lblEth0Netmask;
delete lblEth0Network;
delete lblEth0Broadcast;
delete leEth0IPAddr;
delete leEth0Netmask;
delete leEth0Network;
delete leEth0Broadcast;
delete lblEth1;
delete leEth1IPAddr;
delete leEth1Netmask;
delete leEth1Network;
delete leEth1Broadcast;
delete lblEth2;
delete leEth2IPAddr;
delete leEth2Netmask;
delete leEth2Network;
delete leEth2Broadcast;
delete lblGateway;
delete leGateway;
delete lblSeparator1;
delete lblSeparator2;
for (i = 0; i < 3; i++)
delete cbEthNetCard[i];
delete lblEth0NetCard;
delete lblEth1NetCard;
delete lblEth2NetCard;
delete bttnCancel;
delete bttnApply;
delete lblGenericNetworkTitle;
delete frEthInfo;
}
/* Network에 관한 Setting이 위의 몇십줄로 끝나는 것은 아니다. */
/* Network 설정값이 변할 때 같이 변경되는 관련 file들도 다뤄주어 */
/* 야하기 때문이다. */
/* 이 함수는 설정값을 변경하고 적용버튼을 눌렀을 때, 그러한 관련 */
/* file들을 관리한다. */
void clssDefGeneric::setApply()
{
char *pszIfCfgEthFile = "DEVICE=%s\nIPADDR=%s\nNETMASK=%s\n\
NETWORK=%s\nBROADCAST=%s\nONBOOT=yes\n";
char *pszNetworkFile = "NETWORKING=yes\nFORWARD_IPV4=true\n\
HOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszOptions[95];
char *pszSaveCardLine[3], pszSaveHostName[256], pszSaveDomainName[256];
NetTab pNet, pNetPrivate1, pNetPrivate2;
FILE *fp;
S_Addr pAddr, pSaveAddr;
char pszTmpSearch[100];
char pszTmpInsert[100];
char pszSaveIP[18];
int i;
memset(pszSaveIP, '\0', 18);
getCurrentIPAddr(pszSaveIP);
pSaveAddr = separateAddress(pszSaveIP);
pNet = calculateNetMaskTab((char *)leEth0IPAddr->text(),
(char *)leEth0Netmask->text());
pNetPrivate1 = calculateNetMaskTab((char *)leEth1IPAddr->text(),
(char *)leEth1Netmask->text());
pNetPrivate2 = calculateNetMaskTab((char *)leEth2IPAddr->text(),
(char *)leEth2Netmask->text());
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
/* ifcfg-eth0, ifcfg-eth1, ifcfg-eth2 file들을 다룬다. */
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "w");
fprintf(fp, pszIfCfgEthFile,
"eth0", leEth0IPAddr->text(), leEth0Netmask->text(),
leEth0Network->text(), leEth0Broadcast->text());
fclose(fp);
if (strlen((char *)leEth1IPAddr->text()) >= 7)
{
char pszPrivate1IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "w");
fprintf(fp, pszIfCfgEthFile,
"eth1", leEth1IPAddr->text(), leEth1Netmask->text(),
leEth1Network->text(), leEth1Broadcast->text());
fclose(fp);
}
if (strlen((char *)leEth2IPAddr->text()) >= 7)
{
char pszPrivate2IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "w");
fprintf(fp, pszIfCfgEthFile,
"eth2", leEth2IPAddr->text(), leEth2Netmask->text(),
leEth2Network->text(), leEth2Broadcast->text());
fclose(fp);
}
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, pszSaveHostName, pszSaveDomainName,
pszSaveDomainName, leGateway->text());
fclose(fp);
for (i = 0; i < 3; i++)
{
if ((pszSaveCardLine[i] = (char *)malloc(sizeof(char)*50)) == NULL)
{
printf("pszSaveCardLine Memory Error!\n");
exit(1);
}
memset(pszSaveCardLine[i], '\0', 50);
}
for (i = 0; i < 3; i++)
{
sprintf(pszSaveCardLine[i], "alias eth%d ", i);
if (cbEthNetCard[i]->currentItem() >= 0 &&
cbEthNetCard[i]->currentItem() <= 2)
strcat(pszSaveCardLine[i], "3c59x");
else if (cbEthNetCard[i]->currentItem() == 3)
strcat(pszSaveCardLine[i], "eepro100");
else if (cbEthNetCard[i]->currentItem() >= 4 &&
cbEthNetCard[i]->currentItem() <= 7)
strcat(pszSaveCardLine[i], "hp100");
else if (cbEthNetCard[i]->currentItem() == 8)
strcat(pszSaveCardLine[i], "ibmtr");
else if (cbEthNetCard[i]->currentItem() == 9)
strcat(pszSaveCardLine[i], "ne2k-pci");
else if (cbEthNetCard[i]->currentItem() == 10 ||
cbEthNetCard[i]->currentItem() == 11)
strcat(pszSaveCardLine[i], "pcnet32");
else if (cbEthNetCard[i]->currentItem() >= 12 &&
cbEthNetCard[i]->currentItem() <= 15)
strcat(pszSaveCardLine[i], "rtl8139");
else if (cbEthNetCard[i]->currentItem() == 16)
strcat(pszSaveCardLine[i], "smc-ultra");
else if (cbEthNetCard[i]->currentItem() >= 17 ||
cbEthNetCard[i]->currentItem() <= 22)
strcat(pszSaveCardLine[i], "tlan");
else if (cbEthNetCard[i]->currentItem() >= 23 ||
cbEthNetCard[i]->currentItem() <= 38)
strcat(pszSaveCardLine[i], "tulip");
}
for (i = 0; i < 3; i++)
strcat(pszSaveCardLine[i], "\n");
/* conf.modules file을 변경한다. proc_file.c에서 설명한 바와 */
/* 같이 바로 아래함수가 의미하는 것은 */
/* conf.modules file에서 최대 200line, 100column 을 허용하여 */
/* alias eth0라는 문자열이 포함된 line을 찾아 Network Card */
/* 값인 pszSaveCardLine[0]을 대치시켜라 라는 뜻이다. */
addOnNotExistChangeOnExist(pszSaveCardLine[0], "alias eth0",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[1], "alias eth1",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[2], "alias eth2",
"/etc/conf.modules", 200, 100);
if (cbEthNetCard[0]->currentItem() == 39)
insertStrToFile("", "alias eth0", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[1]->currentItem() == 39)
insertStrToFile("", "alias eth1", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[2]->currentItem() == 39)
insertStrToFile("", "alias eth2", "/etc/conf.modules", 200, 100);
for (i = 0; i < 3; i++)
free(pszSaveCardLine[i]);
if (cbEthNetCard[0]->currentItem() == 39)
{
/* 만약 Eth0 Card가 Setting되어 있지 않다면 ifcfg-eth0 file */
/* 을 삭제하고 각 Network설정값들은 공백문자열로 놓는다. */
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth0");
leEth0IPAddr->setText("");
leEth0Netmask->setText("");
leEth0Network->setText("");
leEth0Broadcast->setText("");
}
if (cbEthNetCard[1]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth1");
leEth1IPAddr->setText("");
leEth1Netmask->setText("");
leEth1Network->setText("");
leEth1Broadcast->setText("");
}
if (cbEthNetCard[2]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth2");
leEth2IPAddr->setText("");
leEth2Netmask->setText("");
leEth2Network->setText("");
leEth2Broadcast->setText("");
}
/**************************************/
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth0 \
/etc/sysconfig/network-scripts/ifcfg-eth0.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth1 \
/etc/sysconfig/network-scripts/ifcfg-eth1.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth2 \
/etc/sysconfig/network-scripts/ifcfg-eth2.org\n");
system("cp -f /etc/sysconfig/network /etc/sysconfig/network.org\n");
system("cp -f /etc/conf.modules /etc/conf.modules.org\n");
system("cp -f /etc/resolv.conf /etc/resolv.conf.org\n");
system("/etc/rc.d/init.d/network \
stop;/etc/rc.d/init.d/network start\n");
}
/* 취소버튼을 눌렀을 때에는 설정했던 값들이 제자리를 찾아간다. */
/* 물론 적용버튼을 누르고 다시 취소버튼을 누르면 소용이 없다. */
void clssDefGeneric::setCancel()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char **pszHostName, *pszDomainName;
char *pszPrivate1IPAddr, *pszPrivate1Netmask;
char *pszPrivate2IPAddr, *pszPrivate2Netmask;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL)||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr,
pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr,
pszPrivate2Netmask);
/***** lineeditbox init: proc -> segmentation fault *****/
leGateway->setText(pszGateway);;
leEth0IPAddr->setText(pszIPAddr);
leEth0Netmask->setText(pszNetmask);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1IPAddr->setText(pszPrivate1IPAddr);
leEth1Netmask->setText(pszPrivate1Netmask);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2IPAddr->setText(pszPrivate2IPAddr);
leEth2Netmask->setText(pszPrivate2Netmask);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
}
/* Title을 나타내주는 부분이다. 별로 중요하지 않은 부분이므로 */
/* 설명은 생략하겠다. */
void clssDefGeneric::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(),
n.dark(), n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
/* 여기부터는 주메뉴, 즉 풀다운메뉴와 icon box등을 정의하는 부분 */
/* 이다. 이 부분들에 대한 설명은 2.2장에서 모두 설명했으므로 */
/* 설명을 생략하겠다. */
--------------- < Source 3.4.3 Network_menu.h > ----------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
};
----------------------------------------------------------------
-------------- < Source 3.4.4 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
//#include "clssDNS.h"
//#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
--------------------- < Makefile 3.4. > ------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
OTHER_OBJS = \
network.o \
proc_file.o
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o \
clssGeneric.o \
clssGeneric_moc.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
network.o: network.c
$(CC) -c network.c -o $@
proc_file.o: proc_file.c
$(CC) -c proc_file.c -o $@
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
clssGeneric_moc.cpp: clssGeneric.h
$(MOC) clssGeneric.h -o clssGeneric_moc.cpp
clssGeneric_moc.o: clssGeneric_moc.cpp
$(CC) -c clssGeneric_moc.cpp $(CFLAGS) -o $@
clssGeneric.o: clssGeneric.cpp
$(CC) -c clssGeneric.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
----------------------------------------------------------------
3.4.2. DNS관리
이 장은 호스트 및 도메인 이름 설정, 그리고 DNS Server를 셋팅하는
방법에 대한 내용이다. 자세한 설명은 생략하겠다. Source가 별로 어
렵지 않으므로 이해하기 쉬우리라 생각한다.
-------------- < Source 3.4.2.1. clssDNS.h > -------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefDNS : public QWidget
{
Q_OBJECT
public:
clssDefDNS();
~clssDefDNS();
public slots:
void printLabelFormat(QLabel *lblDNSTitle);
void rebootSystem();
private slots:
void applySetting();
void cancelSetting();
void addDNS();
void delDNS();
private:
QLabel *lblHostName;
QLabel *lblDomainName;
QLineEdit *leHostName;
QLineEdit *leDomainName;
QLabel *lblDNSServer;
QComboBox *cbDNSServer;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frWorkArea;
QLabel *lblSeparator;
QPushButton *bttnAdd;
QPushButton *bttnDel;
QLabel *lblDNSTitle;
};
----------------------------------------------------------------
-------------- < Source 3.4.2.2. clssDNS.cpp > -----------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <stdio.h>
#include <stdlib.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssDNS.h"
clssDefDNS::clssDefDNS()
{
char *pszNetmask, *pszHostName, *pszDomainName;
int i, j;
NetTab pNet;
if (((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
/* Hostname과 Domainname을 얻는다. */
getCurrentHostName(pszHostName, pszDomainName);
/***********************/
lblDNSTitle = new QLabel("DNS Setting (DNS 설정)", this);
lblDNSTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblDNSTitle);
frWorkArea = new QFrame(this);
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
frWorkArea->setGeometry(30, 30, 330, 430);
/******** Ethernet Card 0 ********/
lblHostName = new QLabel("호스트명", frWorkArea);
lblHostName->setGeometry(20, 50, 80, 20);
leHostName = new QLineEdit(frWorkArea);
leHostName->setGeometry(100, 50, 180, 20);
leHostName->setText(pszHostName);
lblDomainName = new QLabel("도메인명", frWorkArea);
lblDomainName->setGeometry(20, 80, 80, 20);
leDomainName = new QLineEdit(frWorkArea);
leDomainName->setGeometry(100, 80, 180, 20);
leDomainName->setText(pszDomainName);
bttnApply = new QPushButton("적 용", frWorkArea);
bttnApply->setGeometry(50, 160, 80, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this,
SLOT(applySetting()));
bttnCancel = new QPushButton("취 소", frWorkArea);
bttnCancel->setGeometry(180, 160, 80, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(cancelSetting()));
/*************************************/
lblSeparator = new QLabel(frWorkArea);
lblSeparator->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
lblSeparator->setGeometry(20, 230, 290, 2);
lblDNSServer = new QLabel("DNS서버", frWorkArea);
lblDNSServer->setGeometry(20, 280, 80, 20);
cbDNSServer = new QComboBox(TRUE, frWorkArea, "comboBox_DNS");
cbDNSServer->setGeometry(100, 280, 150, 20);
char *pszDNSServer[50];
int nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
for (i = 0; i < 50; i++)
{
if ((pszDNSServer[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszDNSServer[i], '\0', 200);
}
/* DNSServer의 이름을 얻고 그들을 콤보박스에 삽입한다. */
getDNSServer(pszDNSServer);
for (i = 0; i < nCntDNS-1; i++)
cbDNSServer->insertItem(pszDNSServer[i]);
cbDNSServer->setAutoResize(FALSE);
for (i = 0; i < 50; i++)
free(pszDNSServer[i]);
bttnAdd = new QPushButton("추 가", frWorkArea);
bttnAdd->setGeometry(50, 350, 80, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addDNS()));
bttnDel = new QPushButton("삭 제", frWorkArea);
bttnDel->setGeometry(180, 350, 80, 30);
QObject::connect(bttnDel, SIGNAL(clicked()), this, SLOT(delDNS()));
/************************************/
free(pszHostName);
free(pszDomainName);
}
clssDefDNS::~clssDefDNS()
{
int i;
delete lblHostName;
delete lblDomainName;
delete leHostName;
delete leDomainName;
delete bttnCancel;
delete bttnApply;
delete lblDNSServer;
delete cbDNSServer;
delete bttnAdd;
delete bttnDel;
delete frWorkArea;
delete lblDNSTitle;
}
/* DNS의 추가 버튼을 눌렀을 때 실행되는 함수이다. */
/* 여기서는 resolv.conf file을 다룬다. */
void clssDefDNS::addDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
if (strcmp(cbDNSServer->text(cbDNSServer->currentItem()),
cbDNSServer->currentText()) != 0)
cbDNSServer->insertItem(cbDNSServer->currentText());
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
memset(pszTmpInsert, '\0', 100);
sprintf(pszTmpInsert, "nameserver %s\n",
cbDNSServer->currentText());
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->currentText());
/* 만약 resolv.conf에서 pszTempSearch에 저장되어있는 문 */
/* 자열을 찾지 못했다면 */
if (!searchStrInFile(pszTmpSearch,
"/etc/resolv.conf", 100, 100))
/* resolv.conf에서 pszTmpSearch문자열이 있다면 그 라 */
/* 인을 pszTmpInsert문자열로 바꾸고, 없다면 file */
/* 마지막 부분에 pszTmpInsert문자열을 라인단위로 */
/* 삽입하라. */
addOnNotExistChangeOnExist(pszTmpInsert, pszTmpSearch,
"/etc/resolv.conf", 100, 100);
}
}
/* DNS의 삭제버튼을 눌렀을 때 실행되는 함수이다. */
/* addDNS()와 비슷하다. */
void clssDefDNS::delDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->text(cbDNSServer->currentItem()));
if (!searchStrInFile(pszTmpSearch,
"/etc/resolve.conf", 100, 100))
/* pszTmpSearch문자열을 찾았다면 그 라인을 공백문자 */
/* 열로 바꾸어라. */
insertStrToFile("", pszTmpSearch, "/etc/resolv.conf",
100, 100);
cbDNSServer->removeItem(cbDNSServer->currentItem());
cbDNSServer->setCurrentItem(0);
}
}
/* Hostname 혹은 Domainname이 변경되었고 적용버튼을 눌렀을 경우 */
/* 실행되는 함수이다. */
/* Hostname 및 Domainname이 변경되었을 때는 재부팅을 해야만 변경 */
/* 된 내용을 적용시킬 수 있다. 따라서 여기서도 Hostname 혹은 */
/* Domainname을 바꿨을 경우 재부팅을 해준다. */
/* Source상 어려운 부분이 거의 없으므로 설명은 생략하겠다. */
void clssDefDNS::applySetting()
{
char *pszNetworkFile = "NETWORKING=yes\nFORWARD_IPV4=true\n\
HOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszGateway[18];
char pszOptions[95];
char *pszSaveCardLine[3];
FILE *fp;
S_Addr pAddr;
char pszTmpSearch[100], pszTmpInsert[100];
char pszSaveIP[18], pszSaveHostName[256], pszSaveDomainName[256];
int i;
char pszCommand[200];
memset(pszSaveIP, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentIPAddr(pszSaveIP);
getCurrentGateway(pszGateway);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, leHostName->text(), leDomainName->text(),
leDomainName->text(), pszGateway);
fclose(fp);
/**** update named daemon ****/
if (strlen(leHostName->text()) >= 1)
{
pAddr = separateAddress(pszSaveIP);
/*** HOSTNAME Host,Domain changed ***/
char pszTmpDomain[100];
char pszTmpHost[50];
memset(pszTmpInsert, '\0', 100);
memset(pszTmpHost, '\0', 50);
memset(pszTmpDomain, '\0', 100);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
sprintf(pszTmpInsert, "%s.%s\n", pszTmpHost, pszTmpDomain);
addOnNotExistChangeOnExist(pszTmpInsert, pszSaveHostName,
"/etc/HOSTNAME", 100, 100);
memset(pszTmpDomain, '\0', 100);
memset(pszTmpHost, '\0', 50);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
if (strcmp(pszSaveDomainName, pszTmpDomain) != 0 ||
strcmp(pszSaveHostName, pszTmpHost) != 0)
{
QWidget *wdgtRebooting = new QWidget();
wdgtRebooting->setGeometry(300, 300, 300, 150);
QLabel *lblRebooting = new QLabel(
"호스트이름 혹은 도메인 이름이 바뀌었으므로\n재부팅을 하겠습니다.",
wdgtRebooting);
lblRebooting->setGeometry(20, 20, 250, 50);
QPushButton *bttnRebooting = new QPushButton("재 부 팅",
wdgtRebooting);
bttnRebooting->setGeometry(120, 90, 120, 30);
QObject::connect(bttnRebooting, SIGNAL(clicked()), this,
SLOT(rebootSystem()));
wdgtRebooting->show();
}
}
system(
"/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network restart\n");
}
void clssDefDNS::cancelSetting()
{
char *pszHostName, *pszDomainName;
char *pszSaveListStr[2];
if (((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
leHostName->setText(pszHostName);
leDomainName->setText(pszDomainName);
}
void clssDefDNS::rebootSystem()
{
system("sync;sync;sync;sync;sync;init 6\n");
}
void clssDefDNS::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(),
n.dark(), n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
-------------- < Source 3.4.2.3. Network_menu.h > --------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
};
----------------------------------------------------------------
-------------- < Source 3.4.2.4. Network_menu.cpp > ------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
//#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
--------------------- < Makefile 3.4.2. > ----------------------
3.4.1의 Makefile과 마찬가지로 clssDNS_moc.cpp, clssDNS.cpp,
clssDNS.h등을 설정해준다.
----------------------------------------------------------------
3.4.3. IP-Aliasing관리
IP-Aliasing에 대해서는 3.3장에서 어느정도 설명은 했으므로 이곳에
서는 3.3장에서 설명되지 않은 부분들만을 주석처리하겠다.
-------------- < Source 3.4.3.1 clssAlias.h > ------------------
#include <qwidget.h>
class QLineEdit;
class QLabel;
class QLineEdit;
class QListView;
class QListViewItem;
class QFrame;
class QPushButton;
class clssDefAlias : public QWidget
{
Q_OBJECT
public:
clssDefAlias();
~clssDefAlias();
public slots:
void addSetting();
void deleteSetting();
void getAliasingItem();
void printLabelFormat(QLabel *lblAliasingTitle);
private slots:
private:
QFrame *frWorkArea;
QPushButton *bttnAdd;
QPushButton *bttnDelete;
QFrame *frAliasList;
QListView *lvAliasList;
QListViewItem *lviAlias[100];
QLabel *lblNetworkArea;
QLabel *lblIP;
QLineEdit *leIP;
QLabel *lblNetmask;
QLineEdit *leNetmask;
QLabel *lblNetwork;
QLineEdit *leNetwork;
QLabel *lblBroadcast;
QLineEdit *leBroadcast;
QLabel *lblAliasingTitle;
int nAliasCount;
};
----------------------------------------------------------------
-------------- < Source 3.4.3.2 clssAlias.cpp > ----------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <qframe.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlistview.h>
#include <stdio.h>
#include <stdlib.h>
#include "proc_file.h"
#include "network.h"
#include "clssAlias.h"
clssDefAlias::clssDefAlias()
{
int i;
char pszSaveFile[100];
char pszVirtualIP[18];
FILE *fp;
for (nAliasCount = 0; nAliasCount < 10; nAliasCount++)
{
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nAliasCount);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
break;
fclose(fp);
}
lblAliasingTitle = new QLabel("Virtual LAN (가상 네트워크 카드 설정)",
this);
lblAliasingTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblAliasingTitle);
frWorkArea = new QFrame(this, "IP Aliasing Area");
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised |
QFrame::Plain);
frWorkArea->setGeometry(40, 60, 670, 310);
lblNetworkArea = new QLabel("네트워크영역 선택", frWorkArea);
lblNetworkArea->setGeometry(30, 20, 120, 20);
frAliasList = new QFrame(frWorkArea, "Alias List Area");
frAliasList->setFrameStyle(QFrame::Box | QFrame::Sunken |
QFrame::WinPanel);
frAliasList->setGeometry(30, 60, 320, 220);
lvAliasList = new QListView(frAliasList);
lvAliasList->setGeometry(3, 3, 314, 214);
lvAliasList->addColumn(" 가상 네트워크 ");
lvAliasList->addColumn(" IP 주소 ");
lvAliasList->setRootIsDecorated(true);
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
/* Aliasing된 IP를 얻는다. i는 index이다. */
/* 3.3에서 설명한 바와 같이 만약 i에 2가 넘겨 */
/* 진다면 ifcfg-eth0:1에 관한, 즉, eth0:2 Card */
/* 에 대응하는 IP를 얻게 될 것이다. */
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
QObject::connect(lvAliasList, SIGNAL(selectionChanged()), this,
SLOT(getAliasingItem()));
lblIP = new QLabel("IP 주소", frWorkArea);
lblIP->setGeometry(400, 60, 70, 20);
leIP = new QLineEdit(frWorkArea);
leIP->setGeometry(480, 60, 130, 20);
lblNetmask = new QLabel("넷마스크", frWorkArea);
lblNetmask->setGeometry(400, 100, 70, 20);
leNetmask = new QLineEdit(frWorkArea);
leNetmask->setGeometry(480, 100, 130, 20);
leNetmask->setEnabled(false);
lblNetwork = new QLabel("네트워크", frWorkArea);
lblNetwork->setGeometry(400, 140, 70, 20);
leNetwork = new QLineEdit(frWorkArea);
leNetwork->setGeometry(480, 140, 130, 20);
leNetwork->setEnabled(false);
lblBroadcast = new QLabel("브로드캐스트", frWorkArea);
lblBroadcast->setGeometry(400, 180, 70, 20);
leBroadcast = new QLineEdit(frWorkArea);
leBroadcast->setGeometry(480, 180, 130, 20);
leBroadcast->setEnabled(false);
bttnAdd = new QPushButton("추가", this);
bttnAdd->setGeometry(100, 410, 150, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this,
SLOT(addSetting()));
bttnDelete = new QPushButton("삭제", this);
bttnDelete->setGeometry(480, 410, 150, 30);
QObject::connect(bttnDelete, SIGNAL(clicked()), this,
SLOT(deleteSetting()));
}
clssDefAlias::~clssDefAlias()
{
int i;
delete lblNetworkArea;
if (nAliasCount > 0)
for (i = 0; i < nAliasCount; i++)
lviAlias[i];
delete lvAliasList;
delete lblIP;
delete leIP;
delete lblNetmask;
delete leNetmask;
delete lblNetwork;
delete leNetwork;
delete lblBroadcast;
delete leBroadcast;
delete frAliasList;
delete frWorkArea;
delete bttnAdd;
delete bttnDelete;
delete lblAliasingTitle;
}
void clssDefAlias::getAliasingItem()
{
char pszNetmask[18];
NetTab pNet;
memset(pszNetmask, '\0', 18);
getCurrentNetmask(pszNetmask);
leIP->setText(lvAliasList->currentItem()->text(1));
pNet = calculateNetMaskTab((char *)leIP->text(), pszNetmask);
leNetmask->setText(pszNetmask);
leNetwork->setText(pNet.pszNetwork);
leBroadcast->setText(pNet.pszBroadcast);
}
void clssDefAlias::addSetting()
{
FILE *fp;
char pszVirtualCard[10], pszFile[100];
char pszCommand[150];
memset(pszVirtualCard, '\0', 10);
memset(pszFile, '\0', 100);
sprintf(pszVirtualCard, "eth0:%d", nAliasCount);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-%s",
pszVirtualCard);
lviAlias[nAliasCount] = new QListViewItem(lvAliasList,
pszVirtualCard, leIP->text());
if ((fp = fopen(pszFile, "w")) == NULL)
{
emit printf("file open error!\n");
exit(1);
}
fprintf(fp, "DEVICE=%s\nIPADDR=%s\nONBOOT=yes\n",
pszVirtualCard, leIP->text());
fclose(fp);
nAliasCount++;
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::deleteSetting()
{
int i, j;
char pszCommand[150], pszFile[100];
char pszVirtualIP[18];
FILE *fp;
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
lvAliasList->itemPos(lvAliasList->currentItem())/18);
if ((fp = fopen(pszFile, "r")) == NULL)
return;
fclose(fp);
nAliasCount--;
memset(pszCommand, '\0', 150);
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:*");
sprintf(pszCommand, "rm -f %s\n", pszFile);
system(pszCommand);
if (nAliasCount > 0)
{
for (i = 0, j = 0; i < nAliasCount+1; i++)
{
if (i != lvAliasList->itemPos(lvAliasList->currentItem())/18)
{
memset(pszFile, '\0', 100);
sprintf(pszFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", j);
if ((fp = fopen(pszFile, "w")) == NULL)
return;
fprintf(fp, "DEVICE=eth0:%d\nIPADDR=%s\nONBOOT=yes\n",
j, lviAlias[i]->text(1));
fclose(fp);
j++;
}
}
}
/* 여기서 clear시키게 되면 List에 있던 모든 항목들이 지워 */
/* 지게 된다. 그리고 나서 다시 필요한 항목을 삽입시키면 */
/* 마치 refresh하는 효과를 얻을 수 있다. 이렇게 함으로써 */
/* 특정 item의 삭제가 가능해진다. 물론 이러한 방법은 단점 */
/* 이 남는다. 만약 List에 있는 item의 개수가 몇개 안될 때 */
/* 는 clear했다가 다시 item들을 삽입시켜도 system이 충분히 */
/* 속도를 감당해낼 수 있지만 item의 개수가 수십, 수백, 수천 */
/* 개일 경우는 틀려진다. refresh되는 과정이 그대로 보이게 */
/* 되므로 약간 짜증이 날 수도 있다는 것이다. */
/* 따라서 이부분에 대한 수정을 권하고 싶다. Qt에서는 특 */
/* 정 item에 대한 삭제함수가 있다. 이 함수를 쓰기 바란다. */
/* 함수 사용법도 간단하므로 사용하기 쉬울 것이다. */
/* /usr/lib/qt/include/qlistview.h에 보면 QListViewItem */
/* class에 removeItem과 QListView class에 repaint함수가 있 */
/* 다 이들을 적절하게 이용하면 될 것이다. */
lvAliasList->clear();
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
----------------------------------------------------------------
-------------- < Source 3.4.3.3 Network_menu.h > ---------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssDefAlias;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
clssDefAlias *clssAlias;
};
----------------------------------------------------------------
------------ < Source 3.4.3.4 Network_menu.cpp > ---------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric,
GENERIC_TOOLTIP, 0, this, SLOT(funcGenericNetwork()),
tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0,
this, SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP,
0, this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
clssAlias = new clssDefAlias();
clssAlias->setGeometry(150, 150, 750, 500);
clssAlias->show();
}
void clssNetwork::funcQuit()
{
exit(0);
}
----------------------------------------------------------------
------------ < Source 3.4.3.5 main_menu.cpp > ------------------
#include <qapplication.h>
#include "Network_menu.h"
char pszNetConfHost[256];
char pszNetConfDomain[256];
char pszNetConfGateway[18];
char pszNetConfIPAddr[18];
char pszNetConfPrivate1IPAddr[18];
char pszNetConfPrivate2IPAddr[18];
char pszNetConfNetmask[18];
char pszNetConfPrivate1Netmask[18];
char pszNetConfPrivate2Netmask[18];
char pszNetconfBroadcast[18];
char pszNetconfPrivate1Broadcast[18];
char pszNetconfPrivate2Broadcast[18];
char pszNetConfNetwork[18];
char pszNetConfPrivate1Network[18];
char pszNetConfPrivate2Network[18];
char pszNetConfNetCard[3][30];
int nCountListStr;
char pszSaveNameServer[20][30];
int nCountNameServer;
int nCountClient;
extern int nAccountCount;
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
----------------------------------------------------------------
--------------------- < Makefile 3.4.3. > ----------------------
3.4.1의 Makefile과 마찬가지로 clssAlias_moc.cpp, clssAlias.cpp,
clssAlias.h등을 설정해준다.
----------------------------------------------------------------
자. 이로서 모든 과정이 다 끝났다. 부족한 부분이야 수도 없이 많지만
더욱 완벽한 Source는 다음에 올리기로 하고 이쯤에서 Project에 대한
모든 설명은 이만 접기로 하겠다. 이 자료를 보시는 분들께 꼭 한마디 하
고 다음 전체 Source를 쓰기로 하겠다. 우선 이 자료를 Qt를 공부하기 위
해 보시는 분들이라면 제일 먼저 꼭 밑에 있는 전체 Source를 file로 저장
해 compile하고 실행시키시기 바란다. 보통 GUI에 대한 공부는 설명이 먼
저가 아니라 눈으로 보는것이 선행되어야한다.
꼭 먼저 이 Project를 눈으로 확인 해보시기 바란다.
------------------------------------------------------------------------
< *** 전체 Source *** >
// ------------------- < Source : network.h > ---------------------
#ifndef _NETWORK_H
#define _NETWORK_H
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef MAX_LINE
#define MAX_LINE 100
#define MAX_COL 1000
#endif
#ifndef NO_SETTING
#define NO_SETTING "셋팅되어있지 않습니다."
#endif
extern char pszNetConfHost[256];
extern char pszNetConfDomain[256];
extern char pszNetConfGateway[18];
extern char pszNetConfIPAddr[18];
extern char pszNetConfPrivate1IPAddr[18];
extern char pszNetConfPrivate2IPAddr[18];
extern char pszNetConfNetmask[18];
extern char pszNetConfPrivate1Netmask[18];
extern char pszNetConfPrivate2Netmask[18];
extern char pszNetconfBroadcast[18];
extern char pszNetconfPrivate1Broadcast[18];
extern char pszNetconfPrivate2Broadcast[18];
extern char pszNetConfNetwork[18];
extern char pszNetConfPrivate1Network[18];
extern char pszNetConfPrivate2Network[18];
extern char pszNetConfNetCard[3][30];
extern int nCountListStr;
extern char pszSaveNameServer[20][30];
extern int nCountNameServer;
extern int nCountClient;
extern int nAccountCount;
typedef struct tagNETMASKTAB {
char pszNetwork[18];
char pszBroadcast[18];
} NetTab;
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask);
typedef struct tagSEPADDR {
char pszFirst[6];
char pszSecond[6];
char pszThird[6];
char pszFourth[6];
} S_Addr;
S_Addr separateAddress(char *pszAddr);
char *calculateDate(void);
void getCurrentNetmask(char *pszNetmask);
void getCurrentGateway(char *pszGateway);
void getCurrentHostName(char *pszHostName, char *pszDomainName);
void getCurrentIPAddr(char *pszIPAddr);
void getPrivate1Netmask(char *pszPrivateNetmask);
void getPrivate1IPAddr(char *pszPrivateIPAddr);
void getPrivate2Netmask(char *pszPrivateNetmask);
void getPrivate2IPAddr(char *pszPrivateIPAddr);
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nCardIdx);
void getDNSServer(char *pszDNSServer[]);
void getAliasNetmask(char *pszNetmask, int nIdx);
void getAliasIP(char *pszIPAddr, int nIdx);
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[]);
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth, int nRange);
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange);
#endif
// ----------------------------------------------------------------
// ------------------- < Source : network.c > ---------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include "network.h"
#include "proc_file.h"
/*************** Calculate Netmask table **************/
NetTab calculateNetMaskTab(char *pszIPAddr, char *pszNetmask)
{
struct in_addr IP;
struct in_addr Mask;
struct in_addr pNetwork;
struct in_addr pBroadcast;
NetTab pNet;
memset(pNet.pszNetwork, '\0', 18);
memset(pNet.pszBroadcast, '\0', 18);
IP.s_addr = inet_addr(pszIPAddr);
Mask.s_addr = inet_addr(pszNetmask);
pNetwork.s_addr = IP.s_addr & Mask.s_addr;
memcpy(pNet.pszNetwork, inet_ntoa(pNetwork), 18);
pBroadcast.s_addr = pNetwork.s_addr | ~Mask.s_addr;
memcpy(pNet.pszBroadcast, inet_ntoa(pBroadcast), 18);
return pNet;
}
/***************************************/
S_Addr separateAddress(char *pszAddr)
{
int i = 0, j = 0, k = 0;
S_Addr pAddr;
memset(pAddr.pszFirst, '\0', 6);
memset(pAddr.pszSecond, '\0', 6);
memset(pAddr.pszThird, '\0', 6);
memset(pAddr.pszFourth, '\0', 6);
for (k = 0; *(pszAddr+i) != '\0'; i++, k++)
{
if (*(pszAddr+i) == '.')
{
i++;
k = 0;
j++;
}
switch (j)
{
case 0:
pAddr.pszFirst[k] = *(pszAddr+i);
break;
case 1:
pAddr.pszSecond[k] = *(pszAddr+i);
break;
case 2:
pAddr.pszThird[k] = *(pszAddr+i);
break;
case 3:
pAddr.pszFourth[k] = *(pszAddr+i);
break;
default:
break;
}
}
return pAddr;
}
char pszDate[11];
char *calculateDate()
{
time_t tTime;
int i;
memset(pszDate, '\0', 11);
tTime = time(NULL);
for (i = 0; i < 4; i++)
pszDate[i] = *(ctime(&tTime)+20+i);
for (i = 0; i < 3; i++)
pszDate[i+4] = *(ctime(&tTime)+4+i);
for (i = 0; i < 2; i++)
pszDate[i+4+3] = *(ctime(&tTime)+8+i);
return pszDate;
}
void getCurrentNetmask(char *pszNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszNetmask[i] = pszSave[i+8];
pszNetmask[i-1] = '\0';
}
void getCurrentGateway(char *pszGateway)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network", "r")) == NULL)
return;
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "GATEWAY="));
for (i = 0; pszSave[i+8] != 'G'; i++)
pszGateway[i] = pszSave[i+8];
pszGateway[i-1] = '\0';
}
void getPrivate1Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) == NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate1IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "r")) == NULL)
{
// strcpy(pszPrivateIPAddr, "172.31.0.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getPrivate2Netmask(char *pszPrivateNetmask)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) == NULL)
{
// strcpy(pszPrivateNetmask, "255.255.0.0");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "NETMASK="));
for (i = 0; pszSave[i+8] != 'N'; i++)
pszPrivateNetmask[i] = pszSave[i+8];
pszPrivateNetmask[i-1] = '\0';
}
void getPrivate2IPAddr(char *pszPrivateIPAddr)
{
int i = 0;
char pszSaveFile[1024];
char pszSave[1024];
FILE *fp;
memset(pszSaveFile, '\0', 1024);
memset(pszSave, '\0', 1024);
if ((fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "r")) == NULL)
{
// strcpy(pszPrivateIPAddr, "192.168.1.1");
return;
}
while ((pszSaveFile[i] = fgetc(fp)) != EOF)
i++;
fclose(fp);
strcpy(pszSave, (char *)strstr(pszSaveFile, "IPADDR="));
for (i = 0; pszSave[i+7] != 'N'; i++)
pszPrivateIPAddr[i] = pszSave[i+7];
pszPrivateIPAddr[i-1] = '\0';
}
void getCurrentHostName(char *pszHostName, char *pszDomainName)
{
struct utsname name;
int i, j;
uname(&name);
for (i = 0; name.nodename[i] != '.'; i++)
pszHostName[i] = name.nodename[i];
i++;
for (j = 0; name.nodename[i] != '\0'; i++, j++)
pszDomainName[j] = name.nodename[i];
}
void getCurrentIPAddr(char *pszIPAddr)
{
char *pszSaveListStr[20];
int i;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
saveSearchLineToFile("IPADDR", pszSaveListStr,
"/etc/sysconfig/network-scripts/ifcfg-eth0", 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getNetCardIoIrq(char *pszIo, char *pszIrq, int nNetCardIdx)
{
int i;
char *pszPosIo, *pszPosIrq;
int nIrqIdx, nIoIdx;
char *pszTmpStr = "options eth%d";
char pszOptionStr[30];
char *pszSaveListStr[3];
for (i = 0; i < 3; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
memset(pszSaveListStr[i], '\0', 200);
exit(1);
}
}
memset(pszOptionStr, '\0', 30);
sprintf(pszOptionStr, pszTmpStr, nNetCardIdx);
saveSearchLineToFile(pszOptionStr, pszSaveListStr, "/etc/conf.modules",
200, 200);
pszPosIo = strstr(pszSaveListStr[0], "0x");
nIoIdx = pszPosIo-pszSaveListStr[0];
pszPosIrq = strstr(pszSaveListStr[0], "irq=");
nIrqIdx = pszPosIrq-pszSaveListStr[0];
for (i = nIoIdx-1; i < nIrqIdx-4; i++)
pszIo[i-nIoIdx+1] = pszSaveListStr[0][i+3];
for (i = nIrqIdx; pszSaveListStr[0][i+4] != '\n'; i++)
pszIrq[i-nIrqIdx] = pszSaveListStr[0][i+4];
for (i = 0; i < 3; i++)
free(pszSaveListStr[i]);
}
void getDNSServer(char *pszDNSServer[])
{
char *pszSaveListStr[50];
int i;
int nCntDNS;
for (i = 0; i < 50; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
saveSearchLineToFile("nameserver", pszSaveListStr, "/etc/resolv.conf",
50, 200);
nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
nCntDNS--;
for (i = 0; i < nCntDNS; i++)
{
strcpy(pszDNSServer[i], pszSaveListStr[i]+11);
pszDNSServer[i][strlen(pszDNSServer[i])-1] = '\0';
}
for (i = 0; i < 50; i++)
free(pszSaveListStr[i]);
}
void getAliasIP(char *pszIPAddr, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("IPADDR", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+7] != '\n'; i++)
pszIPAddr[i] = pszSaveListStr[0][i+7];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getAliasNetmask(char *pszNetmask, int nIdx)
{
char *pszSaveListStr[20];
int i, j = 0;
char pszSaveFile[100];
FILE *fp;
for (i = 0; i < 20; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*80);
memset(pszSaveListStr[i], '\0', 80);
}
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d", nIdx);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
{
printf("File Open Error!\n");
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
return;
}
fclose(fp);
saveSearchLineToFile("NETMASK", pszSaveListStr, pszSaveFile, 20, 80);
for (i = 0; pszSaveListStr[0][i+8] != '\n'; i++)
pszNetmask[i] = pszSaveListStr[0][i+8];
for (i = 0; i < 20; i++)
free(pszSaveListStr[i]);
}
void getEthNetworkCard(char *pszSaveNetCard[], char *pszCardInfo[])
{
FILE *fp;
int i, j, nIdx, nCount, nCardCount = 0;
char *pszSaveListStr[100];
char *pszSaveLine[4];
if ((fp = fopen("/proc/interrupts", "r")) == NULL)
{
printf("file open error!\n");
return;
}
fclose(fp);
for (i = 0; i < 4; i++)
{
if ((pszSaveLine[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveLine[i], '\0', 200);
}
for (i = 0; i < 100; i++)
{
if ((pszSaveListStr[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("memory allocation error!\n");
exit(1);
}
memset(pszSaveListStr[i], '\0', 200);
}
nCount = saveAllLineToFile(pszSaveListStr, "/proc/interrupts", 100, 200);
for (i = 0, nIdx = 0; i < nCount; i++)
{
for (j = 0; j < 40; j++)
{
if (strstr(pszSaveListStr[i], pszCardInfo[j]) != (char *)NULL)
{
nCardCount++;
strcpy(pszSaveLine[nIdx++], pszSaveListStr[i]);
break;
}
}
}
if (nCardCount == 0)
{
strcpy(pszSaveNetCard[0], NO_SETTING);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 1)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], NO_SETTING);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else if (nCardCount == 2)
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], NO_SETTING);
}
else
{
strcpy(pszSaveNetCard[0], pszSaveLine[0]+33);
strcpy(pszSaveNetCard[1], pszSaveLine[1]+33);
strcpy(pszSaveNetCard[2], pszSaveLine[2]+33);
}
for (i = 0; i < 4; i++)
free(pszSaveLine[i]);
for (i = 0; i < 100; i++)
free(pszSaveListStr[i]);
}
void calcIPRange(char *pszStartIP, char *pszEndIP, int nIPFourth, int nRange)
{
char pszSaveStartIP[4], pszSaveEndIP[4];
memset(pszSaveStartIP, '\0', 4);
memset(pszSaveEndIP, '\0', 4);
if (nIPFourth%nRange != 0)
{
sprintf(pszSaveStartIP, "%d", (nIPFourth/nRange)*nRange);
sprintf(pszSaveEndIP, "%d", (nIPFourth/nRange)*nRange+nRange-1);
}
else
{
sprintf(pszSaveStartIP, "%d", nIPFourth);
sprintf(pszSaveEndIP, "%d", nIPFourth+nRange-1);
}
strcat(pszStartIP, pszSaveStartIP);
strcat(pszEndIP, pszSaveEndIP);
}
void calcIPDiffToRange(char *pszStartIP, char *pszEndIP, int *nRange)
{
S_Addr pAddr;
int i, nSaveRange;
int nStart, nEnd;
pAddr = separateAddress(pszStartIP);
nStart = atoi(pAddr.pszFourth);
pAddr = separateAddress(pszEndIP);
nEnd = atoi(pAddr.pszFourth);
nSaveRange = nEnd-nStart+1;
for (i = 0; nSaveRange > 0; i++)
nSaveRange /= 2;
*nRange = 32-(i-1);
}
// ----------------------------------------------------------------
// ------------------- < Source : proc_file.h > -------------------
#include <stdio.h>
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#ifndef SUCCESS
#define SUCCESS 1
#define FAIL 0
#endif
#ifndef MAX_XXX_NUM
#define MAX_XXX_NUM 10000
#define BLACKLIST_INSERT 1
#define BLACKLIST_DELETE 0
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef _DOUBLE_LINKLIST_
#define _DOUBLE_LINKLIST_
typedef struct tagDOUBLELINK {
void *pzKey;
struct tagDOUBLELINK *next;
struct tagDOUBLELINK *prev;
} DList;
void initDL(void);
DList *searchDL(void *pzSearch);
DList *insertAsFirstDL(void *pzInsert);
DList *insertDL(void *pzInsert, DList *pIns); /* insert front node p */
DList *insertDLAsKey(void *pzInsert, void *pzSearch);
DList *insertDLAsSort(void *pzInsert);
int deleteDL(DList *pDel);
int deleteDLAsKey(void *pzSearch);
void deleteAllDL(void);
void deletePerfectDL(void);
void *printDL(DList *pPrint);
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine);
void insertStrForeSearch(char *pszSave, char *pszInsert, char *pszSearch,
char *pszLine, char *pszTempLine);
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine);
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol);
void *printToFileDL(DList *pPrint, FILE *fp);
int readOneLineSearchFile(char pszBuffer[], FILE *fp);
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void insertStrToFileLast(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol);
int countSearchLineToFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol);
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName,
int nMaxLine, int nMaxCol);
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol);
int saveSearchLineToFileWithoutComment(char *pszSearch,
char *pszSaveListStr[], char cComment, char *pszFileName,
int nMaxLine, int nMaxCol);
void changeStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void insertStrToOneLineToFile(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
int searchStrInFile(char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExistWithoutComment(char *pszIns, char *pszSearch,
char cComment, char *pszFileName, int nMaxLine, int nMaxCol);
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName, int nMaxLine, int nMaxCol);
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void attatchStrToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol);
void saveStrIdxToFileLine(char *pszSave, char *pszSearch, char *pszFileName,
int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol);
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx,
int nMaxLine, int nMaxCol);
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol);
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName,
int nLineIdx, int nColIdx, int nMaxLine, int nMaxCol);
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol);
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol);
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol);
void changeStrInFile(char *pszFile, char *pszSrc, char *pszDest,
int nStatus);
int getUserBlackList(char *pszXXXData[MAX_XXX_NUM], int nMode);
#endif
#endif
// ----------------------------------------------------------------
// ------------------- < Source : proc_file.c > -------------------
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include "proc_file.h"
DList *dblhead;
DList *dbltail;
void initDL(void)
{
dblhead = (DList *)malloc(sizeof(DList));
dbltail = (DList *)malloc(sizeof(DList));
dblhead->prev = dblhead;
dblhead->next = dbltail;
dbltail->prev = dblhead;
dbltail->next = dbltail;
}
DList *searchDL(void *pzSearch)
{
DList *s;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzSearch, sizeof(pzSearch)) == 0)
break;
s = s->next;
}
return s;
}
DList *insertAsFirstDL(void *pzInsert)
{
DList *p;
p = (DList *)malloc(sizeof(DList));
p->pzKey = pzInsert;
p->next = dblhead->next;
dblhead->next->prev = p;
dblhead->next = p;
p->prev = dblhead;
return p;
}
DList *insertAsLastDL(void *pzInsert)
{
insertDL(pzInsert, dbltail);
return (DList *)NULL;
}
DList *insertDL(void *pzInsert, DList *pIns) /* insert front node pIns */
{
DList *s;
if (pIns == dblhead)
return NULL;
s = (DList *)malloc(sizeof(DList));
s->pzKey = pzInsert;
pIns->prev->next = s;
s->prev = pIns->prev;
s->next = pIns;
pIns->prev = s;
return s;
}
DList *insertDLAsKey(void *pzInsert, void *pzSearch)
{ /* insert insk front findk */
DList *s;
DList *r = NULL;
s = searchDL(pzSearch);
if (s != dbltail)
{
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
}
return r;
}
DList *insertDLAsSort(void *pzInsert)
{
DList *s;
DList *r;
s = dblhead->next;
while (s != dbltail)
{
if (memcmp(s->pzKey, pzInsert, sizeof(pzInsert)) >= 0)
break;
s = s->next;
}
r = (DList *)malloc(sizeof(DList));
r->pzKey = pzInsert;
s->prev->next = r;
r->prev = s->prev;
r->next = s;
s->prev = r;
return r;
}
int deleteDL(DList *pDel)
{
if (pDel == dblhead || pDel == dbltail)
return FAIL;
pDel->prev->next = pDel->next;
pDel->next->prev = pDel->prev;
free(pDel);
return SUCCESS;
}
int deleteDLAsKey(void *pzSearch)
{
DList *s;
s = searchDL(pzSearch);
if (s != dbltail)
{
s->prev->next = s->next;
s->next->prev = s->prev;
free(s);
return SUCCESS;
}
return FAIL;
}
void deleteAllDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
dblhead->next = dbltail;
dbltail->prev = dblhead;
}
void deletePerfectDL(void)
{
DList *s;
DList *p;
p = dblhead->next;
while (p != dbltail)
{
s = p;
p = p->next;
free(s);
}
free(dblhead);
free(dbltail);
}
void *printDL(DList *pPrint)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
printf("%s", (char *)(pPrint->pzKey));
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
/****** Insert to FILE ******/
void deleteStrFromOneLine(char *pszSave, char *pszDel, char *pszLine)
{
char *pszPnt;
int i, nFirstLen;
if ((pszPnt = (char *)strstr(pszLine, pszDel)) == NULL)
return;
nFirstLen = pszPnt-pszLine;
for (i = 0; i < nFirstLen; i++)
pszSave[i] = pszLine[i];
for (i = nFirstLen; pszLine[i+strlen(pszDel)] != '\0'; i++)
pszSave[i] = pszLine[i+strlen(pszDel)];
pszSave[i] = '\0';
}
void insertStrForeSearch(char *pszSave, char *pszInsert,
char *pszSearch, char *pszLine, char *pszTempLine)
{
int i = 0;
int nLen;
char *pszPos;
if ((char *)strstr(pszLine, pszInsert) != NULL)
{
strcat(pszSave, pszTempLine);
return;
}
pszPos = (char *)strstr(pszLine, pszSearch);
nLen = pszPos-pszLine;
for (i = 0; i < nLen; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszInsert);
strcat(pszSave, strstr(pszLine, pszSearch));
}
void insertStrToOneLine(char *pszSave, char *pszIns, char *pszLine)
{
int nFirstPos, nSecondPos;
if ((char *)strstr(pszLine, pszIns) != NULL)
return;
for (nFirstPos = 0; nFirstPos < strlen(pszLine); nFirstPos++)
pszSave[nFirstPos] = pszLine[nFirstPos];
for (nSecondPos = 0; nSecondPos < strlen(pszIns); nSecondPos++)
pszSave[nSecondPos+nFirstPos] = pszIns[nSecondPos];
pszSave[nSecondPos+nFirstPos] = '\0';
}
void changeSearchStr(char *pszIns, char *pszSearch, char *pszLine,
char *pszSave, int nMaxCol)
{
int i = 0;
char *pszPos;
int nPos;
pszPos = (char *)strstr(pszLine, pszSearch);
nPos = pszPos-pszLine;
for (i = 0; i < nPos; i++)
pszSave[i] = pszLine[i];
strcat(pszSave, pszIns);
strcat(pszSave, pszLine+nPos+strlen(pszSearch));
pszPos = (char *)strstr(pszSave, pszSearch);
if (pszPos == NULL)
return;
memset(pszLine, '\0', nMaxCol);
strcpy(pszLine, pszSave);
memset(pszSave, '\0', nMaxCol);
changeSearchStr(pszIns, pszSearch, pszLine, pszSave, nMaxCol);
}
int nLine;
void *printToFileDL(DList *pPrint, FILE *fp)
{
pPrint = dblhead->next;
while (pPrint != dbltail)
{
fprintf(fp, pPrint->pzKey);
pPrint = pPrint->next;
}
return pPrint->pzKey;
}
int readOneLineSearchFile(char pszBuffer[], FILE *fp)
{
int i = 0;
char c = '\0';
do
{
c = getc(fp);
pszBuffer[i++] = c;
if (c == EOF || c == '\n')
break;
} while (1);
pszBuffer[i] = '\0';
nLine++;
return c;
}
void insertStrToFileLast(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
fclose(fp);
deletePerfectDL();
return;
}
}
insertAsLastDL(pszInsert);
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
}
int countAllLineToFile(char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (nCount = 0; (readOneLineSearchFile(pszBuffer[nCount], fp) != EOF) &&
(nCount < nMaxLine); nCount++);
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
int countSearchLineToFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0;
int nCount = 0;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
nCount++;
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return nCount;
}
int saveAllLineToFile(char *pszSaveListStr[], char *pszFileName, int nMaxLine,
int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return 0;
for (j = 0; j < nMaxLine; j++)
{
pszBuffer[j] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[j], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
strcpy(pszSaveListStr[i], pszBuffer[i]);
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return i;
}
int saveSearchLineToFileWithoutComment(char *pszSearch, char *pszSaveListStr[],
char cComment, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL &&
pszBuffer[i][0] != cComment)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
int saveSearchLineToFile(char *pszSearch, char *pszSaveListStr[],
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
int j = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
if ((fp = fopen(pszFileName, "r")) == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
strcpy(pszSaveListStr[j], pszBuffer[i]);
j++;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return TRUE;
}
void changeStrToOneLineToFile(char *pszIns, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0, j = 0;
FILE *fp;
char *pszLine[nMaxLine];
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
pszLine[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszLine[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
changeSearchStr(pszIns, pszSearch, pszBuffer[i], pszLine[j],
nMaxCol);
insertAsLastDL(pszLine[j]);
j++;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
{
free(pszBuffer[i]);
free(pszLine[i]);
}
}
void insertStrToOneLineToFile(char *pszIns, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertStrForeSearch(pszLine, pszIns, pszSearch, pszBuffer[i],
pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void deleteStrToOneLineToFile(char *pszDel, char *pszSearch, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char pszLine[nMaxCol];
char *pszBuffer[nMaxLine];
memset(pszLine, '\0', nMaxCol);
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
deleteStrFromOneLine(pszLine, pszDel, pszBuffer[i]);
insertAsLastDL(pszLine);
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertStrToFile(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
insertAsLastDL(pszInsert);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
int searchStrInFile(char *pszSearch, char *pszFileName, int nMaxLine,
int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return FALSE;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
fclose(fp);
return TRUE;
}
}
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return FALSE;
}
/** if Search is true, change.. else add **/
void addOnNotExistChangeOnExist(char *pszIns, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void addOnNotExistChangeOnExistWithoutComment(char *pszIns, char *pszSearch,
char cComment, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) == NULL ||
pszBuffer[i][0] == cComment)
insertAsLastDL(pszBuffer[i]);
else
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void addOnNotExistChangeOnExist2Search(char *pszIns, char *pszFirstSearch,
char *pszSecondSearch, char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
int flgAdd = TRUE;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszFirstSearch) != NULL &&
(char *)strstr(pszBuffer[i], pszSecondSearch) != NULL)
{
insertAsLastDL(pszIns);
flgAdd = FALSE;
}
else
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
if (flgAdd == TRUE)
insertAsLastDL(pszIns);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertForeSearchToFile(char *pszInsert, char *pszSearch,
char *pszFileName, int nMaxLine, int nMaxCol)
{
int i = 0;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
insertAsLastDL(pszBuffer[i]);
fclose(fp);
insertDLAsKey(pszInsert, pszSearch);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrToFileLine(char *pszInsert, char *pszSearch, char *pszFileName,
int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][strlen(pszBuffer[i])-1] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void saveStrIdxToFileLine(char *pszSave, char *pszSearch, char *pszFileName,
int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nStartIdx);
for (j = 0; j < nEndIdx-nStartIdx; j++)
pszSave[j] = pszEndBuffer[j];
}
}
fclose(fp);
}
void changeStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nStartIdx, int nEndIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
char pszEndBuffer[nMaxCol];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
memset(pszEndBuffer, '\0', nMaxCol);
strcpy(pszEndBuffer, pszBuffer[i]+nEndIdx);
pszBuffer[i][nStartIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
strcat(pszBuffer[i], pszEndBuffer);
pszBuffer[i][strlen(pszBuffer[i])] = '\0';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrIdxToFileLine(char *pszInsert, char *pszSearch,
char *pszFileName, int nIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszSearch) != NULL)
{
pszBuffer[i][nIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void attatchStrToFileIdxLine(char *pszInsert, char *pszFileName, int nLineIdx,
int nColIdx, int nMaxLine, int nMaxCol)
{
int i = 0, j;
FILE *fp;
char *pszBuffer[nMaxLine];
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if (i == nLineIdx-1)
{
pszBuffer[i][nColIdx] = '\0';
strcat(pszBuffer[i], pszInsert);
pszBuffer[i][strlen(pszBuffer[i])] = '\n';
}
insertAsLastDL(pszBuffer[i]);
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
}
void insertAfterStrToFile(char *pszInsert, char *pszStartLine,
char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
insertAsLastDL(pszInsert);
insertAsLastDL("\n");
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
insertAsLastDL(pszBuffer[j]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
void saveBetweenStrToFile(char *pszSaveLine[], char *pszStartLine,
char *pszEndLine, char *pszFileName, int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
{
if ((char *)strstr(pszBuffer[j], pszEndLine) == NULL)
strcpy(pszSaveLine[j-(i+1)], pszBuffer[j]);
else
break;
}
fclose(fp);
for (j = 0; j < nMaxLine; j++)
free(pszBuffer[j]);
return;
}
}
}
void changeBetweenStrToFile(char *pszInsert[], int nInsertNum,
char *pszStartLine, char *pszEndLine, char *pszFileName,
int nMaxLine, int nMaxCol)
{
char *pszBuffer[nMaxLine];
int i = 0, j, k;
FILE *fp;
nLine = 0;
fp = fopen(pszFileName, "r");
if (fp == NULL)
return;
for (i = 0; i < nMaxLine; i++)
{
pszBuffer[i] = (char *)malloc(sizeof(char)*nMaxCol);
memset(pszBuffer[i], '\0', nMaxCol);
}
initDL();
for (i = 0; readOneLineSearchFile(pszBuffer[i], fp) != EOF; i++)
{
insertAsLastDL(pszBuffer[i]);
if ((char *)strstr(pszBuffer[i], pszStartLine) != NULL)
{
for (j = i+1; readOneLineSearchFile(pszBuffer[j], fp) != EOF; j++)
if ((char *)strstr(pszBuffer[j], pszEndLine) != NULL)
break;
for (k = 0; k < nInsertNum; k++)
insertAsLastDL(pszInsert[k]);
insertAsLastDL(pszBuffer[j]);
for (k = j+1; readOneLineSearchFile(pszBuffer[k], fp) != EOF; k++)
insertAsLastDL(pszBuffer[k]);
break;
}
}
fclose(fp);
fp = fopen(pszFileName, "w");
printToFileDL(dblhead->next, fp);
deletePerfectDL();
fclose(fp);
for (i = 0; i < nMaxLine; i++)
free(pszBuffer[i]);
return;
}
// ----------------------------------------------------------------
// ---------------- < Source : clssGeneric.h > --------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefGeneric : public QWidget
{
Q_OBJECT
public:
clssDefGeneric();
~clssDefGeneric();
private slots:
void setApply();
void setCancel();
void printLabelFormat(QLabel *lblBold);
private:
QLabel *lblGenericNetworkTitle;
QLabel *lblGateway;
QLineEdit *leGateway;
QLabel *lblEth0;
QLabel *lblEth0IPAddr;
QLineEdit *leEth0IPAddr;
QLabel *lblEth0Netmask;
QLineEdit *leEth0Netmask;
QLabel *lblEth0Network;
QLineEdit *leEth0Network;
QLabel *lblEth0Broadcast;
QLineEdit *leEth0Broadcast;
QLabel *lblEth0NetCard;
QComboBox *cbEthNetCard[3]; /* to combobox */
QLabel *lblEth1;
QLineEdit *leEth1IPAddr;
QLineEdit *leEth1Netmask;
QLineEdit *leEth1Network;
QLineEdit *leEth1Broadcast;
QLabel *lblEth1NetCard;
QLabel *lblEth2;
QLineEdit *leEth2IPAddr;
QLineEdit *leEth2Netmask;
QLineEdit *leEth2Network;
QLineEdit *leEth2Broadcast;
QLabel *lblEth2NetCard;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frEthInfo;
QLabel *lblSeparator1;
QLabel *lblSeparator2;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssGeneric.cpp > ------------------
#include <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <qpalette.h>
#include <stdio.h>
#include <stdlib.h>
/* test */
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include "network.h"
#include "proc_file.h"
#include "clssGeneric.h"
clssDefGeneric::clssDefGeneric()
{
char *pszIPAddr, *pszNetmask, *pszGateway;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
int i, j, nCardIdx;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
const char *pszNetCard[40] = {
" 3Com Vortex series (3c590, 3c592, 3c597, 3c595) (3c59x) ",
" 3Com Boomerang (3c900, 3c905, 3c575) (3c59x) ",
" 3Com Cyclone (3c905B) (3c59x) ",
" Intel EtherExpress Pro 100 (eepro100) ",
" HP J2585B, J2585A, J2970, J2973 (hp100) ",
" HP J2573 (hp100) ",
" Compex ReadyLink ENET100-VG4 (hp100) ",
" Compex FreedomLine 100/VG (hp100) ",
" IBM token ring (ibmtr) ",
" NE2000 (PCI) (ne2k-pci) ",
" AMD PCnet/PCI 79C970/PCnet32/PCnet/PCI II 79C970A (pcnet32) ",
" PCnet/PCI II 79C971A (pcnet32) ",
" Allied Telesyn AT2550 (rtl8139) ",
" Genius GF100TXR (RTL8139) (rtl8139) ",
" NDC Communications NE100TX-E (rtl8139) ",
" RealTek RTL8129/8139 Fast (rtl8139) ",
" SMC Ultra/SMC UltraEZ/SMC Ultra32 (smc-ultra) ",
" Compaq Netelligent 10 T PCI UTP (tlan) ",
" Compaq Netelligent 10/100 TX PCI UTP (tlan) ",
" Compaq Netelligent Integrated 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10/100 TX Embedded UTP (tlan) ",
" Compaq Netelligent 10/100 TX UTP (tlan) ",
" Compaq Netelligent 10 T/2 PCI UTP/Coax (tlan) ",
" Accton EtherDuo PCI/Accton EN1207 (tulip) ",
" Adaptec ANA6901/C/Adaptec ANA6911/TX (tulip) ",
" C-NET CNE-935 (tulip) ",
" Cogent EM100/Cogent EM110/Cogent EM400 (tulip) ",
" Cogent EM960/Cogent EM964 Quartet (tulip) ",
" Danpex EN-9400P3 (tulip) ",
" D-Link DFE500-Tx/D-Link DE-530CT (tulip) ",
" Linksys EtherPCI (tulip) ",
" Kingston EtherX KNT40T/Kingston EtherX KNE100TX (tulip) ",
" Netgear FX310 TX 10/100 (tulip) ",
" SMC EtherPower/SMC 8432BT/ SMC Ether Power10/100 (tulip) ",
" Surecom EP-320X (tulip) ",
" Thomas Conrad TC5048 (tulip) ",
" Znyx ZX312 EtherAction/Znyx ZX314/ZX315 (tulip) ",
" Znyx ZX342/ZX344/ZX345/ZX346/ZX348 (tulip) ",
" Znyx ZX351 (tulip) ",
" 세팅되어있지 않습니다! (No Setting)"
};
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr, pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr, pszPrivate2Netmask);
/***********************/
lblGenericNetworkTitle = new QLabel(
"Network Setting (일반적인 네트워크 설정)", this);
lblGenericNetworkTitle->setGeometry(20, 20, 400, 20);
// printLabelFormat(lblGenericNetworkTitle);
/***********************/
frEthInfo = new QFrame(this);
frEthInfo->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frEthInfo->setGeometry(25, 50, 700, 362);
lblGateway = new QLabel("게이트웨이", frEthInfo);
lblGateway->setGeometry(10, 15, 80, 20);
leGateway = new QLineEdit(frEthInfo);
leGateway->setGeometry(90, 15, 150, 20);
leGateway->setText(pszGateway);
lblSeparator1 = new QLabel(frEthInfo);
lblSeparator1->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator1->setGeometry(20, 45, 630, 2);
/******** Ethernet Card 0 ********/
lblEth0 = new QLabel("첫번째 이더넷카드", frEthInfo);
lblEth0->setGeometry(90, 10+50, 100, 20);
lblEth0IPAddr = new QLabel("IP 주소 ", frEthInfo);
lblEth0IPAddr->setGeometry(10, 40+50, 80, 20);
leEth0IPAddr = new QLineEdit(frEthInfo);
leEth0IPAddr->setGeometry(90, 40+50, 150, 20);
leEth0IPAddr->setText(pszIPAddr);
/*** text -> proc ***/
lblEth0Netmask = new QLabel("Netmask ", frEthInfo);
lblEth0Netmask->setGeometry(10, 40+30+50, 80, 20);
leEth0Netmask = new QLineEdit(frEthInfo);
leEth0Netmask->setGeometry(90, 40+30+50, 150, 20);
leEth0Netmask->setText(pszNetmask);
lblEth0Network = new QLabel("Network ", frEthInfo);
lblEth0Network->setGeometry(10, 40+60+50, 80, 20);
leEth0Network = new QLineEdit(frEthInfo);
leEth0Network->setGeometry(90, 40+60+50, 150, 20);
leEth0Network->setEnabled(0);
leEth0Network->setText(pNet.pszNetwork);
lblEth0Broadcast = new QLabel("Broadcast ", frEthInfo);
lblEth0Broadcast->setGeometry(10, 40+90+50, 80, 20);
leEth0Broadcast = new QLineEdit(frEthInfo);
leEth0Broadcast->setGeometry(90, 40+90+50, 150, 20);
leEth0Broadcast->setEnabled(0);
leEth0Broadcast->setText(pNet.pszBroadcast);
lblSeparator2 = new QLabel(frEthInfo);
lblSeparator2->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator2->setGeometry(20, 40+90+50+40, 630, 2);
/*** text -> proc ***/
/*********************************/
/******** Ethernet Card 1 ********/
lblEth1 = new QLabel("두번째 이더넷카드", frEthInfo);
lblEth1->setGeometry(300, 10+50, 100, 20);
leEth1IPAddr = new QLineEdit(frEthInfo);
leEth1IPAddr->setGeometry(300, 40+50, 150, 20);
leEth1IPAddr->setText(pszPrivate1IPAddr);
/*** text -> proc ***/
leEth1Netmask = new QLineEdit(frEthInfo);
leEth1Netmask->setGeometry(300, 40+30+50, 150, 20);
leEth1Netmask->setText(pszPrivate1Netmask);
/*** text -> proc ***/
leEth1Network = new QLineEdit(frEthInfo);
leEth1Network->setGeometry(300, 40+60+50, 150, 20);
leEth1Broadcast = new QLineEdit(frEthInfo);
leEth1Broadcast->setGeometry(300, 40+90+50, 150, 20);
leEth1Network->setEnabled(0);
leEth1Broadcast->setEnabled(0);
if (strlen(pszPrivate1IPAddr) >= 7)
{
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
}
/*********************************/
/******** Ethernet Card 2 ********/
lblEth2 = new QLabel("세번째 이더넷카드", frEthInfo);
lblEth2->setGeometry(520, 10+50, 100, 20);
leEth2IPAddr = new QLineEdit(frEthInfo);
leEth2IPAddr->setGeometry(520, 40+50, 150, 20);
leEth2IPAddr->setText(pszPrivate2IPAddr);
/*** text -> proc ***/
leEth2Netmask = new QLineEdit(frEthInfo);
leEth2Netmask->setGeometry(520, 40+30+50, 150, 20);
leEth2Netmask->setText(pszPrivate2Netmask);
/*** text -> proc ***/
leEth2Network = new QLineEdit(frEthInfo);
leEth2Network->setGeometry(520, 40+60+50, 150, 20);
leEth2Broadcast = new QLineEdit(frEthInfo);
leEth2Broadcast->setGeometry(520, 40+90+50, 150, 20);
leEth2Network->setEnabled(0);
leEth2Broadcast->setEnabled(0);
if (strlen(pszPrivate2IPAddr) >= 7)
{
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
}
/*********************************/
for (i = 0; i < 2; i++)
{
pszSaveListStr[i] = (char *)malloc(sizeof(char)*200);
memset(pszSaveListStr[i], '\0', 200);
}
/*********************************/
lblEth0NetCard = new QLabel("Ethernet 0 카드", frEthInfo);
lblEth0NetCard->setGeometry(10, 40+90+70+60, 90, 20);
cbEthNetCard[0] = new QComboBox(frEthInfo, "comboBox_Eth0");
cbEthNetCard[0]->setGeometry(110, 40+90+70+60, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[0]->insertItem(pszNetCard[i]);
cbEthNetCard[0]->setAutoResize(FALSE);
if (saveSearchLineToFile("alias eth0", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[0], pszSaveListStr[0]+11);
pszNetConfNetCard[0][strlen(pszNetConfNetCard[0])-1] = '\0';
}
if (strlen(pszIPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[0]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[0]) < 2)
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[0]->setCurrentItem(nCardIdx);
}
/*********************************/
lblEth1NetCard = new QLabel("Ethernet 1 카드", frEthInfo);
lblEth1NetCard->setGeometry(10, 40+90+70+90, 90, 20);
cbEthNetCard[1] = new QComboBox(frEthInfo, "comboBox_Eth1");
cbEthNetCard[1]->setGeometry(110, 40+90+70+90, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[1]->insertItem(pszNetCard[i]);
cbEthNetCard[1]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth1", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[1], pszSaveListStr[0]+11);
pszNetConfNetCard[1][strlen(pszNetConfNetCard[1])-1] = '\0';
}
if (strlen(pszPrivate1IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[1]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[1]) < 2)
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[1]->setCurrentItem(nCardIdx);
}
/**********************************/
lblEth2NetCard = new QLabel("Ethernet 2 카드", frEthInfo);
lblEth2NetCard->setGeometry(10, 40+90+70+120, 90, 20);
cbEthNetCard[2] = new QComboBox(frEthInfo, "comboBox_Eth2");
cbEthNetCard[2]->setGeometry(110, 40+90+70+120, 470, 20);
for (i = 0; i < 40; i++)
cbEthNetCard[2]->insertItem(pszNetCard[i]);
cbEthNetCard[2]->setAutoResize(FALSE);
for (i = 0; i < 2; i++)
memset(pszSaveListStr[i], '\0', 200);
if (saveSearchLineToFile("alias eth2", pszSaveListStr,
"/etc/conf.modules", 80, 200))
{
strcpy(pszNetConfNetCard[2], pszSaveListStr[0]+11);
pszNetConfNetCard[2][strlen(pszNetConfNetCard[2])-1] = '\0';
}
if (strlen(pszPrivate2IPAddr) >= 7)
{
for (nCardIdx = 0; nCardIdx < 40; nCardIdx++)
if (strstr(pszNetCard[nCardIdx], pszNetConfNetCard[2]) !=
(char *)NULL)
break;
if (strlen(pszNetConfNetCard[2]) < 2)
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
else
{
nCardIdx = 39;
cbEthNetCard[2]->setCurrentItem(nCardIdx);
}
cbEthNetCard[2]->setGeometry(110, 40+90+70+125, 470, 20);
/*************************************/
bttnApply = new QPushButton("적 용", this);
bttnApply->setGeometry(150, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this, SLOT(setApply()));
bttnCancel = new QPushButton("취 소", this);
bttnCancel->setGeometry(450, 50+60+90+70+120+80, 150, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this, SLOT(setCancel()));
/************************************/
for (i = 0; i < 2; i++)
free(pszSaveListStr[i]);
free(pszIPAddr);
free(pszNetmask);
free(pszPrivate1IPAddr);
free(pszPrivate1Netmask);
free(pszPrivate2IPAddr);
free(pszPrivate2Netmask);
free(pszGateway);
}
clssDefGeneric::~clssDefGeneric()
{
int i;
delete lblEth0;
delete lblEth0IPAddr;
delete lblEth0Netmask;
delete lblEth0Network;
delete lblEth0Broadcast;
delete leEth0IPAddr;
delete leEth0Netmask;
delete leEth0Network;
delete leEth0Broadcast;
delete lblEth1;
delete leEth1IPAddr;
delete leEth1Netmask;
delete leEth1Network;
delete leEth1Broadcast;
delete lblEth2;
delete leEth2IPAddr;
delete leEth2Netmask;
delete leEth2Network;
delete leEth2Broadcast;
delete lblGateway;
delete leGateway;
delete lblSeparator1;
delete lblSeparator2;
for (i = 0; i < 3; i++)
delete cbEthNetCard[i];
delete lblEth0NetCard;
delete lblEth1NetCard;
delete lblEth2NetCard;
delete bttnCancel;
delete bttnApply;
delete lblGenericNetworkTitle;
delete frEthInfo;
}
void clssDefGeneric::setApply()
{
char *pszIfCfgEthFile =
"DEVICE=%s\nIPADDR=%s\nNETMASK=%s\nNETWORK=%s\nBROADCAST=%s\nONBOOT=yes\n";
char *pszNetworkFile =
"NETWORKING=yes\nFORWARD_IPV4=true\nHOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszOptions[95];
char *pszSaveCardLine[3], pszSaveHostName[256], pszSaveDomainName[256];
NetTab pNet, pNetPrivate1, pNetPrivate2;
FILE *fp;
S_Addr pAddr, pSaveAddr;
char pszTmpSearch[100];
char pszTmpInsert[100];
char pszSaveIP[18];
int i;
memset(pszSaveIP, '\0', 18);
getCurrentIPAddr(pszSaveIP);
pSaveAddr = separateAddress(pszSaveIP);
pNet = calculateNetMaskTab((char *)leEth0IPAddr->text(),
(char *)leEth0Netmask->text());
pNetPrivate1 = calculateNetMaskTab((char *)leEth1IPAddr->text(),
(char *)leEth1Netmask->text());
pNetPrivate2 = calculateNetMaskTab((char *)leEth2IPAddr->text(),
(char *)leEth2Netmask->text());
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth0", "w");
fprintf(fp, pszIfCfgEthFile,
"eth0", leEth0IPAddr->text(), leEth0Netmask->text(),
leEth0Network->text(), leEth0Broadcast->text());
fclose(fp);
if (strlen((char *)leEth1IPAddr->text()) >= 7)
{
char pszPrivate1IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth1", "w");
fprintf(fp, pszIfCfgEthFile,
"eth1", leEth1IPAddr->text(), leEth1Netmask->text(),
leEth1Network->text(), leEth1Broadcast->text());
fclose(fp);
memset(pszPrivate1IPAddr, '\0', 20);
memset(pszCommand, '\0', 150);
getPrivate1IPAddr(pszPrivate1IPAddr);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip del %s\n",
pszPrivate1IPAddr);
system(pszCommand);
memset(pszCommand, '\0', 150);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip add %s\n",
leEth1IPAddr->text());
system(pszCommand);
}
if (strlen((char *)leEth2IPAddr->text()) >= 7)
{
char pszPrivate2IPAddr[20];
char pszCommand[150];
fp = fopen("/etc/sysconfig/network-scripts/ifcfg-eth2", "w");
fprintf(fp, pszIfCfgEthFile,
"eth2", leEth2IPAddr->text(), leEth2Netmask->text(),
leEth2Network->text(), leEth2Broadcast->text());
fclose(fp);
memset(pszPrivate2IPAddr, '\0', 20);
memset(pszCommand, '\0', 150);
getPrivate2IPAddr(pszPrivate2IPAddr);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip del %s\n",
pszPrivate2IPAddr);
system(pszCommand);
memset(pszCommand, '\0', 150);
sprintf(pszCommand, "/usr/local/topflash/bin/host_ip add %s\n",
leEth2IPAddr->text());
system(pszCommand);
}
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, pszSaveHostName, pszSaveDomainName,
pszSaveDomainName, leGateway->text());
fclose(fp);
for (i = 0; i < 3; i++)
{
if ((pszSaveCardLine[i] = (char *)malloc(sizeof(char)*50)) == NULL)
{
printf("pszSaveCardLine Memory Error!\n");
exit(1);
}
memset(pszSaveCardLine[i], '\0', 50);
}
for (i = 0; i < 3; i++)
{
sprintf(pszSaveCardLine[i], "alias eth%d ", i);
if (cbEthNetCard[i]->currentItem() >= 0 &&
cbEthNetCard[i]->currentItem() <= 2)
strcat(pszSaveCardLine[i], "3c59x");
else if (cbEthNetCard[i]->currentItem() == 3)
strcat(pszSaveCardLine[i], "eepro100");
else if (cbEthNetCard[i]->currentItem() >= 4 &&
cbEthNetCard[i]->currentItem() <= 7)
strcat(pszSaveCardLine[i], "hp100");
else if (cbEthNetCard[i]->currentItem() == 8)
strcat(pszSaveCardLine[i], "ibmtr");
else if (cbEthNetCard[i]->currentItem() == 9)
strcat(pszSaveCardLine[i], "ne2k-pci");
else if (cbEthNetCard[i]->currentItem() == 10 ||
cbEthNetCard[i]->currentItem() == 11)
strcat(pszSaveCardLine[i], "pcnet32");
else if (cbEthNetCard[i]->currentItem() >= 12 &&
cbEthNetCard[i]->currentItem() <= 15)
strcat(pszSaveCardLine[i], "rtl8139");
else if (cbEthNetCard[i]->currentItem() == 16)
strcat(pszSaveCardLine[i], "smc-ultra");
else if (cbEthNetCard[i]->currentItem() >= 17 ||
cbEthNetCard[i]->currentItem() <= 22)
strcat(pszSaveCardLine[i], "tlan");
else if (cbEthNetCard[i]->currentItem() >= 23 ||
cbEthNetCard[i]->currentItem() <= 38)
strcat(pszSaveCardLine[i], "tulip");
}
for (i = 0; i < 3; i++)
strcat(pszSaveCardLine[i], "\n");
addOnNotExistChangeOnExist(pszSaveCardLine[0], "alias eth0",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[1], "alias eth1",
"/etc/conf.modules", 200, 100);
addOnNotExistChangeOnExist(pszSaveCardLine[2], "alias eth2",
"/etc/conf.modules", 200, 100);
if (cbEthNetCard[0]->currentItem() == 39)
insertStrToFile("", "alias eth0", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[1]->currentItem() == 39)
insertStrToFile("", "alias eth1", "/etc/conf.modules", 200, 100);
if (cbEthNetCard[2]->currentItem() == 39)
insertStrToFile("", "alias eth2", "/etc/conf.modules", 200, 100);
for (i = 0; i < 3; i++)
free(pszSaveCardLine[i]);
if (cbEthNetCard[0]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth0");
leEth0IPAddr->setText("");
leEth0Netmask->setText("");
leEth0Network->setText("");
leEth0Broadcast->setText("");
}
if (cbEthNetCard[1]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth1");
leEth1IPAddr->setText("");
leEth1Netmask->setText("");
leEth1Network->setText("");
leEth1Broadcast->setText("");
}
if (cbEthNetCard[2]->currentItem() == 39)
{
system("rm -f /etc/sysconfig/network-scripts/ifcfg-eth2");
leEth2IPAddr->setText("");
leEth2Netmask->setText("");
leEth2Network->setText("");
leEth2Broadcast->setText("");
}
/**************************************/
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth0 \
/etc/sysconfig/network-scripts/ifcfg-eth0.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth1 \
/etc/sysconfig/network-scripts/ifcfg-eth1.org\n");
system("cp -f /etc/sysconfig/network-scripts/ifcfg-eth2 \
/etc/sysconfig/network-scripts/ifcfg-eth2.org\n");
system("cp -f /etc/sysconfig/network /etc/sysconfig/network.org\n");
system("cp -f /etc/conf.modules /etc/conf.modules.org\n");
system("cp -f /etc/resolv.conf /etc/resolv.conf.org\n");
system("/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network start\n");
}
void clssDefGeneric::setCancel()
{
char *pszIPAddr, *pszNetmask, *pszGateway, *pszHostName, *pszDomainName;
char *pszPrivate1IPAddr, *pszPrivate1Netmask, *pszPrivate2IPAddr;
char *pszPrivate2Netmask;
NetTab pNet, pNetPrivate1, pNetPrivate2;
char *pszSaveListStr[2];
if (((pszIPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate1Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2IPAddr = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszPrivate2Netmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszGateway = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("DefGeneric Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszIPAddr, '\0', 18);
memset(pszNetmask, '\0', 18);
memset(pszPrivate1IPAddr, '\0', 18);
memset(pszPrivate1Netmask, '\0', 18);
memset(pszPrivate2IPAddr, '\0', 18);
memset(pszPrivate2Netmask, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
getCurrentGateway(pszGateway);
getCurrentIPAddr(pszIPAddr);
getCurrentNetmask(pszNetmask);
pNet = calculateNetMaskTab(pszIPAddr, pszNetmask);
getPrivate1Netmask(pszPrivate1Netmask);
getPrivate1IPAddr(pszPrivate1IPAddr);
pNetPrivate1 = calculateNetMaskTab(pszPrivate1IPAddr, pszPrivate1Netmask);
getPrivate2Netmask(pszPrivate2Netmask);
getPrivate2IPAddr(pszPrivate2IPAddr);
pNetPrivate2 = calculateNetMaskTab(pszPrivate2IPAddr, pszPrivate2Netmask);
/***** lineeditbox init: proc -> segmentation fault *****/
leGateway->setText(pszGateway);;
leEth0IPAddr->setText(pszIPAddr);
leEth0Netmask->setText(pszNetmask);
leEth0Network->setText(pNet.pszNetwork);
leEth0Broadcast->setText(pNet.pszBroadcast);
leEth1IPAddr->setText(pszPrivate1IPAddr);
leEth1Netmask->setText(pszPrivate1Netmask);
leEth1Network->setText(pNetPrivate1.pszNetwork);
leEth1Broadcast->setText(pNetPrivate1.pszBroadcast);
leEth2IPAddr->setText(pszPrivate2IPAddr);
leEth2Netmask->setText(pszPrivate2Netmask);
leEth2Network->setText(pNetPrivate2.pszNetwork);
leEth2Broadcast->setText(pNetPrivate2.pszBroadcast);
}
void clssDefGeneric::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : clssDNS.h > ------------------------
#include <qwidget.h>
class QLabel;
class QLineEdit;
class QComboBox; /* to combobox */
class QPushButton;
class QFrame;
class clssDefDNS : public QWidget
{
Q_OBJECT
public:
clssDefDNS();
~clssDefDNS();
public slots:
void printLabelFormat(QLabel *lblDNSTitle);
void rebootSystem();
private slots:
void applySetting();
void cancelSetting();
void addDNS();
void delDNS();
private:
QLabel *lblHostName;
QLabel *lblDomainName;
QLineEdit *leHostName;
QLineEdit *leDomainName;
QLabel *lblDNSServer;
QComboBox *cbDNSServer;
QPushButton *bttnCancel;
QPushButton *bttnApply;
QFrame *frWorkArea;
QLabel *lblSeparator;
QPushButton *bttnAdd;
QPushButton *bttnDel;
QLabel *lblDNSTitle;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssDNS.cpp > ----------------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <stdio.h>
#include <stdlib.h>
/* test */
#include <qlabel.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include "network.h"
#include "proc_file.h"
#include "clssDNS.h"
clssDefDNS::clssDefDNS()
{
char *pszNetmask, *pszHostName, *pszDomainName;
int i, j;
NetTab pNet;
if (((pszNetmask = (char *)malloc(sizeof(char)*18)) == NULL) ||
((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
/***********************/
lblDNSTitle = new QLabel("DNS Setting (DNS 설정)", this);
lblDNSTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblDNSTitle);
frWorkArea = new QFrame(this);
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frWorkArea->setGeometry(30, 30, 330, 430);
/******** Ethernet Card 0 ********/
lblHostName = new QLabel("호스트명", frWorkArea);
lblHostName->setGeometry(20, 50, 80, 20);
leHostName = new QLineEdit(frWorkArea);
leHostName->setGeometry(100, 50, 180, 20);
leHostName->setText(pszHostName);
lblDomainName = new QLabel("도메인명", frWorkArea);
lblDomainName->setGeometry(20, 80, 80, 20);
leDomainName = new QLineEdit(frWorkArea);
leDomainName->setGeometry(100, 80, 180, 20);
leDomainName->setText(pszDomainName);
bttnApply = new QPushButton("적 용", frWorkArea);
bttnApply->setGeometry(50, 160, 80, 30);
QObject::connect(bttnApply, SIGNAL(clicked()), this, SLOT(applySetting()));
bttnCancel = new QPushButton("취 소", frWorkArea);
bttnCancel->setGeometry(180, 160, 80, 30);
QObject::connect(bttnCancel, SIGNAL(clicked()), this,
SLOT(cancelSetting()));
/*************************************/
lblSeparator = new QLabel(frWorkArea);
lblSeparator->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
lblSeparator->setGeometry(20, 230, 290, 2);
lblDNSServer = new QLabel("DNS서버", frWorkArea);
lblDNSServer->setGeometry(20, 280, 80, 20);
cbDNSServer = new QComboBox(TRUE, frWorkArea, "comboBox_DNS");
cbDNSServer->setGeometry(100, 280, 150, 20);
char *pszDNSServer[50];
int nCntDNS = countAllLineToFile("/etc/resolv.conf", 50, 200);
for (i = 0; i < 50; i++)
{
if ((pszDNSServer[i] = (char *)malloc(sizeof(char)*200)) == NULL)
{
printf("Memory allocation error!\n");
exit(1);
}
memset(pszDNSServer[i], '\0', 200);
}
getDNSServer(pszDNSServer);
for (i = 0; i < nCntDNS-1; i++)
cbDNSServer->insertItem(pszDNSServer[i]);
cbDNSServer->setAutoResize(FALSE);
for (i = 0; i < 50; i++)
free(pszDNSServer[i]);
bttnAdd = new QPushButton("추 가", frWorkArea);
bttnAdd->setGeometry(50, 350, 80, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addDNS()));
bttnDel = new QPushButton("삭 제", frWorkArea);
bttnDel->setGeometry(180, 350, 80, 30);
QObject::connect(bttnDel, SIGNAL(clicked()), this, SLOT(delDNS()));
/************************************/
free(pszHostName);
free(pszDomainName);
}
clssDefDNS::~clssDefDNS()
{
int i;
delete lblHostName;
delete lblDomainName;
delete leHostName;
delete leDomainName;
delete bttnCancel;
delete bttnApply;
delete lblDNSServer;
delete cbDNSServer;
delete bttnAdd;
delete bttnDel;
delete frWorkArea;
delete lblDNSTitle;
}
void clssDefDNS::addDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
if (strcmp(cbDNSServer->text(cbDNSServer->currentItem()),
cbDNSServer->currentText()) != 0)
cbDNSServer->insertItem(cbDNSServer->currentText());
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
memset(pszTmpInsert, '\0', 100);
sprintf(pszTmpInsert, "nameserver %s\n", cbDNSServer->currentText());
sprintf(pszTmpSearch, "nameserver %s", cbDNSServer->currentText());
if (!searchStrInFile(pszTmpSearch, "/etc/resolve.conf", 100, 100))
addOnNotExistChangeOnExist(pszTmpInsert, pszTmpSearch,
"/etc/resolv.conf", 100, 100);
}
}
void clssDefDNS::delDNS()
{
char pszTmpSearch[100], pszTmpInsert[100];
if (strlen(cbDNSServer->text(cbDNSServer->currentItem())) != 0)
{
/*** resolv.conf DNS server changed ***/
memset(pszTmpSearch, '\0', 100);
sprintf(pszTmpSearch, "nameserver %s",
cbDNSServer->text(cbDNSServer->currentItem()));
if (!searchStrInFile(pszTmpSearch, "/etc/resolve.conf", 100, 100))
insertStrToFile("", pszTmpSearch, "/etc/resolv.conf", 100, 100);
cbDNSServer->removeItem(cbDNSServer->currentItem());
cbDNSServer->setCurrentItem(0);
}
}
void clssDefDNS::applySetting()
{
char *pszNetworkFile =
"NETWORKING=yes\nFORWARD_IPV4=true\nHOSTNAME=%s.%s\nDOMAINNAME=%s\nGATEWAY=%s\nGATEWAYDEV=eth0\n";
char pszGateway[18];
char pszOptions[95];
char *pszSaveCardLine[3];
FILE *fp;
S_Addr pAddr;
char pszTmpSearch[100], pszTmpInsert[100];
char pszSaveIP[18], pszSaveHostName[256], pszSaveDomainName[256];
int i;
char pszCommand[200];
memset(pszSaveIP, '\0', 18);
memset(pszGateway, '\0', 18);
memset(pszSaveHostName, '\0', 256);
memset(pszSaveDomainName, '\0', 256);
getCurrentIPAddr(pszSaveIP);
getCurrentGateway(pszGateway);
getCurrentHostName(pszSaveHostName, pszSaveDomainName);
fp = fopen("/etc/sysconfig/network", "w");
fprintf(fp, pszNetworkFile, leHostName->text(), leDomainName->text(),
leDomainName->text(), pszGateway);
fclose(fp);
/**** update named daemon ****/
if (strlen(leHostName->text()) >= 1)
{
pAddr = separateAddress(pszSaveIP);
/*** HOSTNAME Host,Domain changed ***/
char pszTmpDomain[100];
char pszTmpHost[50];
memset(pszTmpInsert, '\0', 100);
memset(pszTmpHost, '\0', 50);
memset(pszTmpDomain, '\0', 100);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
sprintf(pszTmpInsert, "%s.%s\n", pszTmpHost, pszTmpDomain);
addOnNotExistChangeOnExist(pszTmpInsert, pszSaveHostName,
"/etc/HOSTNAME", 100, 100);
memset(pszTmpDomain, '\0', 100);
memset(pszTmpHost, '\0', 50);
strcpy(pszTmpHost, leHostName->text());
strcpy(pszTmpDomain, leDomainName->text());
if (strcmp(pszSaveDomainName, pszTmpDomain) != 0 ||
strcmp(pszSaveHostName, pszTmpHost) != 0)
{
QWidget *wdgtRebooting = new QWidget();
wdgtRebooting->setGeometry(300, 300, 300, 150);
QLabel *lblRebooting = new QLabel(
"호스트이름 혹은 도메인 이름이 바뀌었으므로\n재부팅을 하겠습니다.",
wdgtRebooting);
lblRebooting->setGeometry(20, 20, 250, 50);
QPushButton *bttnRebooting = new QPushButton("재 부 팅",
wdgtRebooting);
bttnRebooting->setGeometry(120, 90, 120, 30);
QObject::connect(bttnRebooting, SIGNAL(clicked()), this,
SLOT(rebootSystem()));
wdgtRebooting->show();
}
}
system("/etc/rc.d/init.d/network stop;/etc/rc.d/init.d/network restart\n");
}
void clssDefDNS::cancelSetting()
{
char *pszHostName, *pszDomainName;
char *pszSaveListStr[2];
if (((pszHostName = (char *)malloc(sizeof(char)*256)) == NULL) ||
((pszDomainName = (char *)malloc(sizeof(char)*256)) == NULL))
{
emit printf("GenericNetwork Class/Network: Memory 할당 에러\n");
exit(1);
}
memset(pszHostName, '\0', 256);
memset(pszDomainName, '\0', 256);
getCurrentHostName(pszHostName, pszDomainName);
leHostName->setText(pszHostName);
leDomainName->setText(pszDomainName);
}
void clssDefDNS::rebootSystem()
{
system("sync;sync;sync;sync;sync;sync;sync;sync;init 6\n");
}
void clssDefDNS::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : clssAlias.h > ----------------------
#include <qwidget.h>
class QLineEdit;
class QLabel;
class QLineEdit;
class QListView;
class QListViewItem;
class QFrame;
class QPushButton;
class clssDefAlias : public QWidget
{
Q_OBJECT
public:
clssDefAlias();
~clssDefAlias();
public slots:
void addSetting();
void deleteSetting();
void getAliasingItem();
void printLabelFormat(QLabel *lblAliasingTitle);
private slots:
private:
QFrame *frWorkArea;
QPushButton *bttnAdd;
QPushButton *bttnDelete;
QFrame *frAliasList;
QListView *lvAliasList;
QListViewItem *lviAlias[100];
QLabel *lblNetworkArea;
QLabel *lblIP;
QLineEdit *leIP;
QLabel *lblNetmask;
QLineEdit *leNetmask;
QLabel *lblNetwork;
QLineEdit *leNetwork;
QLabel *lblBroadcast;
QLineEdit *leBroadcast;
QLabel *lblAliasingTitle;
int nAliasCount;
};
// ----------------------------------------------------------------
// ---------------- < Source : clssAlias.cpp > --------------------
#include <qapplication.h>
#include <qwidget.h>
#include <qpushbutton.h>
#include <qframe.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qlistview.h>
#include <stdio.h>
#include <stdlib.h>
#include "proc_file.h"
#include "network.h"
#include "clssAlias.h"
clssDefAlias::clssDefAlias()
{
int i;
char pszSaveFile[100];
char pszVirtualIP[18];
FILE *fp;
for (nAliasCount = 0; nAliasCount < 10; nAliasCount++)
{
memset(pszSaveFile, '\0', 100);
sprintf(pszSaveFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
nAliasCount);
if ((fp = fopen(pszSaveFile, "r")) == NULL)
break;
fclose(fp);
}
lblAliasingTitle = new QLabel("Virtual LAN (가상 네트워크 카드 설정)",
this);
lblAliasingTitle->setGeometry(10, 10, 400, 20);
// printLabelFormat(lblAliasingTitle);
frWorkArea = new QFrame(this, "IP Aliasing Area");
frWorkArea->setFrameStyle(QFrame::Box | QFrame::Raised | QFrame::Plain);
frWorkArea->setGeometry(40, 60, 670, 310);
lblNetworkArea = new QLabel("네트워크영역 선택", frWorkArea);
lblNetworkArea->setGeometry(30, 20, 120, 20);
frAliasList = new QFrame(frWorkArea, "Alias List Area");
frAliasList->setFrameStyle(QFrame::Box | QFrame::Sunken | QFrame::WinPanel);
frAliasList->setGeometry(30, 60, 320, 220);
lvAliasList = new QListView(frAliasList);
lvAliasList->setGeometry(3, 3, 314, 214);
lvAliasList->addColumn(" 가상 네트워크 ");
lvAliasList->addColumn(" IP 주소 ");
lvAliasList->setRootIsDecorated(true);
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
QObject::connect(lvAliasList, SIGNAL(selectionChanged()), this,
SLOT(getAliasingItem()));
lblIP = new QLabel("IP 주소", frWorkArea);
lblIP->setGeometry(400, 60, 70, 20);
leIP = new QLineEdit(frWorkArea);
leIP->setGeometry(480, 60, 130, 20);
lblNetmask = new QLabel("넷마스크", frWorkArea);
lblNetmask->setGeometry(400, 100, 70, 20);
leNetmask = new QLineEdit(frWorkArea);
leNetmask->setGeometry(480, 100, 130, 20);
leNetmask->setEnabled(false);
lblNetwork = new QLabel("네트워크", frWorkArea);
lblNetwork->setGeometry(400, 140, 70, 20);
leNetwork = new QLineEdit(frWorkArea);
leNetwork->setGeometry(480, 140, 130, 20);
leNetwork->setEnabled(false);
lblBroadcast = new QLabel("브로드캐스트", frWorkArea);
lblBroadcast->setGeometry(400, 180, 70, 20);
leBroadcast = new QLineEdit(frWorkArea);
leBroadcast->setGeometry(480, 180, 130, 20);
leBroadcast->setEnabled(false);
bttnAdd = new QPushButton("추가", this);
bttnAdd->setGeometry(100, 410, 150, 30);
QObject::connect(bttnAdd, SIGNAL(clicked()), this, SLOT(addSetting()));
bttnDelete = new QPushButton("삭제", this);
bttnDelete->setGeometry(480, 410, 150, 30);
QObject::connect(bttnDelete, SIGNAL(clicked()), this,
SLOT(deleteSetting()));
}
clssDefAlias::~clssDefAlias()
{
int i;
delete lblNetworkArea;
if (nAliasCount > 0)
for (i = 0; i < nAliasCount; i++)
lviAlias[i];
delete lvAliasList;
delete lblIP;
delete leIP;
delete lblNetmask;
delete leNetmask;
delete lblNetwork;
delete leNetwork;
delete lblBroadcast;
delete leBroadcast;
delete frAliasList;
delete frWorkArea;
delete bttnAdd;
delete bttnDelete;
delete lblAliasingTitle;
}
void clssDefAlias::getAliasingItem()
{
char pszNetmask[18];
NetTab pNet;
memset(pszNetmask, '\0', 18);
getCurrentNetmask(pszNetmask);
leIP->setText(lvAliasList->currentItem()->text(1));
pNet = calculateNetMaskTab((char *)leIP->text(), pszNetmask);
leNetmask->setText(pszNetmask);
leNetwork->setText(pNet.pszNetwork);
leBroadcast->setText(pNet.pszBroadcast);
}
void clssDefAlias::addSetting()
{
FILE *fp;
char pszVirtualCard[10], pszFile[100];
char pszCommand[150];
memset(pszVirtualCard, '\0', 10);
memset(pszFile, '\0', 100);
sprintf(pszVirtualCard, "eth0:%d", nAliasCount);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-%s", pszVirtualCard);
lviAlias[nAliasCount] = new QListViewItem(lvAliasList, pszVirtualCard,
leIP->text());
if ((fp = fopen(pszFile, "w")) == NULL)
{
emit printf("file open error!\n");
exit(1);
}
fprintf(fp, "DEVICE=%s\nIPADDR=%s\nONBOOT=yes\n",pszVirtualCard,
leIP->text());
fclose(fp);
nAliasCount++;
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::deleteSetting()
{
int i, j;
char pszCommand[150], pszFile[100];
char pszVirtualIP[18];
FILE *fp;
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:%d",
lvAliasList->itemPos(lvAliasList->currentItem())/18);
if ((fp = fopen(pszFile, "r")) == NULL)
return;
fclose(fp);
nAliasCount--;
memset(pszCommand, '\0', 150);
memset(pszFile, '\0', 100);
sprintf(pszFile, "/etc/sysconfig/network-scripts/ifcfg-eth0:*");
sprintf(pszCommand, "rm -f %s\n", pszFile);
system(pszCommand);
if (nAliasCount > 0)
{
for (i = 0, j = 0; i < nAliasCount+1; i++)
{
if (i != lvAliasList->itemPos(lvAliasList->currentItem())/18)
{
memset(pszFile, '\0', 100);
sprintf(pszFile,
"/etc/sysconfig/network-scripts/ifcfg-eth0:%d", j);
if ((fp = fopen(pszFile, "w")) == NULL)
return;
fprintf(fp, "DEVICE=eth0:%d\nIPADDR=%s\nONBOOT=yes\n", j,
lviAlias[i]->text(1));
fclose(fp);
j++;
}
}
}
lvAliasList->clear();
if (nAliasCount > 0)
{
char pszVirtualCard[10];
for (i = 0; i < nAliasCount; i++)
{
memset(pszVirtualCard, '\0', 10);
memset(pszVirtualIP, '\0', 18);
sprintf(pszVirtualCard, "eth0:%d", i);
getAliasIP(pszVirtualIP, i);
lviAlias[i] = new QListViewItem(lvAliasList, pszVirtualCard,
pszVirtualIP);
}
}
system("/etc/rc.d/init.d/network restart\n");
}
void clssDefAlias::printLabelFormat(QLabel *lblBold)
{
QPalette p = QWidget::palette();
QColorGroup n = palette().normal();
QColorGroup g(n.background(), n.foreground(), n.light(), n.dark(),
n.mid(), n.background(), n.base());
p.setNormal(g);
setPalette(p);
lblBold->setPalette(p);
lblBold->setMargin(3);
QFont bold = *QApplication::font();
bold.setBold(TRUE);
bold.setPointSize(bold.pointSize()+2);
lblBold->setFont(bold);
lblBold->setFixedSize(lblBold->sizeHint());
lblBold->setFixedSize(lblBold->sizeHint());
}
// ----------------------------------------------------------------
// ---------------- < Source : Network_menu.h > -------------------
#include <qmainwindow.h>
class QMenuBar;
class QPopupMenu;
class QToolBar;
class clssDefGeneric;
class clssDefDNS;
class clssDefAlias;
class clssNetwork : public QMainWindow
{
Q_OBJECT
public:
clssNetwork();
~clssNetwork();
public slots:
void funcGenericNetwork();
void funcDNS();
void funcAlias();
void funcQuit();
protected:
private:
QMenuBar *mnuMainBar;
QPopupMenu *mnuNetwork;
QToolBar *tbNetwork;
clssDefGeneric *clssGeneric;
clssDefDNS *clssDNS;
clssDefAlias *clssAlias;
};
// ----------------------------------------------------------------
// ---------------- < Source : Network_menu.cpp > -----------------
#include <qapplication.h>
#include <qkeycode.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qpixmap.h>
#include <stdio.h>
#include "Network_menu.h"
#include "clssGeneric.h"
#include "clssDNS.h"
#include "clssAlias.h"
#ifndef GENERIC_TOOLTIP
#define GENERIC_TOOLTIP "일반적인 네트워크 설정"
#define DNS_TOOLTIP "DNS 설정"
#define ALIAS_TOOLTIP "Alias 설정"
#endif
clssNetwork::clssNetwork()
{
QPixmap iconGeneric, iconDNS, iconAlias;
iconGeneric.load("./generic.gif");
iconDNS.load("./dns.gif");
iconAlias.load("./alias.gif");
qApp->setStyle(WindowsStyle);
mnuNetwork = new QPopupMenu;
mnuNetwork->insertItem("일반 네트워크 관리", this,
SLOT(funcGenericNetwork()));
mnuNetwork->insertItem("DNS 관리", this, SLOT(funcDNS()));
mnuNetwork->insertItem("IP-Aliasing 관리", this, SLOT(funcAlias()));
mnuNetwork->insertSeparator();
mnuNetwork->insertItem("종료", this, SLOT(funcQuit()));
mnuMainBar = new QMenuBar(this);
mnuMainBar->insertItem(" 네트워크 ", mnuNetwork);
tbNetwork = new QToolBar(this);
tbNetwork->setOrientation(tbNetwork->Horizontal);
QToolButton *tbttnGeneric = new QToolButton(iconGeneric, GENERIC_TOOLTIP,
0, this, SLOT(funcGenericNetwork()), tbNetwork, "generic");
QToolButton *tbttnDNS = new QToolButton(iconDNS, DNS_TOOLTIP, 0, this,
SLOT(funcDNS()), tbNetwork, "dns");
QToolButton *tbttnAlias = new QToolButton(iconAlias, ALIAS_TOOLTIP, 0,
this, SLOT(funcAlias()), tbNetwork, "alias");
}
clssNetwork::~clssNetwork()
{
}
void clssNetwork::funcGenericNetwork()
{
clssGeneric = new clssDefGeneric();
clssGeneric->setGeometry(150, 150, 750, 550);
clssGeneric->show();
}
void clssNetwork::funcDNS()
{
clssDNS = new clssDefDNS();
clssDNS->setGeometry(150, 150, 400, 500);
clssDNS->show();
}
void clssNetwork::funcAlias()
{
clssAlias = new clssDefAlias();
clssAlias->setGeometry(150, 150, 750, 500);
clssAlias->show();
}
void clssNetwork::funcQuit()
{
exit(0);
}
// ----------------------------------------------------------------
// ------------------ < Source : main_menu.cpp > ------------------
#include <qapplication.h>
#include "Network_menu.h"
char pszNetConfHost[256];
char pszNetConfDomain[256];
char pszNetConfGateway[18];
char pszNetConfIPAddr[18];
char pszNetConfPrivate1IPAddr[18];
char pszNetConfPrivate2IPAddr[18];
char pszNetConfNetmask[18];
char pszNetConfPrivate1Netmask[18];
char pszNetConfPrivate2Netmask[18];
char pszNetconfBroadcast[18];
char pszNetconfPrivate1Broadcast[18];
char pszNetconfPrivate2Broadcast[18];
char pszNetConfNetwork[18];
char pszNetConfPrivate1Network[18];
char pszNetConfPrivate2Network[18];
char pszNetConfNetCard[3][30];
int nCountListStr;
char pszSaveNameServer[20][30];
int nCountNameServer;
int nCountClient;
extern int nAccountCount;
int main(int argc, char* argv[])
{
QApplication myapp(argc, argv);
clssNetwork *clssTest = new clssNetwork();
clssTest->setGeometry(100, 100, 800, 600);
myapp.setMainWidget(clssTest);
clssTest->show();
return myapp.exec();
}
// ----------------------------------------------------------------
# ------------------------ < Makefile > --------------------------
PROGS = main_menu
LIBS = -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
CC = g++
GCC = gcc
INCLUDE = -I/usr/lib/qt/include
C_FLAG = -pipe -DNO_DEBUG -O2
CFLAGS = $(INCLUDE) $(C_FLAG)
SYSCONF_LINK = $(CC)
SYSCONF_MOC = /usr/bin/moc
MOC = $(SYSCONF_MOC)
OTHER_OBJS = \
network.o \
proc_file.o
MNU_OBJS = \
main_menu.o \
Network_menu_moc.o \
Network_menu.o \
clssGeneric.o \
clssGeneric_moc.o \
clssDNS.o \
clssDNS_moc.o \
clssAlias.o \
clssAlias_moc.o
all: $(PROGS)
clean:
rm -f *.o
rm -f main_menu
rm -f *_moc.*
############# COMPILE #############
network.o: network.c
$(CC) -c network.c -o $@
proc_file.o: proc_file.c
$(CC) -c proc_file.c -o $@
main_menu.o: main_menu.cpp
$(CC) -c main_menu.cpp $(CFLAGS) -o $@
Network_menu_moc.cpp: Network_menu.h
$(MOC) Network_menu.h -o Network_menu_moc.cpp
Network_menu_moc.o: Network_menu_moc.cpp
$(CC) -c Network_menu_moc.cpp $(CFLAGS) -o $@
Network_menu.o: Network_menu.cpp
$(CC) -c Network_menu.cpp $(CFLAGS) -o $@
clssGeneric_moc.cpp: clssGeneric.h
$(MOC) clssGeneric.h -o clssGeneric_moc.cpp
clssGeneric_moc.o: clssGeneric_moc.cpp
$(CC) -c clssGeneric_moc.cpp $(CFLAGS) -o $@
clssGeneric.o: clssGeneric.cpp
$(CC) -c clssGeneric.cpp $(CFLAGS) -o $@
clssDNS_moc.cpp: clssDNS.h
$(MOC) clssDNS.h -o clssDNS_moc.cpp
clssDNS_moc.o: clssDNS_moc.cpp
$(CC) -c clssDNS_moc.cpp $(CFLAGS) -o $@
clssDNS.o: clssDNS.cpp
$(CC) -c clssDNS.cpp $(CFLAGS) -o $@
clssAlias_moc.cpp: clssAlias.h
$(MOC) clssAlias.h -o clssAlias_moc.cpp
clssAlias_moc.o: clssAlias_moc.cpp
$(CC) -c clssAlias_moc.cpp $(CFLAGS) -o $@
clssAlias.o: clssAlias.cpp
$(CC) -c clssAlias.cpp $(CFLAGS) -o $@
main_menu: $(MNU_OBJS) $(OTHER_OBJS)
$(CC) $(MNU_OBJS) $(OTHER_OBJS) $(LIBS) -o $@
# ----------------------------------------------------------------
3.5. 개선되어야할 내용
여러가지로 모자란 프로그램을 올린 것에 대해 이 글을 읽는 분들께 죄송
스러운 마음뿐이다.
Qt Library는 제공하는 Library만을 써서 그다지 문제될 것은 없겠지만,
파일처리루틴에 있어 모든 procedure들이 최적화되어있다고는 말씀드릴 수
없다. 즉, 이식성과 확장성문제를 고려한다 하더라도 메모리에 대한 완벽
한 최적화를 이루지는 못했다. 또한 네트워크처리루틴에 대해서도 일정한
패턴 혹은 일관성있는 처리를 해주어야 하는데 그렇게 하지 못했다. 즉,
리눅스 버젼이 업데이트될 때마다 네트워크 관련 파일들의 Format이 변할
지도 모르는 상황에서 이를 통합관리하는 파일의 생성없이 각 파일들을
직접 접근한다는 것은 여러모로 비합리적인 방법이다.
필자는 직장에서 개발했던 프로그램의 일부인 이 네트워크 처리부분을 사
정상 그대로 이곳에 올려놓지는 않았다. 이점 무척 죄송스럽게 생각한다.
위의 Source들은 필자가 (주)아이탑의 Topflash project개발 초기에 만든
최적화작업이 되지않은 Source들이다.
지금 학내망쪽에 공급되어 나가고 있는 상품이므로 최적화 되어있는
Source들은 굳이 싣지 못했음을 알려드리며 이점 다시한번 죄송스럽게 생
각한다.
이 Source들에서의 개선방향은 바로 위에서 말씀드린바와 같으며 이 프로
젝트에 대한 모든 이야기는 여기서 마치겠다.
4. 프로젝트를 마치고...
이 프로젝트는 초반에도 말씀드렸듯이 Qt 1.44를 사용한 Network 처리 프로
젝트입니다. 그리고 이는 제가 지금 몸담고 있는 (주)아이탑의 생산제품군
중 하나인 TopmanagerX의 일부분에 대한-초기 최적화되지 않은- 자료이기
도 합니다. Qt를 기반으로 어떤 프로젝트를 개발하고 그를 상품화시켜 판
매하기 위해서는 Gtk와는 다르게 trolltech와 License계약을 맺어야한다는
것은 모두들 아시리라 생각합니다.
그래서 저는 되도록이면 Qt보다는 Gtk기반의 Application개발을 권해드리고
싶습니다. 최근에 와서야 Qt가 약간씩 인기를 끌고 있지만 Open Source개념
의 노하우가 상당히 축적되어있는 Gtk보다는 발전 가능성이 적다고 감히 생
각합니다. Qt는, 물론 GUI에 대해서 Gtk보다 월등합니다만 Gtk의 Open Source
사상(?)은 조만간 Qt의 GUI를 앞설 것이라 생각합니다.
그리고 또 Borland사에서 Delphi를 리눅스에 포팅하고 있다는 사실은 여러
분들도 잘 아시리라 믿습니다. 이렇듯 리눅스용 개발 툴들이 상당히 많이
만들어지고 있으므로 GUI개발에서 획기적으로 두각을 나타낼 만한 개발툴이
머지않아 나올 것이라 생각합니다.
각설하고, 어쨌든 다음에 글을 올릴 때는 MailServer Setting과 WebServer
Setting에 대해 Gtk Library를 써서 구현한 Project를 올리겠습니다.
모자란 글 끝까지 읽어주셔서 진심으로 감사드립니다.
'Linux > QT' 카테고리의 다른 글
[QT] spin & slider bar (0) | 2013.09.26 |
---|---|
[QT] hello (0) | 2013.09.26 |
[QT] button (0) | 2013.09.26 |
QT Designer (0) | 2013.09.26 |
QT설치 방법입니다. (0) | 2013.09.26 |