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);
    }
}

效果

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值