├── README.md
├── chapter1
├── 01.c
└── my_more.c
├── chapter10
├── close-then-open.c
├── fork-exec.c
├── open-close-dup-close.c
└── pipe.c
├── chapter11
├── ntp_client.c
├── ntp_server.c
└── popen.c
├── chapter15
├── lock_client.c
├── lock_server.c
├── select.c
├── shmget_client.c
└── shmget_server.c
├── chapter2
├── my_cp.c
└── my_who.c
├── chapter3
└── my_ls.c
├── chapter4
└── my_pwd.c
├── chapter5
├── echo_stat.c
├── my_stty.c
├── my_write.c
└── set_stat.c
├── chapter6
└── my_play.c
├── chapter7
└── my_timer.c
├── chapter8
└── my_shell.c
└── chapter9
└── my_shell.c
/README.md:
--------------------------------------------------------------------------------
1 | 大三上学期
2 | 书籍《linux编程实践教程》
3 | 代码集合
4 | 都是我一手一脚码的
5 | 亲测有效
6 |
--------------------------------------------------------------------------------
/chapter1/01.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(){
4 |
5 | int c;
6 | while( (c = getchar()) != EOF ){
7 | putchar(c);
8 | }
9 |
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/chapter1/my_more.c:
--------------------------------------------------------------------------------
1 | /**********************
2 | *2016.12.2
3 | *有重定向功能
4 | *
5 | *
6 | **********************/
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #define PAGE_LEN 24 //每页24行
13 | #define LINE_LEN 512 //每行最多512字节
14 |
15 | void more(FILE *);
16 |
17 | int main(int argc, char *argv[]){
18 | char buffer[LINE_LEN];
19 |
20 | FILE *pf;
21 |
22 | if(argc == 1){
23 | //fgets(buffer, LINE_LEN, stdin);
24 | more(stdin); //用重定向是从这里输入的
25 | }else{
26 | //strcpy(buffer, argv[1]);
27 | while(--argc){
28 | if((pf = fopen(*++argv, "r")) != NULL){
29 | more(pf);
30 | fclose(pf);
31 | }else
32 | break;
33 | }
34 | }
35 | /*
36 | if( (pf = fopen(buffer, "r")) == NULL ){
37 | printf("打开文件失败!\n");
38 | return 0;
39 | }
40 | more(pf);
41 | */
42 | return 0;
43 | }
44 |
45 | void more(FILE *pf){
46 |
47 | FILE *ptty; //从/dev/tty获取数据
48 | char line_buffer[LINE_LEN]; //存放文件读出来的一行内容
49 | int line_read_num = 0; //已读的行数
50 | int getchar_num = 0;
51 | char c;
52 |
53 | //打开文件
54 |
55 |
56 | if((ptty = fopen("/dev/tty", "r")) == NULL){
57 | printf("打开tty失败!\n");
58 | exit(0);
59 | }
60 |
61 | //循环输出文件内容,每输出24行则等待输入,没到24行则退出程序
62 | while(fgets(line_buffer, LINE_LEN, pf)){
63 |
64 | //如果输出了24行
65 | if(line_read_num == PAGE_LEN){
66 | printf("\n\033[7m more? \033[m");
67 | while((c = getc(ptty)) != EOF){ //这儿的数据是/dev/tty传入的
68 | if(c == 'q'){
69 | fclose(pf);
70 | exit(0);
71 | }
72 | else if(c == '\n'){
73 | getchar_num = 1;
74 | break;
75 | }
76 | else if(c == ' '){
77 | getchar_num = 24;
78 | break;
79 | }
80 | }
81 |
82 | line_read_num -= getchar_num;
83 | }
84 |
85 | //
86 | if(fputs(line_buffer, stdout) == EOF){
87 | exit(0);
88 | }
89 |
90 | line_read_num++;
91 | }
92 |
93 | fclose(ptty);
94 | fclose(pf);
95 | }
96 |
--------------------------------------------------------------------------------
/chapter10/close-then-open.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define BUFFER_SIZE 1024
6 |
7 | int main(int argc, char *argv){
8 |
9 | char buffer[BUFFER_SIZE];
10 |
11 | fgets(buffer, BUFFER_SIZE, stdin);
12 | printf("%s", buffer);
13 |
14 |
15 |
16 |
17 | close(0);
18 |
19 | //这儿打开的是0标识符,所以用if(!pf)会出文件
20 | int pf = open("/etc/passwd", O_RDONLY);
21 | printf("%d", pf);
22 |
23 | fgets(buffer, BUFFER_SIZE, stdin);
24 | printf("%s", buffer);
25 |
26 | return 0;
27 | }
--------------------------------------------------------------------------------
/chapter10/fork-exec.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include //fork
4 | #include //wait
5 | #include
6 |
7 | int main(int argc, char *argv[]){
8 |
9 | int pid = fork();
10 |
11 | //如果是子进程
12 | if(pid == 0){
13 | close(1);
14 | creat("test.c", 0755);
15 | execlp("who", "who", NULL);
16 | exit(1);
17 |
18 | }else{
19 | wait(NULL);
20 | printf("done\n");
21 | }
22 |
23 |
24 |
25 |
26 | return 0;
27 | }
--------------------------------------------------------------------------------
/chapter10/open-close-dup-close.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define BUFFER_SIZE 1024
6 |
7 | int main(int argc, char *argv){
8 |
9 | char buffer[BUFFER_SIZE];
10 |
11 | fgets(buffer, BUFFER_SIZE, stdin);
12 | printf("%s", buffer);
13 |
14 |
15 |
16 | int pf = open("/etc/passwd", O_RDONLY);
17 | printf("pf: %d\n", pf);
18 |
19 | close(0);
20 |
21 | int newpf = dup(pf);
22 | printf("newpf: %d\n", newpf);
23 |
24 | close(pf);
25 |
26 |
27 |
28 | fgets(buffer, BUFFER_SIZE, stdin);
29 | printf("%s", buffer);
30 |
31 | return 0;
32 | }
--------------------------------------------------------------------------------
/chapter10/pipe.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 |
8 | #define BUFFER_SIZE 1024
9 | #define oops(m,x) {printf(m); exit(x);}
10 |
11 |
12 | int main(int argc, char *argv[]){
13 |
14 | int argList[2];
15 | char send_buffer[BUFFER_SIZE] = "";
16 | char recv_buffer[BUFFER_SIZE] = "";
17 | int len;
18 |
19 | int read_pipe = creat("read", 0755);
20 | int write_pipe = creat("write", 0755);
21 |
22 | argList[0] = read_pipe;
23 | argList[1] = write_pipe;
24 |
25 |
26 | printf("%d %d", argList[0], argList[1]);
27 | if( pipe(argList) == -1)
28 | oops("pipe", -1);
29 |
30 | switch(fork()){
31 | case -1:
32 | oops("fork: ", -1);
33 | break;
34 |
35 | //子进程write
36 | case 0:
37 | close(argList[0]);
38 | if( dup2(argList[1], 1) == -1)
39 | oops("dups2: ", -1);
40 |
41 | execlp("cat", "who", "/etc/passwd", NULL);
42 | exit(0);
43 | //父进程read,读完后输出结果
44 | default:
45 | sleep(1);
46 | close(argList[1]);
47 | if( dup2(argList[0], 0) == -1)
48 | oops("dup2: ", -1);
49 |
50 | execlp("head", "head", "-1", NULL);
51 | }
52 |
53 | return 0;
54 | }
--------------------------------------------------------------------------------
/chapter11/ntp_client.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include //memset
9 |
10 |
11 | #define oops(m, x) {perror(m); exit(x);}
12 | #define BUFFER_SIZE 1024
13 |
14 | int main(int argc, char *argv[]){
15 |
16 | struct sockaddr_in server_addr;
17 | int client_socket;
18 | FILE *client_pf;
19 |
20 | char recv_buffer[BUFFER_SIZE];
21 |
22 | //建立socket
23 | client_socket = socket(PF_INET, SOCK_STREAM, 0);
24 |
25 | //填充IP信息
26 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
27 | server_addr.sin_port = 6666;
28 | server_addr.sin_family = AF_INET;
29 |
30 |
31 | //连接
32 | if( connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1 )
33 | oops("connect: ", -1);
34 |
35 |
36 | memset(recv_buffer, 0, BUFFER_SIZE);
37 | //读数据
38 | client_pf = fdopen(client_socket, "r");
39 | fgets(recv_buffer, BUFFER_SIZE, client_pf);
40 |
41 | printf("%s\n", recv_buffer);
42 |
43 | close(client_socket);
44 |
45 | return 0;
46 | }
--------------------------------------------------------------------------------
/chapter11/ntp_server.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define oops(m, x) {perror(m); exit(x);}
10 |
11 |
12 | int main(int argc, char *argv[]){
13 |
14 | struct sockaddr_in server_addr, client_addr;
15 | int server_socket, client_socket;
16 | FILE *client_pf;
17 |
18 | time_t current_time;
19 |
20 | //建立socket
21 | server_socket = socket(PF_INET, SOCK_STREAM, 0);
22 |
23 | //填充IP信息
24 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
25 | server_addr.sin_port = 6666;
26 | server_addr.sin_family = AF_INET;
27 |
28 | //绑定
29 | if( bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) != 0)
30 | oops("bind: ", -1);
31 |
32 | //监听
33 | if( listen(server_socket, 1) != 0 )
34 | oops("listen: ", -1);
35 |
36 | while(1){
37 |
38 | int len = sizeof(client_addr);
39 | if( (client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &len)) == -1)
40 | oops("accept: ", -1);
41 |
42 | client_pf = fdopen(client_socket, "w");
43 | if(client_pf == NULL)
44 | oops("fdopen: ", -1);
45 |
46 |
47 | current_time = time(NULL);
48 | fprintf(client_pf, "The time is : %s", ctime(¤t_time));
49 | fclose(client_pf);
50 |
51 | }
52 |
53 | close(server_socket);
54 | close(client_socket);
55 |
56 | return 0;
57 | }
--------------------------------------------------------------------------------
/chapter11/popen.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define BUFFER_SIZE 1024
4 |
5 | int main(int argc, char *argv[]){
6 |
7 | FILE *pf = popen("cat /etc/passwd", "r");
8 | char buffer[BUFFER_SIZE];
9 |
10 | while( fgets(buffer, BUFFER_SIZE, pf) ){
11 | printf("%s", buffer);
12 | }
13 |
14 | pclose(pf);
15 |
16 | return 0;
17 | }
--------------------------------------------------------------------------------
/chapter15/lock_client.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | void lock_opeartion(int, int);
6 |
7 | int main(int argc, char*argv[]){
8 |
9 | int fd = 0;
10 | char current_time[1024];
11 |
12 | fd = open("test.txt", O_CREAT|O_RDONLY);
13 |
14 | while(1){
15 | lock_opeartion(fd, F_RDLCK);
16 |
17 | read(fd, current_time, sizeof(current_time));
18 | printf("%s", current_time);
19 | lock_opeartion(fd, F_UNLCK);
20 | }
21 |
22 |
23 | return 0;
24 | }
25 |
26 | void lock_opeartion(int fd, int flag){
27 | struct flock lockinfo;
28 |
29 | lockinfo.l_type = flag;
30 | lockinfo.l_pid = getpid();
31 | lockinfo.l_start = 0;
32 | lockinfo.l_whence = SEEK_SET;
33 | lockinfo.l_len = 0;
34 |
35 | fcntl(fd, F_SETLKW, &lockinfo);
36 |
37 | }
--------------------------------------------------------------------------------
/chapter15/lock_server.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | void lock_opeartion(int, int);
7 |
8 | int main(int argc, char*argv[]){
9 |
10 | time_t now;
11 | int fd = 0;
12 | char *current_time;
13 |
14 | fd = open("test.txt", O_CREAT|O_WRONLY, 0644);
15 |
16 | while(1){
17 | time(&now);
18 | current_time = ctime(&now);
19 | lock_opeartion(fd, F_WRLCK);
20 |
21 | write(fd, current_time, strlen(current_time));
22 |
23 | lock_opeartion(fd, F_UNLCK);
24 | }
25 |
26 |
27 | return 0;
28 | }
29 |
30 | void lock_opeartion(int fd, int flag){
31 | struct flock lockinfo;
32 |
33 | lockinfo.l_type = flag;
34 | lockinfo.l_pid = getpid();
35 | lockinfo.l_start = 0;
36 | lockinfo.l_whence = SEEK_SET;
37 | lockinfo.l_len = 0;
38 |
39 | fcntl(fd, F_SETLKW, &lockinfo);
40 |
41 | }
--------------------------------------------------------------------------------
/chapter15/select.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define BUFFER_SIZE 1024
10 | #define oops(m, x) {perror(m); exit(x);}
11 |
12 | void show_data(int fd);
13 |
14 | int main(int argc, char *argv[]){
15 | int fd1, fd2; //两个文件描述符
16 | fd_set read_fds; //select的read参数
17 | struct timeval timeout; //超时设置
18 | int maxfd;
19 | int retval;
20 |
21 | if( (fd1 = open(argv[1], O_RDONLY)) == -1)
22 | oops("open", -1);
23 |
24 | if( (fd2 = open(argv[2], O_RDONLY)) == -1)
25 | oops("open", -1);
26 | maxfd = (fd1 > fd2) ? fd1 : fd2;
27 | maxfd++;
28 |
29 | while(1){
30 | FD_ZERO(&read_fds);
31 | FD_SET(fd1, &read_fds);
32 | FD_SET(fd2, &read_fds);
33 |
34 | timeout.tv_sec = atoi(argv[3]);
35 | timeout.tv_usec = 0;
36 |
37 | retval = select(maxfd, &read_fds, NULL, NULL, &timeout);
38 | if(retval == -1)
39 | oops("select", -1);
40 |
41 | if(retval > 0){
42 | if(FD_ISSET(fd1, &read_fds))
43 | show_data(fd1);
44 | if(FD_ISSET(fd2, &read_fds))
45 | show_data(fd2);
46 | }else{
47 | //超时
48 | printf("time out......\n");
49 | }
50 |
51 | }
52 | return 0;
53 | }
54 |
55 |
56 | void show_data(int fd){
57 |
58 | int len;
59 | char buffer[BUFFER_SIZE];
60 | memset(buffer, 0, BUFFER_SIZE);
61 |
62 | len = read(fd, buffer, BUFFER_SIZE);
63 | if( len == -1 )
64 | oops("read", -1);
65 |
66 | write(1, buffer, len);
67 | write(1, "\n", 1);
68 |
69 | }
--------------------------------------------------------------------------------
/chapter15/shmget_client.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define KEY 100
9 | #define SEG_SIZE ((size_t)100)
10 | #define BUFFER_SIZE 1024
11 |
12 | #define oops(m, x) {perror(m); exit(x);}
13 |
14 | int main(int argc, char *argv[]){
15 | int seg_id;
16 | char *seg_mem;
17 | char my_time[BUFFER_SIZE];
18 |
19 | //建立对象
20 | if( (seg_id = shmget(KEY, SEG_SIZE, IPC_CREAT|0777)) == -1)
21 | oops("shmget", -1);
22 |
23 | //建立内存
24 | if( (seg_mem = shmat(seg_id, NULL, 0)) == (void *)-1 )
25 | oops("shmat", -1);
26 |
27 | //读取内容
28 | strcpy(my_time, seg_mem);
29 |
30 | printf("%s\n", my_time);
31 |
32 |
33 | return 0;
34 | }
--------------------------------------------------------------------------------
/chapter15/shmget_server.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define KEY 100
9 | #define SEG_SIZE ((size_t)100)
10 |
11 | #define oops(m, x) {perror(m); exit(x);}
12 |
13 | int main(int argc, char *argv[]){
14 | int seg_id;
15 | char *seg_mem;
16 | time_t my_time;
17 |
18 | //建立对象
19 | if ( (seg_id = shmget(KEY, SEG_SIZE, IPC_CREAT|0777)) == -1)
20 | oops("shmget", -1);
21 |
22 | //分配内存
23 | if( (seg_mem = shmat(seg_id, NULL, 0)) == (void *)-1)
24 | oops("shmat", -1);
25 |
26 | time(&my_time); //获取时间
27 | strcpy(seg_mem, ctime(&my_time));
28 |
29 | while(1);
30 |
31 | shmctl(seg_id, IPC_RMID, NULL);//删除
32 |
33 | return 0;
34 | }
--------------------------------------------------------------------------------
/chapter2/my_cp.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define BUFFER_SIZE 512
7 |
8 | int main(int argc, char *argv[]){
9 |
10 | int pf_sou, pf_des; //源文件,目标文件
11 | char buffer[BUFFER_SIZE]; //缓冲区
12 | int read_num; //已读取的字节数
13 |
14 | if(argc != 3){
15 | printf("参数不够!\n");
16 | exit(1);
17 | }
18 |
19 | if( (pf_sou = open(argv[1], O_RDONLY)) == -1 ){
20 | perror(argv[1]);
21 | exit(1);
22 | }
23 |
24 | if( (pf_des = creat(argv[2], 0755)) == -1 ){
25 | perror(argv[2]);
26 | exit(1);
27 | }
28 |
29 | while( (read_num = read(pf_sou, buffer, BUFFER_SIZE)) >0){
30 | if(write(pf_des, buffer, read_num) != read_num){
31 | perror("write error ");
32 | exit(1);
33 | }
34 | }
35 |
36 | if(read_num == -1){
37 | perror("read error ");
38 | exit(1);
39 | }
40 |
41 | close(pf_sou);
42 | close(pf_des);
43 |
44 |
45 | return 0;
46 | }
--------------------------------------------------------------------------------
/chapter2/my_who.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define RECORD_NUM 5
9 | #define RECORD_BUF (sizeof(struct utmp))
10 |
11 | void show_info(struct utmp *record_buffer);
12 | void show_time(long timeval);
13 | struct utmp *get_next_record(void); //获取下一个记录
14 |
15 | int pf_utmp; //文件指针
16 |
17 | char record_buffer[RECORD_NUM * RECORD_BUF]; //10个数据的总大小
18 |
19 | int current_num=0; //从文件中读了多少个数据过来,可能不到10个
20 | int read_num=0; //当前已经读到第几个数据了
21 | int flag = 0; //是否把文件内容读完了
22 |
23 | int main(void){
24 |
25 | struct utmp *record;
26 |
27 | //打开文件
28 | if( (pf_utmp = open(UTMP_FILE, O_RDONLY)) == -1 ){
29 | perror(UTMP_FILE);
30 | exit(1);
31 | }
32 |
33 | //while(read(pf_utmp, &record_buffer, record_size))
34 | // show_info(&record_buffer);
35 |
36 | while( (record = get_next_record()) != NULL){
37 | show_info(record);
38 | }
39 |
40 | close(pf_utmp); //关闭指针
41 |
42 | return 0;
43 | }
44 |
45 | void show_info(struct utmp *record_buffer){
46 | if(record_buffer->ut_type != USER_PROCESS) //这条信息如果不是已经登录用户,就退出
47 | return;
48 |
49 | printf("%s\t", record_buffer->ut_user); //登录账户
50 | printf("%s\t", record_buffer->ut_line); //tty
51 | show_time(record_buffer->ut_time); //时间
52 | }
53 |
54 | void show_time(long timeval){
55 | char *cp;
56 | cp = ctime(&timeval);
57 | printf("%s", cp); //时间后面有一个回车
58 | }
59 |
60 | struct utmp *get_next_record(){
61 | struct utmp *utmp_buffer;
62 |
63 | if(current_num == read_num && flag)
64 | return NULL;
65 |
66 | //当读完了缓存中的5个数后再读取
67 | if(current_num == read_num){
68 | int size = read(pf_utmp, record_buffer, RECORD_NUM * RECORD_BUF); //读取5个数据
69 | current_num = size / RECORD_BUF; //里面真正读了有多少个数
70 | if(current_num < 5) //不足10个,说明已经读完了
71 | flag = 1;
72 | if(current_num == 0) //没有数据直接退出
73 | return NULL;
74 |
75 | read_num = 0; //置0
76 | }
77 |
78 | utmp_buffer = (struct utmp*)&record_buffer[read_num * RECORD_BUF];
79 | read_num++;
80 | return utmp_buffer; //返回当前读取的数值
81 |
82 | }
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/chapter3/my_ls.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include //getpwuid
7 | #include //getgrgid
8 | #include //ctime
9 | #include
10 |
11 | void ls_info(char *dirname);
12 |
13 | char *show_mode(int mode); //mode
14 | char *show_uid(int uid); //uid
15 | char *show_gid(int gid); //gid
16 |
17 | int main(int argc, char *argv[]){
18 | int num = argc-1;
19 | if(argc == 1)
20 | ls_info(".");
21 | else{
22 | while(num){
23 | printf("%s:\n", argv[num]);
24 | ls_info(argv[num--]);
25 | }
26 |
27 | }
28 |
29 | return 0;
30 | }
31 |
32 | void ls_info(char *dirname){
33 |
34 | DIR *pd; //目录
35 | struct dirent *dir_info; //目录结构体
36 | struct stat file_stat; //文件的属性结构体
37 |
38 | //打开目录
39 | if( (pd = opendir(dirname)) == NULL){
40 | perror(dirname);
41 | }
42 |
43 | //读取目录内容
44 | while( (dir_info=readdir(pd)) != NULL){
45 | //printf("%s\n", dir_info->d_name);
46 | //过滤
47 | if( (strcmp(dir_info->d_name, ".") == 0) || (strcmp(dir_info->d_name, "..") == 0) )
48 | continue;
49 |
50 | //获取属性
51 |
52 | char str[100];
53 | sprintf(str, "%s/%s", dirname, dir_info->d_name);
54 | //注意文件路径!!!!
55 | if(stat(str, &file_stat) == -1){
56 | perror(dir_info->d_name);
57 | exit(1);
58 | }else{
59 | printf("%s ", show_mode(file_stat.st_mode)); //mode
60 | printf("%-4d ", file_stat.st_nlink); //hard link
61 | printf("%-10s", show_uid(file_stat.st_uid)); //UID
62 | printf("%-10s", show_gid(file_stat.st_gid)); //GID
63 | printf("%-8ld ", file_stat.st_size); //size
64 | printf("%.12s ", 4+ctime(&file_stat.st_mtime)); //mtime,%m.ns 输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格
65 | printf("%s\n", dir_info->d_name); //name
66 | }
67 |
68 | }
69 |
70 | //关闭目录
71 | closedir(pd);
72 | }
73 |
74 | char *show_mode (int mode){
75 | static char str[10];
76 |
77 | strcpy(str, "----------"); //重置。不然会和上次一样
78 | if(S_ISDIR(mode)) str[0] = 'd';
79 | if(S_ISCHR(mode)) str[0] = 'c';
80 | if(S_ISBLK(mode)) str[0] = 'b';
81 | if(S_ISFIFO(mode)) str[0] = 'p';
82 | if(S_ISLNK(mode)) str[0] = 'l';
83 |
84 | if(S_IRUSR & mode) str[1] = 'r';
85 | if(S_IWUSR & mode) str[2] = 'w';
86 | if(S_IXUSR & mode) str[3] = 'x';
87 |
88 | if(S_IRGRP & mode) str[4] = 'r';
89 | if(S_IWGRP & mode) str[5] = 'w';
90 | if(S_IXGRP & mode) str[6] = 'x';
91 |
92 | if(S_IROTH & mode) str[7] = 'r';
93 | if(S_IWOTH & mode) str[8] = 'w';
94 | if(S_IXOTH & mode) str[9] = 'x';
95 |
96 | if(S_ISUID & mode) str[1] = 's';
97 | if(S_ISGID & mode) str[5] = 's';
98 | if(S_ISVTX & mode) str[9] = 't';
99 |
100 | return str;
101 | }
102 |
103 | char* show_uid(int uid){
104 | struct passwd *username;
105 | static char str[10]; //设置静态变量,不然会被提示返回局部变量地址
106 |
107 | if((username = getpwuid(uid)) == NULL){ //搜索passwd没有找到就返回UID
108 | sprintf(str, "%s", uid);
109 | return str;
110 | }
111 |
112 | return username->pw_name;
113 | }
114 |
115 | char* show_gid(int gid){
116 | struct group *groupname;
117 | static char str[10];
118 |
119 | if((groupname = getgrgid(gid)) == NULL){ //搜索group没有找到就返回GID
120 | sprintf(str, "%s", gid);
121 | return str;
122 | }
123 |
124 | return groupname->gr_name;
125 | }
126 |
127 |
128 |
--------------------------------------------------------------------------------
/chapter4/my_pwd.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define BUFFER_SIZE 512
9 |
10 | void pwd(char *filename);
11 | char *inode_to_dirname(ino_t inode);
12 | ino_t get_inode(char *filename);
13 |
14 | char dir_path[BUFFER_SIZE]="";
15 |
16 | int main(int argc, int *argv[]){
17 |
18 | int path_len = 0;
19 |
20 | pwd(".");
21 |
22 | //下面只是为了将最后面的"/"删除
23 | path_len = strlen(dir_path);
24 | dir_path[path_len-1] = '\0';
25 |
26 | printf("%s\n", dir_path);
27 |
28 | return 0;
29 | }
30 |
31 | void pwd(char *filename){
32 |
33 | ino_t current_inode;
34 | current_inode = get_inode(".");
35 |
36 | //char str[BUFFER_SIZE]="";
37 | char dir_temp[BUFFER_SIZE]="";
38 |
39 | strcpy(dir_temp, dir_path); //把路径赋值下来方便下面输出
40 |
41 | if(get_inode("..") == current_inode){
42 | sprintf(dir_path, "/%s", dir_temp);
43 | return;
44 | }else{
45 | chdir("..");
46 |
47 | //sprintf(st, "%s", inode_to_dirname(current_inode));
48 | //printf("%s\n", st);
49 |
50 | //如果把dir_temp换为dir_path,你会发现那两个%s会一样,因为dir_path先被赋值了,然后又被自己赋值了一次
51 | sprintf(dir_path, "%s/%s", inode_to_dirname(current_inode), dir_temp);
52 | pwd(".");
53 | }
54 | }
55 |
56 | //返回文件的inode号,只在文件在当前目录下有效
57 | ino_t get_inode(char *filename){
58 | struct stat current_dir_stat; //获取当前目录中“.”的inode号
59 |
60 | //打开当前filename所在目录
61 | if(stat(filename, ¤t_dir_stat) == -1){
62 | perror(filename);
63 | exit(1);
64 | }
65 |
66 | return current_dir_stat.st_ino;
67 | }
68 |
69 | //打开当前目录,查看当前目录下是否有和参数inode相同的文件,如果有返回dirname
70 | char *inode_to_dirname(ino_t inode){
71 |
72 | DIR *current_dir; // 打开当前目录
73 | struct dirent *current_dir_info; // 当前目录的信息
74 |
75 | //打开当前目录
76 | if( (current_dir = opendir(".")) == NULL){
77 | perror(".");
78 | exit(1);
79 | }
80 |
81 | //获取父目录的inode号
82 | while((current_dir_info = readdir(current_dir)) != NULL){
83 | if( current_dir_info->d_ino == inode ){
84 | close(current_dir);
85 | return current_dir_info->d_name; //返回filename
86 |
87 | }
88 | }
89 |
90 | //获取inode失败
91 | if(current_dir_info == NULL){
92 | perror(".");
93 | exit(2);
94 | }
95 | }
--------------------------------------------------------------------------------
/chapter5/echo_stat.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main(int argc, char *argv[]){
8 |
9 | struct termios stty_info;
10 |
11 | if((tcgetattr(0, &stty_info)) == -1){
12 | perror("tcgetattr:");
13 | exit(1);
14 | }
15 |
16 | if( stty_info.c_lflag & ECHO)
17 | printf("ECHO : NO\n");
18 | else
19 | printf("ECHO : OFF\n");
20 |
21 | return 0;
22 | }
23 |
--------------------------------------------------------------------------------
/chapter5/my_stty.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 |
6 | int main()
7 | {
8 | struct termios ttyinfo;
9 |
10 | if ( tcgetattr( 0 , &ttyinfo ) == -1 ){
11 | perror( "cannot get params about stdin");
12 | exit(1);
13 | }
14 |
15 | showbaud ( cfgetospeed( &ttyinfo ) );
16 |
17 | printf("VINTER = ^%c\t", ttyinfo.c_cc[VINTR] - 1 + 'A');
18 | printf("VQUIT = ^%c\t", ttyinfo.c_cc[VQUIT]- 1 + 'A');
19 | printf("VERASE = ^%c\t", '?');
20 | printf("VKILL = ^%c\t\n", ttyinfo.c_cc[VKILL]- 1 + 'A');
21 | printf("VEOF = ^%c\t", ttyinfo.c_cc[VEOF]- 1 + 'A');
22 | printf("VMIN = ^%c\t", ttyinfo.c_cc[VMIN]- 1 + 'A');
23 | printf("VEOL = ^%c\t", ttyinfo.c_cc[VEOL]- 1 + 'A');
24 | printf("VTIME = ^%c\t\n", ttyinfo.c_cc[VTIME]- 1 + 'A');
25 |
26 |
27 | show_some_flags( &ttyinfo );
28 |
29 | return 0;
30 | }
31 |
32 | int showbaud( int thespeed ){
33 | printf("spend ");
34 | switch ( thespeed ){
35 | case B300: printf("300\n"); break;
36 | case B600: printf("600\n"); break;
37 | case B1200: printf("1200\n"); break;
38 | case B1800: printf("1800\n"); break;
39 | case B2400: printf("2400\n"); break;
40 | case B4800: printf("4800\n"); break;
41 | case B9600: printf("9600\n"); break;
42 | case B19200: printf("19200\n"); break;
43 | case B38400: printf("38400\n"); break;
44 | default: printf("Fast\n"); break;
45 | }
46 | }
47 |
48 | struct flaginfo { int fl_value; char *fl_name; };
49 |
50 | struct flaginfo input_flags[] = {
51 | IGNBRK , "Ignore break condition",
52 | BRKINT , "Signal interrupt on break",
53 | IGNPAR , "Ignore chars with parity errors",
54 | PARMRK , "Mark parity errors",
55 | INPCK , "Enable input parity check",
56 | ISTRIP , "Strip character",
57 | INLCR , "Map NL to CR on input",
58 | IGNCR , "Ignore CR",
59 | ICRNL , "Map CR to NL on input",
60 | IXON , "Enable start/stop output control",
61 | IXOFF , "Enable start/stop input control",
62 | 0 , NULL };
63 |
64 | struct flaginfo output_flags[] = {
65 | OPOST , "Post-process output",
66 | ONLCR , "Map NL to CR-NL on output",
67 | OCRNL , "Map CR to NL on output",
68 | OFILL , "Use fill characters for delay",
69 | NLDLY , "Select newline delays",
70 | CRDLY , "Select carriage-return delays",
71 | TABDLY , "Select horizontal-tab delays",
72 | BSDLY , "Select backspace delays:",
73 | FFDLY , "Select form-feed delays",
74 | VTDLY , "Select vertical-tab delays",
75 | 0 , NULL };
76 |
77 |
78 | struct flaginfo c_flags[] = {
79 | CSIZE , "Character size",
80 | CSTOPB , "Send two stop bits, else one",
81 | CREAD , "Enable receiver",
82 | PARENB , "Parity enable",
83 | PARODD , "Odd parity, else even",
84 | HUPCL , "Hang up on last close",
85 | CLOCAL , "Ignore modem status lines",
86 | 0 , NULL };
87 |
88 |
89 | struct flaginfo local_flags[] = {
90 | ISIG , "Enable signals",
91 | ICANON , "Canonical input (erase and kill)",
92 | ECHO , "Enable echo",
93 | ECHOE , "Echo ERASE as BS-SPACE-BS",
94 | ECHOK , "Echo KILL by starting new line",
95 | 0 , NULL };
96 |
97 |
98 | int show_some_flags( struct termios *ttyp ){
99 | printf("c_iflag: \n");
100 | show_flagset( ttyp->c_iflag, input_flags );
101 |
102 | printf("c_oflag: \n");
103 | show_flagset( ttyp->c_oflag, output_flags );
104 |
105 | printf("c_cflag: \n");
106 | show_flagset( ttyp->c_cflag, c_flags );
107 |
108 | printf("c_lflag: \n");
109 | show_flagset( ttyp->c_lflag, local_flags );
110 | }
111 |
112 | int show_flagset( int thevalue, struct flaginfo thebitnames[] ){
113 | int i;
114 |
115 | for ( i=0; thebitnames[i].fl_value ; i++ ) {
116 | printf( " %s is ", thebitnames[i].fl_name);
117 | if ( thevalue & thebitnames[i].fl_value )
118 | printf("ON\n");
119 | else
120 | printf("OFF\n");
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/chapter5/my_write.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #define BUFFER_SIZE 512
8 |
9 | //向终端发送消息,不是向某人发送消息
10 | int main(int argc, char *argv[]){
11 |
12 | int p_dev;
13 | char send_buffer[BUFFER_SIZE];
14 |
15 | if(argc != 2){
16 | printf("参数错误!");
17 | exit(1);
18 | }
19 |
20 | if( (p_dev = open(argv[1], O_WRONLY)) == -1){
21 | perror(argv[1]);
22 | exit(1);
23 | }
24 |
25 | //EOF也可以退出
26 | while(fgets(send_buffer, BUFFER_SIZE, stdin) != NULL){
27 | if(write(p_dev, send_buffer, strlen(send_buffer)) != strlen(send_buffer)){
28 | perror("send:");
29 | }
30 | }
31 |
32 | close(p_dev);
33 | return 0;
34 | }
--------------------------------------------------------------------------------
/chapter5/set_stat.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main(int argc, char *argv[]){
8 |
9 | struct termios stty_info;
10 |
11 | if(argc != 2){
12 | printf("参数错误!\n");
13 | }
14 |
15 | if((tcgetattr(0, &stty_info)) == -1){
16 | perror("tcgetattr:");
17 | exit(1);
18 | }
19 |
20 | if(argv[1][0] == 'y' || argv[1][0] == 'Y'){
21 | stty_info.c_lflag |= ECHO;
22 | }
23 |
24 | if(argv[1][0] == 'n' || argv[1][0] == 'N'){
25 | stty_info.c_lflag &= ~ECHO;
26 | }
27 |
28 | if((tcsetattr(0, TCSANOW, &stty_info)) == -1){
29 | perror("tcsetattr:");
30 | exit(1);
31 | }
32 |
33 | return 0;
34 | }
--------------------------------------------------------------------------------
/chapter6/my_play.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define SELLPTIME 2
9 |
10 | int get_resopnse(void);
11 | void save_stty(void); //保存终端属性
12 | void renew_stty(void); //回复终端属性
13 | void set_stty(void); //设置非规范模式和单字符输入
14 | void set_flags(void); //设置非阻塞
15 | void ctrl_c_init(int); //CTRL+C
16 |
17 | static struct termios stty_info_buffer;
18 | static flags;
19 |
20 | int main(int argc, char *argv[]){
21 |
22 | int answer=2; //0:no, 1:yes,2:没选择
23 |
24 | save_stty(); //保存终端属性
25 | set_stty(); //设置当前环境的终端属性
26 | set_flags(); //设置非阻塞
27 | signal(SIGINT, ctrl_c_init); //CTRL+C
28 | signal(SIGQUIT, SIG_IGN); //忽略CTRL_\
29 |
30 | answer = get_resopnse();
31 |
32 | if(answer == 1)
33 | printf("YES\n");
34 | if(answer == 0)
35 | printf("NO\n");
36 | if(answer == 2)
37 | printf("NOT CHOOSE\n");
38 |
39 | renew_stty(); //恢复磁盘属性
40 | return 0;
41 | }
42 |
43 | int get_resopnse(void){
44 | int num = 3; //有3次输入的机会
45 | char answer;
46 |
47 | printf("%s: ", "Do you want to go dead?");
48 | fflush(stdout); //强制把输出缓冲区的数据输出
49 |
50 | while(num > 0){
51 | sleep(SELLPTIME); //睡眠2秒,期间如果没输入则继续睡两秒
52 | answer = getchar(); //因为是非阻塞,所以没有数据会直接跳过
53 | switch(answer){
54 | case 'y':
55 | case 'Y': return 1;
56 | case 'n':
57 | case 'N': return 0;
58 | }
59 | putchar('\a');
60 | num--;
61 | }
62 |
63 | return 2;
64 | }
65 |
66 | void save_stty(void){
67 | flags = fcntl(0, F_GETFL); //获取磁盘属性
68 | tcgetattr(0, &stty_info_buffer); //把设备终端保存下来以便恢复
69 | }
70 |
71 | void renew_stty(void){
72 | tcsetattr(0, TCSANOW, &stty_info_buffer); //恢复
73 | fcntl(0, F_SETFL, flags);//恢复磁盘属性
74 | }
75 |
76 | void set_stty(void){
77 | struct termios stty_info;
78 | tcgetattr(0, &stty_info);
79 | stty_info.c_lflag &= ~ICANON; //关闭规范模式
80 | stty_info.c_cc[VMIN] = 1; //设单字符模式,一个字符一个字符输入
81 | stty_info.c_lflag &= ~ECHO; //关闭回显
82 | tcsetattr(0, TCSANOW, &stty_info);
83 | }
84 |
85 | void set_flags(void){
86 | int flags;
87 | flags = fcntl(0, F_GETFL);
88 | flags |= O_NDELAY; //关闭阻塞
89 | fcntl(0, F_SETFL, flags);
90 | }
91 |
92 | void ctrl_c_init(int signum){
93 | renew_stty();
94 | exit(1);
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/chapter7/my_timer.c:
--------------------------------------------------------------------------------
1 | /*******
2 | **定时器
3 | **参数两个(毫秒):开始时间,间隔时间
4 | **定时完毕输出“timer over!”
5 | *******/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | void set_timer(int start_time, int interval_time);
13 | void timer_fuc(int signum);
14 |
15 | int main(int argc, char *argv[]){
16 |
17 | if(argc != 3){
18 | printf("参数错误\n");
19 | }
20 |
21 | set_timer( atoi(argv[1]), atoi(argv[2]));
22 | while(1)
23 | pause();
24 | return 0;
25 | }
26 |
27 |
28 | void set_timer(int start_time, int interval_time){
29 | signal(SIGALRM, timer_fuc);
30 |
31 | struct itimerval new_timer;
32 | int start_sec=0, start_usec=0;
33 | int interval_sec=0, interval_usec=0;
34 |
35 | start_sec = start_time / 1000; //秒
36 | start_usec = (start_time % 1000) * 1000L; //毫秒
37 |
38 | new_timer.it_value.tv_sec = start_sec;
39 | new_timer.it_value.tv_usec = start_usec;
40 |
41 | interval_sec = interval_time / 1000; //秒
42 | interval_usec = (interval_time % 1000) * 1000L; //毫秒
43 |
44 | new_timer.it_interval.tv_sec = interval_sec;
45 | new_timer.it_interval.tv_usec = interval_usec;
46 |
47 | setitimer(ITIMER_REAL, &new_timer, NULL);
48 | }
49 |
50 |
51 | void timer_fuc(int signum){
52 |
53 | printf("timer over!\n");
54 | }
--------------------------------------------------------------------------------
/chapter8/my_shell.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define ARGLIST_NUM 10 //参数个数
7 | #define ARG_LEN 100 //每个参数长度
8 |
9 | void exec(char *arglist[]);
10 |
11 |
12 | int main(int argc, char *argv[]){
13 |
14 | char *arglist[ARGLIST_NUM]; //参数列表,注意这里没分配内存
15 | char arg_buffer[ARG_LEN]; //元素缓存
16 | int i=0, j=0;
17 | //get_arglist(arglist);
18 |
19 |
20 | //循环获取参数
21 | while(i < ARGLIST_NUM){
22 |
23 | printf("arg[%d]: ", i);
24 |
25 | fgets(arg_buffer, ARG_LEN, stdin); //arglist没有分配内存不能直接赋值
26 |
27 | if( strcmp(arg_buffer, "\n") == 0 ){
28 | arglist[i] == NULL;
29 | exec(arglist);
30 |
31 | //释放空间
32 | for(j=0; j
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define ARGLIST_NUM 10 //参数个数
13 | #define ARG_LEN 100 //每个参数长度
14 |
15 | #define BUFFER_SIZE 10 //命令行大小
16 | #define ADD_BUFFER_SIZE 5 //命令行不够再加5
17 |
18 | void exec(char *arglist[]); //执行程序
19 | char *get_cmd(void); //获取一整条命令,包括参数
20 | char **get_arglist(char *current_cmd); //把命名拆分成到arglist数组中
21 |
22 | int main(int argc, char *argv[]){
23 |
24 | char *current_cmd; //存储输入的每条命令
25 | char **arglist; //参数列表,注意这里没分配内存
26 |
27 | int i=0;
28 |
29 | //忽略信号
30 | signal(SIGINT, SIG_IGN);
31 | signal(SIGQUIT, SIG_IGN);
32 |
33 | while( (current_cmd = get_cmd() ) != NULL){
34 | if( strcmp(current_cmd, "") == 0)
35 | continue;
36 |
37 | arglist = get_arglist(current_cmd); //获取参数数组
38 |
39 | //while(arglist[i] != NULL)
40 | // printf("%s\n", arglist[i++]);
41 |
42 | //执行程序
43 | exec(arglist);
44 |
45 | //释放空间
46 | while(arglist[i] != NULL)
47 | free(arglist[i++]);
48 | }
49 |
50 | return 0;
51 | }
52 |
53 | char **get_arglist(char *current_cmd){
54 | static char *arglist[ARGLIST_NUM]; //要返回的字符串数组
55 | char arg_buffer[ARG_LEN]; //缓存每个元素
56 | char *cmd_buffer; //把命令复制到这里
57 | int i=0, arg_num=0;
58 |
59 | //分配空间,并赋值命令
60 | cmd_buffer=malloc(strlen(current_cmd));
61 | strcpy(cmd_buffer, current_cmd);
62 | //printf("%s", cmd_buffer);
63 | //list -a -l
64 | while(1){
65 | if(cmd_buffer[i] == ' ' || cmd_buffer[i] == '\0'){
66 | arglist[arg_num] = malloc(i+1); //分配
67 | strncpy(arglist[arg_num], cmd_buffer, i); //赋值
68 | arglist[arg_num][i] = '\0'; //添加'\0'
69 |
70 | // printf("%s\n", arglist[arg_num]);
71 | if(cmd_buffer[i] == '\0'){
72 | arglist[arg_num+1] = NULL;
73 | return arglist;
74 | }
75 |
76 |
77 | cmd_buffer = cmd_buffer+i+1; //把指针移到空格后面那一字节
78 | arg_num++;
79 | i=0;
80 | }
81 | i++;
82 | }
83 |
84 | }
85 |
86 |
87 | char *get_cmd(void){
88 | char *currnet_cmd;
89 |
90 | int buffer_flag = BUFFER_SIZE; //用来重新分配内存
91 | int c_num = 0; //已输入字符数的数量
92 | char c; //缓存输入字符
93 |
94 | currnet_cmd = malloc(BUFFER_SIZE); //先分配一个小内存,10个字符
95 |
96 | printf("[SKING_SHELL] ");
97 |
98 | while( (c = fgetc(stdin)) != EOF){
99 |
100 | //如果是回车则直接退出子程序
101 | if(c == '\n'){
102 | currnet_cmd[c_num] = '\0';
103 | return currnet_cmd;
104 | }
105 |
106 | currnet_cmd[c_num++] = c;
107 |
108 | //重新分配内存
109 | if( ((c_num - BUFFER_SIZE) % ADD_BUFFER_SIZE) == 0){
110 | currnet_cmd = realloc(currnet_cmd, buffer_flag+ADD_BUFFER_SIZE);
111 | buffer_flag += ADD_BUFFER_SIZE;
112 | }
113 |
114 | }
115 |
116 | return NULL;
117 | }
118 |
119 | void exec(char *arglist[]){
120 |
121 | int ret_pid = 0; //子进程PID
122 | int ret_val = 0; //子进程exit返回值
123 |
124 | ret_pid = fork(); //开启新进程
125 | switch(ret_pid){
126 | case 0: //子进程执行程序
127 | if( execvp(arglist[0], arglist) == -1){
128 | perror(arglist[0]);
129 | exit(2);
130 | }
131 | _exit(1);
132 |
133 | case -1: //错误
134 | perror("fork failed!");
135 | exit(1);
136 |
137 | default: //父进程
138 | while(ret_pid != wait(&ret_val)); //死循环等待子进程结束
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------