1. 程式人生 > >Unix/Linux程式設計實踐教程–od在OS X的實現

Unix/Linux程式設計實踐教程–od在OS X的實現

環境:OS X 10.12.4

抱歉,本文章並不是關於Ollydbg的實現(笑)。

照舊man 1 od

od 是一個能把指定的檔案或者標準輸入按照使用者定義的格式列印。(
The od utility is a filter which displays the specified files, or standard input if no files are specified, in a user specified format.)

乍一看這個命令的引數有一大堆,本文只挑一部分去實現,包括-A指定地址基數,-j跳過指定數目的字元,-N最多列印n個字元。-t輸出格式。

實現起來並不難,只是引數比較多,實現起來比較繁瑣,同樣可以使用前面寫的xc_file.c

快取輸入。

od.c 不完全實現,BUG N多

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <limits.h>

enum{
    DEC,
    HEX,
    OCT,
    NOADDR
}addr_base, output_format;

void xc_open(char *aFName);
void xc_readFromStdin(void);
int xc_getchar(void
); void xc_close(void); void xc_moveto(int offset, int whence); void print_char(int ch, int size); void print_addr(int addr); void format_error(void); int dump_bytes(char *str); /* Usage: od [-A base] [-j skip] [-N length] [-t type] [file] */ /* default for od -t o2 [file] if no option is given */ int
main(int ac, char *av[]) { addr_base = OCT; int skip = 0; int length = INT_MAX; int cnt = 0; int size = 2; /* output size */ int i, j; int end_print = 0; int bytes_print; output_format = OCT; while(--ac && (*++av)[0] == '-'){ switch(*++av[0]){ case 'A': switch((*++av)[0]){ case 'd': addr_base = DEC; break; case 'o': break; case 'x': addr_base = HEX; break; case 'n': addr_base = NOADDR; break; default: format_error(); } --ac; /* substract because read a option value */ break; case 'j': skip = dump_bytes(*++av); if(skip <= 0) format_error(); --ac; /* substract because read a option value */ break; case 'N': length = atoi(*++av); if(length <= 0) format_error(); --ac; /* substract because read a option value */ break; case 't': switch((*++av)[0]){ case 'd': /* signed decimal */ case 'u': /* unsigned decimal */ /* do not reconize signed or unsigned */ output_format = DEC; break; case 'o': /* octal */ output_format = OCT; break; case 'x': /* hexadecimal */ output_format = HEX; break; default: format_error(); } switch(*++av[0]){ case 'C': size = sizeof(char); break; case 'S': size = sizeof(short); break; case 'I': size = sizeof(int); break; case 'L': size = sizeof(long); break; default: if(*av[0] >= '0' && *av[0] <= '9') { size = atoi(av[0]); if(size <= 0) format_error(); }else format_error(); break; } --ac; /* substract because read a option value */ break; } } if(ac == 1) xc_open(*av); else xc_readFromStdin(); /* default `skip` is zero if `-j` option is not given */ xc_moveto(skip, SEEK_SET); cnt = skip; while(cnt < length && !end_print){ int size_count = 0; int buf[sizeof(long)]; int tmpValue = 0; int ch; print_addr(cnt); while(cnt < length && !end_print){ size_count = 0; while(size_count < size && cnt < length && (ch = xc_getchar()) != EOF){ buf[size_count++] = ch; cnt++; } tmpValue = 0; for(i = size_count - 1; i >= 0; --i) tmpValue = tmpValue * 256 + buf[i]; print_char(tmpValue, size); if(ch == EOF || cnt == length){ // int tmp = cnt; // while(++tmp % 16) // ; // tmp = (tmp - cnt) / size; // while(tmp--) // print_char(' ', size); end_print = 1; while(++cnt % 16) ; } if(cnt % 16 == 0){ /* 16 bytes per line */ printf("\n"); break; } } } print_addr(cnt); printf("\n"); xc_close(); return 0; } void print_char(int ch, int size) { switch(output_format){ case OCT: switch(size){ case 1: printf(" %.3o", ch); break; case 2: printf(" %.6o", ch); break; case 4: break; } break; case DEC: printf("%d ", ch); break; case HEX: printf("%x ", ch); break; } } void print_addr(int addr) { switch(addr_base){ case OCT: printf("%.7o ", addr); break; case HEX: printf("%.7x ", addr); break; case DEC: printf("%.7d ", addr); break; case NOADDR: printf("%7.7s ", " "); break; } } int dump_bytes(char *str) { int ans = 0; while(*str >= '0' && *str <= '9'){ ans = ans * 10 + (*str - '0'); str++; } switch(*str){ case '\0': break; case 'b': /* block(512 bytes) */ ans *= 512; break; case 'k': /* kilobyte */ ans *= 1024; break; case 'm': /* megabyte */ ans *= 1024 * 1024; break; } return ans; } void format_error(void) { fprintf(stderr, "Usage: od [-A base] [-j skip] [-N length] [-t type] [file]\n"); exit(1); }

xc_file.c

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

/* BUFSIZ define in stdio.h, commonly is 1024 */
static unsigned char chBuf[BUFSIZ];
static int fd = -1;
static char fName[BUFSIZ];
static int chCur;
static int chSum;

void xc_readFromStdin(void)
{
    /* define in unistd.h */
    fd = STDIN_FILENO;
}

void xc_open(char *aFName)
{
    if((fd = open(aFName, O_RDONLY)) == -1){
        perror(aFName);
        exit(1);
    }
    strcpy(fName, aFName); /* record which file is opened */
    chCur = chSum = 0;
}

int xc_reload(void)
{
    int bytes_read;
    if((bytes_read = read(fd, chBuf, BUFSIZ)) > 0){
        chCur = 0;
        chSum = bytes_read;
        return chBuf[chCur++];
    }else if(bytes_read == -1){
        perror(fName);
        exit(1);
    }else if (bytes_read == 0)
        return EOF;
}

int xc_getchar(void)
{
    if(fd == -1)
        return EOF;
    if(chSum == chCur)
        return xc_reload();
    return chBuf[chCur++];
}

void xc_close(void)
{
    if(fd != -1)
    {
        if(close(fd) == -1){
            perror(fName);
            exit(1);
        }
        fd = -1;
    }
}
void xc_moveto(int offset, int whence)
{
    if(fd == -1)
        return ;
    if(lseek(fd, offset, whence) == -1){
        perror("target position are illegal");
        exit(1);
    }
}

效果

這裡寫圖片描述