데비안에서는 FreeNX 패키지를 기본으로 제공하지 않기 때문에 저장소 추가가 필요하다. 다음 줄을 '/etc/apt/source.list' 에 추가한다.

deb http://www.linux.lk/~anuradha/nx/ ./

이렇게 하고 나면 다음과 같이 하는 것으로 설치가 가능하다.

# apt-get update
# apt-get install freenx

설치하면 몇가지를 물어보는데 key는 nomachine key로 하는 것이 편하다. 보안을 위해서라면 ssh를 위한 키를 새로 만들어 써도 무방하다. 설치가 끝나면 다음과 같이 사용자를 등록한다.

# nxserver --adduser < 유저명>
# nxserver --passwd < 유저명>

설정파일 '/etc/nxserver/node.conf를 적당히 고쳐준다. ssh 포트 번호와 kde, gnome 실행파일이 적혀있는 부분의 주석을 풀어주면 된다.

SSHD_PORT=ssh 포트번호
COMMAND_START_KDE=startkde
COMMAND_START_GNOME=gnome-session

이렇게 하고 클라이언트로 접속하면 안되는 경우가 있는데, 특히 Detail 메지시에서 'NX> 1004 Error: nxagent failed to start with: Unrecognized option: 1' 란 메시지가 나오고 접속이 안될때는 Backingstore 문제라고 한다. 이 문제는 '/usr/bin/nxnode' 파일을 편집하는 것으로 해결이 가능하다.

...
node_start_agent()
...
[ -n "$backingstore" ] && B="-bs $backingstore"
# 다음을 추가한다.
# backingstore = { "when_requested", "always", ... }
[ -n "$backingstore" -a "$ENABLE_2_0_0_BACKEND" != "1" -a "$backingstore" != "1" ] && B="-bs $backingstore"
# backingstore = 1 (new nxclient 2.0.0 doesn't send any strings in the option-string for backingstore anymore)
[ -n "$backingstore" -a "$ENABLE_2_0_0_BACKEND" != "1" -a "$backingstore" = "1" ] && B="+bs"
# backingstore = 1 and 2.0.0-Backend EXPERIMENTAL
[ -n "$backingstore" -a "$ENABLE_2_0_0_BACKEND" = "1" ] && B="-bs $backingstore"

출처 : http://openfacts.berlios.de

GNU enscript를 이용해서 소스를 하이라이팅해서 ps 파일로 만들 수 있다.

$ enscript -Bp OUTPUT_FILE.ps --color -E CODE_FILE.c

enscript는 꽤 많은 옵션을 가지고 있으며, 'enscript --help'를 이용해 옵션을 확인할 수 있다. 다른 옵션을 사용하면, 페이지를 다른 모양으로 꾸미는 것도 가능하고, ps 파일 외에 html로 만드는 것도 가능하다. 이렇게 만들어진 ps파일은 'ps2pdf'를 이용해서 pdf로 쉽게 만들 수 있다.

$ ps2pdf INPUT.ps OUTPUT.pdf

pdf 문서 뒤쪽에 소스 파일을 첨부하고 싶을 경우에는 pdf 합치는 유틸리티인 'pdftk'를 이용하면 된다.

$ pdftk 1.pdf 2.pdf ... n.pdf output OUTPUT.pdf

한가지 단점이 있다면, enscript가 한글을 지원하지 않아서 소스 안에 주석으로 달린 한글이 모두 깨진다는 문제가 있었다. /etc/enscript.cfg 파일에서 인코딩 관련 설정을 고치면 될 것도 같은데, 아직 해결 방법은 모르겠다.

NetworkManager는 자동으로 AP를 찾아서 접속을 해주어서 편하긴 하지만, (우리 학교처럼) 제대로 동작하지 않는 AP가 있는 곳에서 해당 AP로 접속이 한번 이루어지면 다른 AP로 전환이 되지 않는 경우가 생겼다.

이러한 경우가 나의 경우 (Linksys WPC54G v3, xubuntu 6.06) 에서만 발생하는지 어떤지는 잘 모르겠지만, 제대로 동작하는 다른 AP로 먼저 접속하면 인터넷 연결에 문제가 없었기 때문에 잘못된 AP로 먼저 접속하는 것만 막으면, 문제가 해결되었다.

