Ok, I don't have an answer for why it doesn't work but I do have a solution.
I discovered that sound is also broken for audible announcements via procmail for specific email senders.
So I created to VERY simple [Tcl][1] scripts. The first, run instead of espeak, etc., simply writes the text to a ~/.alerts
file. The second sits in the background, a sort of daemon, waiting for that file to exist, and when it does, it reads and speaks every line in the file (usually only one) and then deletes the file. File locking is used in both scripts to avoid any collisions.
The Tcl script that checks ~/.alerts
is run from an xterm, so it doesn't have whatever bug is messing with stuff from cron, procmail, and who knows what else. It just works.
So that's my solution. Like it, love it, hate it… it works for me.
The first script is addalert.
And this is the script---it just waits if the file is locked (max 20s
then assume it's stuck) and writes the message from procmail:
#!/usr/local/bin/tclsh8.5
set lockfile /home/jim/.alertlock
proc checklock {} {
global lockfile
if {![file exists $lockfile]} { return }
set counter 20
while {[file exists $lockfile]} {
incr counter -1
if {$counter <= 0} {
file delete -force $lockfile
} ;# stuck lockfile
after 333 ;
after 333 ;
after 333 ;
}
file delete -force $lockfile
}
# wait if file is locked, then lock file while adding alert
checklock
set lock [open $lockfile w] ; puts $lock "" ; close $lock
set f [open /home/jim/.alerts a]
puts $f [lindex $argv 0]
close $f
file delete -force $lockfile
I could shorten both scripts by moving the checklock procedure to its own file, but for tiny stuff like this, it's not worth it (to me...I just use cut/paste like the above for quick hacks like this). This next one is called doalerts, and it does the real work (it's launched from an xterm, or terminal if you use that command line).
#!/usr/local/bin/wish8.4
set home /home/jim
set say /home/jim/bin/speak
set alertsfile $home/.alerts
set lockfile $home/.alertlock
cd $home
proc checklock {} {
global lockfile
if {![file exists $lockfile]} { return }
set counter 20
while {[file exists $lockfile]} {
incr counter -1
if {$counter <= 0} {
file delete -force $lockfile
} ;# stuck lockfile
after 333 ;
after 333 ;
after 333 ;
}
file delete -force $lockfile
}
proc handle_alerts {} {
global say alertsfile lockfile
set lock [open $lockfile w] ; puts $lock "" ; close $lock
set f [open $alertsfile r]
set alertlist [split [read $f] \n]
close $f
foreach alert $alertlist { exec $say $alert }
file delete $alertsfile
file delete $lockfile
}
while {1} {
after 333 ;
after 333 ;
after 333 ;
if {[file exists $alertsfile] && ![file exists $lockfile]} {
handle_alerts
}
}
Simply put, it waits (again, max 20s) for the lock file to be removed, it it exists, then opens the file, reads it (splitting it into lines, as each alert is on its own line), closes it, and then uses a TTS program (espeak) to read the alert(s). Then it deletes the lock file (~/.alertlock) and the alerts file (~/.alerts).
env
) in your xterm session and in the cron job and comparing them?