Làm cho tôi một chiếc bánh sandwich


21

XKCD: Sandwich

Thách thức: Viết một tệp thực hiện, điều này sẽ dẫn đến hành vi này:

% make me a sandwich
What? Make it yourself
% sudo make me a sandwich
Okay

Quy tắc:

  1. Nên hoạt động trên máy Linux, nơi người dùng không root nhưng được phép sử dụng sudo.
  2. Không được nói Okayvới bất kỳ lệnh make ngắn hơn (ví dụ sudo make sandwich).
  3. Lệnh thứ hai sẽ hoạt động vì sudo, không phải vì đó là lệnh thứ hai.

Hướng dẫn:

  1. Giữ cho nó ngắn gọn (sau tất cả, đó là một trang web Code Golf).
  2. Sẽ thật tuyệt nếu nó thực sự làm một chiếc bánh sandwich.
  3. Cố gắng khéo léo che giấu tại sao sudolàm cho một sự khác biệt.

Người chiến thắng sẽ được quyết định bằng phiếu bầu.



@ardnew, thật không may, tôi đặc biệt yêu cầu viết một makefile, mà theo tôi, làm mất hiệu lực các giải pháp dựa trên việc vá lỗi make.
ugoren

hoàn toàn đồng ý, @ugoren. không có nghĩa là bình luận đó để loại bỏ thách thức hoặc đề xuất một giải pháp
ardew

Câu trả lời:


12

Được rồi, tôi sẽ cắn. Điều này không nhất thiết phải tuân thủ hướng dẫn số 3, nhưng nó thực hiện công việc theo hai hướng dẫn khác. Nó cũng làm sạch sau đó, như bất kỳ nhà sản xuất bánh sandwich tốt nên.

.SILENT:

%:%.c
        $(CC) -o $@ $^ && rm -f $^

default:
        echo 'The makings for a sandwich are here.'

a.c:
        echo '#include <stdio.h>' > a.c
        echo 'int main() {' >> a.c
        echo '  char *txt[] = { "What? Make it yourself.", "Okay." };' >> a.c
        echo '  int n = 0;' >> a.c
        echo '  while (getchar() != EOF) n ^= 1;' >> a.c
        echo '  puts(txt[n]); return 0; }' >> a.c

me.c:
        echo '#include <stdio.h>' > me.c
        echo '#include <unistd.h>' >> me.c
        echo 'int main() {' >> me.c
        echo '  char *txt[] = { "/dev/null", "sandwich" };' >> me.c
        echo '  puts(txt[!getuid()]); return 0; }' >> me.c

sandwich:
        ./me | ./a | tee `./me`
        rm -f me a

clean:
        rm -f sandwich

(Ít lỗi hơn và hy vọng sẽ bớt nhàm chán hơn so với lần gửi ban đầu của tôi.)


Có vẻ như nó vi phạm quy tắc số 2 - sudo make me sandwich.
ugoren


Argh, bạn nói đúng. Phiên bản này sẽ làm tốt hơn việc tuân thủ các quy tắc.
hộp bánh mì

1
bạn chắc chắn có tên thích hợp nhất, @breadbox
ardew

9

Một giải pháp khá nhỏ gọn mà bỏ qua hướng dẫn số 2 (127 ký tự, bao gồm một số khoảng trắng không cần thiết). Tôi theo dõi thực hành dọn dẹp bánh mì của chính mình. Đừng đặt bất kỳ tệp nào khác vào cùng thư mục với tệp thực hiện! Ngoài ra, lưu ý rằng tệp tạo tệp phải được gọi Makefile, các tên khác sẽ không hoạt động.

me: ; echo echo Okay >$@
a: ; chmod u=x me
sandwich: ; ./me 2>/dev/null || echo 'What? Make it yourself'; rm -f [!M]*
.SILENT:

Sử dụng:

$ make me a sandwich
What? Make it yourself
$ sudo make me a sandwich
Okay
$ sudo make me sandwich  
What? Make it yourself
$ sudo make a sandwich
chmod: cannot access `me': No such file or directory
make: *** [a] Error 1
$ sudo make sandwich  
What? Make it yourself

Tôi thích cách cái này liên quan đến hướng dẫn # 3. Chỉ cần một lần nhấn Shiftlàm cho sự khác biệt.


3

Giải pháp này không tuân thủ hướng dẫn số 2 - hoặc có bị mơ hồ đếm hình bánh sandwich không? Tôi đã đi vào một loại chủ đề palindrom lúc đầu, nhưng tôi chỉ có thể tìm thấy rất nhiều cách để làm cho các đường đối xứng mà không cần dùng đến sự khập khiễng real code # ecod laer. Tôi đã không coi trọng hướng dẫn số 1, thẩm mỹ là ưu tiên hàng đầu.

Hãy nhớ rằng đó là một makefile; 3 dòng liên tiếp bắt đầu với if, rmechobắt đầu với một tab. Các dòng thụt lề khác bắt đầu bằng khoảng trắng.

me : mr ; env | grep -q DO_US || rm -- mr || SU_OD q- perg | vne ; rm : em
                            .SILENT:##:TNELIS.
                              . = a.  .a = .
$(.:.=):;:>$@
sandwich:
    if expr>/dev/null $$(id -u); then echo 'What? Make it yourself'; fi
    rm f- a me mr 2>/dev/null
    echo Okay
mr : ; true : ; touch me : em f- mr || rm -f me : em hcuot ; : eurt ; : rm

Cách sử dụng (các lệnh có thể được ban hành theo thứ tự bất kỳ):

$ sudo make me a sandwich     
Okay
$ sudo make me sandwich  
make: *** [sandwich] Error 1
$ sudo make a sandwich 
make: *** [sandwich] Error 1
$ sudo make sandwich  
make: *** [sandwich] Error 1
$ make me a sandwich
What? Make it yourself
make: *** [sandwich] Error 1

Đối với hướng dẫn số 3, điều này không được giấu khéo léo, chỉ hơi kỳ lạ. Một số gợi ý:

Có hai bài kiểm tra khác nhau: một tìm kiếm SUDO_USER, và một bài kiểm tra về việc liệu id -uin 0. Đỗ bạn thấy tại sao What?không in cho rễ? Bạn có thấy làm thế nào thiếu SUDO_USERnguyên nhân Okaykhông được in?


2

Đây là lần đầu tiên sử dụng một kỹ thuật khác biệt và đơn giản hơn:

.SILENT:

reset_command:
    @rm -f command

me a sandwich: reset_command
    @echo $@ >> command
    -@make `cat command | tr "\n" "_"` 2>/dev/null

me_a_sandwich_: reset_command
    @if [ `whoami` == "root" ]; then echo "Okay"; else echo "What? Make it yourself."; fi

Tôi khá chắc chắn rằng có nhiều hơn những gì tôi có thể làm với điều này - lấy nó để đáp ứng với các lệnh đầu vào khác chẳng hạn. Tôi sẽ phải làm việc trên obfuscation root và làm bánh sandwich thực tế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.