그 방법으로는, ~/.gconf/system/networking/wireless/networks/ 디렉토리 안에 있는 AP정보들이 담긴 디렉토리 중에서, 잘못된 AP의 이름을 가진 디렉토리를 지워주면, NetworkManager가 잘못된 AP로 자동 접속하는 것을 막을수 있다.

'Operating' 카테고리의 다른 글

소스 하이라이팅해서 출력하기  (0) 2006.10.10
WPC54G on ubuntu 6.06 dapper LTS  (0) 2006.09.22
우분투 XGL/compiz  (0) 2006.08.21

Linksys 사에서 나온 PCMCIA 타입의 무선 랜카드 중에 하나인 WPC54G 를 우분투에서 기본 지원하지 않는다. 리눅스 커널에서 지원하지 않기 때문인데, 내 랜카드가 바로 이것이다. 리눅스에서 지원하지 않는 이것을 사용하기 위한 방법이 나와있는데, 그것이 바로 ndiswrapper를 이용해서 Windows Driver를 사용하는 방법이다.

# apt-get install ndiswrapper-utils bcm43xx-fwcutter

Linksys 사이트로 가서 Windows Driver를 다운로드 받는다. v1,v2,v4용이 있지만 v3 용은 존재하지 않으니 CD에서 직접 복사해야 한다. Driver를 받아왔으면 적당한 디렉토리에 압축을 푼 뒤에 다음을 수행한다.

# bcm43xx-fwcutter bcmwl5.sys
# cp *.fw /lib/firmware
# ndiswrapper -i LSBCMNDS.inf

이것으로 랜카드는 잡혔고, 다음으로 network-admin을 이용해서 네트워크 설정(IP입력등..)만 마무리 하면 끝이다.

마지막으로 WPC54G v3 Driver를 첨부한다.

wpc54g31.zip


/*
ID: ****
LANG: C
TASK: friday
*/

/*#define __DEBUG__*/

#include <stdio.h>

int main()
{
    int period, last, year, leap, i;
    int day=0; // 0=Mon ... 6=Sun
    int count[7];
    for(i=0 ; i<7 ; i++)
        count[i] = 0;
#ifndef __DEBUG__
    FILE *fin;
    FILE *fout;
   
    fin = fopen("friday.in","r");
    fout = fopen("friday.out","w");
    fscanf(fin,"%d",&period);
#else
    do{
        printf("Enter period(N years) : ");
        scanf("%d",&period);
    }while(period<=0 || period>400);
#endif

    last = 1900+period;

    for(year=1900 ; year<last ; year++)
    {
        if(year%100 == 0)
        {
            if(year%400 == 0)
                leap = 1;
            else
                leap = 0;
        }
        else if(year%4 == 0)
            leap = 1;
        else
            leap = 0;

        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+leap)%7;
        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+2)%7;
        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+2)%7;
        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+2)%7;
        count[day]++;
        day = (day+3)%7;
        count[day]++;
        day = (day+2)%7;
        count[day]++;
        day = (day+3)%7;
    }

#ifndef __DEBUG__
    for(i=0 ; i<6 ; i++)
        fprintf(fout,"%d ",count[i]);
    fprintf(fout,"%dn",count[6]);
    fclose(fin);
    fclose(fout);
#else
    for(i=0 ; i<7 ; i++)
        printf("%d ",count[i]);
#endif
    return 0;
}

1900년부터 시작해서 주어진 몇년의 기간동안 날짜가 13일이 되는 요일의 수를 구하는 프로그램인데, 조금 생각하고 코딩을 했더니 결과가 너무 지저분해졌다. 게다가 1월부터 12월까지 달마다 요일을 구하는 부분에서 날짜를 미리 계산해서 넣는 만행을...;

저부분을 제대로 하자면, 각 달의 날짜수를 배열같은 곳에 저장해둔 다음, 윤년을 판단해서 윤년일 경우 2월 계산부분에 하루를 더해주고, 반복문으로 해결을 볼수 있을 듯한데, 일단 이걸로 이번문제는 통과..;;; 더 고치기가 귀찮다.

'Developing' 카테고리의 다른 글

The Java Programming Language - 1일차  (0) 2007.02.03
PERL에서의 웹 프로그래밍  (0) 2006.06.03
USACO Training - What Time Is It?  (0) 2006.05.15

Mac OS X 만 멋있는 줄 알았더니, 이제 리눅스도 이정도는 된다.

