/* 
written by kaspy (kaspyx@gmail.com)
*/ 


정말로 오랫만에 toybox 관련 포스팅을하는데

예전에 strings 라는 명령어를 기부(contribution) 했을때 소스코드입니다.

strigns 명령어는 바이너리에 존재하는 출력가능한 아스키코드등을 출력해주는 명령어입니다.

toybox 인프라에 맞게 코딩을 한후 toybox@lists.landley.net 으로 보내주면 됩니다.


  1. /*strings.c - print the strings of printable characters in files.
  2.  *
  3.  * Copyright 2014 Kyung-su Kim <kaspyx@gmail.com>
  4.  * Copyright 2014 Kyungwan Han <asura321@gmail.com>
  5.  *
  6.  * No Standard
  7.  * TODO: utf8 strings
  8.  * TODO: posix -t
  9.  
  10. USE_STRINGS(NEWTOY(strings, "an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
  11.  
  12. config STRINGS
  13.   bool "strings"
  14.   default n
  15.   help
  16.     usage: strings [-fo] [-n LEN] [FILE...]
  17.  
  18.     Display printable strings in a binary file
  19.  
  20.     -f  Precede strings with filenames
  21.     -n  At least LEN characters form a string (default 4)
  22.     -o  Precede strings with decimal offsets
  23. */
  24.  
  25. #define FOR_strings
  26. #include "toys.h"
  27.  
  28. GLOBALS(
  29.   long num;
  30. )
  31.  
  32. void do_strings(int fd, char *filename)
  33. {
  34.   int nread, i, wlen = TT.num, count = 0;
  35.   off_t offset = 0;
  36.   char *string = xzalloc(wlen + 1);
  37.  
  38.   for (;;) {
  39.     nread = read(fd, toybuf, sizeof(toybuf));
  40.     if (nread < 0) perror_msg("%s", filename);
  41.     if (nread < 1) break;
  42.     for (= 0; i < nread; i++, offset++) {
  43.       if (((toybuf[i] >= 32) && (toybuf[i] <= 126)) || (toybuf[i] == '\t')) {
  44.         if (count == wlen) fputc(toybuf[i], stdout);
  45.         else {
  46.           string[count++] = toybuf[i];
  47.           if (count == wlen) {
  48.             if (toys.optflags & FLAG_f) printf("%s: ", filename);
  49.             if (toys.optflags & FLAG_o)
  50.               printf("%7lld ",(long long)(offset - wlen));
  51.             printf("%s", string);
  52.           }
  53.         }
  54.       } else {
  55.         if (count == wlen) xputc('\n');
  56.         count = 0;
  57.       }
  58.     }
  59.   }
  60.   xclose(fd);
  61.   free(string);
  62. }
  63.  
  64. void strings_main(void)
  65. {
  66.   loopfiles(toys.optargs, do_strings);
  67. }

위의 코드는 rob이 다듬어준 코드인데, 원래 코드는 어디있는지 까먹어버렸네요 보내준 소스코드를 rob 에게로부터 간단한 소스코드 리뷰를 받고, 좀더 다듬어서 최종 commit이 되게됩니다.

아래는 rob으로부터 받은 code review 내용입니다.

나중에 UTF8 옵션에대한 처리가 필요하다고 하는군요

