I'm currently packaging a printer driver, which uses a shell script as the CUPS filter. Obviously, CUPS needs to be able to run that script. Currently, however, it is giving me an exec format error while trying it. The shell script starts with a #!/bin/sh
shebang.
The following code for the package is going to be really ugly/hacky because my knowledge of Nix is very basic, so sorry in advance. If you feel like providing suggestions for making it better, go ahead, but I'm mostly concerned with how to get it to work for now.
with import <nixpkgs> {};
let
srcs = {
lpr-deb = fetchurl {
url = "http://download.brother.com/welcome/dlf101620/mfc9332cdwlpr-1.1.3-0.i386.deb";
sha256 = "0mmqcwpbw4dx2hqaxhnvm52jm84vq8c55xrixsvapxwrdbpkdcca";
name = "mfc9332cdwlpr-1.1.3-0.i386.deb";
};
cupswrapper-deb = fetchurl {
url = "http://download.brother.com/welcome/dlf101621/mfc9332cdwcupswrapper-1.1.4-0.i386.deb";
sha256 = "1q9y90hdrgl80zwqk2vn7b1znjvf15l8q0zg868sv0by6rdq8r5w";
name = "mfc9332cdwcupswrapper-1.1.4-0.i386.deb";
};
};
in stdenv.mkDerivation rec {
name="brother-mfc9332cdw";
rev = "1.1.4-0";
buildInputs = [ pkgs.wget pkgs.dpkg pkgs.perl pkgs.bash ];
unpackPhase = ''
dpkg-deb -x ${srcs.lpr-deb} .
dpkg-deb -x ${srcs.cupswrapper-deb} .
'';
dontBuild = true;
installPhase = ''
perl -i -pe 's#printcap\.local#printcap#g' opt/brother/Printers/mfc9332cdw/inf/setupPrintcapij
cp -rf usr $out/
cp -rf opt $out/
mkdir -p $out/share/cups/model/Brother
cp $out/opt/brother/Printers/mfc9332cdw/cupswrapper/brother_mfc9332cdw_printer_en.ppd $out/share/cups/model/Brother
chmod 644 $out/share/cups/model/Brother/brother_mfc9332cdw_printer_en.ppd
cat $out/opt/brother/Printers/mfc9332cdw/cupswrapper/cupswrappermfc9332cdw | sed -n "/ENDOFWFILTER/,/ENDOFWFILTER/p" | tail -n +2 | sed "$ d" > brother_lpdwrapper_mfc9332cdw
perl -i -pe 's#/usr/#$out/#g' brother_lpdwrapper_mfc9332cdw && perl -i -pe 's#/opt/#$out/opt/#g' brother_lpdwrapper_mfc9332cdw
cat <<!ENDOFWFILTER! > brother_lpdwrapper_mfc9332cdw
#!/bin/sh
#
# Copyright (C) 2005-2016 Brother. Industries, Ltd.
# Ver1.10
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
LOGFILE="/dev/null"
LOGLEVEL="1"
LOGCLEVEL="7"
DEBUG=0
NUPENABLE=1
LOG_LATESTONLY=1
touch /tmp/mfc9332cdw_latest_print_info
chmod 600 -R /tmp/mfc9332cdw_latest_print_info
errorcode=0
if [ \$DEBUG != 0 ]; then
LOGFILE=/tmp/br_cupsfilter_debug_log
fi
PPDC=\`printenv | grep "PPD="\`
PPDC=\`echo \$PPDC | sed -e 's/PPD=//'\`
if [ "\$PPDC" = "" ]; then
PPDC="$out/share/cups/model/Brother/brother_mfc9332cdw_printer_en.ppd"
fi
if [ \$LOGFILE != "/dev/null" ]; then
if [ \$LOG_LATESTONLY == "1" ]; then
rm -f \$LOGFILE
date >\$LOGFILE
else
if [ -e \$LOGFILE ]; then
date >>\$LOGFILE
else
date >\$LOGFILE
fi
fi
echo "arg0 = \$0" >>\$LOGFILE
echo "arg1 = \$1" >>\$LOGFILE
echo "arg2 = \$2" >>\$LOGFILE
echo "arg3 = \$3" >>\$LOGFILE
echo "arg4 = \$4" >>\$LOGFILE
echo "arg5 = \$5" >>\$LOGFILE
echo "arg6 = \$6" >>\$LOGFILE
echo "PPD = \$PPD" >>\$LOGFILE
fi
cp $out/opt/brother/Printers/mfc9332cdw/inf/brmfc9332cdwrc /tmp/brmfc9332cdwrc_\$$
chmod 777 -R /tmp/brmfc9332cdwrc_\$$
export BRPRINTERRCFILE=/tmp/brmfc9332cdwrc_\$$
INPUT_TEMP_PS=\`mktemp /tmp/br_input_ps.XXXXXX\`
nup="cat"
if [ "\`echo \$5 | grep 'Nup='\`" != "" ] && [ \$NUPENABLE != 0 ]; then
if [ "\`echo \$5 | grep 'Nup=64'\`" != "" ]; then
nup="psnup -64"
elif [ "\`echo \$5 | grep 'Nup=32'\`" != "" ]; then
nup="psnup -32"
elif [ "\`echo \$5 | grep 'Nup=25'\`" != "" ]; then
nup="psnup -25"
elif [ "\`echo \$5 | grep 'Nup=16'\`" != "" ]; then
nup="psnup -16"
elif [ "\`echo \$5 | grep 'Nup=8'\`" != "" ]; then
nup="psnup -8"
elif [ "\`echo \$5 | grep 'Nup=6'\`" != "" ]; then
nup="psnup -6"
elif [ "\`echo \$5 | grep 'Nup=4'\`" != "" ]; then
nup="psnup -4"
elif [ "\`echo \$5 | grep 'Nup=2'\`" != "" ]; then
nup="psnup -2"
elif [ "\`echo \$5 | grep 'Nup=1'\`" != "" ]; then
nup="cat"
fi
echo "NUP=\$nup" >>\$LOGFILE
if [ -e /usr/bin/psnup ]; then
if [ \$# -ge 7 ]; then
cat \$6 | \$nup > \$INPUT_TEMP_PS
else
cat | \$nup > \$INPUT_TEMP_PS
fi
else
if [ \$# -ge 7 ]; then
cp \$6 \$INPUT_TEMP_PS
else
cat > \$INPUT_TEMP_PS
fi
fi
else
if [ \$# -ge 7 ]; then
cp \$6 \$INPUT_TEMP_PS
else
cat > \$INPUT_TEMP_PS
fi
fi
if [ -e "$out/opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw" ]; then
:
else
echo "ERROR: /opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw does not exist" >>\$LOGFILE
echo "ERROR: /opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw does not exist" >>/tmp/mfc9332cdw_latest_print_info
errorcode=30
exit
fi
CUPSOPTION=\`echo "\$5 Copies=1" | sed -e 's/BrMirror=OFF/MirrorPrint=OFF/' -e 's/BrMirror=ON/MirrorPrint=ON/' -e 's/BrChain/Chain/' -e 's/BrBrightness/Brightness/' -e 's/BrContrast/Contrast/' -e 's/BrHalfCut/HalfCut/' -e 's/BrAutoTapeCut/AutoCut/' -e 's/BrHalftonePattern/Halftone/' -e 's/Binary/Binary/' -e 's/Dither/Dither/' -e 's/ErrorDiffusion/ErrorDiffusion/' -e 's/BrSheets/Sheets/' -e 's/multiple-document-handling/Collate/' -e 's/separate-documents-collated-copies/ON/' -e 's/separate-documents-uncollated-copies/OFF/'\`
if [ -e "$out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1" ]; then
if [ \$DEBUG = 0 ]; then
$out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1 MFC9332CDW \$PPDC 0 "\$CUPSOPTION" "mfc9332cdw" \$BRPRINTERRCFILE>> /dev/null
else
$out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1 MFC9332CDW \$PPDC \$LOGCLEVEL "\$CUPSOPTION" "mfc9332cdw" \$BRPRINTERRCFILE>>\$LOGFILE
fi
fi
if [ \$DEBUG -lt 10 ]; then
cat \$INPUT_TEMP_PS | $out/opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw
echo brmfc9332cdwrc_\$$ > /tmp/mfc9332cdw_latest_print_info
cat /tmp/brmfc9332cdwrc_\$$ >> /tmp/mfc9332cdw_latest_print_info
rm -f /tmp/brmfc9332cdwrc_\$$
if [ \$LOGLEVEL -gt 2 ]; then
if [ \$LOGFILE != "/dev/null" ]; then
echo "" >>\$LOGFILE
echo " ------PostScript Data-------" >>\$LOGFILE
cat \$INPUT_TEMP_PS >>\$LOGFILE
fi
fi
fi
rm -f \$INPUT_TEMP_PS
exit $errorcode
!ENDOFWFILTER!
chmod 755 brother_lpdwrapper_mfc9332cdw
mkdir -p $out/lib/cups/filter
cp brother_lpdwrapper_mfc9332cdw $out/lib/cups/filter
'';
}
The bash script I'm talking about is the one that is set up with cat
in installPhase
(I know, terribly sorry, but this is actually just a modified version of what they did in the original brother install script, so that's my excuse).
Also, here's the relevant part of the CUPS log:
Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/pdftopdf (PID 11799)
Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/pdftops (PID 11800)
Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/brother_lpdwrapper_mfc9332cdw (PID 11801)
Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started backend /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/backend/lpd (PID 11802)
Jan 29 15:43:22 kenix-vaio cupsd[11674]: REQUEST localhost - - POST /printers/MFC9332CDW HTTP/1.1 200 127388 Send-Document successful-ok
Jan 29 15:43:22 kenix-vaio cupsd[11674]: execv failed: Exec format error
Jan 29 15:43:22 kenix-vaio cupsd[11674]: PID 11801 (/nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/brother_lpdwrapper_mfc9332cdw) stopped with status 108 (Exec format error)
/nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/brother_lpdwrapper_mfc9332cdw
directly (as a program), what happens?