2024年2月9日发(作者:)

388

389 /* set the read end of the socket to non-blocking */

390 if (set_nonblock_fd(pipes[0]) == -1) {

391 log_error_time();

392 perror("cgi-fcntl");

393 close(pipes[0]);

394 close(pipes[1]);

395 return 0;

396 }

397 }

398

399 child_pid = fork();

400 switch(child_pid) {

401 case -1:

402 /* fork unsuccessful */

403 log_error_time();

404 perror("fork");

405

406 if (use_pipes) {

407 close(pipes[0]);

408 close(pipes[1]);

409 }

410 send_r_error(req);

411 /* FIXME: There is aproblem here. send_r_error would work

412 for NPH and CGI, but not for GUNZIP. Fix that. */

413 /* i'd like to send_r_error, */

414 return 0;

415 break;

416 case 0:

417 /* child */

418 if (req->is_cgi == CGI || req->is_cgi == NPH) {

419 char *foo = strdup(req->pathname);

420 char *c;

421

422 if (!foo) {

423 WARN("unable to strdup pathname for req->pathname");

424 _exit(1);

425 }

426 c = strrchr(foo, '/');

427 if (c) {

428 ++c;

429 *c = '0';

430 } else {

431 /* we have a serious problem */

432 log_error_time();

433 perror("chdir");

434 if (use_pipes)

435 close(pipes[1]);

436 _exit(1);

437 }

438 if (chdir(foo) != 0) {

439 log_error_time();

440 perror("chdir");

441 if (use_pipes)

442 close(pipes[1]);

443 _exit(1);

444 }

445 }

446 if (use_pipes) {

447 close(pipes[0]);

448 /* tie cgi's STDOUT to it's write end of pipe */

449 if (dup2(pipes[1], STDOUT_FILENO) == -1) {

450 log_error_time();

451 perror("dup2 - pipes");

452 close(pipes[1]);

453 _exit(1);

454 }

455 close(pipes[1]);

456 if (set_block_fd(STDOUT_FILENO) == -1) {

457 log_error_time();

458 perror("cgi-fcntl");

459 _exit(1);

460 }

461 } else {

462 /* tie stdout to socket */

463 if (dup2(req->fd, STDOUT_FILENO) == -1) {

464 log_error_time();

465 perror("dup2 - fd");

466 _exit(1);

467 }

468 /* Switch socket flags back to blocking */

469 if (set_block_fd(req->fd) == -1) {

470 log_error_time();

471 perror("cgi-fcntl");

472 _exit(1);

473 }

474 }

475 /* tie post_data_fd to POST stdin */

476 if (req->method == M_POST) { /* tie stdin to file */

477 lseek(req->post_data_fd, SEEK_SET, 0);

478 dup2(req->post_data_fd, STDIN_FILENO);

479 close(req->post_data_fd);

480 }

481 /* Close access log, so CGI program can't scribble

482 * where it shouldn't

483 */

484 close_access_log();

485

486 /*

487 * tie STDERR to cgi_log_fd

488 * cgi_log_fd will automatically close, close-on-exec rocks!

489 * if we don't tied STDERR (current log_error) to cgi_log_fd,

490 * then we ought to close it.

491 */

492 if (!cgi_log_fd)

493 dup2(devnullfd, STDERR_FILENO);

494 else

495 dup2(cgi_log_fd, STDERR_FILENO);

496

497 if (req->is_cgi) {

498 char *aargv[CGI_ARGC_MAX + 1];

499 create_argv(req, aargv);

500 execve(req->pathname, aargv, req->cgi_env);

501 } else {

502 if (req->pathname[strlen(req->pathname) - 1] == '/')

503 execl(dirmaker, dirmaker, req->pathname, req->request_uri,