그리고 fencepost 오류가 있을거같았다고 했는데 아니었다는군요~!
(fencepost 에러?? -> http://egloos.zum.com/tools/v/18549)

보는바와같이 어렵지 않은 명령어도 많으니 리눅스 명령어 개발 및 Contribution에 관심이 많으신분은 한번 도전해보세요~!


 

Tweak help so -N is consistently using "LEN" isntead of sometimes "count".

 

Redo the read() part to catch errors in reading from the file. (I'd like to have a warning-only version of xread() but we'd still have to check for errors on return to break out of the file, so it wouldn't save us much. Have to think about it...)

 

This doesn't handle UTF8 strings. At some point in the future I may want to redo it so it does. (I guess 4 consecutive valid utf8 characters count as a hit, and then continue as long as the utf8 sequences are valid? Not sure how that would affect the false positive rate...)

 

Posix wants -t and hex output, this doesn't do that. Might also revisit for that. Accept (and ignore) -a.

 

Redo output so only the newline is using xputc(), and the other stuff is using printf() and fputc(). The rationale is to let the stdio buffer do its thing, rather than making a syscall for every byte. Hopefully if we have a short write stdio will notice and either retry or set the error flag, and then xputc() catches the error flag and the error case of nontransient output failure (disk full, pipe to a dead process, etc).

For the common case stdio should buffer the output and xputc flush it anyway.

 

trivial: I made wlen be equal to TT.len instead of TT.len-1, had the assignment postincrement, and checked for equality rather than greater than. (Having the constraint be TT.len-1 and the allocation be TT.len+1 looked like a fencepost error. It wasn't, but I didn't want other readers to have to work out why.)

 

Couple whitespace tweaks. Other than that, it was in pretty good shape.

 

Rob

_______________________________________________

Toybox mailing list

Toybox@lists.landley.net

http://lists.landley.net/listinfo.cgi/toybox-landley.net







저작자 표시
신고
Posted by 캐스피
/* 
written by kaspy (kaspyx@gmail.com)
*/ 

toybox 공식 홈페이지 : http://www.landley.net/toybox/


- 리눅스 유틸리티 프로그램

- BSD License


안녕하세요 이어서 toybox 오픈소스 프로젝트 참여하기 2부를 쓰도록 하겠습니다.


참고로 toybox는 안드로이드 및 타이젠에도 탑재된다고 하니 toybox는 앞으로도 더욱 많이 쓰여질거 같네요!!


busybox을 대체하기에도 좋은 툴인거같습니다.


아래 설명은 http://www.landley.net/toybox/code.html 에나와있는 내용을 정리한 내용입니다.


1. Toybox 코딩 스타일


vimrc


toybox 코딩스타일은 기본적으로 리눅스 커널 코딩 스타일을 따릅니다.


첨부한 vimrc라는 파일을 받아서 사용하면 됩니다. 


cp ~/vimrc ~/vimrc.bak

vi ~/.vimrc

첨부한 파일내용 저장

source ~/.vimrc

 

2. 명령어 파라미터 옵션


 저번장에서 명령어를 추가 구현하는 내용에 대해서 다루었습니다. 이번에는 명령어 구현시 필요한 명령어 파라미터 옵션에 대해서 설명을 해보도록 하겠습니다. 이에대한 내용은 /toys/example/skeleton.c 라는 파일을 참조하면 이해하기좋습니다. 이전 내용은 여기를 참조해주시구요


명령어 파라미터 옵션은 '인자' 라고 쓰도록 하겠습니다.


아래 파일을 열어서


cd toybox

vi toys/example/skeleton.c

 

16번째쯤 라인의 default n -> y로 수정해주세요




그리고 빌드를 진행해줍니다


make clean

make defconfig

make

 

이를 실행해주면 인자에 대한 입력값을 확인할수 있습니다.



그럼 이런 입력된 파라미터는 어떻게 처리해야 할까요?


바로 요놈을 보시면 됩니다. (11,12 라인 부근)



우리가 봐야할건 빨강색 박스의 첫번째 라인입니다.(두번째 라인까지는 안봐도됨)


앞에있는 (walrus) 긴 인자에 대한 입력값입니다. 예를들어 긴 인자이름에 대한 입력값은 괄호 열고 닫고로 '(asfd)' 으로 표현합니다.


"toybox skeleton --walrus" 라고 입력을 하였다면 아래와 같이 출력됩니다.



위그림처럼, walrus라는 옵션에 맞는 조건이 있다면 따로 처리해주면 됩니다. ( '--argv' 형식으로 입력)


또한 단일 인자에 대한 입력은 문자 하나로 지정해주면 됩니다. ( '-a' 형식으로 입력)


그렇다면 뒤에 붙어있는 특수한 문자는 뭘까요?


예를들어 (walrus) 뒤에있는 (also): 이거 (콜론 하나':') 말입니다. 


toybox 홈페이지에서는 입력 인자에대한 정보를 아래와 같이 설명하고있습니다.

  • : - plus a string argument, keep most recent if more than one. : 문자열을 추가로 입력받음
  • * - plus a string argument, appended to a linked list. : 문자열을 띄어쓰기로 여러개 입력받음
  • @ - plus an occurrence counter (stored in a long) : 인자가 몇번 나왔는지 셈
  • # - plus a signed long argument. : 양수 숫자를 추가로 입력받음
  • - - plus a signed long argument defaulting to negative (start argument with + to force a positive value). : 양수를 입력받으나, 음수로 처리함
  • . - plus a floating point argument (if CFG_TOYBOX_FLOAT). : 부동소수를 추가로 입력받음
    • The following can be appended to a float or double:
    • <123 - error if argument is less than this
    • >123 - error if argument is greater than this
    • =123 - default value if argument not supplied

':' 라는 옵션은 입력인자에 대한 문자열 값이 있을때 써주면됩니다.


예를들어 위의 입력 인자 선언구문


USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))


