#include #include #include #include #include #include #include #include #include #include #include // 터미널 연결을 위한 디파인들. #define BAUDRATE B9600 #define MODEMDEVICE "/dev/ttyUSB0" #define POSIX_SOURCE 1 // 참, 거짓 #define FALSE 0 #define TRUE 1 // 왼쪽 오른쪽. #define RIGHT 1 #define LEFT 2 void signal_handler_IO (int status); void intrAction(char *); void goWM(int); void* showLCD(void *); void parseLvr(char *); int parse(char *, char *, char *); void getSystemInfo(); void printLCD(char *); void printScrolledLCD(char *, char *, char *); void makeUpperLine(char *, char *, char *); void systemTrayIcon(); int wait_flag = TRUE; // RS232로 부터 받은 명령. char intrcmd[1024]={0}; // 외부인터럽트 신호를 조절하기 위해 시간을 백업해놓는 변수들. int ps = 0; // 밀리세컨드 백업 time_t ps_sec = 0; // 초 백업 int fd; // 시리얼 통신 디스크립터. // 시스템 트레이에 정보를 뿌리기 위해 FIFO 를 사용한다. int fifofd; int main(int argc, char *argv[]) { // 터미널 관련 변수들 int c, res; struct termios oldtio, newtio; struct sigaction saio; char buf[100]={0}; char ch[100]={0}; // LCD 에 정보를 뿌리기 위해 쓰레드를 사용한다. 쓰레드에서 사용하는 변수들 pthread_t thrid; int status; // 데몬으로 변신! if(fork() != 0){ exit(0); } // stdout 을 닫음. close(1); setsid(); fd = open(MODEMDEVICE,O_RDWR|O_NOCTTY); if(fd<0){perror(MODEMDEVICE);exit(-1);} tcgetattr(fd,&oldtio); bzero(&newtio,sizeof(newtio)); // 터미널 관련 값 설정. newtio.c_cflag = BAUDRATE|CS8|CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 1; tcflush(fd,TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); // 시스템 트레이와 통신할 FIFO를 만든다. mkfifo("/tmp/exdt",0777); // 시스템 트레이 아이콘을 만든다. systemTrayIcon(); fifofd = open("/tmp/exdt",O_WRONLY); // LCD 에 정보를 뿌림. pthread_create(&thrid,NULL,showLCD,NULL); while(1){ res = read(fd, buf, 100); buf[res] = 0; printf("%s",buf); // 데탑 전환.. intrAction(buf); } tcsetattr(fd,TCSANOW,&oldtio); pthread_join(thrid,(void **)&status); } void systemTrayIcon() { int pid; if((pid = fork())){ // 부모 return; }else{ // 자식 execvp("StatusIcon.py",NULL); } } void signal_handler_IO(int status) { wait_flag = TRUE; putchar('.'); } // 이전 명령이 있었던 시간과 비교해서, // 그 차이가 너무 적으면 false 를 반환한다. int ignGo(int sec, int mil) { printf("ps: %ld.%d\n",ps_sec,ps); printf("nw: %ld.%d\n",sec,mil); if((sec-ps_sec)>1){ // 시간이 1초이상 차이나면 통과. ps_sec = sec; ps = mil; return 1; }else if((sec-ps_sec)==1){ // 시간이 1초 차이나면, 밀리세컨드 단위는 현재 값이 더 적으므로 // 1000을 더하고.. mil += 1000; } ps_sec = sec; if((mil-ps) <= 300){ // 그 차이가 300밀리 세컨드 이하이면, 연달아 인터럽트 발생한것이므로 // false 리턴. ps = mil; return 0; }else{ // 그 이상이면 명령 허가. ps = mil; return 1; } } void intrAction(char *intr) { // 1~3 바이트 마다 read 하므로 당최 알 수 없다. // 그래서 버퍼를 적분하는 함수를 만들었다. strcat(intrcmd,intr); if(strstr(intr,"\r") || strstr(intr,"\n") || strstr(intr,"\r\n")){ if(!strncmp(intrcmd,"INT3",4)){ // 3으로 끝나면 외부 인터럽트 3번. // 왼쪽으로 이동한다. goWM(LEFT); }else if(!strncmp(intrcmd,"INT2",4)){ // 2로 끝나면 외부 인터럽트 2번. // 오른쪽으로 이동한다. goWM(RIGHT); } write(fifofd,intrcmd,strlen(intrcmd)); bzero(intrcmd,1024); } } void withMetacity(int dir) { FILE *fp; char buf[1024]={0}; int nowDT=0; // wmctrl 을 이용한다. fp = popen("wmctrl -d | awk '{print $1,$2;}'","r"); while(fgets(buf,1024,fp)){ if(buf[2] == '*'){ buf[1] = '\0'; // 0 * DG ... // 1 - DG ... // 이런식으로 들어가 있기 때문에, buf[1] 에 '\0' 을 넣고 // atoi 를 하면 바로 현재 데스크탑의 번호를 구할 수 있다. nowDT = atoi(buf); break; } } pclose(fp); if(dir==RIGHT){ nowDT++; // 데탑은 4개라고 고정해서 생각한다. // XXX 이후에 수정해야 함. nowDT = (nowDT < 4)?nowDT:4; printf(" Right\n"); }else{ nowDT--; nowDT = (nowDT >0)?nowDT:0; printf(" Left\n"); } // 실행. sprintf(buf,"wmctrl -s%d",nowDT); system(buf); } void withBeryl(int dir) { char *dbusString = "dbus-send --type=method_call --dest=org.freedesktop.beryl /org/freedesktop/beryl/rotate/allscreens/rotate_%s org.freedesktop.beryl.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'`"; char buf[1024] = {0}; if(dir == RIGHT){ sprintf(buf,dbusString,"right"); printf(" Right\n"); }else{ sprintf(buf,dbusString,"left"); printf(" Left\n"); } system(buf); } void goWM(int dir) { FILE *fp; char buf[1024]={0}; struct timeb tb; // 현재 시간을 구한다. ftime(&tb); if(!ignGo(tb.time, tb.millitm)){ // 직전 명령과 시간차가 300밀리세컨드 이상 이어야 이후 // 코드를 수행한다. 300밀리세컨드 이하이면 여기서 리턴. return; } fp = popen("wmctrl -m | head -1 | awk '{print $2;}'","r"); while(fgets(buf,1024,fp)){ if(!strncmp(buf,"Metacity",8)){ withMetacity(dir); }else if(!strncmp(buf,"beryl",5)){ withBeryl(dir); } } pclose(fp); return ; } /*********************************************************** * * 다른 스레드 * ***********************************************************/ void parseLvr(char *l) { int fp; char buf[1024] = {0}; char tempLvr[1024] = {0}; fp = open("/proc/loadavg",O_RDONLY); read(fp,buf,1024); close(fp); char *lvr; lvr = strstr(buf," "); strncpy(tempLvr,buf,lvr-buf); sprintf(l,"LVR %s",tempLvr); } int parse(char *t, char *c, char *b) { char *con; if(strstr(b,"load")){ return 0; } con = strstr(b,":"); strncpy(t,b,con-b); sprintf(c,"%s",con+1); c[strlen(c)-1] = '\0'; return 1; } void split(char dest[50][1024], char *src, char delim){ int i,j=0,k=0; int isdelim = 0; for(i= 0; i < strlen(src); i++){ if(src[i] != delim){ if(src[i] == '\n') continue; dest[j][k++] = src[i]; isdelim = 0; }else{ if(isdelim) continue; j++; k = 0; isdelim = 1; } } } void getCpuInfo(char *c) { FILE *stat; char buf[1024] = {0}; char result[50][1024]; stat = fopen("/proc/stat","r"); fgets(buf, 1024,stat); fclose(stat); memset(result,0,(50*1024)); split(result,buf,' '); // cpu 의 각 모드별 클럭 사용량을 구한다. long us,ni,sy,id, total; us = atol(result[1]); ni = atol(result[2]); sy = atol(result[3]); id = atol(result[4]); total = us+ni+sy+id; // 각 모드별 클럭 사용 비율을 구한다. float usp, nip, syp, idp; usp = (float)us/(float)total*100; nip = (float)ni/(float)total*100; syp = (float)sy/(float)total*100; idp = (float)id/(float)total*100; memset(c,0,1024); sprintf(c,"%2.2f%% us, %2.2f%% ni, %2.2f%% sy, %2.2f%% id",usp,nip,syp,idp); } void getTaskInfo(char *c) { FILE *task; char buf[1024] = {0}; int R=0,S=0,T=0,W=0,Z=0; task = popen("ps -eo stat","r"); while(fgets(buf, 1024, task)){ switch(buf[0]){ case 'R': R++; break; case 'S': S++; break; case 'T': T++; break; case 'W': W++; break; case 'Z': Z++; break; } } pclose(task); int To=0; To = R+S+T+W+Z; memset(c,0,1024); sprintf(c,"%d Total, %d Run, %d Sleep, %d Stop, %d paging, %d Zombies", To, R, S, T, W, Z); } void getMemInfo(char *c) { FILE *meminfo; char buf[1024] = {0}; char result[50][1024]; meminfo = popen("free","r"); fgets(buf,1024,meminfo); // 첫번째 줄 무시.. fgets(buf,1024,meminfo); pclose(meminfo); memset(result,0,(50*1024)); split(result,buf,' '); long to,us,fr,sh,bu,ca; to = atol(result[1]); us = atol(result[2]); fr = atol(result[3]); sh = atol(result[4]); bu = atol(result[5]); ca = atol(result[6]); memset(c,0,1024); sprintf(c,"%ldK Total, %ldK Used, %ldK Free, %ldK Shared, %ldK Buffers, %ldK Cached",to,us,fr,sh,bu,ca); } void getSwapInfo(char *c) { FILE *meminfo; char buf[1024] = {0}; char result[50][1024]; meminfo = popen("free","r"); fgets(buf,1024,meminfo); fgets(buf,1024,meminfo); fgets(buf,1024,meminfo); // 위로 세줄 무시 fgets(buf,1024,meminfo); pclose(meminfo); memset(result,0,(50*1024)); split(result,buf,' '); long to,us,fr,sh,bu,ca; to = atol(result[1]); us = atol(result[2]); fr = atol(result[3]); memset(c,0,1024); sprintf(c,"%ldK Total, %ldK Used, %ldK Free",to,us,fr); } void getSystemInfo() { FILE *fp; char buf[1024] = {0}; char lvr[10] = {0}; char title[10] = {0}; char contents[1024] = {0}; /* fp = popen("top -n1 | head -5 | sed -e 's/\\(B//g' | sed -e 's/\\\\[.....m//g' | sed -e 's/\\\\[.//g'","r"); while(fgets(buf, 1024, fp)){ if(!parse(title,contents,buf)) continue; printScrolledLCD(title,lvr,contents); } pclose(fp); */ getCpuInfo(contents); printScrolledLCD("Cpu",lvr,contents); getTaskInfo(contents); printScrolledLCD("Task",lvr,contents); getMemInfo(contents); printScrolledLCD("Memory",lvr,contents); getSwapInfo(contents); printScrolledLCD("Swap",lvr,contents); } void printLCD(char *s) { char data[33] = {0}; strncpy(data,s,32); // 전송시작 알림 unsigned char h = 1; write(fd,&h,1); usleep(100); int i; for(i=0; i < 32 ; i++){ write(fd,&data[i],1); usleep(100); } // 전송종료 알림 h = 3; write(fd,&h,1); usleep(100); } void makeUpperLine(char *u, char *t, char *l) { int i; int t_len = strlen(t); int l_len = strlen(l); memset(u,0,17); strncpy(u, t, t_len); int remaind = 16 - strlen(u); remaind -= l_len; for(i=0 ; i title + lvr parseLvr(l); makeUpperLine(upperLine,t,l); // 두번째 줄을 만든다. // 한글자씩 앞 에서 부터 버린다. (스크롤 효과.) memset(underLine, 0, 1024); memset(underLine, ' ', 500); strncpy(underLine,c+i,c_len-i); memset(data,0,1024); strcat(data,upperLine); strcat(data,underLine); printLCD(data); // printf("%s\n",data); usleep(200000); } } void *showLCD(void *arg) { while(1){ getSystemInfo(); } pthread_exit(NULL); return 0; }