2011-10-05 10 views
8

Chúng tôi đang gặp rất nhiều rắc rối khi diễn giải giáo viên của chúng tôi. Chúng tôi đề nghị làm rõ và nhận được những điều sau lại từ anh ấycác yêu cầu hiểu biết để thực hiện và thiết lập các vars môi trường

  1. Đối với execve, gửi cho nó một môi trường bạn thiết lập với các biến xuất khẩu của bạn và tạo ra một lệnh dựng sẵn để đẻ trứng một subshell của/bin/bash, như vậy bạn có thể xem các biến đã xuất của bạn bằng env.

    (Anh ấy đang nói về việc tạo ra các lọ môi trường riêng của chúng tôi tại đây.)

  2. Có tạo của riêng bạn. Bạn có thể bắt đầu bằng cách sao chép môi trường khi trình bao bắt đầu và chỉ thêm các biến đã xuất

Điều này liên quan đến bài đăng sau đây trên Stack Overflow by me (đọc bài đăng khác này sẽ giúp bạn hiểu những gì tôi đang cố gắng làm):

using a new path with execve to run ls command

Chúng tôi rất bối rối về điều này. Một lần nữa tôi sẽ giải thích những gì chúng tôi đang cố gắng làm bây giờ. Tương tự như cách trình bao Linux của bạn thực hiện điều này, chúng ta cần phải viết chương trình riêng của chúng ta có thể thiết lập các biến môi trường như PATH và USER và bất kỳ biến nào khác mà người dùng muốn xác định.

Một ví dụ về cách bạn sẽ gọi đây sẽ là (bên trong chương trình của bạn tại dấu nhắc của nó):

mysetenv dog spike 

mà sẽ tạo ra một biến môi trường trông như "con chó = cành"

Quan trọng hơn, chúng ta cần có khả năng thiết lập biến PATH của riêng mình và gửi nó đến một lệnh exec. Đây là phần khó hiểu bởi vì, dựa trên tất cả các câu hỏi của chúng tôi, chúng tôi không hiểu chúng tôi phải làm gì.

Trả lời

26

Nó thực sự rất đơn giản. Bạn đã biết rằng đối số của bạn là một danh sách của char *, chấm dứt bởi một con trỏ NULL. Tương tự, môi trường chỉ đơn giản là một danh sách của char *, chấm dứt bởi một con trỏ NULL. Thông thường, các giá trị trong danh sách có dạng VARNAME=var-value, mặc dù bạn có thể chuyển các định dạng khác nếu muốn.

Vì vậy, để có một trường hợp đơn giản:

#include <unistd.h> 
#include <stdio.h> 

int main(void) 
{ 
    char *argv[] = { "/bin/sh", "-c", "env", 0 }; 
    char *envp[] = 
    { 
     "HOME=/", 
     "PATH=/bin:/usr/bin", 
     "TZ=UTC0", 
     "USER=beelzebub", 
     "LOGNAME=tarzan", 
     0 
    }; 
    execve(argv[0], &argv[0], envp); 
    fprintf(stderr, "Oops!\n"); 
    return -1; 
} 

Trong ví dụ này, chương trình sẽ chạy /bin/sh với đối số -cenv, có nghĩa là vỏ sẽ chạy chương trình env tìm thấy trên PATH hiện tại của nó. Môi trường ở đây được đặt để chứa 5 giá trị theo định dạng chính thống. Nếu bạn thay đổi env thành date (hoặc env; date), bạn sẽ thấy hiệu ứng của cài đặt TZ, chẳng hạn. Khi tôi chạy mà trên máy tính hệ điều hành MacOS X của tôi, đầu ra là:

USER=beelzebub 
PATH=/bin:/usr/bin 
PWD=/Users/jleffler/tmp/soq 
TZ=UTC0 
SHLVL=1 
HOME=/ 
LOGNAME=tarzan 
_=/usr/bin/env 

Vỏ đã được thêm vào biến môi trường SHLVL, _PWD đến những cái tôi thiết lập một cách rõ ràng trong execve() gọi.

Bạn cũng có thể làm những điều quan trọng hơn, chẳng hạn như sao chép vào một số biến môi trường khác từ môi trường chính hãng của bạn, nơi chúng không xung đột với những biến bạn muốn đặt rõ ràng.Bạn cũng có thể chơi các trò chơi như có hai giá trị cho một biến duy nhất trong môi trường - cái nào có hiệu lực? Và bạn có thể chơi trò chơi với tên biến chứa khoảng trống (vỏ không giống như nhiều), hoặc các mục không khớp với ký hiệu 'varname = value' (không có dấu bằng).

+0

Bạn thực sự đã xóa tất cả cho tôi. Tôi đã biến mọi thứ, nhưng cảm ơn! bây giờ tôi hiểu rồi. – james

1

Mã từ Jonathan Leffler hoạt động tốt, ngoại trừ nếu bạn muốn thay đổi biến số PWD (thư mục hoạt động).

Những gì tôi đã làm, để thay đổi thư mục làm việc, là đặt một chdir(..) trước execve(..) và gọi:

chdir("/foo/bar"); 
execve(argv[0], &argv[0], envp); 
0

Tôi là một chút muộn để đảng ở đây, nhưng nếu bạn muốn giữ các biến môi trường cũ cũng như tạo biến môi trường của riêng bạn, sử dụng setenv và sau đó vượt qua environ đến execve().

setenv("dog", "spike", 1); 
    extern char** environ; 
    execve(argv[0], argv, environ); 

environ là một biến khai báo trong unistd.h, và nó theo dõi các biến môi trường trong quá trình hoạt động này.

setenv()putenv() sửa đổi environ, vì vậy khi bạn vượt qua nó qua execve(), các biến môi trường sẽ giống như bạn mong đợi.