에서 "b:" 을 봐보도록 하겠습니다.


위에서 보면 알수있듯이 단일 입력인자 'b'는 문자열에 대한 정보를 입력받는 것입니다



위에 그림을 보는것과 같이 'b'라는 입력 인자에 추가 문자열을 넣어줬다니 잘 입력된것을 확인할수 있습니다.


만약 'b' 인자에 추가 문자열을 입력해주지 않으면 에러가 납니다. 그런 예외처리가 잘되어있어서 프로그래머에게는 편하겠군요.


나머지도 마찬가지로, 설명을 참고해주면 됩니다.


그리고 밑에 

    The following can be appended to a float or double:
  • <123 - error if argument is less than this
  • >123 - error if argument is greater than this
  • =123 - default value if argument not supplied

이것은 무슨말이냐하면, 정수를 추가로 받는 인자에 대한 기본값 및 에러값을 지정해주기 위해 사용할수 있습니다.


USE_STRINGS(NEWTOY(example, "n#=4<1", TOYFLAG_USR|TOYFLAG_BIN))


위와같이 n이라는 인자를 정수와 같이 입력받고, 입력이 없을시에는 기본값이 4이며, 1보다 작은값이 들어오면 에러라는 뜻입니다.


위에서 추가적으로 입력받는 인자들은 소스코드를 수정하여 전역변수로 선언해줘야 합니다.


아래와같은 몇개는 c언어 문법을 따르지 않습니다. 컴파일 하기전에 toybox에서 전처리 과정을 거쳐서 c언어문법에 맞게 바꿔줄것입니다.



실제로 저건 입력받는 인자들이 많아서 그런경우라서 복잡할수 있겠지만.. 한두개 인자들에대해 다루는 경우가 더 많기 때문에 위에 코드는 그냥 참고만 하시는게 좋습니다.


입력받은 인자들에대한 처리를 하는 코드를 보도록 하겠습니다. 아래 코드에대한 내용이 많아서 헛갈리수도 있겠지만 굳이 다 안알아도 되는 내용이고 참고로만 하도록 하겠습니다.



toybox의 전역변수가 있고, toys 구조체에 저장되어있는것을 볼수 있습니다.


이에 대한 접근은 toys.optflags과 같이 하면 됩니다.


전연변수를 사용하면 좋은점이 많습니다. 우선 toybox에서 공용으로 사용되는 메모리인 만큼, 메모리를 절약할수 있구요, 소스도 더 간결해집니다.


예를들어 문자열을 입력받는 버퍼를 지역버퍼로 선언하거나, 전역변수 (는 지양해야함)에 선언할수 있겠지만 


전역변수 버퍼인 toybuf를 활용하면 좋습니다.


toybox의 전역변수에 대한 더많은 내용을 보고싶다면 http://www.landley.net/toybox/code.html#top을 참고하시기 바랍니다.