이런저런 문제들로 정신없는 와중에 새로운 일을 떠 맡았다. PHP와 펄을 이용한 간단한 웹 프로그래밍이었는데, 두가지 경우 모두 FORM을 이용해서 값을 넘겨받아야 했다. PHP의 경우는 그냥 간단히 name과 동일한 변수로 받아서 해결되었지만, 펄의 경우에는 약간 해줘야할 것이 있어서 머리가 아팠다. 아무래도 PHP처럼 원래 CGI 전용으로 나온 스크립트가 아니라서 그런가보다.

어쨌든 아래와 같은 방법으로 해결했다.

예제 : 간단한 사칙연산 프로그램

#!/usr/bin/perl

print "Content-type: text/htmlnn";
&parse;
$first = $FORM{'first'};
$second = $FORM{'second'};

print "<html><head><title>계산 결과</title></head><body>";
print "<h1>계산 결과</h1><br />";
print "<table><tr><td>더하기</td><td>";
print $first+$second;
print "</td></tr><tr><td>빼 기</td><td>";
print $first-$second;
print "</td></tr><tr><td>곱하기</td><td>";
print $first*$second;
print "</td></tr><tr><td>나누기</td><td>";
print $first/$second;
print "</td></tr><tr><td>나머지</td><td>";
print $first%$second;
print "</td></tr></table></body></html>";

