Re: Inappropriate ioctl for device



PekinSOFT@xxxxxxxxx wrote:
Hey All!

Hello,

I've written a Bash script called `clock`, which is called by one of
two symbolic links: `clock-in` and `clock-out`. This script is,
effectively, a time-clock for tracking time spent on various projects
for clients. This script generates a "time card" file, if one does
not exist in my "$HOME/Timecards" folder, and/or appends to the "time
card' file. The file name is the first parameter passed into my
`clock` script. The second parameter is a note to be placed with
either the clock-in or clock-out to give a little detail to the "time
card".

Now, I'm trying to write a Perl script that will open a "time card"
and process it to generate an invoice based on the information in the
"time card" file. However, whenever I try to open any of the time
card files in my Timecards folder, I get the error "Inappropriate
ioctl for device". I've read other posts in this group, as well as
many others, but have not found a solution to this error. I am
pasting the code below for your review, to see if I've made some kind
of odd mistake with the Perl syntax. I've got a lot of programming
experience, but not much with Perl, so I'm just applying my knowledge
of other languages to Perl and trying to learn the syntax as I go.
Please forgive any conventions that I may have used that aren't common
to Perl. Here's the code in question:

######################################################################
# Create a variable to hold the path to the TimeCard files. These #
# should be located in a folder, under the user's home folder, called#
# 'Timecards'. #
######################################################################
$TimeCardsPath = $ENV{'HOME'} . "/Timecards/";

#######################################################################
# Check for command-line arguments. If there are none, call exit()
#
# with the command-line usage error as a parameter.
#
#######################################################################
if ( !defined( $ARGV[0] ) ) {

That is usually written as:

if ( @ARGV != 1 ) {


$ExitStatus = $EX_USAGE;
ExitScript();

Why not pass $EX_USAGE to ExitScript() instead of using global $ExitStatus?

ExitScript( $EX_USAGE );


} else {
# Let the user know that we are processing the filename that they
passed
# in to the script. Also, this shows the user that we are processing
# TimeCards from a specific directory in their $HOME folder,
according
# to the Bash Environment Variable.
print "Processing: $TimeCardsPath$ARGV[0]\n";

# Declare a variable to hole each line of the TimeCard file.
$Line = "";

# Declare four variables to hold the introductory note, time in, time
out
# and closing note of the clock punch.
$iNote = "";
$TimeIn = "";
$TimeOut = "";
$cNote = "";

# Now, we need to create a file handle to access the TimeCard file.
open ( TIMECARD, $TimeCardsPath . $ARGV[0] ) ||
die $ExitStatus = $EX_NOINPUT;

die() exits the program.


# Check to see if we were able to open the TimeCard file:
if ( $ExitStatus = $EX_NOINPUT ) {

You are using the assignment operator so the test is always true. You need to test for numerical equality instead:

if ( $ExitStatus == $EX_NOINPUT ) {


# We need to let the user know that we were unable to open
# the TimeCard and exit the script.
print "Unable to open the file:\n";
print "\t$TimeCardsPath$ARGV[0]\n";
print "Please make sure that the file exists in the above path\n";
print "and that you have read access to the file.\n";
print "\nReturned Error:\n\t";
print "$!\n\n";

You are using the $! variable six statements away from the open() statement which means that there is no guarantee that its value will be related to what open() may have set it to.


ExitScript();
} else { # Process the file and create the invoice.
# Implement processing here.


# Close the input file.
close ( TIMECARD );
# Exit the script with normal termination status.
exit ( $EX_OK );
} # End of invoice generation.
} # End of command-line parameter check.

sub ExitScript {

Pass the exit code to your subroutine:

my $ExitStatus = shift;


if ( $ExitStatus == 64 ) {

Shouldn't that be:

if ( $ExitStatus == $EX_USAGE ) {


system ( 'clear' );
print "INVOICE GENERATOR v0.6\n";
print "~~~~~~~~~~~~~~~~~~~~~~\n";
print "PekinSOFT Systems\n";
print "Copyright(c) 2008\n";
print "\n";
print "\n";
print "USAGE: invoice {TimeCard Filename}\n";
print "\n";
print " TimeCard Filename\tName of the time card for which to have
an invoice generated.\n";
print "\n";

The subroutine is named 'ExitScript' but you are not exiting here?


} else {
exit( $ExitStatus );
} # End of ExitStatus check.
} # End of ExitScript() function.

This code includes everything except my opening comments describing
the script and the definition of my exit status codes, which are taken
directly from `sysexits.h`. In my `die` statement, I'm setting the
ExitStatus variable, which is not something that I see in examples of
the `open` statement...I only see something like: `die "Error
message"`, so I don't know if that's causing the problem or even if
that is a legal statement.

Here is the output that I'm getting when I run the script:

Processing: /home/sean/Timecards/TimeCards
Unable to open the file:
/home/sean/Timecards/TimeCards
Please make sure that the file exists in the above path
and that you have read access to the file.

Returned Error:
Inappropriate ioctl for device

As you can see in the output, the path is displaying correctly, so I
assume that the path is also correct in the `open` statement.
However, in the `open` statement, I am using the concatenation
operator (.) instead of doing like it is in my `print` statements.
Could this be causing the problem?

Steps that I've taken:
1) Checked to make sure that I have no typos in my path and I don't.
2) Checked to make sure that the file exists and it does.
3) Checked to make sure that I have read access to the file and the
Timecards folder, which I do because I
created the folder and the file through my Bash script.
4) Made sure that I have no errors on my file system and I don't.


John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
.