3. 래퍼(wrapper) 함수


toybox에서는 자체적으로 래퍼(wrapper) 함수를 지원합니다. 아마도 보안이나 안정성을 좋게 하려고 만든것 같은데, 


아래와 같이 있습니다.

더많은 내용을 보고싶다면 http://www.landley.net/toybox/code.html#generated를 봐보시기 바랍니다.


4. 마치며


 이상으로 toybox 오픈소스 프로젝트를 참여하기 위한 기본적인 내용은 전부 다룬것 같습니다. 


추가적으로 필요한 것이 있다면 lib/dirtree.c 에 있는 함수를 설명하면 좋을것 같은데, 이것은 다음에 실제 contribution을 한 명령어를 예제로 활용하여 설명 하도록 하겠습니다.

저작자 표시
신고
Posted by 캐스피
/* 
written by kaspy (kaspyx@gmail.com)
*/ 

toybox 공식 홈페이지 : http://www.landley.net/toybox/


- 리눅스 유틸리티 프로그램

- BSD License


프로그래머라면 누구나 한번 해보싶은게 오픈소스에 참여하여 자신의 copyright이 새겨 contribution을 하는것을 해보고 싶지 않을까요??  


오픈소스 프로젝트 toybox에 참여하는것도 좋은 방법입니다.


아래 설명은 http://www.landley.net/toybox/code.html 에나와있는 내용을 정리한 내용입니다.


1. 소스코드 clone 하기


 오픈소스니까 당연히 소스코드가 공개되어있습니다!! mercurial을 통해서 소스코드를 가져오는방법입니다.
(머큐리얼 설치는 'sudo apt-get install mercurial')


아래 명령어는 홈 디렉토리 경로(~) 아래에있는 toybox 디렉토리에 최신버전에 대한 코드를 다운받는 명령입니다.


hg clone http://landley.net/hg/toybox ~/toybox



2. 빌드 & 컴파일 하기


 다운받은 소스코드를 빌드 하기위한 명령어는 아래와 같이 하나씩 순차적으로 실행해주면 됩니다.


첫번째 "make defconfig" 명령어는 빌드할 명령어를 어떤것들로 지정해주는지를 기본으로 지정해줍니다.


두번째는 지정된 명령어를 빌드를 합니다.

(마지막 "make install" 명령어는 굳이 실행하지 않아도 되는데 환경변수에 등록해주는 명령어입니다.)


make defconfig

make

make install


빌드가 완료되면 아래와 그림과 같이 초록색 이름인 실행 바이너리(ELF)가 만들어지게 되니다.



사용법은, 빌드한 toybox를 실행하려면 아래와 같이 "./toybox ls" 같이 명령어를 실행해줍니다.



help 명령어를 사용하여 각 명령어에대한 ls 명령어에대한 사용법(usage)를 확인할수 있습니다.



명령어들은 기본적으로 종류별 toybox 디렉토리 경로 아래 toys/posix, toys/android, toys/lsb 디렉토리 경로에 소스코드가 위치해있습니다.


3. 명령어 추가/구현 하기


1) 코딩 스타일: 기본적으로 리눅스 커널 코딩 스타일을 따르는데 관련 내용은 여기를 참조하면되는데, 뭐.. 그리중요하진않슴니다.


2) 샘플 코드 복사하기 


toybox는 아직 busybox에 비해 구현된 명령어가 부족한 편입니다. 


구현 완료된 명령어는 여기링크를 참조하고, 만들어보고 싶은 (간단한 명령어 부터)명령어가 있다면  도전해보는것도 좋을거같습니다.


명령어를 추가 구현하기위한 가장 좋은 방법은 toybox 내에 있는 샘플 명령어 소스코드를 복사해서 수정하여 사용하는 것이 제일 좋습니다.


샘플 소스코드는 toybox 디렉토리 아래 toys/example/hello.c 그리고 toys/example/skeleton.c 에 위치해있습니다.


