Рейтинговые книги
Читем онлайн Разработка приложений в среде Linux. Второе издание - Майкл Джонсон

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 138 139 140 141 142 143 144 145 146 ... 150

362:   strcpy(job->text, *commandPtr);

363:  } else {

364:   /*Оставляем любые хвостовые пробелы, хотя и получится это несколько небрежно*/

365:

366:   count = returnCommand - *commandPtr;

367:   job->text = malloc(count + 1);

368:   strncpy(job->text, *commandPtr, count);

369:   job->text[count] = '';

370:  }

371:

372:  *commandPtr = returnCommand;

373:

374:  return 0;

375: }

376:

377: int setupRedirections(struct childProgram * prog) {

378:  int i;

379:  int openfd;

380:  int mode;

381:  struct redirectionSpecifier * redir = prog->redirections;

382:

383:  for (i = 0; i < prog->numRedirections; i++, redir++) {

384:   switch (redir->type) {

385:   case REDIRECT_INPUT:

386:    mode = O_RDONLY;

387:    break;

388:   case REDIRECT_OVERWRITE:

389:    mode = O_RDWR | O_CREAT | O_TRUNC;

390:    break;

391:   case REDIRECT_APPEND:

392:    mode = O_RDWR | O_CREAT | O_APPEND;

393:    break;

394:   }

395:

396:   openfd = open(redir->filename, mode, 0666);

397:   if (openfd < 0) {

398:    /* мы могли потерять это в случае переадресации stderr,

399:       хотя bash и ash тоже потеряют его (а вот

400:       zsh - нет!) */

401:    fprintf(stderr, "ошибка при открытии %s: %sn",

402:    redir->filename, strerror(errno));

403:    return 1;

404:   }

405:

406:   if (openfd != redir->fd) {

407:    dup2(openfd, redir->fd);

408:    close(openfd);

409:   }

410:  }

411:

412:  return 0;

413: }

414:

415: int runCommand(struct job newJob, struct jobSet * jobList,

416:  int inBg) {

417:  struct job * job;

418:  char * newdir, * buf;

419:  int i, len;

420:  int nextin, nextout;

421:  int pipefds[2]; /* pipefd[0] предназначен для чтения */

422:  char * statusString;

423:  int jobNum;

424:  int controlfds[2] ;/*канал для возможности приостановки работы дочернего процесса*/

425:

426:  /* здесь производится обработка встраиваемых модулей — мы не используем fork(),

427:     поэтому, чтобы поместить процесс в фон, придется потрудиться */

428:  if (!strcmp(newJob.progs[0].argv[0], "exit")) {

429:   /* здесь возвращается реальный код выхода */

430:   exit(0);

431:  } else if (!strcmp(newJob.progs[0].argv[0], "pwd")) {

432:   len = 50;

433:   buf = malloc(len);

434:   while (!getcwd(buf, len) && errno == ERANGE) {

435:    len += 50;

436:    buf = realloc(buf, len);

437:   }

438:   printf("%sn", buf);

439:   free(buf);

440:   return 0;

441:  } else if (!strcmp(newJob.progs[0].argv[0], "cd")) {

442:   if (!newJob.progs[0].argv[1] == 1)

443:    newdir == getenv("HOME");

444:   else

445:    newdir = newJob.progs[0].argv[1];

446:   if (chdir(newdir))

447:    printf("сбой при смене текущего каталога: %sn",

448:     strerror(errno));

449:   return 0;

450:  } else if (!strcmp(newJob.progs[0].argv[0], "jobs")) {

451:   for (job = jobList->head; job; job = job->next) {

452:    if (job->runningProgs == job->stoppedProgs)

453:     statusString = "Остановлено";

454:    else

455:     statusString = "Выполняется";

456:

457:    printf(JOB_STATUS_FORMAT, job->jobId, statusString,

458:     job->text);

459:   }

460:   return 0;

461:  } else if (!strcmp(newJob.progs[0].argv[0], "fg") ||

462:   !strcmp(newJob.progs[0].argv[0], "bg")) {

463:   if (!newJob.progs[0].argv[1] || newJob.progs[0].argv[2]) {

464:    fprintf(stderr,

465:     "%s: ожидался в точности один аргументn",

466:     newJob.progs[0].argv[0]);

467:    return 1;

468:   }

469:

470:   if (sscanf(newJob.progs[0].argv[1], "%%%d", &jobNum) != 1) {

471:    fprintf(stderr, "%s: неверный аргумент '%s'n",

472:     newJob.progs[0].argv[0],

473:     newJob.progs[0].argv[1]);

474:    return 1;

475:   }

476:

477:   for (job = jobList->head; job; job = job->next)

478:    if (job->jobId == jobNum) break;

479:

480:   if (!job) {

481:    fprintf(stderr, "%s: неизвестное задание %dn",

482:     newJob.progs[0].argv[0], jobNum);

483:    return 1;

484:   }

485:

486:   if (*new Job. progs[0].argv[0] == 'f') {

487:    /* Переводим задание на передний план */

488:

489:    if (tcsetpgrp(0, job->pgrp))

490:     perror("tcsetpgrp");

491:    jobList->fg = job;

492:   }

493:

494:   /* Повторяем запуск процессов в задании */

495:   for (i = 0; i<job->numProgs; i++)

496:    job->progs[i].isStopped = 0;

497:

498:   kill(-job->pgrp, SIGCONT);

499:

500:   job->stoppedProgs = 0;

501:

502:   return 0;

503:  }

504:

505:  nextin = 0, nextout = 1;

506:  for (i = 0; i < newJob.numProgs; i++) {

507:   if ((i + 1) < newJob.numProgs) {

508:    pipe(pipefds);

509:    nextout = pipefds[1];

510:   } else {

511:    nextout = 1;

512:   }

513:

514:   pipe(controlfds);

515:

516:   if (!(newJob.progs[i].pid = fork())) {

517:    signal(SIGTTOU, SIG_DFL);

518:

519:    close(controlfds[1]);

520:    /* при чтении будет возвращен 0, когда записывающая сторона закрыта */

521:    read(controlfds[0], &len, 1);

522:    close(controlfds[0]);

523:

524:    if (nextin != 0) {

525:     dup2(nextin, 0);

526:     close(nextin);

527:    }

528:

529:    if (nextout != 1) {

530:     dup2(nextout, 1);

531:     close(nextout);

532:    }

533:

534:    /* явные переадресации подменяют каналы */

535:    setupRedirections(newJob.progs + i);

536:

537:    execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);

538:    fprintf(stderr, "сбой exec() для %s: %sn",

539:    newJob.progs[i].argv[0],

540:    strerror(errno));

541:    exit(1);

542:   }

543:

544:   /* помещаем дочерний процесс в группу процессов, лидером в которой

545:      является первый процесс в этом канале */

546:   setpgid(newJob.progs[i].pid, newJob.progs[0].pid);

547:

548:   /* закрываем канал управления, чтобы продолжить работу дочернего процесса */

549:   close(controlfds[0]);

550:   close(controlfds[1]);

551:

552:   if (nextin !=0) close(nextin);

553:   if (nextout !=1) close(nextout);

554:

555:   /* Если другого процесса нет, то nextin является "мусором",

556:      хотя это и не является помехой */

557:   nextin = pipefds[0];

558:  }

