libuvでcat

uvbookのサンプルをベースに複数ファイルを読めるcatを書いてみた

Filesystem — An Introduction to libuv

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

#define BUFSIZE 2048

void on_open(uv_fs_t *);
void on_read(uv_fs_t *);
void on_write(uv_fs_t *);
void on_close(uv_fs_t *);
void do_cat(const char *);

struct cat_t {
    int argc;
    char **argv;
    uv_file file;
    uv_fs_t open_req;
    uv_fs_t read_req;
    uv_fs_t write_req;
    uv_buf_t iov;
    char buffer[BUFSIZE];
} cat;


void on_open(uv_fs_t *req) {
    if (req->result >= 0) {
        cat.argc--;
        cat.argv++;
        cat.file = req->result;
        uv_fs_read(uv_default_loop(), &cat.read_req, cat.file, &cat.iov, 1, -1, on_read);
    } else {
        fprintf(stderr, "open error: %s\n", uv_strerror(req->result));
    }
}

void on_read(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "read error: %s\n", uv_strerror(req->result));
    } else if (req->result == 0) {
        uv_fs_t close_req;
        uv_fs_close(uv_default_loop(), &close_req, cat.file, NULL);

        if (cat.argc > 0)
            do_cat(*cat.argv);
    } else if (req->result > 0) {
        cat.iov.len = req->result;
        uv_fs_write(uv_default_loop(), &cat.write_req, 1, &cat.iov, 1, -1, on_write);
    }
}

void on_write(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "write error: %s\n", uv_strerror(req->result));
    } else {
        uv_fs_read(uv_default_loop(), &cat.read_req, cat.file, &cat.iov, 1, -1, on_read);
    }
}

void on_close(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "close error: %s\n", uv_strerror(req->result));
    }
    uv_fs_req_cleanup(req);
}


void do_cat(const char* filename) {
    uv_fs_open(uv_default_loop(), &cat.open_req, filename, O_RDONLY, 0, on_open);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s [filename ...]\n", argv[0]);
        exit(1);
    }
    cat.argc = --argc;
    cat.argv = ++argv;

    cat.iov = uv_buf_init(cat.buffer, sizeof(cat.buffer));
    do_cat(*cat.argv);
    uv_run(uv_default_loop(), UV_RUN_DEFAULT);

    uv_fs_req_cleanup(&cat.write_req);
    uv_fs_req_cleanup(&cat.read_req);
    uv_fs_req_cleanup(&cat.write_req);
    return 0;
}

メモ

  • uv_fs_openのcallbackのresultはuv_file_t

ncursesを試す

cでncursesを試すのに、moreとかlessっぽいアレを作ってみた。

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

int main(int argc, char **argv) 
{
    char *filename;
    FILE *fp;
    int ch;
    int h, w;
    int lineno = 1;
    int input;
    WINDOW *win;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
        exit(1);
    }

    filename = argv[1];
    if ((fp = fopen(filename, "r")) == NULL) {
        fprintf(stderr, "Could not open %s\n", filename); 
        exit(1);
    }

    win = initscr();
    noecho();
    cbreak();
    getmaxyx(win, h, w);
    scrollok(win, TRUE);

    while ((ch = fgetc(fp)) != EOF) {
        if (ch == '\n') {
            if (h <= lineno) {
                break;
            }
            wmove(win, lineno++, 0);
        } else {
            waddch(win, ch);
        }
    }
    refresh();

    while ((input = getch()) != 'q') {
        if (ch == EOF) {
            wmove(win, h-1, 0);
            wprintw(win, "(END)");
        } else {
            wscrl(win, 1);
            wmove(win, h-1, 0);
            while ((ch = fgetc(fp)) != EOF) {
                if (ch == '\n') {
                    lineno++;
                    break;
                }
                waddch(win, ch);
            }
            refresh();
        }
    };

    endwin();
    return 0;
}

メモ

  • 左上端の座標が(0, 0)
  • initscr()の返り値はWINDOW *
  • scrollok(win, TRUE) でスクロール許可
  • getmaxyx(win, y, x) でウィンドウのサイズを取得
  • wscrl(win, n)でn行スクロール

vimにflake8の構文チェックを入れる

vimでflake8を使うために、syntasticというプラグインを入れた

github.com

READMEに従って、pathogenとsyntasticを.vimの下にダウンロードする

mkdir -p ~/.vim/autoload ~/.vim/bundle && \
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim

cd ~/.vim/bundle && \
git clone https://github.com/scrooloose/syntastic.git

~/.vimrcに設定を追加

"syntasticの設定
execute pathogen#infect()
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0

"flake8
let g:syntastic_python_checkers = ['flake8']
let g:flake8_cmd="~/.pyenv/versions/3.4.2/bin/flake8"

タブ、末尾スペースの可視化

デフォルトのままだと、listモードでタブでインデントされたファイルの表示が崩れるのでlistcharsを設定した。

行末の$は個人的にいらない子なので、タブと末尾スペースを可視化するように設定した。

set list
set listchars=tab:>-,trail:-

蛇足

setコマンドのオプションの後ろに!をつけると、オプションのトグル

set list!

?をつけると現在の値の表示

set listchars?

Raspberry PiにWifiを設定する

Raspberry Pi 2 B+をWifiでインターネットにつながるように設定した。

使ったWifi USBドングルはこれ

BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM

BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM

まずはドングルを指してから、認識されているか確認

$ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 04f3:0103 Elan Microelectronics Corp.
Bus 001 Device 005: ID 045e:07b2 Microsoft Corp.
Bus 001 Device 007: ID 0411:01a2 BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070]

ドングルが認識されていたら、WPAパスを設定する。 ルーターの本体にSSIDとパスが書かれているはずなので、それをwpa_passphraseに食わせてスニペットを作る。

$ wpa_passphrase "YOUR_NETWORK_NAME" "YOUR_NETWORK_PASSWORD"
network={
    ssid="YOUR_NETWORK_NAME"
    #psk="YOUR_NETWORK_PASSWORD"
    psk=55717106e3e40a8778275318b42399b8040accb6fb28f60c076380c59b1803ed
}

wpa_passphraseの出力結果を/etc/wpa_supplicant/wpa_supplicant.confにコピペして追加の項目を設定する。 部屋のBuffaloのWIFIルータの場合、WPA2なので以下のように設定した。

$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
network={
    ssid="YOUR_NETWORK_NAME"
    #psk="YOUR_NETWORK_PASSWORD"
    psk=55717106e3e40a8778275318b42399b8040accb6fb28f60c076380c59b1803ed
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=CCMP
    auth_alg=OPEN
}

/etc/network/interfacesを編集してwlan0を設定する。

$ sudo vi /etc/network/interfaces
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

最後にネットワークを再起動

$ sudo service networking restart