hello.c 라는 파일은 "Hello world"를 출력해주는 간단한 샘플 코드입니다.


이파일을 복사 및 수정하여 새로운 명령어를 추가해보도록 하겠습니다.


 저는 first 라는 명령어로 이름을 정하여 설명 하도록 하겠습니다. 복사할 위치는 "toys/other" 디렉토리 경로 아래로합니다.

(cp toys/example/hello.c toys/other/first.c)



우선 hello.c 라는 소스코드의 내용은 아래와 같습니다. (수정해야할 내용은 빨강색 박스로 표시)



3) 코드 수정하기


위에 그림처럼 수정해야할 내용은 빨강색으로 표시를 해두었습니다.


첫번째 빨강색 박스는 구현한 날짜, 자신의 copyright 및 이메일주소, 레퍼런스 및 관련 URL을 기입합니다.


두번째 빨강색 박스는 config에 대한 파일입니다.


아래와 같이 수정해줍니다.


USE_HELLO(NEWTOY(hello, 0, TOYFLAG_USR|TOYFLAG_BIN))

 

config HELLO

  bool "hello"

  default n

USE_FIRST(NEWTOY(first, 0, TOYFLAG_USR|TOYFLAG_BIN))

 

config FIRST

  bool "first"

  default y


help 문자 아래는 "toybox help 명령어"를 쳤을때 사용법에 대한 내용을 출력해줍니다.


세번째 #define FOR_hello 는 #define FOR_first


맨 아래 hello_main() 은 first_main() 으로 수정해줍니다.


저는 first 라는 명령어를 그냥 제가 원하는 문자열을 출력해주게 만들었습니다(첨부파일 및 아래 그림 참조)

first.c




4) 명령어 빌드하기

 

 추가한 명령어는 2번의 과정을 다시 한번 해주면 됩니다.


반드시 "make clean" 명령어를 실행한 다음에 아래의 명령어를 순차적으로 실행해줍니다.


make clean

make defconfig #(or menuconfig)

make


추가한 명령어 실행은 아래와 같이 확인합니다.



4. 명령어 기부(Contribution) 하기


 구현 완성한 명령어는 toybox@lists.landley.net 에게 보내주면 됩니다. 물론 저런 명령어를 contribution 할수는 없겟죠.. 


하지만 리눅스를 다루면서 편리하게 할수있는 명령어나, 자신이 구현할줄아는 명령어가 있다면, 또는 새로운 명령어를 만들고싶다면 도전해보시기 바랍니다.


아래 링크, 메일링 리스트에 가입하여 toybox에 대한 궁긍한 내용이나 이슈를 같이 공유하는것도 좋은 방법입니다.


http://lists.landley.net/listinfo.cgi/toybox-landley.net


5. 마치며


 이로써 toybox 오픈소스 프로젝트에 대한 내용을 다루어보았습니다. 다음에는 tobyox 에서 사용하는 래퍼(wrapper) 함수 및 명령 옵션 파라미터 사용법 그리고 실제 contribution한 명령어를 다루도록 하겠습니다.


* 참조 내부링크


 - Toybox 오픈소스 프로젝트 소개


저작자 표시
신고
Posted by 캐스피
/* 
written by kaspy (kaspyx@gmail.com)
*/ 


toybox 공식 홈페이지 : http://www.landley.net/toybox/

프로그래머라면 누구나 한번쯤 관심가져볼만한(?)것이 바로 오픈소스 프로젝트에 참여하는거 아닐까요??ㅎㅎ
개발이 그리 많이되지않았고, 아직 그렇게 많이 알려지지않은 오픈소스 프로젝트가 있는데 하나 소개할까 합니다.

toybox는 리눅스 명령어를 모아둔 유틸리티로써 무료로 배포되는 오픈소스 프로젝트입니다. 2006년부터 개발이 시작되었고 Robert Landley(이하 Rob)에 의해서 유지보수 되고 있습니다. 비슷한 프로젝트로는 busybox나 toolbox 등이 있겠네요.


