• Linux_C smsh1


    这是一个模拟shell端的程序。

    使用了execvp,fork,wait,malloc,realloc以及strtok()函数。

    smsh.h

    1 char* next_cmd();
    2 char** splitline(char* );
    3 void freelist(char **);
    4 int execute(char** );

    smsh1.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <signal.h>
     5 #define DFL_PROMPT ">:"
     6 int main(){
     7   char * cmdline, *prompt, **arglist;
     8   int i;
     9   void setup();
    10   prompt = DFL_PROMPT;
    11   setup();
    12   while((cmdline=next_cmd(prompt, stdin)) != NULL ){
    13     if((arglist=splitline(cmdline))!=NULL){
    14       for(i=0; i<2; i++)
    15     printf("%s  ", arglist[i]);
    16       printf("
    ");
    17       printf("will execute.
    ");
    18       execute(arglist);
    19       freelist(arglist);
    20     }
    21     free(cmdline);
    22   }
    23   
    24   return 0;
    25 }
    26 void setup(){
    27   /*
    28    * purpose: initialize shell
    29    * 在shell中忽略信号SIGINT&SIGQUIT, 但是在子进程中恢复对
    30    * SIGINT&SIGQUIT的默认操作,允许用户通过按表示结束多文件多Ctrl-D来退出
    31    */
    32   signal(SIGINT, SIG_IGN);
    33   signal(SIGQUIT, SIG_IGN);
    34 }

    splitline.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include "smsh.h"
     5 
     6 char* next_cmd(char* prompt, FILE *fp){
     7   /*
     8    * purpose: read next command line from fp
     9    * return: dynamically allocated string holding command line
    10    * note: allocates space in BUFSIZ chunks.其中BUFSIZ是库函数中define过了的
    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 = malloc(BUFSIZ);
    21       else 
    22     buf = realloc(buf, bufspace+BUFSIZ);
    23       bufspace+=BUFSIZ;
    24     }
    25     if(c=='
    ')
    26       break;
    27     buf[pos++]=c;
    28   }
    29   if(c==EOF || pos==0)
    30     return NULL;
    31   buf[pos]=0;
    32   //printf("u cin is end.
    ");
    33   return buf;
    34 }
    35 
    36 char** splitline(char* cmdline){
    37   /*
    38    * purpose: split a line 
    39    * note:注意:在最后一次给arglist赋值时,也就是strtok()返回为NULL的时候,也需要给
    40    *            arglist[i]=malloc(sizeof(char*));一下,即使最后赋的为NULL也需要分配一个指针空间给它。
    41    */
    42   char **arglist;
    43   char *delim=" ";
    44   char *cmdbuf;
    45   int i=1;
    46   cmdbuf=strtok(cmdline,delim);
    47   //printf("cmdbuf0: %s
    ", cmdbuf);
    48   arglist = malloc(sizeof(char*));
    49   arglist[0]=malloc(strlen(cmdbuf)*sizeof(char));
    50   strcpy(arglist[0], cmdbuf);
    51   while((cmdbuf=strtok(NULL, delim))) {
    52     arglist = realloc(arglist, (1+i)*sizeof(char*));
    53     arglist[i]=malloc(strlen(cmdbuf)*sizeof(char));
    54     strcpy(arglist[i], cmdbuf);
    55     //printf("cmdbuf%d: %s
    ",i,cmdbuf);
    56     i++;
    57   }
    58   arglist[i]=malloc(sizeof(char*));
    59   arglist[i]=NULL;
    60   return arglist;
    61 }

    execute.c

     1 /* execute.c- code used by small shell to execute commands
     2  */
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 #include <unistd.h>
     6 #include <signal.h>
     7 #include <sys/wait.h>
     8 
     9 int execute(char** arglist){
    10   /*
    11    *purpose: run a program passing it arguments;
    12    *return: status returned via wait, or -1 on error
    13    *errors: -1 on fork() on wait() errors
    14    */
    15   int pid;
    16   int child_info = -1;
    17   printf("now its go into the function execute
    ");
    18   if((pid=fork()) == -1)
    19     perror("fork");
    20   else if(pid == 0) {
    21     signal(SIGINT, SIG_DFL);
    22     signal(SIGQUIT, SIG_DFL);
    23     execvp(arglist[0], arglist);
    24     perror("cannot execute command");
    25     exit(1);
    26   }
    27   else {
    28     if(wait(&child_info) == -1)
    29       perror("wait");
    30   }
    31   return child_info;
    32 }
    33 void freelist(char** list) {
    34   /*
    35    *purpose: free the list returned by splitline
    36    *returns: nothing
    37    *actoin: free all strings in list and then free the list
    38    */
    39   char **cp=list;
    40   while(*cp)
    41     free(*cp++);
    42   free(list);
    43 }

     关于为什么要开一个进程给execvp()使用,是因为unix运行一个程序;1.将指定的程序复制到调用它的进程。2.将指定的字符串数组作为argv[]传给这个程序。3.运行这个程序。

    如果不开进程就来执行execvp(),就会运行完一个命令后就会结束退出。这是因为execvp()用命令指定的程序代码覆盖了shell的程序代码,然后在命令指定的程序结束之后就退出。

  • 相关阅读:
    C++笔记(2018/2/6)
    2017级面向对象程序设计寒假作业1
    谁是你的潜在朋友
    A1095 Cars on Campus (30)(30 分)
    A1083 List Grades (25)(25 分)
    A1075 PAT Judge (25)(25 分)
    A1012 The Best Rank (25)(25 分)
    1009 说反话 (20)(20 分)
    A1055 The World's Richest(25 分)
    A1025 PAT Ranking (25)(25 分)
  • 原文地址:https://www.cnblogs.com/wizzhangquan/p/4066079.html
Copyright © 2020-2023  润新知