Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 47 48 49 50 51 52 53  54 55 56 57 58 59 60 ... 87
            register eacces = 0;
            char fullpath[256];     /* полное имя программы */

            firstfound = NULL;
            if((path = getenv("PATH")) == NULL )
                path = ".:/bin:/usr/bin:/etc";
            /* имя: короткое или путь уже задан ? */
            cp = strchr(progr, '/') ? "" : path;
            do{     /* пробуем разные варианты */
                    cp = execat(cp, progr, fullpath);
            retry:
                fprintf(stderr, "пробуем \"%s\"\n", fullpath );
                    execve(fullpath, av, envp);
                    /* если программа запустилась, то на этом месте данный
                     * процесс заменился новой программой. Иначе - ошибка. */
                    switch( errno ){  /* какова причина неудачи ? */
                    case ENOEXEC:  /* это командный файл */
                            callshell(fullpath, av, envp);
                            return (-1);
                    case ETXTBSY:   /* файл записывается */
                            if( ++try > 5 ) return (-1);
                            sleep(try); goto retry;
                    case EACCES:    /* не имеете права */
                            if(firstfound == NULL)
                               firstfound = strdup(fullpath);
                            eacces++; break;
                    case ENOMEM:    /* программа не лезет в память */
                    case E2BIG:
                            return (-1);
                    }
            }while( cp );
            if( eacces ) errno = EACCES;
            return (-1);
    }

    /* Склейка очередной компоненты path и имени программы name */
    static char *execat(path, name, buf)
            register char *path, *name;
            char *buf;      /* где будет результат */
    {
            register char *s = buf;
            while(*path && *path != LIM )
                    *s++ = *path++;         /* имя каталога */
            if( s != buf ) *s++ = '/';
            while( *name )
                    *s++ = *name++;         /* имя программы */
            *s = '\0';
            return ( *path ? ++path /* пропустив LIM */ : NULL );
    }

А. Богатырев, 1992-95                  - 276 -                              Си в UNIX

    /* Запуск командного файла при помощи вызова интерпретатора */
    void callshell(progr, av, envp) char *progr, **av, **envp;
    {
            register i; char *sh; char *newav[MAXARGS+2];
            int fd; char first = 0;

            if((fd = open(progr, O_RDONLY)) < 0 )
                    sh = "/bin/sh";
            else{
                    read(fd, &first, 1); close(fd);
                    sh = (first == '#') ? "/bin/csh" : "/bin/sh";
            }
            newav[0] = "Shellscript"; newav[1] = progr;
            for(i=1; av[i]; i++)
                    newav[i+1] = av[i];
            newav[i+1] = NULL;
            printf( "Вызываем %s\n", sh );
            execve(sh, newav, envp);
    }

    /* Ожидать окончания всех процессов, выдать причины смерти. */
    void dowait(){
            int ws; int pid;

            while((pid = wait( &ws)) > 0 ){
              if( WIFEXITED(ws)){
                printf( "Процесс %d умер с кодом %d\n",
                                 pid,            WEXITSTATUS(ws));
              }else if( WIFSIGNALED(ws)){
                printf( "Процесс %d убит сигналом %d\n",
                                 pid,             WTERMSIG(ws));
                if(WCOREDUMP(ws)) printf( "Образовался core\n" );
                /* core - образ памяти процесса для отладчика adb */
              }else if( WIFSTOPPED(ws)){
                printf( "Процесс %d остановлен сигналом %d\n",
                                 pid,            WSTOPSIG(ws));
              }
           }
    }

А. Богатырев, 1992-95                  - 277 -                              Си в UNIX

    /* Расширение шаблонов имен. Это упрощенная версия, которая
     * расширяет имена только в текущем каталоге.
     */
    void glob(dir, args, indx, str /* что расширять */, quote )
         char *args[], *dir; int *indx; char *str;
         char quote; /* кавычки, в которые заключена строка str */
    {
            static char globchars[] = "*?[";
            char *p; char **start = &args[ *indx ];
            short nglobbed = 0;

            register struct dirent *dirbuf;
            DIR *fd; extern DIR *opendir();

            /* Затычка для отмены глоббинга: */
            if( *str == '\\' ){ str++;    goto noGlob; }

            /* Обработка переменных $NAME    */
            if( *str == '$' && quote != '\'' ){
                    char *s = getenv(str+1);
                    if( s ) str = s;
            }
            /* Анализ: требуется ли глоббинг */
            if( quote ) goto noGlob;
            for( p=str; *p; p++ )  /* Есть ли символы шаблона? */
                    if( strchr(globchars, *p))
                            goto doGlobbing;
    noGlob:
            args[ (*indx)++ ] = strdup(str);
            return;

    doGlobbing:
           if((fd = opendir (dir)) == NULL){
                  fprintf(stderr, "Can't read %s\n", dir); return;
           }
           while ((dirbuf = readdir (fd)) != NULL ) {
                  if (dirbuf->d_ino == 0) continue;
                  if (strcmp (dirbuf->d_name, ".") == 0 ||
                      strcmp (dirbuf->d_name, "..") == 0) continue;
                  if( match( dirbuf->d_name, str)){
                      args[ (*indx)++ ] = strdup(dirbuf->d_name);
                      nglobbed++;
                  }
           }
           closedir(fd);
           if( !nglobbed){
               printf( "%s: no match\n", str);
               goto noGlob;
           }else{   /* отсортировать */
               qsort(start, nglobbed, sizeof (char *), cmps);
           }
    }

