APUE 책에 IF - ELSE로 구현 된 것을 switch - case로 재구현 한 것. stat 스트럭쳐 의 st_mode 의 내부를 들여다 본 것.

헤더파일과 구현부로 나뉘어 있음.

 
/* Header : myhdr.h */

#include <sys/types.h>
#include <sys/stat.h>
#include "ourhdr.h"

//Defined Values
#define N_IFREG 32768 // 1000 0000 0000 0000
#define N_IFDIR 16384 // 0100 0000 0000 0000   
#define N_IFCHR 8192 // 0010 0000 0000 0000
#define N_IFBLK 24576 // 0110 0000 0000 0000
#define N_IFIFO 4096 // 0001 0000 0000 0000
#define N_IFLNK 40960 // 1010 0000 0000 0000
#define N_IFSOCK 49152 // 1100 0000 0000 0000
#define MASK 61440 // 1111 0000 0000 0000

/* End of myhdr.h */

/* Source : file_mode.c */

#include "myhdr.h"

int main(int argc, char *argv[])
{
    int  i; //for loop
    int   mode ; //mode checker by bits
    struct stat buf;
    char  *ptr;

    for (i = 1; i < argc; i++)
    {
        printf("%s: ", argv[i]);
        if (lstat(argv[i], &buf) < 0)
        {
            err_ret("lstat error");
            continue;
        }

        mode = buf.st_mode & MASK; //Masking

        switch (mode)
        {
            case N_IFREG :
                ptr = "regular";
            break;

            case N_IFDIR :
                ptr = "directory";
            break;

            case N_IFCHR :
                ptr = "character special";
            break;

            case N_IFBLK :
                ptr = "block special";
            break;

            case N_IFIFO :
                ptr = "fifo";
            break;

#ifdef S_IFLNK
            case N_IFLNK :
                ptr = "symbolic link";
            break;
#endif
#ifdef S_IFSOCK
            case N_IFSOCK :
                ptr = "socket";
            break;
#endif
            default :
                ptr = "** unknown mode **";
            break;    
        }//end of switch

        printf("%s\n", ptr);

    }//end of for

    exit(0);
}
/* End of file_mode.c */

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

File mode checker  (0) 2008.08.12
myShell  (0) 2008.08.12
myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

입력받은 커맨드를 실행하고, 그 실행 시간을 측정한다. 유닉스 쉘의 입력 부분만 흉내낸 것

Get command from user, then calculate the command's execute time.
This is a simple UNIX shell. Just make command input part
 

#include <sys/types.h> //for types for time and etc.
#include <sys/wait.h>  //for wait()
#include <signal.h>  //for signal catching
#include "ourhdr.h"  //System Programming Default Header
#include <sys/times.h> //for times()

//functions
static void sig_int(int);  /* our signal-catching function */
static void report(void);  // print report
static void pr_times(clock_t, struct tms *, struct tms *); //time checker

//global variable : to save data
char cmd[80][80];
double rtime[80];
double utime[80];
double stime[80];

int num_of_cmd = -1; // counter

// MAIN  //////////////////////////////////////

int main(void)
{
    char buf[MAXLINE];
    pid_t pid;
    int status;
    struct tms tmsstart, tmsend; //structure for time check
    clock_t start, end;   //variable for time

    if (signal(SIGINT, sig_int) == SIG_ERR) //signal checker
    { err_sys("signal error"); }

    printf("%% "); /* print prompt (printf requires %% to print %) */

    while (fgets(buf, MAXLINE, stdin) != NULL)  //^D를 제외한 입력의 경우 : ^D이면 루프 끝
    {
        buf[strlen(buf) - 1] = 0; /* replace newline with null */
        num_of_cmd++; // Counter ++

        if ( (pid = fork()) < 0)
        { err_sys("fork error"); }
        else if (pid == 0)
        {
            /* child */
            execlp(buf, buf, (char *) 0);  //입력받은 커맨드 실행 후 else if 블록을 빠져나감
            // 커맨드가 실행되지 않는 경우
            err_ret("couldn't execute: %s", buf);
            exit(127);
        }

        strcpy (cmd[num_of_cmd], buf);  //입력 받은 커맨드를 전역변수 배열에 저장

        if ( (start = times(&tmsstart)) == -1) /* starting values */
        { err_sys("times error"); }

        /* parent */
        if ( (pid = waitpid(pid, &status, 0)) < 0)
        { err_sys("waitpid error"); }

        if ( (end = times(&tmsend)) == -1)  /* ending values */
        { err_sys("times error"); }

        pr_times(end-start, &tmsstart, &tmsend); //시간 계산
        printf("%% "); //프롬프트 출력
    }

    report(); //^D 입력시 루프 종료 후 결과 표시

    exit(0);
}

