Faz-me uma sandes


21

XKCD: Sanduíche

Desafio: Escreva um makefile, o que levaria a este comportamento:

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

Regras:

  1. Deve funcionar em uma máquina Linux, onde o usuário não é root, mas pode usar sudo.
  2. Não devo dizer Okaya nenhum comando make mais curto (por exemplo sudo make sandwich).
  3. O segundo comando deve funcionar por causa sudo, não porque é a segunda invocação.

Diretrizes:

  1. Mantenha-o curto (afinal, é um site da Code Golf).
  2. Seria bom se realmente fizesse um sanduíche.
  3. Tente esconder de maneira inteligente o porquê da sudodiferença.

O vencedor será decidido por votos.



@ardnew, infelizmente, solicitei especificamente a criação de um makefile que, na minha opinião, invalida soluções baseadas em patches make.
ugoren 31/07/2013

concordo totalmente, @ugoren. não quis dizer para que o comentário para descartar o desafio ou sugerir uma solução
ardnew

Respostas:


12

Ok, eu vou morder. Isso não segue necessariamente a diretriz 3, mas faz um bom trabalho nas outras duas diretrizes. Ele também limpa a si próprio, como qualquer bom sanduíche.

.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

(Menos buggy e, espero, um pouco menos chato do que minha submissão inicial.)


Parece que viola a regra 2 - sudo make me sandwich.
Ugoren

&& test -e ./a
Luser droog

Argh, você está certo. Esta versão deve fazer um trabalho melhor de observar as regras.
breadbox

11
você certamente tem o nome mais apropriado, @breadbox #
ardnew

9

Uma solução bastante compacta que ignora a diretriz nº 2 (127 caracteres, incluindo alguns espaços em branco desnecessários). Eu sigo a prática de breadbox de limpeza depois de mim mesmo. Não coloque nenhum outro arquivo no mesmo diretório que o makefile! Além disso, observe que o makefile deve ser chamado Makefile, outros nomes não funcionarão.

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

Uso:

$ 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

Gosto da maneira como este lida com a diretriz nº 3. Apenas um toque de Shiftfaz a diferença.


3

Essa solução não segue a diretriz nº 2 - ou é vagamente em forma de sanduíche? Eu comecei com um tipo de tema palíndromo no começo, mas só consegui encontrar muitas maneiras de tornar as linhas simétricas sem recorrer a coxasreal code # ecod laer . Não levei a diretriz 1 muito a sério, a estética vem primeiro.

Lembre-se de que é um makefile; as 3 linhas sucessivas começando com if, rmeecho começam com um separador. As outras linhas recuadas começam com espaços.

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

Uso (os comandos podem ser emitidos em qualquer ordem):

$ 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

Quanto à diretriz 3, isso não é inteligentemente oculto, apenas um pouco estranho. Algumas dicas:

Existem dois testes diferentes: uma pesquisa SUDO_USERe um teste para id -uimprimir 0. Você vê por que nãoWhat? é impresso para raiz? Você vê como a falta de causas não deve ser impressa?SUDO_USEROkay


2

Aqui está o primeiro passo, usando uma técnica diferente e mais simples:

.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

Tenho certeza de que há mais coisas que posso fazer com isso - faça com que ele responda a outros comandos de entrada, por exemplo. Vou ter que trabalhar na ofuscação do switch raiz e na fabricação de sanduíches.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.