Fammi un panino


21

XKCD: Sandwich

Sfida: scrivi un makefile, che porterebbe a questo comportamento:

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

Regole:

  1. Dovrebbe funzionare su una macchina Linux, in cui l'utente non è root ma è autorizzato a utilizzarlo sudo.
  2. Non devo dire Okaya nessun comando make più breve (es sudo make sandwich.).
  3. Il secondo comando dovrebbe funzionare a causa sudo, non perché è la seconda chiamata.

Linee guida:

  1. Tienilo breve (dopo tutto, è un sito di Code Golf).
  2. Sarebbe bello se davvero facesse un panino.
  3. Cerca di nascondere abilmente perché sudofa la differenza.

Il vincitore sarà deciso con voti.



@ardnew, sfortunatamente, ho espressamente richiesto di scrivere un makefile, che, a mio avviso, invalida le soluzioni basate sul patching make.
ugoren,

sono assolutamente d'accordo, @ugoren. non intendevo per quel commento respingere la sfida o suggerire una soluzione
ardnew

Risposte:


12

Ok, ti ​​mordo. Ciò non rispetta necessariamente la linea guida n. 3, ma fa un buon lavoro sulle altre due linee guida. Pulisce anche dopo se stesso, come dovrebbe fare qualsiasi bravo produttore di sandwich.

.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

(Meno buggy, e si spera un po 'meno noioso, rispetto alla mia presentazione iniziale.)


Sembra che violi la regola n. 2 - sudo make me sandwich.
ugoren,

&& test -e ./a
Luser droog

Argh, hai ragione. Questa versione dovrebbe fare un lavoro migliore osservando le regole.
breadbox

1
hai sicuramente il nome più appropriato, @breadbox
ardnew

9

Una soluzione abbastanza compatta che ignora la linea guida n. 2 (127 caratteri, inclusi alcuni spazi bianchi non necessari). Seguo la pratica del breadbox di ripulire dopo me stesso. Non mettere nessun altro file nella stessa directory del makefile! Si noti inoltre che è necessario chiamare il makefile Makefile, altri nomi non funzioneranno.

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

Mi piace il modo in cui questo tratta la linea guida n. 3. Solo una pressione di Shiftfa la differenza.


3

Questa soluzione non aderisce alla linea guida n. 2 o conta vagamente a forma di sandwich? All'inizio ho seguito una specie di tema palindromo, ma ho trovato solo tanti modi per rendere le linee simmetriche senza ricorrere allo zoppo real code # ecod laer. Non ho preso molto sul serio la linea guida n. 1, l'estetica viene prima di tutto.

Ricorda che è un makefile; le 3 righe successive a cominciare if, rme echoiniziare con una scheda. Le altre linee rientrate iniziano con spazi.

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

Utilizzo (i comandi possono essere emessi in qualsiasi ordine):

$ 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

Per quanto riguarda la linea guida n. 3, questo non è abilmente nascosto, solo leggermente strano. Alcuni suggerimenti:

Esistono due test diversi: uno cerca SUDO_USERe uno verifica se id -ustampa 0. Vedi perché nonWhat? viene stampato per root? Vedi come la mancanza di cause non può essere stampata?SUDO_USEROkay


2

Ecco un primo passo con una tecnica diversa e più semplice:

.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

Sono abbastanza sicuro che ci sia altro che posso fare con questo: far sì che risponda ad altri comandi di input, ad esempio. Dovrò lavorare sull'offuscamento dell'interruttore di root e sull'effettiva realizzazione del sandwich.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.