Purchase | Copyright © 2002 Paul Sheer. Click here for copying permissions. | Home |
This chapter discusses the sendfax program, with reference to the specific example of setting up an artificial printer that will automatically use a modem to send its print jobs to remote fax machines.
Continuing from Section 21.10...
You should go now and read the sendfax section of the info page for mgetty. The sendfax command is just one program that sends faxes through the modem. Like mgetty, it reads a config file in /etc/mgetty+sendfax/. This config file is just sendfax.config and can contain as little as
5 |
verbose y debug 5 fax-devices ttyS0 fax-id 27 21 7654321 max-tries 3 max-tries-continue y |
Below, fax_filter.sh is a script that sends the print job through the fax machine after requesting the telephone number through gdialog. [ gdialog is part of the gnome-utils package.] An appropriate /etc/printcap entry is:
5 |
fax:\ :sd=/var/spool/lpd/fax:\ :mx#0:\ :sh:\ :lp=/dev/null:\ :if=/var/spool/lpd/fax/fax_filter.sh: |
The file fax_filter.sh itself could contain a script like this [Remember to rotate the /var/log/fax log file, see page .] for a modem on /dev/ttyS0:
5 10 15 20 25 30 35 40 45 50 55 |
#!/bin/sh exec 1>>/var/log/fax exec 2>>/var/log/fax echo echo echo $@ echo "Starting fax `date`: I am `id`" export DISPLAY=localhost:0.0 export HOME=/home/lp function error() { gdialog --title "Send Fax" --msgbox "$1" 10 75 || \ echo 'Huh? no gdialog on this machine' cd / rm -Rf /tmp/$$fax || \ gdialog \ --title "Send Fax" \ --msgbox "rm -Rf /tmp/$$fax failed" \ 10 75 exit 1 } mkdir /tmp/$$fax || error "mkdir /tmp/$$fax failed" cd /tmp/$$fax || error "cd /tmp/$$fax failed" cat > fax.ps if /usr/bin/gdialog \ --title "Send Fax" \ --inputbox "Enter the phone number to fax:" \ 10 75 "" 2>TEL ; then : else echo "gdialog failed `< TEL`" rm -Rf /tmp/$$fax exit 0 fi TEL=`< TEL` test -z "$TEL" && error 'no telephone number given' cat fax.ps | gs -r204x98 -sOutputFile=- -sDEVICE=faxg3 -dBATCH -q - \ 1>fax.ps.g3 || error 'gs failed' ls -al /var/lock/ /usr/sbin/sendfax -x 5 -n -l ttyS0 $TEL fax.ps.g3 || \ error "sendfax failed" rm -Rf /tmp/$$fax exit 0 |
The above script is not enough however. Above, sendfax requires access to the /dev/ttyS0 device as well as the /var/lock/ directory (to create a modem lock file--see Section 34.4). It cannot do that as the lp user (under which the above filter runs). On RedHat, the command ls -ald /var/lock /dev/ttyS0 reveals that only uucp is allowed to access modems. We can get around this restriction by creating a setgid (see Chapter 14) binary that runs as the uucp user. Do this by compiling the C program,
5 10 15 20 25 30 |
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <unistd.h> int main (int argc, char **argv) { char **a; int i; /* set the real group ID to that of the effective group ID */ if (setgid (getegid ())) { perror ("sendfax_wrapper: setgid failed"); exit (1); } /* copy all arguments */ a = (char **) malloc ((argc + 1) * sizeof (char *)); for (i = 1; i < argc; i++) a[i] = (char *) strdup (argv[i]); a[argc] = NULL; /* execute sendfax */ a[0] = "/usr/sbin/sendfax"; execvp (a[0], a); /* exit on failure */ perror ("sendfax_wrapper: failed to exececute /usr/sbin/sendfax"); exit (1); } |
using the commands,
|
gcc sendfax_wrapper.c -o /usr/sbin/sendfax_wrapper -Wall chown lp:uucp /usr/sbin/sendfax_wrapper chmod g+s,o-rwx /usr/sbin/sendfax_wrapper |
Then, replace sendfax with sendfax_wrapper in the filter script. You can see that sendfax_wrapper just executes sendfax after changing the group ID to the effective group ID (GID) as obtained from the getegid function on line 12. The effective group ID is uucp because of the setgid group bit (i.e., g+s) in the chmod command, and hence sendfax runs under the uucp group with full access to the modem device.
On your own system it may be cleaner to try implement this without a wrapper. Debian, for example, has a dialout group for the purposes of accessing modems. Also be aware that some distributions may not use the uucp user in the way RedHat does and you may have to create an alternative user especially for this task.