sub parse {
  if($ENV{'REQUEST_METHOD'} eq "GET") {
      $buffer = $ENV{'QUERY_STRING'};
  }
  else {
      read( STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
  }

  @pairs = split(/&/,$buffer);

  foreach (@pairs) {
      ($name, $value) = split(/=/,$_);
      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;

      $FORM{$name} = $value;
  }
}

parse 부분이 핵심 부분인데, 거의 정형화되어있어서 다들 copy&paste한다고 한다.

'Developing' 카테고리의 다른 글

USACO Training - Friday the Thirteenth  (0) 2006.09.12
USACO Training - What Time Is It?  (0) 2006.05.15
USACO Training - Barn Repair  (0) 2006.05.09

/*
ID: ****
LANG: C
TASK: clock
*/

#define __DEBUG__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* itoc(int num);

int main()
{
    char* temp;
    char time[6];
    int hour;
    int min;
    char out[100];
#ifndef __DEBUG__
    FILE *fin;
    FILE *fout;
   
    fin = fopen("clock.in","r");
    fout = fopen("clock.out","w");
    fscanf(fin,"%s",time);
#else
    printf("Input time : ");
    scanf("%s",time);
#endif
   
    temp = strtok(time,":");
    hour = atoi(temp);
    temp = strtok(NULL,":");
    min = atoi(temp);
   
    switch(min)
    {
    case 0:
        sprintf(out,"%s o'clock",itoc(hour));
        break;
    case 15:
        sprintf(out,"Quarter past %s",itoc(hour));
        break;
    case 45:
        sprintf(out,"Quarter to %s",itoc(hour%12+1));
        break;
    default:
        if(min>45)
            sprintf(out,"%s to %s",itoc(60-min),itoc(hour%12+1));
        else
            sprintf(out,"%s %s",itoc(hour),itoc(min));
    }
    out[0]=toupper(out[0]);
#ifndef __DEBUG__
    fprintf(fout,"%sn",out);
    fclose(fin);
    fclose(fout);
#else
    printf("%sn",out);
#endif
    return 0;
}

char* itoc(int num)
{
    char* retval;
    retval = (char*)malloc(sizeof(char)*20);
   
    if(num<20)
    {
        switch(num)
        {
        case 1:    return "one";
        case 2:    return "two";
        case 3:    return "three";
        case 4:    return "four";
        case 5:    return "five";
        case 6:    return "six";
        case 7:    return "seven";
        case 8:    return "eight";
        case 9:    return "nine";
        case 10: return "ten";
        case 11: return "eleven";
        case 12: return "twelve";
        case 13: return "thirteen";
        case 14: return "fourteen";
        case 15: return "fifteen";
        case 16: return "sixteen";
        case 17: return "seventeen";
        case 18: return "eighteen";
        case 19: return "nineteen";
        default: return "";
        }
    }
    else
    {
        switch(num/10)
        {
        case 2:
            sprintf(retval,"twenty");
            break;
        case 3:
            sprintf(retval,"thirty");
            break;
        case 4:
            sprintf(retval,"forty");
            break;
        case 5:
            sprintf(retval,"fifty");
            break;
        }

        switch(num%10)
        {
        case 0:
            break;
        case 1:
            strcat(retval,"-one");
            break;
        case 2:
            strcat(retval,"-two");
            break;
        case 3:
            strcat(retval,"-three");
            break;
        case 4:
            strcat(retval,"-four");
            break;
        case 5:
            strcat(retval,"-five");
            break;
        case 6:
            strcat(retval,"-six");
            break;
        case 7:
            strcat(retval,"-seven");
            break;
        case 8:
            strcat(retval,"-eight");
            break;
        case 9:
            strcat(retval,"-nine");
            break;
        }
    }
    return retval;
}

상당히 간단한 문제였다.

'Developing' 카테고리의 다른 글

PERL에서의 웹 프로그래밍  (0) 2006.06.03
USACO Training - Barn Repair  (0) 2006.05.09
USACO Training - Mixing Milk  (0) 2006.05.03

/*
ID: ****
LANG: C
TASK: barn1
*/

/*#define __DEBUG__*/
#define MAXSTALL1 200+1

#include <stdio.h>

int main()
{
    int max, stal, cow;
    int i, temp;
    int before = 0;
    int total = 0;
    int ival[MAXSTALL1];
    int status[MAXSTALL1];
   
    for(i=0 ; i<MAXSTALL1 ; i++)
    {
        ival[i] = 0;
        status[i] = 0;
    }
   
#ifndef __DEBUG__
    FILE *fin;
    FILE *fout;
   
    fin = fopen("barn1.in","r");
    fout = fopen("barn1.out","w");
    fscanf(fin,"%d %d %d",&max,&stal,&cow);
#else
    printf("Input max & stall & cow : ");
    scanf("%d %d %d",&max,&stal,&cow);
#endif
   
    for(i=0 ; i<cow ; i++)
    {
#ifndef __DEBUG__
        fscanf(fin,"%d",&temp);
#else
        scanf("%d",&temp);
#endif
        status[temp] = 1;
    }
   
    for(i=0 ; i<=stal ; i++)
    {
        if(status[i] == 1)
        {
            if(before != 0)
                ival[i-before-1]++;
            before = i;
        }
    }
   
    max--;
    for(i=stal ; i>0 ; i--)
    {
        if(max > 0)
        {
            if(ival[i] >= max)
            {
                total += (ival[i] - max)*i;
                max = 0;
            }
            else
                max -= ival[i];
        }
        else
            total += ival[i]*i;
    }
#ifndef __DEBUG__
    fprintf(fout,"%dn",total+cow);
    fclose(fin);
    fclose(fout);
#else
    printf("%dn",total+cow);
#endif
    return 0;
}

저번 문제와 비슷한 접근 방법으로 문제를 해결했다.

주어진 갯수의 널판지로 최소한의 길이의 널판지를 이용해서 헛간을 고치겠다는 것이 문제였다. 비어있는 칸은 반드시 고칠 필요가 없고, 소가 있는 칸만 고치면 되므로, 소가 있는 칸 사이의 넓이가 가장 넓은 곳 부터 비우는 방식으로 널판지 갯수를 맞췄다.

소가 있는 칸 번호가 반드시 순서대로 들어오는 것은 아니므로 연산이 더 필요했다.

'Developing' 카테고리의 다른 글

PERL에서의 웹 프로그래밍  (0) 2006.06.03
USACO Training - What Time Is It?  (0) 2006.05.15
USACO Training - Mixing Milk  (0) 2006.05.03

구입할 우유의 양과 구입할 수 있는 목장의 수를 입력 받은 뒤에, 각 목장에서 판매할 수 있는 우유의 양과 가격을 입력받는다.

단위당 우유의 가격이 0~1000으로 한정되어 있는 것에 착안하여 1001짜리 배열을 생성한 뒤에 0으로 초기화 하고, 각 가격별로 구입할 수 있는 양을 더해서 0부터 시작해서 1000까지 구입할 양만큼만 값을 계산하도록 했다.

'Developing' 카테고리의 다른 글

PERL에서의 웹 프로그래밍  (0) 2006.06.03
USACO Training - What Time Is It?  (0) 2006.05.15
USACO Training - Barn Repair  (0) 2006.05.09

+ Recent posts