├── 10 ├── cur ├── pipe │ ├── Makefile │ ├── pip │ ├── pip.c │ ├── pipeDemo │ ├── pipeDemo.c │ ├── pipeDemo2 │ └── pipeDemo2.c ├── prev ├── stdin_redir └── stdin_redir1.c ├── 11 ├── popen.c ├── timeclient ├── timeclnt.c ├── timeserv ├── timeserv.c ├── tinybc └── tinybc.c ├── .gitignore ├── 01 └── more02.c ├── 02 ├── cp01.c ├── tmp ├── tmp.cop ├── utmplib.h └── who01.c ├── 03 ├── ls01.c ├── ls02.c └── utility.h ├── 04 └── spwd.c ├── 05 └── showtty.c ├── 06 ├── myerror ├── myplayagain ├── myplayagain3 ├── myplayagain5 ├── mysignal ├── play_again.c ├── play_again3.c └── signaldemo1.c ├── 07 ├── hello2.c ├── hello3.c ├── myhello ├── myhello2 ├── myticker1 ├── sigactiondemo.c ├── sigdemo3.c ├── sleeptest.c └── ticker_demo1.c ├── 08 ├── 8.2 ├── 8.2.c ├── 8.3 ├── 8.3.c ├── exec1 ├── exec1.c ├── forkdemo1 ├── forkdemo1.c ├── forkdemo2 ├── forkdemo2.c ├── forkdemo3.c ├── forkmode3 ├── promptSh1.c ├── promptSh2.c ├── psh1 ├── psh2 ├── testfile ├── waitdemo1 ├── waitdemo1.c ├── waitdemo2 └── waitdemo2.c ├── 09 ├── execute.c ├── script2.sh ├── smsh.h ├── smsh1.c ├── smsh2 │ ├── controlflow.c │ ├── execute.c │ ├── getenv │ ├── process.c │ ├── showenv │ ├── showenv.c │ ├── smsh.h │ ├── smsh2.c │ ├── splitline.c │ ├── testGetenv.c │ └── varlib.c └── splitline.c ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | my* 2 | !*.cpp 3 | !*.h 4 | !*.c 5 | -------------------------------------------------------------------------------- /01/more02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define LINELEN 512 4 | #define PAGELEN 24 5 | void do_more(FILE* f); 6 | int see_more(FILE* cmd); 7 | int main(int argc, char** argv) 8 | { 9 | FILE* fp; 10 | if(argc==1) 11 | do_more(stdin); 12 | else 13 | while(--argc) 14 | { 15 | if((fp=fopen(*(++argv),"r"))!=NULL) 16 | { 17 | do_more(fp); 18 | fclose(fp); 19 | } 20 | else 21 | exit(1); 22 | } 23 | return 0; 24 | } 25 | void do_more(FILE* fp) 26 | { 27 | char line[LINELEN]; 28 | int num_of_lines=0; 29 | int reply; 30 | FILE* tty_file; 31 | if((tty_file=fopen("/dev/tty","r"))==NULL) 32 | exit(1); 33 | 34 | while(fgets(line,LINELEN,fp)) 35 | { 36 | if(num_of_lines==PAGELEN) 37 | { 38 | reply=see_more(tty_file); 39 | if(reply==0) 40 | break; 41 | num_of_lines-=reply; 42 | } 43 | if(fputs(line,stdout)==EOF) 44 | exit(1); 45 | num_of_lines++; 46 | 47 | } 48 | } 49 | int see_more(FILE* cmd) 50 | { 51 | int c; 52 | printf("more?"); 53 | while((c=fgetc(cmd))!=EOF) 54 | { 55 | if(c=='q') 56 | return 0; 57 | if(c==' ') 58 | return PAGELEN; 59 | if(c=='\n') 60 | return 1; 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /02/cp01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUFSIZE 4096 7 | #define COPMODE 0644 8 | 9 | void oops(char*, char*); 10 | int main(int argc, char** argv) 11 | { 12 | int in_fd, out_fd, n_chars; 13 | char buf[BUFSIZE]; 14 | 15 | if(argc!=3) 16 | { 17 | fprintf(stderr,"usage:%s source destination\n",*argv); 18 | exit(1); 19 | } 20 | 21 | if((in_fd=open(argv[1],O_RDONLY))==-1) 22 | oops("Cann't open", argv[1]); 23 | if((out_fd=creat(argv[2],COPMODE))==-1) 24 | oops("Cann't creat", argv[2]); 25 | 26 | while((n_chars=read(in_fd,buf,BUFSIZE))>0) 27 | if(write(out_fd,buf,n_chars)!=n_chars) 28 | oops("Write error to", argv[2]); 29 | if(n_chars==-1) 30 | oops("Read error from",argv[1]); 31 | 32 | if(close(in_fd)==-1||close(out_fd)==-1) 33 | oops("Close file error",""); 34 | 35 | return 0; 36 | } 37 | void oops(char* err,char* err2) 38 | { 39 | fprintf(stderr,"Error: %s",err); 40 | perror(err2); 41 | exit(1); 42 | } 43 | -------------------------------------------------------------------------------- /02/tmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/02/tmp -------------------------------------------------------------------------------- /02/tmp.cop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/02/tmp.cop -------------------------------------------------------------------------------- /02/utmplib.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NUECS 16 7 | #define NULLUT ((struct utmp*)NULL) 8 | #define UTSIZE (sizeof(struct utmp)) 9 | 10 | static char utmpbuf[NUECS*UTSIZE]; 11 | static int num_recs; 12 | static int curr_recs; 13 | static int fd_utmp=-1; 14 | 15 | int utmp_open(char* filename) 16 | { 17 | fd_utmp=open(filename,O_RDONLY); 18 | curr_recs=num_recs=0; 19 | return fd_utmp; 20 | } 21 | 22 | struct utmp* utmp_next() 23 | { 24 | struct utmp* recp; 25 | if(fd_utmp==-1) 26 | return NULLUT; 27 | if((curr_recs==num_recs)&&(utmp_reload()==0)) 28 | { 29 | return NULLUT; 30 | } 31 | recp = (struct utmp*)&utmpbuf[curr_recs*UTSIZE]; 32 | curr_recs++; 33 | return recp; 34 | } 35 | 36 | int utmp_reload() 37 | { 38 | int utmp_read=read(fd_utmp,utmpbuf,NUECS*UTSIZE); 39 | num_recs=utmp_read/UTSIZE; 40 | curr_recs=0; 41 | return num_recs; 42 | } 43 | void utmp_close() 44 | { 45 | if(fd_utmp!=-1) 46 | close(fd_utmp); 47 | } 48 | -------------------------------------------------------------------------------- /02/who01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "utmplib.h" 8 | 9 | #define SHOWHOST /*include remote machine on output */ 10 | void show_info(struct utmp* utbufp); 11 | void show_time(long); 12 | int main(int argc, char** argv) 13 | { 14 | /* 15 | struct utmp current_record; 16 | int utmpfd; 17 | int reclen = sizeof(struct utmp); 18 | if((utmpfd=open(UTMP_FILE,O_RDONLY))==-1) 19 | { 20 | perror(UTMP_FILE); 21 | exit(1); 22 | } 23 | while(read(utmpfd,¤t_record,reclen)==reclen) 24 | { 25 | show_info(¤t_record); 26 | } 27 | close(utmpfd); 28 | */ 29 | struct utmp* utmpf; 30 | if((utmp_open(UTMP_FILE))==-1) 31 | perror(UTMP_FILE); 32 | 33 | while((utmpf=utmp_next())!=NULL) 34 | show_info(utmpf); 35 | utmp_close(); 36 | 37 | return 0; 38 | } 39 | void show_info(struct utmp* utbufp) 40 | { 41 | if(utbufp->ut_type!=USER_PROCESS) 42 | return ; 43 | printf("% -8.8s",utbufp->ut_user); 44 | printf(" "); 45 | printf("% -8.8s",utbufp->ut_line); 46 | printf(" "); 47 | //printf("%10ld",utbufp->ut_time); 48 | //printf(" "); 49 | show_time(utbufp->ut_time); 50 | #ifdef SHOWHOST 51 | if(utbufp->ut_host[0]!='\0') 52 | printf("(%s)",utbufp->ut_host); 53 | #endif 54 | printf("\n"); 55 | } 56 | void show_time(long time) 57 | { 58 | char* cp; 59 | cp = ctime(&time); 60 | printf("%s",cp); 61 | //it seems there is a '\n' 62 | 63 | } 64 | -------------------------------------------------------------------------------- /03/ls01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void do_list(char*, bool); 8 | bool start_dot(char*); 9 | int main(int argc, char** argv) 10 | { 11 | int a=0; 12 | bool flaga=false; 13 | if(argc==1) 14 | do_list(".",flaga); 15 | else 16 | while((++a)d_name)) 37 | printf("%s\n",dirent->d_name); 38 | else if(flaga) 39 | printf("%s\n",dirent->d_name); 40 | } 41 | closedir(dir_ptr); 42 | } 43 | bool start_dot(char* name) 44 | { 45 | return name[0]=='.'; 46 | } 47 | -------------------------------------------------------------------------------- /03/ls02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "utility.h" 8 | void do_list(char*); 9 | void dostat(char*); 10 | void show_file_info(char*, struct stat*); 11 | void mod_to_letters(int , char*); 12 | char* uid_to_name(uid_t); 13 | char* gid_to_name(gid_t); 14 | int main(int argc, char** argv) 15 | { 16 | if(argc==1) 17 | do_list("."); 18 | else 19 | while(--argc) 20 | { 21 | printf("%s:\n",*++argv); 22 | do_list(*argv); 23 | } 24 | return 0; 25 | 26 | } 27 | void do_list(char* dirname) 28 | { 29 | DIR* dir_ptr; 30 | struct dirent* dirent; 31 | 32 | if((dir_ptr=opendir(dirname))==NULL) 33 | fprintf(stderr,"ls can't open %s\n",dirname); 34 | else 35 | { 36 | while((dirent=readdir(dir_ptr))!=NULL) 37 | { 38 | dostat(dirent->d_name); 39 | } 40 | closedir(dir_ptr); 41 | } 42 | } 43 | void dostat(char* file) 44 | { 45 | struct stat info; 46 | if((stat(file,&info)==-1)) 47 | perror(file); 48 | else 49 | { 50 | show_file_info(file,&info); 51 | } 52 | } 53 | void show_file_info(char* filename, struct stat * info) 54 | { 55 | char mode[10]; 56 | mod_to_letters(info->st_mode,mode); 57 | printf("%s",mode); 58 | printf("%4d",(int)info->st_nlink); 59 | printf("%8s",uid_to_name(info->st_uid)); 60 | printf("%8s",gid_to_name(info->st_gid)); 61 | printf("%10ld",(long)info->st_size); 62 | printf("%.12s",4+ctime(&info->st_mtime)); 63 | printf("%s\n",filename); 64 | } 65 | void mod_to_letters(int mode, char* str) 66 | { 67 | strcpy(str,"----------"); 68 | if(S_ISDIR(mode)) 69 | str[0]='d'; 70 | if(S_ISCHR(mode)) 71 | str[0]='c'; 72 | if(S_ISBLK(mode)) 73 | str[0]='b'; 74 | 75 | if(mode& S_IRUSR) 76 | str[1]='r'; 77 | if(mode& S_IWUSR) 78 | str[2]='w'; 79 | if(mode & S_IXUSR) 80 | str[3]='x'; 81 | 82 | if(mode & S_IRGRP) 83 | str[4]='r'; 84 | if(mode & S_IWGRP) 85 | str[5]='w'; 86 | if(mode & S_IXGRP) 87 | str[6]='x'; 88 | 89 | if(mode & S_IROTH) 90 | str[7]='r'; 91 | if(mode & S_IWOTH) 92 | str[8]='w'; 93 | if(mode & S_IXOTH) 94 | str[9]='x'; 95 | 96 | } 97 | -------------------------------------------------------------------------------- /03/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTILITY_H__ 2 | #define __UTILITY_H__ 3 | #include 4 | #include 5 | char* uid_to_name(uid_t uid) 6 | { 7 | struct passwd * pw_ptr; 8 | static char numstr[10]; 9 | if((pw_ptr=getpwuid(uid))==NULL) 10 | { 11 | sprintf(numstr,"%d",uid); 12 | return numstr; 13 | } 14 | return pw_ptr->pw_name; 15 | } 16 | char* gid_to_name(gid_t gid) 17 | { 18 | struct group* grp_ptr; 19 | static char numstr[10]; 20 | if((grp_ptr=getgrgid(gid))==NULL) 21 | { 22 | sprintf(numstr,"%d",gid); 23 | return numstr; 24 | } 25 | return grp_ptr->gr_name; 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /04/spwd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFSIZE NAME_MAX 10 | ino_t get_inode(char*); 11 | void printpathto(ino_t); 12 | void inum_to_name(ino_t,char*,int); 13 | int main(int argc, char** argv) 14 | { 15 | printpathto(get_inode(".")); 16 | putchar('\n'); 17 | return 0; 18 | } 19 | ino_t get_inode(char* filename) 20 | { 21 | struct stat info; 22 | if(stat(filename,&info)==-1) 23 | { 24 | fprintf(stderr,"Cannot stat"); 25 | perror(filename); 26 | exit(1); 27 | } 28 | return info.st_ino; 29 | } 30 | void printpathto(ino_t this_node) 31 | { 32 | ino_t my_inode; 33 | char its_name[BUFSIZE]; 34 | if(get_inode("..")!=this_node) //if this is not root 35 | { 36 | chdir(".."); 37 | inum_to_name(this_node,its_name,BUFSIZE); 38 | my_inode=get_inode("."); 39 | printpathto(my_inode); //recursive print 40 | printf("/%s",its_name); 41 | } 42 | } 43 | void inum_to_name(ino_t inode_to_find, char* namebuf, int bufsize) 44 | { 45 | DIR* dir_ptr; 46 | struct dirent * direntp; 47 | dir_ptr=opendir("."); 48 | if(dir_ptr==NULL) 49 | { 50 | perror("."); 51 | exit(1); 52 | } 53 | while((direntp=readdir(dir_ptr))!=NULL) 54 | { 55 | if(direntp->d_ino == inode_to_find) 56 | { 57 | strncpy(namebuf, direntp->d_name, bufsize); 58 | namebuf[bufsize-1] = '\0'; //just in case 59 | closedir(dir_ptr); 60 | return ; 61 | } 62 | 63 | } 64 | fprintf(stderr, "error looking for inum %d\n",(int)inode_to_find); 65 | exit(1); 66 | 67 | } 68 | -------------------------------------------------------------------------------- /05/showtty.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | struct flaginfo 7 | { 8 | int fl_value; 9 | char* fl_name; 10 | }; 11 | struct flaginfo local_flags[]= 12 | { 13 | {ISIG, "Enble signal"}, 14 | {ICANON, "Cannonical input (erase and kill)"}, 15 | {ECHO, "Enable echo"}, 16 | {ECHOE, "Echo ERASE as BS-SPACE-BS"}, 17 | {ECHOK, "Echo KILL by starting new line"}, 18 | {0, NULL} 19 | }; 20 | struct flaginfo input_flags[]= 21 | { 22 | {IGNBRK, "Ignore break condition"}, 23 | {BRKINT, "Signal interrupt on break"}, 24 | {IGNPAR, "Ignore chars with parity erros"}, 25 | {PARMRK, "Mark parity errors"}, 26 | {INPCK, "Enable input parity check"}, 27 | {ISTRIP, "Strip character"}, 28 | {INLCR, "Map NL to CR on input"}, 29 | {IGNCR, "Ignore CR"}, 30 | {ICRNL, "Map CR to NL on input"}, 31 | {IXON, "Enable start/stop output control"}, 32 | {IXOFF, "Enable start/stop input control"}, 33 | {0, NULL} 34 | 35 | }; 36 | void showbaud(int thespeed); 37 | void show_flagset(int thevalue, struct flaginfo thebitnames[]); 38 | void show_some_flag(struct termios* ttyp); 39 | int main() 40 | { 41 | struct termios ttyinfo; 42 | if(tcgetattr(0, &ttyinfo)==-1) 43 | { 44 | perror("cann't not get params about stdin"); 45 | exit(1); 46 | } 47 | showbaud((int)cfgetospeed(&ttyinfo)); 48 | printf("The erase character is ascii %d, Ctrl-%c\n", 49 | ttyinfo.c_cc[VERASE], ttyinfo.c_cc[VERASE]-1+'A'); 50 | printf("The line kill character is ascii %d, Ctrl-%c\n", 51 | ttyinfo.c_cc[VKILL], ttyinfo.c_cc[VKILL]-1+'A'); 52 | show_some_flag(&ttyinfo); 53 | return 0; 54 | } 55 | void showbaud(int thespeed) 56 | { 57 | printf("The baud rate is"); 58 | switch(thespeed) 59 | { 60 | case B300: 61 | printf("300\n");break; 62 | case B600: 63 | printf("600\n");break; 64 | case B1200: 65 | printf("1200\n");break; 66 | case B1800: 67 | printf("1800\n");break; 68 | case B2400: 69 | printf("2400\n");break; 70 | case B4800: 71 | printf("4800\n");break; 72 | case B9600: 73 | printf("9600\n");break; 74 | default: 75 | printf("Fast\n");break; 76 | } 77 | } 78 | 79 | 80 | 81 | void show_some_flag(struct termios* ttyp) 82 | { 83 | show_flagset(ttyp->c_iflag, input_flags); 84 | show_flagset(ttyp->c_lflag, local_flags); 85 | } 86 | void show_flagset(int thevalue, struct flaginfo thebitnames[]) 87 | { 88 | int i; 89 | for(i=0;thebitnames[i].fl_value;i++) 90 | { 91 | printf("%s is", thebitnames[i].fl_name); 92 | if(thevalue & thebitnames[i].fl_value) 93 | printf("ON\n"); 94 | else 95 | printf("OFF\n"); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /06/myerror: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/06/myerror -------------------------------------------------------------------------------- /06/myplayagain: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/06/myplayagain -------------------------------------------------------------------------------- /06/myplayagain3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/06/myplayagain3 -------------------------------------------------------------------------------- /06/myplayagain5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/06/myplayagain5 -------------------------------------------------------------------------------- /06/mysignal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/06/mysignal -------------------------------------------------------------------------------- /06/play_again.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define QUESTION "Do you want another transaction" 4 | /*how==0 > save current mode how==1 >restore mode */ 5 | void tty_mode(int how) 6 | { 7 | static struct termios original_mode; 8 | if(how == 0) 9 | { 10 | tcgetattr(0,&original_mode); 11 | //0 is the standard input 12 | } 13 | else 14 | tcsetattr(0,TCSANOW, &original_mode); 15 | } 16 | void set_rc_noecho_mode(); 17 | int get_response(char*); 18 | int main() 19 | { 20 | int response; 21 | tty_mode(0); 22 | set_rc_noecho_mode(); 23 | response = get_response(QUESTION); 24 | tty_mode(1); 25 | return response; 26 | } 27 | void set_rc_noecho_mode() 28 | { 29 | struct termios ttystate; 30 | tcgetattr(0,&ttystate); 31 | ttystate.c_lflag &= ~ICANON; 32 | ttystate.c_lflag &= ~ECHO; 33 | ttystate.c_cc[VMIN] = 1; 34 | tcsetattr(0,TCSANOW,&ttystate); 35 | } 36 | int get_response(char* question) 37 | { 38 | printf("%s (y/n)?",question); 39 | while(1) 40 | { 41 | switch(getchar()) 42 | { 43 | case 'Y': 44 | case 'y': 45 | return 0; 46 | case 'N': 47 | case 'n': 48 | case EOF: 49 | return 1; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /06/play_again3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define ASK "Do you want another transaction?" 9 | #define TRIES 3 10 | #define SLEEPTIME 5 11 | #define BEEP putchar('\a') 12 | /*how==0 > save current mode how==1 >restore mode */ 13 | void tty_mode(int how) 14 | { 15 | static struct termios original_mode; 16 | static int original_flags; 17 | static int stored = 0; 18 | if(how == 0) 19 | { 20 | tcgetattr(0,&original_mode); 21 | //0 is the standard input 22 | original_flags = fcntl(0,F_GETFL); 23 | stored =1; 24 | } 25 | else if(stored) 26 | { 27 | tcsetattr(0, &original_mode); 28 | fcntl(0,F_SETFL, original_flags); 29 | } 30 | } 31 | void set_rc_noecho_mode(); 32 | int get_response(char*, int); 33 | void set_nodelay_mode(); 34 | int main() 35 | { 36 | int response; 37 | tty_mode(0); 38 | set_rc_noecho_mode(); 39 | set_nodelay_mode(); 40 | response = get_response(ASK, TRIES); 41 | tty_mode(1); 42 | return response; 43 | } 44 | void set_rc_noecho_mode() 45 | { 46 | struct termios ttystate; 47 | tcgetattr(0,&ttystate); 48 | ttystate.c_lflag &= ~ICANON; 49 | ttystate.c_lflag &= ~ECHO; 50 | ttystate.c_cc[VMIN] = 1; 51 | tcsetattr(0,TCSANOW,&ttystate); 52 | } 53 | int get_ok_char() 54 | { 55 | int c; 56 | while((c=getchar())!=EOF && strchr("yYnN",c)== NULL) 57 | ; 58 | return c; 59 | } 60 | int get_response(char* question, int maxtries) 61 | { 62 | int input; 63 | printf("%s (y/n)?",question); 64 | fflush(stdout); //fouce output 65 | while(1) 66 | { 67 | sleep(SLEEPTIME); 68 | input = tolower(get_ok_char()); 69 | if(input == 'y') 70 | return 0; 71 | if(input == 'n') 72 | return 1; 73 | if(maxtries-- == 0) 74 | return 2; 75 | BEEP; 76 | } 77 | } 78 | void set_nodelay_mode() 79 | { 80 | int termflags; 81 | termflags = fcntl(0, F_GETFL); 82 | termflags |= O_NONBLOCK; 83 | fcntl(0, F_SETFL, termflags); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /06/signaldemo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main() 5 | { 6 | void f(int); 7 | int i; 8 | signal(SIGINT, f); 9 | for(i=0;i<5;i++) 10 | { 11 | printf("hello world\n"); 12 | sleep(1); 13 | } 14 | return 0; 15 | } 16 | void f(int signal) 17 | { 18 | printf("oohps\n"); 19 | } 20 | -------------------------------------------------------------------------------- /07/hello2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | int i; 6 | initscr(); 7 | clear(); 8 | for(i=0;i 2 | #include 3 | #include 4 | 5 | #define LEFTEDGE 10 6 | #define RIGHTEDGE 30 7 | #define ROW 10 8 | int main() 9 | { 10 | char* message = "Hello"; 11 | char* blank = " "; 12 | int dir = 1; 13 | int pos = LEFTEDGE; 14 | initscr(); 15 | clear(); 16 | while(1) 17 | { 18 | move(ROW, pos); 19 | addstr(message); 20 | move(LINES-1,COLS-1); 21 | refresh(); 22 | sleep(1); 23 | move(ROW, pos); 24 | addstr(blank); 25 | pos+=dir; 26 | if(pos>=RIGHTEDGE) 27 | dir = -1; 28 | if(pos<=LEFTEDGE) 29 | dir = 1; 30 | } 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /07/myhello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/07/myhello -------------------------------------------------------------------------------- /07/myhello2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/07/myhello2 -------------------------------------------------------------------------------- /07/myticker1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/07/myticker1 -------------------------------------------------------------------------------- /07/sigactiondemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define INPUTLEN 100 5 | 6 | int main() 7 | { 8 | struct sigaction newhander; 9 | sigset_t blocked; 10 | void inthander(int); 11 | char x[INPUTLEN]; 12 | 13 | newhander.sa_handler = inthander; 14 | newhander.sa_flags = SA_RESETHAND | SA_RESTART; 15 | 16 | sigemptyset(&blocked); 17 | sigaddset(&blocked, SIGQUIT); 18 | newhander.sa_mask = blocked; 19 | 20 | if(sigaction(SIGINT, &newhander, NULL)== -1) 21 | perror("sigaction error"); 22 | else while(1) 23 | { 24 | fgets(x, INPUTLEN, stdin); 25 | printf("input %s\n",x); 26 | } 27 | 28 | return 0; 29 | } 30 | void inthander(int s) 31 | { 32 | printf("Calling with signal %d\n", s); 33 | sleep(2); 34 | printf("Done handling signal %d\n", s); 35 | } 36 | -------------------------------------------------------------------------------- /07/sigdemo3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define INPUTLEN 100 7 | int main() 8 | { 9 | void inthander(int); 10 | void quithander(int); 11 | char input[INPUTLEN]; 12 | int nchars; 13 | 14 | signal(SIGINT, inthander); 15 | signal(SIGQUIT, quithander); 16 | 17 | do{ 18 | printf("\nType a message:\n"); 19 | nchars = read(0, input, INPUTLEN-1); 20 | if(nchars == -1) 21 | perror("read return an error"); 22 | else { 23 | input[nchars] = '\0'; 24 | printf("You typed: %s\n", input); 25 | } 26 | }while(strncmp(input,"quit",4)!=0); 27 | return 0; 28 | } 29 | void inthander(int s) 30 | { 31 | printf("Received signal %d ....waiting\n", s); 32 | sleep(2); /* 在debian7 上测试,此处sleep一直等待*/ 33 | printf("Leaving inthander"); 34 | } 35 | void quithander(int s) 36 | { 37 | printf("Received signal %d ...Waiting\n", s); 38 | sleep(2);/* 在debian7 上测试,此处sleep一直等待*/ 39 | printf("Leaving quithander"); 40 | } 41 | -------------------------------------------------------------------------------- /07/sleeptest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("hello world\n"); 7 | sleep(2); 8 | printf("The second hello world\n"); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /07/ticker_demo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | void countdown(int); 10 | int set_ticker(int n_msecs); 11 | signal(SIGALRM, countdown); 12 | if(set_ticker(500)==-1) 13 | perror("set_ticker"); 14 | else while(1) 15 | { 16 | pause(); 17 | } 18 | return 0; 19 | } 20 | void countdown(int signum) 21 | { 22 | static int num =10; 23 | printf("%d..", num--); 24 | fflush(stdout); 25 | if(num<0) 26 | { 27 | printf("DONE!\n"); 28 | exit(0); 29 | } 30 | } 31 | int set_ticker(int n_msecs) /* n_msecs is m seconds */ 32 | { 33 | struct itimerval new_timeset; 34 | long n_sec, n_usecs; 35 | 36 | n_sec = n_msecs/1000; /*The seconds */ 37 | n_usecs = (n_msecs%1000) * 1000L; /*The u seconds */ 38 | 39 | new_timeset.it_interval.tv_sec = n_sec; 40 | new_timeset.it_interval.tv_usec = n_usecs; 41 | 42 | new_timeset.it_value.tv_sec = n_sec; 43 | new_timeset.it_value.tv_usec = n_usecs; 44 | 45 | return setitimer(ITIMER_REAL, &new_timeset, NULL); 46 | } 47 | -------------------------------------------------------------------------------- /08/8.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/8.2 -------------------------------------------------------------------------------- /08/8.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | int i; 8 | for (i = 0; i < 10; ++i) { 9 | printf("my pid = %d, n= %d\n", getpid(), i); 10 | sleep(1); 11 | /* if(fork() != 0) { 12 | exit(0); 13 | } */ 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /08/8.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/8.3 -------------------------------------------------------------------------------- /08/8.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | int fd; 9 | int pid; 10 | char msg1[] = "Test 1 2 3\n"; 11 | char msg2[] = "Hello world\n"; 12 | if((fd = creat("testfile", 0644)) == -1) { 13 | return 0; 14 | } 15 | if(write(fd, msg1, strlen(msg1)) == -1) { 16 | return 0; 17 | } 18 | if((pid = fork()) == -1) { 19 | return 0; 20 | } 21 | if(write(fd, msg2, strlen(msg2)) == -1) { 22 | return 0; 23 | } 24 | close(fd); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /08/exec1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/exec1 -------------------------------------------------------------------------------- /08/exec1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char* arglist[3]; 7 | arglist[0] = "ls"; 8 | arglist[1] = "-l"; 9 | arglist[2] = 0; 10 | printf("*** About to exec ls -l\n"); 11 | execvp("ls", arglist); 12 | printf("*** ls is done, bye\n"); 13 | } 14 | -------------------------------------------------------------------------------- /08/forkdemo1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/forkdemo1 -------------------------------------------------------------------------------- /08/forkdemo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | int ret_from_fork=-1, myPid; 6 | myPid = getpid(); 7 | printf("Before: myPid is %d\n", myPid); 8 | ret_from_fork = fork(); 9 | sleep(1); 10 | printf("After: myPid is %d, fork() said %d\n",getpid(), ret_from_fork); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /08/forkdemo2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/forkdemo2 -------------------------------------------------------------------------------- /08/forkdemo2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | printf("my pid is %d\n", getpid()); 6 | fork(); 7 | fork(); 8 | fork(); 9 | printf("my pid is %d\n", getpid()); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /08/forkdemo3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | int fork_rv; 6 | printf("Before, my pid is %d \n", getpid()); 7 | fork_rv = fork(); 8 | if(fork_rv == -1) 9 | { 10 | perror("fork"); 11 | } 12 | else if(fork_rv == 0) 13 | { 14 | printf("I am the child, my pid is %d\n", getpid()); 15 | } 16 | else 17 | { 18 | printf("I am the parent, my child is %d\n", fork_rv); 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /08/forkmode3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/forkmode3 -------------------------------------------------------------------------------- /08/promptSh1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAXARGS 20 8 | #define ARGLEN 100 9 | 10 | int execute(char* arglist[]); 11 | char* makestring(char* ); 12 | int main() 13 | { 14 | char* arglist[MAXARGS+1]; 15 | int numargs; 16 | // 存储每次读入的参数 17 | char argbuf[ARGLEN]; 18 | numargs = 0; 19 | while(numargs < MAXARGS) 20 | { 21 | printf("Arg[%d]?", numargs); 22 | if(fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n') 23 | { 24 | // 为什么不能直接使用 argbuf 而要拷贝一份,因为第二次赋值会覆盖第一次的信息 25 | arglist[numargs++] = makestring(argbuf); 26 | } 27 | else 28 | { 29 | if(numargs >0) 30 | { 31 | arglist[numargs] = NULL; 32 | execute(arglist); 33 | numargs = 0; 34 | } 35 | } 36 | } 37 | return 0; 38 | } 39 | 40 | int execute(char* arglist[]) 41 | { 42 | execvp(arglist[0], arglist); 43 | perror("execvp failed"); 44 | exit(1); 45 | } 46 | 47 | // 将 buf 中的内容拷贝一份 48 | char* makestring(char* buf) 49 | { 50 | char* cp; 51 | buf[strlen(buf) -1] = '\0'; 52 | cp = (char*)malloc(strlen(buf) + 1); 53 | if(cp == NULL) 54 | { 55 | fprintf(stderr, "no memory\n"); 56 | exit(1); 57 | } 58 | strcpy(cp, buf); 59 | return cp; 60 | } 61 | -------------------------------------------------------------------------------- /08/promptSh2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAXARGS 20 9 | #define ARGLEN 100 10 | 11 | char* makeString(char* buf); 12 | void execute(char**); 13 | int main(int argc, char *argv[]) 14 | { 15 | char* arglist[MAXARGS + 1]; 16 | int numArgs; 17 | char argBuf[ARGLEN]; 18 | numArgs = 0; 19 | while(numArgs 0) 29 | { 30 | arglist[numArgs] = NULL; 31 | execute(arglist); 32 | numArgs = 0; 33 | } 34 | } 35 | } 36 | return 0; 37 | } 38 | 39 | void execute(char* arglist[]) 40 | { 41 | int pid, exitStatus; 42 | pid = fork(); 43 | switch(pid) 44 | { 45 | case 0: 46 | execvp(arglist[0], arglist); 47 | // the two line below will never be executed !!! 48 | perror("execvp failed"); 49 | exit(1); 50 | break; 51 | case -1: 52 | perror("fork"); 53 | break; 54 | default: 55 | while(wait(&exitStatus) != pid) 56 | { 57 | 58 | } 59 | printf("child exited with status %d, %d\n",exitStatus>>8, exitStatus & 0377 ); 60 | } 61 | } 62 | 63 | // fgets will read the newline character '\n' into destination 64 | char* makeString(char* buf) 65 | { 66 | char* ret; 67 | buf[strlen(buf) - 1] = '\0'; // trim newline, make the buf Null-terminated 68 | int len = strlen(buf); 69 | ret = (char*)malloc(len +1); 70 | strcpy(ret, buf); 71 | return ret; 72 | } 73 | -------------------------------------------------------------------------------- /08/psh1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/psh1 -------------------------------------------------------------------------------- /08/psh2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/psh2 -------------------------------------------------------------------------------- /08/testfile: -------------------------------------------------------------------------------- 1 | Test 1 2 3 2 | Hello world 3 | Hello world 4 | -------------------------------------------------------------------------------- /08/waitdemo1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/waitdemo1 -------------------------------------------------------------------------------- /08/waitdemo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define DELY 2 6 | int main() 7 | { 8 | int newPid; 9 | void child_code(int); 10 | void parent_code(int); 11 | printf("before, mypid is %d\n", getpid()); 12 | if((newPid = fork()) == -1) 13 | { 14 | perror("fork"); 15 | } 16 | else if(newPid == 0) 17 | { 18 | child_code(DELY); 19 | } 20 | else 21 | { 22 | parent_code(newPid); 23 | } 24 | } 25 | 26 | void child_code(int dely) 27 | { 28 | printf("child %d here. will sleep for %d seconds\n", getpid(), dely); 29 | sleep(dely); 30 | printf("child done, about to exit\n"); 31 | exit(17); 32 | } 33 | 34 | void parent_code(int childPid) 35 | { 36 | int wait_rv; 37 | wait_rv = wait(NULL); 38 | printf("done waiting for %d. Wait return: %d\n", childPid, wait_rv); 39 | } 40 | -------------------------------------------------------------------------------- /08/waitdemo2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/08/waitdemo2 -------------------------------------------------------------------------------- /08/waitdemo2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define DELAY 10 7 | 8 | int main() 9 | { 10 | int newPid; 11 | void child_code(int); 12 | void parent_code(int); 13 | printf("before: mypid is %d\n", getpid()); 14 | if((newPid = fork()) == -1) 15 | { 16 | perror("fork"); 17 | } 18 | else if(newPid == 0) 19 | { 20 | child_code(DELAY); 21 | } 22 | else 23 | { 24 | parent_code(newPid); 25 | } 26 | } 27 | 28 | void child_code(int delay) 29 | { 30 | printf("child %d here, will sleep for %d seconds\n", getpid(), delay); 31 | sleep(delay); 32 | printf("child done. abouut to exit\n"); 33 | exit(17); 34 | } 35 | 36 | void parent_code(int childPid) 37 | { 38 | int wait_rv; 39 | int child_status; 40 | int high_8, low_7, bit7; 41 | wait_rv = wait(&child_status); 42 | printf("done waiting for %d. Wait returned: %d\n", childPid, wait_rv); 43 | high_8 = child_status >>8; 44 | low_7 = child_status & 0x7f; 45 | bit7 = child_status & 0x80; 46 | printf("status:exit = %d, sig = %d, core = %d\n", high_8, low_7, bit7); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /09/execute.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int execute(char *argv[]) 8 | { 9 | int pid; 10 | int child_info = -1; 11 | if(argv[0] == NULL) { 12 | return 0; 13 | }else if((pid = fork()) == -1) { 14 | perror("fork"); 15 | }else if(pid == 0) { 16 | signal(SIGINT, SIG_DFL); 17 | signal(SIGQUIT, SIG_DFL); 18 | execvp(argv[0], argv); 19 | perror("cannot execute command"); 20 | exit(1); 21 | }else{ 22 | if(wait(&child_info) == -1) { 23 | perror("Wait"); 24 | } 25 | } 26 | return child_info; 27 | } 28 | -------------------------------------------------------------------------------- /09/script2.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | BOOK = $HOME/phonebook.data 4 | echo find what name in phonebook 5 | read NAME 6 | if grep $NAME $BOOK > /tmp/pb.tmp 7 | then 8 | echo Entries for $NAME 9 | cat /tmp/pb.tmp 10 | else 11 | echo No entries for $NAME 12 | fi 13 | 14 | rm /tmp/pb.tmp 15 | 16 | -------------------------------------------------------------------------------- /09/smsh.h: -------------------------------------------------------------------------------- 1 | #include 2 | #define YES 1 3 | #define NO 0 4 | char* next_cmd(); 5 | char** splitline(char*); 6 | void freelist(char**); 7 | void* emalloc(size_t); 8 | int execute(char**); 9 | void fatal(char*, char*, int); 10 | -------------------------------------------------------------------------------- /09/smsh1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "smsh.h" 6 | 7 | #define DFL_PROMPT ">" 8 | 9 | void setup(); 10 | int main(int argc, char *argv[]) 11 | { 12 | char *cmdline, *prompt, **arglist; 13 | int result; 14 | 15 | prompt = (char*)DFL_PROMPT; 16 | setup(); 17 | 18 | while((cmdline = next_cmd(prompt, stdin)) != NULL) { 19 | if((arglist = splitline(cmdline)) != NULL) { 20 | result = execute(arglist); 21 | freelist(arglist); 22 | } 23 | free(cmdline); 24 | } 25 | return 0; 26 | } 27 | 28 | void setup() 29 | { 30 | signal(SIGINT, SIG_IGN); 31 | signal(SIGQUIT, SIG_IGN); 32 | } 33 | 34 | void fatal(char *s1, char *s2, int n) 35 | { 36 | fprintf(stderr, "Error: %s, %s\n", s1, s2); 37 | exit(n); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /09/smsh2/controlflow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "smsh.h" 4 | 5 | enum states { NEUTRAL, WANT_THEN, THEN_BLOCK }; 6 | enum result { SUCCESS, FAIL }; 7 | 8 | static int if_state = NEUTRAL; 9 | static int if_result = SUCCESS; 10 | static int last_stat = 0; 11 | 12 | int syn_err(const char*); 13 | 14 | int ok_to_execute() 15 | { 16 | int rv = 1; 17 | if(if_state == WANT_THEN) 18 | { 19 | syn_err("then expected"); 20 | rv = 0; 21 | } 22 | else if(if_state == THEN_BLOCK && if_result == SUCCESS) 23 | { 24 | rv = 1; 25 | } 26 | else if(if_state == THEN_BLOCK && if_result == FAIL) 27 | { 28 | rv = 0; 29 | } 30 | return rv; 31 | } 32 | 33 | bool is_control_command(const char* s) 34 | { 35 | return strcmp(s, "if") == 0 || strcmp(s, "then") == 0 || strcmp(s, "fi") == 0; 36 | } 37 | int do_control_command(const char** args) 38 | { 39 | char* cmd = args[0]; 40 | int rv = -1; 41 | if(strcmp(cmd, "if") == 0) 42 | { 43 | if(if_state != NEUTRAL) 44 | { 45 | rv = syn_err("if unexpected"); 46 | } 47 | else 48 | { 49 | // execute the command after "if" 50 | last_stat = process(args + 1); 51 | if_result = (last_stat == 0 ? SUCCESS : FAIL); 52 | if_state = WANT_THEN; 53 | rv = 0; 54 | } 55 | } 56 | else if(strcmp(cmd, "then") == 0) 57 | { 58 | if(if_state != WANT_THEN) 59 | { 60 | rv = syn_err("then unexpected"); 61 | } 62 | else 63 | { 64 | if_state = THEN_BLOCK; 65 | if(if_result == SUCCESS) 66 | { 67 | process(args + 1); 68 | } 69 | rv = 0; 70 | } 71 | } 72 | else if(strcmp(cmd, "fi") == 0) 73 | { 74 | if(if_state != THEN_BLOCK) 75 | { 76 | rv = syn_err("fi unexpected"); 77 | } 78 | else 79 | { 80 | if_state = NEUTRAL; 81 | rv = 0; 82 | } 83 | } 84 | else 85 | fatal("internal error processing :", cmd, 2); 86 | return rv; 87 | } 88 | -------------------------------------------------------------------------------- /09/smsh2/execute.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int execute(char *argv[]) 8 | { 9 | int pid; 10 | int child_info = -1; 11 | if(argv[0] == NULL) { 12 | return 0; 13 | }else if((pid = fork()) == -1) { 14 | perror("fork"); 15 | }else if(pid == 0) { 16 | signal(SIGINT, SIG_DFL); 17 | signal(SIGQUIT, SIG_DFL); 18 | execvp(argv[0], argv); 19 | perror("cannot execute command"); 20 | exit(1); 21 | }else{ 22 | if(wait(&child_info) == -1) { 23 | perror("Wait"); 24 | } 25 | } 26 | return child_info; 27 | } 28 | -------------------------------------------------------------------------------- /09/smsh2/getenv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/09/smsh2/getenv -------------------------------------------------------------------------------- /09/smsh2/process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "smsh.h" 3 | 4 | int is_control_command(const char*); 5 | int do_control_command(const char**); 6 | int ok_to_execute(); 7 | 8 | int process(const char** args) 9 | { 10 | int rv = 0; 11 | if(args[0] == NULL) 12 | { 13 | rv = 0; 14 | } 15 | else if(is_control_command(args[0])) 16 | { 17 | rv = do_control_command(args); 18 | } 19 | else if(ok_to_execute()) 20 | { 21 | rv = execute(args); 22 | } 23 | return rv; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /09/smsh2/showenv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/09/smsh2/showenv -------------------------------------------------------------------------------- /09/smsh2/showenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern char **environ; 5 | int main(int argc, char *argv[]) 6 | { 7 | int i=0; 8 | for (i = 0; environ[i]; ++i) { 9 | printf("%s\n", environ[i]); 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /09/smsh2/smsh.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define YES 1 4 | #define NO 0 5 | char* next_cmd(char*, FILE* fp); 6 | char** splitline(char*); 7 | void freelist(char**); 8 | void* emalloc(size_t); 9 | int execute(char**); 10 | void fatal(const char*, const char*, int); 11 | -------------------------------------------------------------------------------- /09/smsh2/smsh2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "smsh.h" 6 | 7 | #define DFL_PROMPT ">" 8 | 9 | void setup(); 10 | int main(int argc, char *argv[]) 11 | { 12 | char *cmdline, *prompt, **arglist; 13 | int result; 14 | 15 | prompt = (char*)DFL_PROMPT; 16 | setup(); 17 | 18 | while((cmdline = next_cmd(prompt, stdin)) != NULL) { 19 | if((arglist = splitline(cmdline)) != NULL) { 20 | result = execute(arglist); 21 | freelist(arglist); 22 | } 23 | free(cmdline); 24 | } 25 | return 0; 26 | } 27 | 28 | void setup() 29 | { 30 | signal(SIGINT, SIG_IGN); 31 | signal(SIGQUIT, SIG_IGN); 32 | } 33 | 34 | void fatal(char *s1, char *s2, int n) 35 | { 36 | fprintf(stderr, "Error: %s, %s\n", s1, s2); 37 | exit(n); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /09/smsh2/splitline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "smsh.h" 5 | 6 | #define BUFSIZE 255 7 | 8 | // read a line until '\n' 9 | // the reason do not use fgets is tha we could not know the length of the line 10 | char* next_cmd(char *prompt, FILE *fp) 11 | { 12 | char *buf; 13 | int bufspace = 0; 14 | int pos = 0; 15 | int c; 16 | printf("%s",prompt); 17 | while((c = getc(fp)) != EOF) { 18 | if(pos + 1 >= bufspace) { 19 | if(bufspace == 0) { 20 | buf = (char*)emalloc(BUFSIZE); 21 | }else { 22 | buf = (char*)realloc(buf, bufspace + BUFSIZE); 23 | } 24 | bufspace += BUFSIZE; 25 | } 26 | if(c == '\n') { 27 | break; 28 | } 29 | buf[pos++] = c; 30 | } 31 | if(c == EOF && pos == 0) { 32 | return NULL; 33 | } 34 | 35 | buf[pos] = '\0'; 36 | return buf; 37 | } 38 | 39 | #define is_delim(x) ((x) == ' ' || (x) == '\t') 40 | 41 | char** splitline(char *line) 42 | { 43 | char* newstr(char*, int); 44 | char** args; 45 | int spots = 0; 46 | int bufspace = 0; 47 | int argnum = 0; 48 | char* cp = line; 49 | char* start; 50 | int len; 51 | if(line == NULL) { 52 | return NULL; 53 | } 54 | args = (char**)malloc(BUFSIZE); 55 | bufspace = BUFSIZE; 56 | spots = BUFSIZE/sizeof(char*); 57 | 58 | while(*cp != '\0') { 59 | //skip leading spaces 60 | while(is_delim(*cp)) { 61 | cp++; 62 | } 63 | if(*cp == '\0'){ 64 | break; 65 | } 66 | if(argnum + 1 >= spots) { 67 | args = (char**)realloc(args, bufspace + BUFSIZE); 68 | bufspace += BUFSIZE; 69 | spots += (BUFSIZE/sizeof(char*)); 70 | } 71 | start = cp; 72 | len = 1; 73 | while(*++cp != '\0' && !(is_delim(*cp))) { 74 | len++; 75 | } 76 | args[argnum++] = newstr(start, len); 77 | } 78 | args[argnum] = NULL; 79 | return args; 80 | } 81 | 82 | char* newstr(char* s, int len) 83 | { 84 | char* rv =(char*)malloc(len + 1); 85 | rv[len] = '\0'; 86 | strncpy(rv,s, len); 87 | return rv; 88 | } 89 | 90 | void freelist(char** list) 91 | { 92 | char** cp = list; 93 | while(*cp) { 94 | free(*cp++); 95 | } 96 | free(list); 97 | } 98 | 99 | void* emalloc(size_t n) 100 | { 101 | void* rv; 102 | if((rv = malloc(n)) == NULL) { 103 | fatal("out of memory","", 1); 104 | } 105 | return rv; 106 | } 107 | 108 | -------------------------------------------------------------------------------- /09/smsh2/testGetenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | char* cp = getenv("LANG"); 6 | if(cp != NULL) 7 | { 8 | printf("%s\n", cp); 9 | } 10 | return 0; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /09/smsh2/varlib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXVARS 200 6 | 7 | struct var 8 | { 9 | char* str; 10 | int global; 11 | }; 12 | 13 | static struct var tab[MAXVARS]; 14 | 15 | static char* new_string(const char*,const char*); 16 | 17 | struct var* find_item(const char* name, int first_blank) 18 | { 19 | int i = 0; 20 | int len = strlen(name); 21 | char* s; 22 | for (i = 0; i < MAXVARS && tab[i].str != NULL; ++i) { 23 | s = tab[i].str; 24 | if(strncmp(s, name, len) == 0 && s[len] == '=') 25 | { 26 | // if find key name and the value 27 | return &tab[i]; 28 | } 29 | } 30 | if(istr) 45 | { 46 | free(item->str); 47 | } 48 | item->str = s; 49 | rv = 0; 50 | } 51 | return rv; 52 | } 53 | 54 | char* new_string(const char* name, const char* val) 55 | { 56 | char* retval = (char*) malloc(strlen(name) + strlen(val) + 2); 57 | if(retval != NULL) 58 | { 59 | sprintf(retval, "%s=%s", name, val); 60 | } 61 | return retval; 62 | } 63 | 64 | const char* VLlookup(char* name) 65 | { 66 | struct var* item; 67 | if((item = find_item(name, 0)) != NULL) 68 | { 69 | // return the value 70 | return item->str + 1 + strlen(name); 71 | } 72 | return ""; 73 | } 74 | 75 | int VLexport(char* name) 76 | { 77 | struct var* item; 78 | int rv = 1; 79 | if((item = find_item(name, 0)) != NULL) 80 | { 81 | item->global = 1; 82 | rv = 0; 83 | } 84 | else if(VLstore(name, "") == 1) 85 | { 86 | rv = VLexport(name); 87 | } 88 | return rv; 89 | } 90 | 91 | void VLlist() 92 | { 93 | int i; 94 | for(i=0; i 2 | #include 3 | #include 4 | 5 | // read a line until '\n' 6 | // the reason do not use fgets is tha we could not know the length of the line 7 | char* next_cmd(char *prompt, FILE *fp) 8 | { 9 | char *buf; 10 | int bufspace = 0; 11 | int pos = 0; 12 | int c; 13 | printf("%s",prompt); 14 | while((c = getc(fp)) != EOF) { 15 | if(pos + 1 >= bufspace) { 16 | if(bufspace == 0) { 17 | buf = malloc(BUFSIZE); 18 | }else { 19 | buf = realloc(buf, bufspace + BUFSIZE); 20 | } 21 | bufspace += BUFSIZE; 22 | } 23 | if(c == '\n') { 24 | break; 25 | } 26 | buf[pos++] = c; 27 | } 28 | if(c == EOF && pos == 0) { 29 | return NULL; 30 | } 31 | 32 | buf[pos] = '\0'; 33 | return buf; 34 | } 35 | 36 | #define is_delim(x) ((x) == ' ' || (x) == '\t') 37 | 38 | char** splitlien(char *line) 39 | { 40 | char* newstr(); 41 | char** args; 42 | int spots = 0; 43 | int bufspace = 0; 44 | int argnum = 0; 45 | char* cp = line; 46 | char* start; 47 | int len; 48 | if(line == NULL) { 49 | return NULL; 50 | } 51 | args = (char**)malloc(BUFSIZE); 52 | bufspace = BUFSIZE; 53 | spots = BUFSIZE/sizeof(char*); 54 | 55 | while(*cp != '\0') { 56 | //only skip leading spaces 57 | while(is_delim(*cp)) { 58 | cp++; 59 | } 60 | if(*cp == '\0'){ 61 | break; 62 | } 63 | if(argnum + 1 >= spots) { 64 | args = realloc(args, bufspace + BUFSIZE); 65 | bufspace += BUFSIZE; 66 | spots += (BUFSIZE/sizeof(char*)); 67 | } 68 | start = cp; 69 | len = 1; 70 | while(*++cp != '\0' && !(is_delim(*cp))) { 71 | len++; 72 | } 73 | args[argnum] = newstr(start, len); 74 | } 75 | args[argnum] = NULL; 76 | return args; 77 | } 78 | 79 | char* newstr(char* s, int len) 80 | { 81 | char* rv = malloc(len + 1); 82 | rv[len] = '\0'; 83 | strncpy(rv,s, len); 84 | return rv; 85 | } 86 | 87 | void freelist(char** list) 88 | { 89 | char** cp = list; 90 | while(*cp) { 91 | free(*cp++); 92 | } 93 | free(list); 94 | } 95 | 96 | void* emalloc(size_t n) 97 | { 98 | void* rv; 99 | if((rv = malloc(n)) == NULL) { 100 | fatal("out of memory","", 1); 101 | } 102 | return rv; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /10/cur: -------------------------------------------------------------------------------- 1 | liuhao console Dec 31 22:04 2 | liuhao ttys001 Jan 14 00:54 3 | -------------------------------------------------------------------------------- /10/pipe/Makefile: -------------------------------------------------------------------------------- 1 | pipeDemo: pipeDemo.o 2 | gcc -o pipeDemo pipeDemo.o 3 | 4 | pipeDemo.o: pipeDemo.c 5 | gcc -c pipeDemo.c 6 | 7 | clean: 8 | rm *.o 9 | -------------------------------------------------------------------------------- /10/pipe/pip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/10/pipe/pip -------------------------------------------------------------------------------- /10/pipe/pip.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define oops(m, x) {perror(m); exit(x);} 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | fprintf(stderr, "%s %s %s", argv[0], argv[1], argv[2]); 10 | int pipefd[2], newfd, pid; 11 | if(argc != 3) 12 | { 13 | fprintf(stderr, "usage: pip cmd1 cmd2"); 14 | exit(1); 15 | } 16 | if(pipe(pipefd) == -1) 17 | { 18 | oops("Cann't get a pip", 1); 19 | } 20 | if((pid = fork()) == -1) 21 | { 22 | oops("Cann't fork", 2); 23 | } 24 | if(pid == 0) 25 | { 26 | //close(pipefd[0]); 27 | dup2(pipefd[1], 1); 28 | close(pipefd[1]); 29 | execlp(argv[1],argv[1]); 30 | oops(argv[1], 4); 31 | } 32 | else 33 | { 34 | close(pipefd[1]); 35 | dup2(pipefd[0], 0); 36 | close(pipefd[0]); 37 | execlp(argv[2], argv[2]); 38 | oops(argv[1], 5); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /10/pipe/pipeDemo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/10/pipe/pipeDemo -------------------------------------------------------------------------------- /10/pipe/pipeDemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | int len, i, apipe[2]; 9 | char buf[256]; 10 | 11 | if(pipe(apipe) == -1) 12 | { 13 | perror("could not make pipe"); 14 | exit(1); 15 | } 16 | printf("Got a pipe! It is file descriptors: { %d %d }\n", apipe[0], apipe[1]); 17 | while(fgets(buf, 256, stdin)) 18 | { 19 | len = strlen(buf); 20 | if(write(apipe[1], buf, len) != len) 21 | { 22 | perror("writing ti pipe"); 23 | break; 24 | } 25 | for(i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define CHILD_MESS "I want a cookie\n" 7 | #define PAR_MESS "testing.. \n" 8 | #define oops(m, x) {perror(m); exit(x);} 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int pipefd[2]; 13 | int len; 14 | char buf[256]; 15 | int read_len; 16 | if(pipe(pipefd) == -1) 17 | { 18 | oops("cann't get a pip", 1); 19 | } 20 | switch (fork()) { 21 | case -1: 22 | oops("cann't fork", 2); 23 | break; 24 | case 0: // child thread 25 | len = strlen(CHILD_MESS); 26 | while(1) 27 | { 28 | if(write(pipefd[1], CHILD_MESS, len) != len) 29 | { 30 | oops("write", 3); 31 | } 32 | sleep(5); 33 | } 34 | default: 35 | len = strlen(PAR_MESS); 36 | while(1) 37 | { 38 | if(write(pipefd[1], PAR_MESS, len) != len) 39 | { 40 | oops("write", 4); 41 | } 42 | sleep(1); 43 | read_len = read(pipefd[0], buf, 256); 44 | if(read_len <0) 45 | { 46 | break; 47 | } 48 | write(1, buf, read_len); 49 | } 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /10/prev: -------------------------------------------------------------------------------- 1 | liuhao console Dec 31 22:04 2 | liuhao ttys000 Jan 11 22:55 3 | liuhao ttys001 Jan 14 00:54 4 | -------------------------------------------------------------------------------- /10/stdin_redir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/10/stdin_redir -------------------------------------------------------------------------------- /10/stdin_redir1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | int fd; 9 | char line[100]; 10 | fgets(line, 100, stdin); 11 | printf("%s",line ); 12 | fgets(line, 100, stdin); 13 | printf("%s",line ); 14 | fgets(line, 100, stdin); 15 | printf("%s",line ); 16 | 17 | close(0); 18 | fd = open("/etc/passwd", O_RDONLY); 19 | if(fd != 0) 20 | { 21 | fprintf(stderr, "Could not open data as fd 0\n"); 22 | exit(1); 23 | } 24 | fgets(line, 100, stdin); 25 | printf("%s",line ); 26 | fgets(line, 100, stdin); 27 | printf("%s",line ); 28 | fgets(line, 100, stdin); 29 | printf("%s",line ); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /11/popen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define READ 0 7 | #define WRITE 1 8 | 9 | FILE* popen(const char* command, const char* mode) 10 | { 11 | int pfp[2]; 12 | int pid; 13 | int parent_end, child_end; 14 | 15 | if(*mode == 'r') 16 | { 17 | parent_end = READ; 18 | child_end = WRITE; 19 | } else if(*mode == 'w') 20 | { 21 | parent_end = WRITE; 22 | child_end = READ; 23 | } else { 24 | return NULL; 25 | } 26 | if(pipe(pfp) == -1) 27 | { 28 | return NULL; 29 | } 30 | if((pid = fork()) == -1) 31 | { 32 | close(pfp[0]); 33 | close(pfp[1]); 34 | return NULL; 35 | } 36 | //parent code here 37 | if(pid >0) 38 | { 39 | if(close(pfp[child_end]) == -1) 40 | { 41 | return NULL; 42 | } 43 | return fdopen(pfp[parent_end], mode); 44 | } 45 | //child code here 46 | if(close(pfp[parent_end]) == -1) 47 | { 48 | exit(1); 49 | } 50 | 51 | if(dup2(pfp[child_end], child_end) == -1) 52 | { 53 | exit(1); 54 | } 55 | execl("/bin/sh", "sh", "-c", command, NULL); 56 | exit(1); 57 | } 58 | -------------------------------------------------------------------------------- /11/timeclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/11/timeclient -------------------------------------------------------------------------------- /11/timeclnt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | struct sockaddr_in server_add; 13 | struct hostent* hp; 14 | int socket_id; 15 | char message[BUFSIZ]; 16 | int messlen; 17 | socket_id = socket(AF_INET, SOCK_STREAM, 0); 18 | memset(&server_add, 0, sizeof(server_add)); 19 | 20 | hp = gethostbyname(argv[1]); 21 | if(hp == NULL) 22 | { 23 | return 1; 24 | } 25 | memcpy(&server_add.sin_addr, hp->h_addr, hp->h_length); 26 | server_add.sin_port = htons(atoi(argv[2])); 27 | server_add.sin_family = AF_INET; 28 | if(connect(socket_id, (struct sockaddr*)&server_add, sizeof(server_add)) != 0) 29 | { 30 | return 2; 31 | } 32 | messlen = read(socket_id, message, BUFSIZ); 33 | if(messlen == -1) 34 | { 35 | return 3; 36 | } 37 | write(1, message, messlen); 38 | close(socket_id); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /11/timeserv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/11/timeserv -------------------------------------------------------------------------------- /11/timeserv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | const int port = 13000; 12 | const int hostLen = 256; 13 | #define oops(msg) {perror(msg); exit(1);} 14 | int main(int argc, char *argv[]) 15 | { 16 | struct sockaddr_in saddr; 17 | struct hostent* hp; 18 | char hostName[hostLen]; 19 | int sock_id, sock_fd; 20 | FILE* sock_fp; 21 | time_t theTime; 22 | 23 | sock_id = socket(PF_INET, SOCK_STREAM, 0); 24 | if(sock_id == -1) 25 | { 26 | oops("socket"); 27 | } 28 | //bzero((void*)&saddr, sizeof(saddr)); 29 | memset(&saddr, 0, sizeof(saddr)); 30 | gethostname(hostName, hostLen); 31 | hp = gethostbyname(hostName); 32 | 33 | //bcopy((void*)hp->h_addr, (void*)&saddr.sin_addr, hp->h_length); 34 | memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); 35 | saddr.sin_port = htons(port); 36 | saddr.sin_family = AF_INET; 37 | 38 | if(bind(sock_id, (struct sockaddr*)&saddr, sizeof(saddr)) != 0) 39 | { 40 | oops("bind"); 41 | } 42 | 43 | if(listen(sock_id, 1) != 0) 44 | { 45 | oops("listen"); 46 | } 47 | 48 | while(1) 49 | { 50 | sock_fd = accept(sock_id, NULL, NULL); 51 | printf("Get a call\n"); 52 | if(sock_fd == -1) 53 | { 54 | oops("accept"); 55 | } 56 | sock_fp = fdopen(sock_fd, "w"); 57 | if(sock_fp == NULL) 58 | { 59 | oops("fdopen"); 60 | } 61 | theTime = time(NULL); 62 | fprintf(sock_fp, "the time is .."); 63 | fprintf(sock_fp, "%s", ctime(&theTime)); 64 | fclose(sock_fp); 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /11/tinybc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/momadacoding/understanding-unix-programming/0c234ec96bbdff2ffd2f3655e0ac05d947758633/11/tinybc -------------------------------------------------------------------------------- /11/tinybc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | #define oops(m, x) {perror(m); exit(x);} 7 | void fatal(const char* message); 8 | void be_bc(int in[2], int out[2]); 9 | void be_dc(int in[2], int out[2]); 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | // pipe[0] for read, pipe[1] for write 14 | int pid, todc[2], fromdc[2]; 15 | if(pipe(todc) == -1 || pipe(fromdc) == -1) 16 | { 17 | oops("pipe failed", 1); 18 | } 19 | if((pid = fork()) == -1) 20 | { 21 | oops("cannot fork", 2); 22 | } 23 | 24 | if(pid == 0) 25 | { 26 | //child 27 | be_dc(todc, fromdc); 28 | } 29 | else { 30 | be_bc(todc, fromdc); 31 | wait(NULL); 32 | } 33 | return 0; 34 | } 35 | void be_dc(int in[2], int out[2]) 36 | { 37 | // setup stdin from pipein 38 | if(dup2(in[0], 0) == -1) 39 | { 40 | oops("dc: cannot redirect stdin", 3); 41 | } 42 | close(in[0]); 43 | close(in[1]); 44 | 45 | // setup stdout to pipout 46 | if(dup2(out[1], 1) == -1) 47 | { 48 | oops("dc: cannot redirect stdout", 4); 49 | } 50 | close(out[0]); 51 | close(out[1]); 52 | 53 | execlp("dc", "dc", "-", NULL); 54 | oops("Cannot run dc", 5); 55 | } 56 | 57 | void be_bc(int todc[2], int fromdc[2]) 58 | { 59 | int num1, num2; 60 | char operation[BUFSIZ], message[BUFSIZ]; 61 | FILE *fpout, *fpin; 62 | 63 | close(todc[0]); 64 | close(fromdc[1]); 65 | 66 | // pipe[1] for write, could read from pipe[0] 67 | fpout = fdopen(todc[1],"w"); 68 | // pipe[0] for read 69 | fpin = fdopen(fromdc[0], "r"); 70 | 71 | if(fpout == NULL || fpin == NULL) 72 | { 73 | fatal("Error converting pipes to stream"); 74 | } 75 | while(printf("tinybc:"), fgets(message, BUFSIZ, stdin) != NULL) 76 | { 77 | if(sscanf(message, "%d %[- + * / ^] %d", &num1, operation, &num2) != 3) 78 | { 79 | printf("syntax error\n"); 80 | continue; 81 | } 82 | 83 | // send input to dc 84 | if(fprintf(fpout, "%d\n %d\n %c\n p \n", num1, num2, *operation) == EOF) 85 | { 86 | fatal("Error writing"); 87 | } 88 | //make sure to write 89 | fflush(fpout); 90 | // get result from dc 91 | if(fgets(message, BUFSIZ, fpin) == NULL) 92 | break; 93 | printf("%d %c %d = %s", num1, *operation, num2, message); 94 | } 95 | 96 | fclose(fpout); 97 | fclose(fpin); 98 | } 99 | 100 | void fatal(const char* message) 101 | { 102 | fprintf(stderr, "Error: %s\n", message); 103 | exit(1); 104 | } 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 haolly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | understanding-unix-programming 2 | ============================== 3 | 4 | The code when i read the book Understanding Unix/Linux Programming 5 | --------------------------------------------------------------------------------