559:

560:  newJob.pgrp = newJob.progs[0].pid;

561:

562:  /* поиск идентификатора используемого задания */

563:  newJob.jobld = 1;

564:  for (job = jobList->head; job; job = job->next)

565:   if (job->jobId> = newJob.jobId)

566:    newJob.jobId = job->jobId + 1;

567:

568:  /* добавляем задание в список выполняющихся заданий */

569:  if (!jobList->head) {

570:   job = jobList->head = malloc(sizeof(*job));

571:  } else {

572:   for (job = jobList->head; job->next; job = job->next);

573:   job->next = malloc(sizeof(*job));

574:   job = job->next;

575:  }

576:

577:  *job = newJob;

578:  job->next = NULL;

579:  job->runningProgs = job->numProgs;

580:  job->stoppedProgs = 0;

581:

582:  if (inBg) {

583:   /* мы не ожидаем возврата фоновых заданий - добавляем их

584:      в список фоновых заданий и оставляем их */

585:

586:   printf("[%d] %dn", job->jobId,

587:    newJob.progs[newJob.numProgs - 1].pid);

588:  } else {

589:   jobList->fg = job;

590:

591:   /* перемещаем новую группу процессов на передний план */

592:

593:   if (tcsetpgrp(0, newJob.pgrp))

594:    perror("tcsetpgrp");

595:  }

596:

597:  return 0;

598: }

599:

600: void removeJob(struct jobSet * jobList, struct job * job) {

601:  struct job * prevJob;

602:

603:  freeJob(job);

604:  if (job == jobList->head) {

605:   jobList->head = job->next;

606:  } else {

607:   prevJob = jobList->head;

608:   while (prevJob->next != job) prevJob = prevJob->next;

609:   prevJob->next = job->next;

610:  }

611:

612:  free(job);

613: }

614:

615: /* Проверяем, завершился ли какой-либо фоновый процесс - если да, то

616:    устанавливаем причину и проверяем, окончилось ли выполнение задания */

617: void checkJobs(struct jobSet * jobList) {

618:  struct job * job;

619:  pid_t childpid;

620:  int status;

621:  int progNum;

622:  char * msg;

623:

1 ... 138 139 140 141 142 143 144 145 146 ... 150
На этой странице вы можете бесплатно читать книгу Разработка приложений в среде Linux. Второе издание - Майкл Джонсон бесплатно.
Похожие на Разработка приложений в среде Linux. Второе издание - Майкл Джонсон книги

Оставить комментарий