А. Богатырев, 1992-95                  - 278 -                              Си в UNIX

    /* Разбор командной строки */
    int parse(s) register char *s;
    {
            int i; register char *p;
            char tmp[80];   /* очередной аргумент */
            char c;

            /* очистка старых аргументов */
            for(i=0; arg[i]; i++) free(arg[i]), arg[i] = NULL;
            if( fin  ) free(fin ), fin  = NULL;
            if( fout ) free(fout), fout = NULL;
            rout = 0;

            /* разбор строки */
            for( i=0 ;; ){
                    char quote = '\0';

                    /* пропуск пробелов - разделителей слов */
                    while((c = *s) && isspace(c)) s++;
                    if( !c ) break;
                    /* очередное слово */
                    p = tmp;
                    if(*s == '\'' || *s == '"' ){
                    /* аргумент в кавычках */
                            quote = *s++;  /* символ кавычки */
                            while((c = *s) != '\0' && c != quote){
                               if( c == '\\' ){ /* заэкранировано */
                                   c = *++s;
                                   if( !c ) break;
                               }
                               *p++ = c; ++s;
                            }
                            if(c == '\0')
                      fprintf(stderr, "Нет закрывающей кавычки %c\n", quote);
                            else s++; /* проигнорировать кавычку на конце */

А. Богатырев, 1992-95                  - 279 -                              Си в UNIX

                    } else
                            while((c = *s) && !isspace(c)){
                               if(c == '\\') /* заэкранировано */
                                    if( !(c = *++s))
                                         break /* while */;
                               *p++ = c; s++;
                            }
                    *p = '\0';
                    /* Проверить, не есть ли это перенаправление
                     * ввода/вывода. В отличие от sh и csh
                     * здесь надо писать >ФАЙЛ <ФАЙЛ
                     * >< вплотную к имени файла.
                     */
                    p = tmp;        /* очередное слово */
                    if( *p == '>'){ /* перенаправлен вывод */
                        p++;
                        if( fout ) free(fout), rout = 0; /* уже было */
                        if( *p == '>' ){ rout |= APPEND; p++; }
                        if( *p == '&' ){ rout |= ERRTOO; p++; }
                        if( !*p ){
                                fprintf(stderr, "Нет имени для >\n");
                                fout = NULL; rout = 0;
                        } else  fout = strdup(p);
                    } else if( *p == '<' ){  /* перенаправлен ввод */
                        p++;
                        if( fin ) free(fin);        /* уже было */
                        if( !*p ){
                                fprintf(stderr, "Нет имени для <\n");
                                fin = NULL;
                        } else  fin = strdup(p);
                    } else /* добавить имена к аргументам */
                                glob( ".", arg, &i, p, quote );
            }
            arg[i] = NULL; return i;
    }

    /* Установить имя пользователя */
    void setuser(){
            int uid = getuid();     /* номер пользователя, запустившего Шелл */
            char *user = "mr. Nobody";      /* имя пользователя     */
            char *home = "/tmp";            /* его домашний каталог */
            struct passwd *pp = getpwuid( uid );
            if( pp != NULL ){
                    if(pp->pw_name && *pp->pw_name ) user = pp->pw_name;
                    if(               *pp->pw_dir  ) home = pp->pw_dir;
            }
            setenv("USER", user); setenv("HOME", home);
    }

    void setcwd(){ /* Установить имя текущего каталога */
            char cwd[512];
            getwd(cwd); setenv( "CWD", cwd );
    }

    void main(ac, av, ev) char *av[], *ev[]; {
            int argc;              /* количество аргументов */
            char *prompt;          /* приглашение           */

            setuser(); setcwd();
            signal(SIGINT, SIG_IGN);
            setbuf(stdout, NULL);  /* отменить буферизацию */
            for(;;){
                 prompt = getenv( "prompt" ); /* setenv prompt -->\  */
                 printf( prompt ? prompt : "@ ");/* приглашение */
                 if( gets(cmd) == NULL /* at EOF  */ ) exit(0);
                 argc = parse(cmd);
                 if( !argc) continue;
                 if( !strcmp(arg[0], "exit" )) exit(0);

                 if( !strcmp(arg[0], "cd" )){
                     char *d = (argc==1) ? getenv("HOME"):arg[1];
                     if(chdir(d) < 0)
                        printf( "Не могу войти в %s\n", d );
                     else setcwd();
                     continue;
                 }

                 if( !strcmp(arg[0], "echo" )){
                     register i; FILE *fp;
                     if( fout ){
                        if((fp = fopen(fout, rout & APPEND ? "a":"w"))
                               == NULL) continue;
                     }  else fp = stdout;
                     for(i=1; i < argc; i++ )
                        fprintf( fp, "%s%s", arg[i], i == argc-1 ? "\n":"   ");
                     if( fp != stdout ) fclose(fp);
                     continue;
                 }

                 if( !strcmp(arg[0], "setenv" )){
                          if( argc == 1 ) printenv();
                     else if( argc == 2 ) setenv( arg[1], "" );
                     else                 setenv( arg[1], arg[2]);
                     continue;
                 }
                 cmdExec(arg[0], (char **) arg, environ, fin, fout, rout);
Предыдущая страница Следующая страница
1 ... 47 48 49 50 51 52 53  54 55 56 57 58 59 60 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама