Сделай мне бутерброд


21

XKCD: сэндвич

Задача: Напишите make-файл, который приведет к такому поведению:

% 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, к сожалению, я специально попросил написать make-файл, который, я думаю, лишает законной силы решения, основанные на исправлениях make.
Угорен

полностью согласен, @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
Люзер Дрог

Ааа, ты прав. Эта версия должна лучше выполнять правила.
хлебница

1
у вас наверняка есть самое подходящее имя, @breadbox
ardnew

9

Довольно компактное решение, которое игнорирует рекомендацию № 2 (127 символов, включая некоторые ненужные пробелы). Я следую практике уборки после себя. Не помещайте другие файлы в тот же каталог, что и make-файл! Также обратите внимание, что make-файл должен быть вызван 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 очень серьезно, эстетика на первом месте.

Помните, что это make-файл; в 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.