참고로 

Rob은 busybox 프로젝트 참여 멤버로서 있다가 따로 나와서 toybox 오픈소스를 만들었다고 하네요~


* toybox와 busybox의 다른점


 둘다 리눅스 명령어를 탑재한 유틸리티 오픈소스 프로젝트라는 것과 목적은 같지만 toybox는 BSD 라이선스를 사용하고 있지만 busybox는 GPL2 라이선스를 사용하고 있다는 점에서 조금 다릅니다.(그리고 busybox가 구현된 명령어가 훨씬 많습니다.)

라이선스 때문에 무슨 차이가 발생할수 있냐면 일반적으로 busybox나 toybox는 리눅스 운영체제를 탑재한 임베디드 환경에서 작동을 하는데(예를들어 스마트폰, TV, 냉장고 등등) 만약 busybox와같은 GPL2 라이선스를 사용하여 임베디드 환경에서 개발을 하게되면 busybox의 소스코드를 참고하여 만든 산출물은 모두 GPL2로 묶이게 된다는거죠. 그래서 제품을 출시할때에도 제품 가이드 문서등에 이 제품은 busybox 유틸을 사용하였다는 고지문과 함께 관련 소스코드도 반드시 공개를 해야한다는 원칙을 가지게 됩니다.

그러나 toybox는 조금 다른 BSD 라이선스를 사용하고 있는데, 이 라이선스는 소스코드를 사용하게되도 그냥 toybox 소스코드를 썻다는 고지문 하나만 제품 가이드 문서에 고지하면 되는것입니다.

만약 오픈소스 라이선스에 대한 준수사항을 지키지 않으면 위반에 해당되어 법적으로 소송을 받을수도 있습니다.


* toybox 특징

- 디자인 및 목적

 toybox는 심플함과 경량화 그리고 빠른 속도 그리고 모든 명령어 지원을 추구합니다.

 명령어 구현 및 속도 그리고 사이즈의 경량화의 추진의 최적화를 목표로 개발 중입니다.

 명령어 구현 roadmap은 여기를 클릭해주세요

 

- 이식성 문제

리눅스 운영체제 계열에서 작동함

32bit/64bit 지원

Unsigned char 기본 문자

문자열 처리는 UTF8로 하는것이 최종목표


바이너리 다운로드 

http://www.landley.net/toybox/bin/


나는 리눅스용 x86/64bit 바이너리를 다운받았습니다.


현재 toybox에서 지원하는 명령어는 아래와 같습니다.


acpi base64 basename blkid blockdev bzcat cal cat catv chattr chgrp

chmod chown chroot chvt cksum clear cmp comm count cp cpio cut date

df dirname dmesg dos2unix du echo egrep eject env expand factor false

fgrep find free freeramdisk fsfreeze fstype grep groups halt head

help hexedit hostname hwclock id ifconfig inotifyd insmod install

ionice iorenice kill killall killall5 link ln login logname losetup

ls lsattr lsmod lspci lsusb makedevs md5sum mix mkdir mkfifo mknod

mkpasswd mkswap mktemp modinfo mount mountpoint mv nbd-client nc netcat

nice nl nohup nproc nsenter od oneit partprobe passwd paste patch

pidof pivot_root pmap poweroff printenv printf pwd pwdx readahead

readlink realpath reboot renice reset rev rfkill rm rmdir rmmod sed

seq setsid sha1sum shred sleep sort split stat strings su swapoff

swapon switch_root sync sysctl tac tail taskset tee time timeout touch

true truncate tty umount uname uniq unix2dos unlink unshare uptime

usleep uudecode uuencode vconfig vmstat w wc which who whoami xargs

xxd yes


분명 busybox의 명령어에 비해 없거나 부족한 기능이 많을수 있겠지만 라이선스도 자유롭고 busybox만의 무거움을 탈출하고 싶다면 toybox를 사용해도 좋을것이라고 생각합니다.ㅋ



저작자 표시
신고
Posted by 캐스피


티스토리 툴바