void sig_int(int signo) //시그널 입력 시 출력
{
 //printf("interrupt\n%% ");
}

static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) // 시간 체크
{
    static long clktck = 0;

    if (clktck == 0) /* fetch clock ticks per second first time */
    {
        if ( (clktck = sysconf(_SC_CLK_TCK)) < 0) //시스템 상수를 받아옴
        { err_sys("sysconf error"); }
    }

    // fprintf(stderr, "  real:\t\t%7.2f\n", real / (double) clktck);
    // fprintf(stderr, "  user:\t\t%7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
    // fprintf(stderr, "  system:\t%7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);

    rtime[num_of_cmd] = real / (double) clktck; //시간을 계산하여 배열에 저장
    utime[num_of_cmd] = (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck;
    stime[num_of_cmd] = (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck;
}

void report(void)
{
    int loop;

    for (loop = 0; loop <=num_of_cmd; loop++) //전체 시행 시간을 계산, 배열의 마지막에 추가
    {
        strcpy (cmd[num_of_cmd+1], "Total");
        rtime[num_of_cmd+1] += rtime[loop];
        utime[num_of_cmd+1] += utime[loop];
        stime[num_of_cmd+1] += stime[loop];
    }

    // 출력 시작
    printf ("\n\t\tProcess\tSystem time\tUse time\tReal time\n");

    for (loop = 0; loop <=num_of_cmd; loop++)
    {
        if (rtime[loop]==0 && utime[loop]==0 && stime[loop]==0) //커맨드 오류시 모든 시간이 0로 표시됨을 이용, 에러커맨드는 출력하지 않음
        {   /* Do nothing */    }
        else
        {
            fprintf(stderr, "  %s:\t", cmd[loop]);
            fprintf(stderr, "  \t\t%7.2f",rtime[loop]);
            fprintf(stderr, "  \t%7.2f", utime[loop]);
            fprintf(stderr, "  \t%7.2f\n", stime[loop]);
        }
    }

    // total 값 출력
    printf ("-------------------------------------------------------------------\n");
    fprintf(stderr, "  %s:\t", cmd[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f",rtime[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f", utime[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f\n", stime[num_of_cmd+1]);
}

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

File mode checker  (0) 2008.08.12
myShell  (0) 2008.08.12
myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

파일의 내용을 보여주거나, 둘 이상의 파일을 내용을 합쳐서 출력해주는 cat(1)을 직접 구현한 것.

cat는 유닉스에 기본으로 포함되어 있는 명령어이다.

 

#include "ourhdr.h"  //기본 헤더파일 //Common header

int main (int argc, char *argv[])
{
    FILE *file[argc-1];  //파일 포인터 배열 : 입력 받은 파일 명의 수 만큼 파일포인터를 선언
    int loop;    //순환문을 위한 변수
    char buffer;   //Read Buffer

    if (argc <2)   //입력받은 파라메터의 수를 확인
    { err_quit ("Error - One or more parameter is needed."); } //에러 메세지

    for (loop = 0; loop <argc -1; loop++) //출력 루프
    {
        if ( (file[loop] = fopen( argv[loop+1], "r" ) ) ==NULL) //파일 Open이이 실패한 경우
        {
            printf ("cat : %s : No such file or directory\n", argv[loop+1]); //에러메세지
        }
        else           //파일 Open이 성공한 경우
        {
            while ( (buffer = fgetc(file[loop]) )> 0)   //한 바이트씩 읽어서 출력
            {
                printf ("%c",buffer);     //STDOUT 출력
            }     

            if ( (fclose (file[loop])) !=0 )     //출력이 끝나면 파일 Close
            {
                err_sys("%d번째 파일", loop);    //Close 실패 시 에러메세지
            }  
        }
    }

    return 0;
}

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

File mode checker  (0) 2008.08.12
myShell  (0) 2008.08.12
myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

UNIX의 wc(1)의 기능을 구현한 것.

#include "ourhdr.h"  //System Programming Default Header

enum bool {false, true}; //C dosen't support the "boolean" type. So, I defined as enumeration type.


/////////////////////////////////////////
//main function  ////////////
////////////////////////////////////////

int main (int agrc, char *agrv[])
{
    int c = 0;       //get character input
    int lines = 0, words = 0 , bytes = 0; //count lines, words, bytes
    enum bool real_word = false;   //check a byte whether a part of the first word or not

    while ( (c = getchar() )> 0)    //count loop - until EOF (This retuns -1)
    {
        if (c > 33)     //check first character is input or not
            real_word = true;  //character inputed

        if (c=='\n')     //check new-line character
        {
            lines++;     //line count
            words++;     //word count
        }
        else if (c==' ' || c=='\t' || c=='\r' || c=='\v' || c=='\f') //check word seperation conditions
        {
            if (real_word)      //first character inputed
                words++;        //word count
        }

        bytes++;      //byte count
    }

    if (ferror(stdin))     //check stdin error
        err_sys("input error");  //system error massage

    printf ("      %d       %d      %d\n", lines, words, bytes); //print out to stdout

    return 0;
}

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

myShell  (0) 2008.08.12
myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
ourhdr.h  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

Advanced Programming in the UNIX Environment 의 기본적인 error처리 library. 컴파일 해서 Object파일을 만든 후, 실제 실행파일 컴파일 시 링크시켜 줄 것.

 

#include <errno.h>  /* for definition of errno */
#include <stdarg.h>  /* ANSI C header file */
#include "ourhdr.h"

static void err_doit(int, const char *, va_list);

char *pname = NULL;  /* caller can set this from argv[0] */

/* Nonfatal error related to a system call.
 * Print a message and return. */

void
err_ret(const char *fmt, ...)
{
    va_list  ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error related to a system call.
 * Print a message and terminate. */

void
err_sys(const char *fmt, ...)
{
    va_list  ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Fatal error related to a system call.
 * Print a message, dump core, and terminate. */

void
err_dump(const char *fmt, ...)
{
    va_list  ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    abort();  /* dump core and terminate */
    exit(1);  /* shouldn't get here */
}

/* Nonfatal error unrelated to a system call.
 * Print a message and return. */

void
err_msg(const char *fmt, ...)
{
    va_list  ap;

    va_start(ap, fmt);
    err_doit(0, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error unrelated to a system call.
 * Print a message and terminate. */

void
err_quit(const char *fmt, ...)
{
    va_list  ap;

    va_start(ap, fmt);
    err_doit(0, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Print a message and return to caller.
 * Caller specifies "errnoflag". */

static void
err_doit(int errnoflag, const char *fmt, va_list ap)
{
    int  errno_save;
    char buf[MAXLINE];

    errno_save = errno;  /* value caller might want printed */
    vsprintf(buf, fmt, ap);
    if (errnoflag)
        sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
    strcat(buf, "\n");
    fflush(stdout);  /* in case stdout and stderr are the same */
    fputs(buf, stderr);
    fflush(NULL);  /* flushes all stdio output streams */
    return;
}

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
ourhdr.h  (0) 2008.08.10
Advanced Programming in the UNIX Environment  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

역시, Advanced Programming in the UNIX Environment(이하 APUE)의 기본 헤더파일. 다운 받아도 좋고, 직접 긁어 저장해도 좋다.
 

/* Our own header, to be included *after* all standard system headers */

#ifndef __ourhdr_h
#define __ourhdr_h

#include <sys/types.h> /* required for some of our prototypes */
#include <stdio.h>  /* for convenience */
#include <stdlib.h>  /* for convenience */
#include <string.h>  /* for convenience */
#include <unistd.h>  /* for convenience */

#define MAXLINE 4096   /* max line length */

#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
     /* default file access permissions for new files */
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
     /* default permissions for new directories */

typedef void Sigfunc(int); /* for signal handlers */

     /* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
#if defined(SIG_IGN) && !defined(SIG_ERR)
#define SIG_ERR ((Sigfunc *)-1)
#endif

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

     /* prototypes for our own functions */
char *path_alloc(int *);   /* {Prog pathalloc} */
int   open_max(void);   /* {Prog openmax} */
void  clr_fl(int, int);   /* {Prog setfl} */
void  set_fl(int, int);   /* {Prog setfl} */
void  pr_exit(int);    /* {Prog prexit} */
void  pr_mask(const char *);  /* {Prog prmask} */
Sigfunc *signal_intr(int, Sigfunc *);/* {Prog signal_intr_function} */

int   tty_cbreak(int);   /* {Prog raw} */
int   tty_raw(int);    /* {Prog raw} */
int   tty_reset(int);   /* {Prog raw} */
void  tty_atexit(void);   /* {Prog raw} */
#ifdef ECHO /* only if <termios.h> has been included */
struct termios *tty_termios(void); /* {Prog raw} */
#endif

void  sleep_us(unsigned int); /* {Ex sleepus} */
ssize_t  readn(int, void *, size_t);/* {Prog readn} */
ssize_t  writen(int, const void *, size_t);/* {Prog writen} */
int   daemon_init(void);   /* {Prog daemoninit} */

int   s_pipe(int *);    /* {Progs svr4_spipe bsd_spipe} */
int   recv_fd(int, ssize_t (*func)(int, const void *, size_t));
         /* {Progs recvfd_svr4 recvfd_43bsd} */
int   send_fd(int, int);   /* {Progs sendfd_svr4 sendfd_43bsd} */
int   send_err(int, int, const char *);/* {Prog senderr} */
int   serv_listen(const char *); /* {Progs servlisten_svr4 servlisten_44bsd} */
int   serv_accept(int, uid_t *); /* {Progs servaccept_svr4 servaccept_44bsd} */
int   cli_conn(const char *); /* {Progs cliconn_svr4 cliconn_44bsd} */
int   buf_args(char *, int (*func)(int, char **));
         /* {Prog bufargs} */

int   ptym_open(char *);   /* {Progs ptyopen_svr4 ptyopen_44bsd} */
int   ptys_open(int, char *); /* {Progs ptyopen_svr4 ptyopen_44bsd} */
#ifdef TIOCGWINSZ
pid_t  pty_fork(int *, char *, const struct termios *,
      const struct winsize *); /* {Prog ptyfork} */
#endif

int  lock_reg(int, int, int, off_t, int, off_t);
         /* {Prog lockreg} */
#define read_lock(fd, offset, whence, len) \
   lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
#define readw_lock(fd, offset, whence, len) \
   lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)
#define write_lock(fd, offset, whence, len) \
   lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
#define writew_lock(fd, offset, whence, len) \
   lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)
#define un_lock(fd, offset, whence, len) \
   lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)

pid_t lock_test(int, int, off_t, int, off_t);
         /* {Prog locktest} */

#define is_readlock(fd, offset, whence, len) \
   lock_test(fd, F_RDLCK, offset, whence, len)
#define is_writelock(fd, offset, whence, len) \
   lock_test(fd, F_WRLCK, offset, whence, len)

void err_dump(const char *, ...); /* {App misc_source} */
void err_msg(const char *, ...);
void err_quit(const char *, ...);
void err_ret(const char *, ...);
void err_sys(const char *, ...);

void log_msg(const char *, ...);  /* {App misc_source} */
void log_open(const char *, int, int);
void log_quit(const char *, ...);
void log_ret(const char *, ...);
void log_sys(const char *, ...);

void TELL_WAIT(void);  /* parent/child from {Sec race_conditions} */
void TELL_PARENT(pid_t);
void TELL_CHILD(pid_t);
void WAIT_PARENT(void);
void WAIT_CHILD(void);

#endif /* __ourhdr_h */


'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
ourhdr.h  (0) 2008.08.10
Advanced Programming in the UNIX Environment  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

http://www.yendor.com/programming/unix/apue/apue.html


Advanced Programming in the


UNIX Environment

by W. Richard Stevens

Addison-Wesley Professional Computing Series
0-201-56317-7 * Hardback * 768 pages * ©1992
Web/HTML/man-page-linking by: Ariel Faigon


위 주소에 가면 이 책의 모든 소스를 구할 수 있다.


정말, 주옥같은 소스코드들이 실려있는 책이다. 아직 본격적으로 본문을 읽지는 않고, 소스코드만 보고 있는데, 그것만으로도 이 책의 진가를 알 수 있다.

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10
ourhdr.h  (0) 2008.08.10
Advanced Programming in the UNIX Environment  (0) 2008.08.10
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


BLOG main image
일상, 프로그래밍, IT 그리고 직장생활, Dive, 여행 by 지그프리드

카테고리

Class List (402)
Studies (30)
Exercise & Quizz (10)
Term Project (0)
ECIM list (Help!) (10)
Issues & News (0)
Gossip about IT & Job (22)
Tools (2)
Think about the Justice (23)
Book Review (170)
조엘 온 소프트웨어(번역) (28)
Diary (87)
Vacations (9)
Clash of clans 클래시 오브.. (11)

글 보관함

달력

«   2019/10   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Total : 314,682
Today : 22 Yesterday : 15