You're mixing shell and make
variables in there. Both make
and the shell use $
for their variables.
In Makefile, variables are $(var)
or $v
for single-letter variables, and $var
or ${var}
in shells.
But if you write $var
in a Makefile, make
will understand it as $(v)ar
. If you want to pass a literal $
to the shell, you need to enter it as $$
, as in $$var
or $${var}
so that it becomes $var
or ${var}
for the shell.
Also, make
runs sh
, not bash
to interpret that code (Edit, sorry missed your SHELL := /bin/bash
above, note that many systems don't have bash
in /bin
if they have bash
at all and :=
is GNU specific), so you need to use sh
syntax there. echo -n
, read -s
are zsh
/bash
syntax, not sh
syntax.
Best here would be to add a zsh
/bash
script to do that (and add a build dependency on bash
). Something like:
#! /usr/bin/env bash
printf 'Welcome\nPlease enter the MySQL host (default: localhost): '
read host || exit
host=${host:-localhost}
printf "Please enter the MySQL username: "
read username || exit
printf "Please enter the MySQL password:"
IFS= read -rs password || exit
printf '\n'
mv includes/config.php.example includes/config.php 2>/dev/null
repl=${password//\\/\\\\}
repl=${repl//&/\\&}
repl=${repl//:/\\:}
{ rm includes/config.php &&
sed 's/"USER", ""/"USER", "'"$username"'"/g
s:"PASSWORD", "":"PASSWORD", "'"$repl"'"/g' > includes/config.php
} < includes/config.php || exit
mysql -u "$username" -p"$password" codeday-team < ./codeday-team.sql || exit
echo "Configuration complete. For further configuration options, check the config file"
It addresses a few more issues:
- you need
-r
when reading the password if you want to allow the user to use backslashes in their password.
- you need
IFS=
if you want to allow the user to have a password that starts or ends in blanks
- same would apply for the username, but here we're making the assumption that the user won't use anything silly for the username, and the blank stripping and backslash handling could be seen as a /feature/.
- your
;true
after mv
doesn't do what you think it does. It doesn't cancel the effect of the errexit
option (for make
implementations that call the shell with -e
). You'd need ||true
instead. Here, we're not using errexit
but doing the error handling ourselves with || exit
where needed.
- You need to escape backslash,
&
and the s:pattern:repl:
separator (here :
) or it won't work (and could have nasty side effects).
You can't do sed ... < file > file
, as file
would be truncated before sed
is even started. Some sed
implementations support a -i
or -i ''
option for that. Alternatively you could use perl -pi
. Here we're doing the equivalent of perl -pi
manually (delete and recreate the input file after it has been open for reading) but without taking care of the file's metadata.
Here, it would be better to use the example one as input and the final one as output.
It still doesn't address a few more issues:
- the new
config.php
is created with permissions derived from the current umask
which is likely to be world readable and owned by the user running make
. You may need to adapt the umask
and/or change ownership if the includes
dir is not otherwise restricted as that file contains sensitive information.
- if the password contains
"
characters, that will likely break (this time for php
). You'd want to either forbid those (by returning an error) or add another layer of escaping for them in the right syntax for that php
file. You're likely to have similar problems with backslash and you may want to exclude non-ascii or control characters as well.
Passing the password on the command-line of mysql
is generally a bad idea as that means it shows in the output of ps -f
. It would be better to use:
mysql --defaults-file=<(
printf '[client]\nuser=%s\npassword="%s"\n' "$username" "$password") ...
printf
being built-in, it wouldn't show up in ps
output.
the $host
variable is not used.
- prompting the user like that means that your script can not easily be automated. You could take the input from arguments or (better for the password) with environment variables instead.
$
characters need to be escaped as$$
in Makefile if you want them passed to the shell. I'd use a script here and avoid passing the password on the command line.$
in there as if they were copy-pasted fromnano
.