Зробіть мені сендвіч


21

XKCD: Сендвіч

Завдання: Напишіть файл, який призведе до такої поведінки:

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

Правила:

  1. Має працювати на машині Linux, де користувач не має root, але дозволений до використання sudo.
  2. Не слід говорити Okayжодній коротшій команді make (наприклад sudo make sandwich).
  3. Друга команда повинна працювати через sudo, а не тому, що це друге виклик.

Правила:

  1. Нехай це буде коротко (зрештою, це сайт Code Golf).
  2. Було б непогано, якби насправді зробити бутерброд.
  3. Спробуйте вміло приховати, чому це sudoмає значення.

Переможець визначатиметься голосами.



@ardnew, на жаль, я спеціально попросив написати makefile, який, я думаю, визнає недійсним рішення на основі виправлення make.
ugoren

повністю згоден, @ugoren. не означав для цього коментаря відхиляти виклик або запропонувати рішення
ardnew

Відповіді:


12

Гаразд, я кусаю. Це не обов'язково дотримується вказівки №3, але це робить справедливу роботу щодо двох інших вказівок. Він також очищається після себе, як і будь-який хороший виробник сендвічів.

.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

(Менше баггі, і, сподіваюся, трохи менш нудно, ніж моє первісне подання.)


Схоже, це порушує правило №2 - sudo make me sandwich.
угорен

&& test -e ./a
luser droog

Аргу, ти маєш рацію. Ця версія повинна зробити кращу роботу з дотримання правил.
хлібниця

1
у вас, безумовно, є найбільш відповідне ім’я, @breadbox
ardnew

9

Досить компактне рішення, яке ігнорує керівництво №2 (127 символів, включаючи деяку зайву пробіл). Я дотримуюся практики прибирання хлібопечки після себе. Не ставте жоден інший файл у ту саму директорію, що і makefile! Також зауважте, що makefile потрібно викликати Makefile, інші імена не працюватимуть.

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

Використання:

$ 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

Мені подобається, як це стосується керівництва №3. Лише одне натискання значень Shiftмає значення.


3

Це рішення не дотримується вказівки № 2 - чи має місце розпливчасті сендвіч-форми? Я на початку пішов на тему паліндром, але я міг знайти лише стільки способів зробити лінії симетричними, не вдаючись до кульгавого real code # ecod laer. Я не сприймав настанови №1 дуже серйозно, естетика на першому місці.

Пам'ятайте, що це makefile; 3 послідовних рядки, що починаються з if, rmі echoпочинаються з вкладки. Інші відступні лінії починаються з пробілів.

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

Використання (команди можуть бути видані в будь-якому порядку):

$ 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

Що стосується настанови №3, то це не хитро приховано, а трохи дивно. Деякі підказки:

Є два різних тестів: один пошук SUDO_USER, і один тест чи id -uгравюр 0. Чи бачите ви , чому What?це НЕ друкуються на корінь? Ви бачите, як відсутність SUDO_USERпричин Okayне надрукувати?


2

Ось перший похід з використанням іншої та простішої техніки:

.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

Я впевнений, що з цим я можу зробити більше - змусити його відповідати, наприклад, на інші вхідні команди. Мені доведеться попрацювати над притупленням кореневого перемикача та власне виготовленням сендвічів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.