Languages and Scripting
cancel
Showing results for 
Search instead for 
Did you mean: 

Getting error codes from system calls, in C

 
SOLVED
Go to solution
Highlighted
Michael D. Zorn
Regular Advisor

Getting error codes from system calls, in C

I have a ksh script for tape backup that does

...
mt -t $TAPE | grep 'BOT ONLINE'
errCode=$?
... other stuff
return $errCode

I'd like to recode it in C, but I'm not sure how to get the error code.

I can do
...
system("mt -t $TAPE | grep 'BOT ONLINE'");
...

. but then what?

I tried a small example:

...
#include
...
system("mt -t $TAPE status");
printf("err code=%d\n", errno)
...

. but it seems to return 0 no matter what the tape status is.

The script does a backup, first checking the tape, and then:

call system("dump -0 -f /dev/rmt/0h /important/files");

7 REPLIES 7
Highlighted
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: Getting error codes from system calls, in C

You are overlooking the obvious:

#include

int call_system(char *cmd)
{
int status = 0;

status = system(cmd);
if (status != 0)
{
(void) printf(stderr,"Status %d\n",status);
}
return(status);
}

errno is only set when a system call (not the same as the system() function) fails.

If it ain't broke, I can fix that.
Highlighted
A. Clay Stephenson
Acclaimed Contributor

Re: Getting error codes from system calls, in C

Ooops, that should be:

(void) fprintf(stderr,"Status %d\n",status);
If it ain't broke, I can fix that.
Highlighted
James R. Ferguson
Acclaimed Contributor

Re: Getting error codes from system calls, in C

Hi Michael:

Calling system() is simply invoking the shell as a child process to perform some command. The return value from the system() call is essentially the exit status of the command as Clay clearly shows.

At most, you can also get the signal number, if any, (excepting SIGINT and SIGQUIT, which are ignored by system()), that caused the child to die.

Regards!

...JRF...
Highlighted
Michael D. Zorn
Regular Advisor

Re: Getting error codes from system calls, in C

That worked (status = system(cmd) )

At least, I got 0 when the tape was ready, and 256 when it wasn't.

Unfortunately, I've uncovered a bigger problem: I'm trying to do this on a Red Hat Linux system that I'm doing backups for. For some odd reason, RHLinux doesn't seem to know about setuid. I set the ksh script to 4755 root:root, and when I run it as me, it says "effective UID=me". This is now a problem for the Red Hat SysAdmin.

It just might have to do with the way setuid is handled in different systems. There's a detailed writeup at

http://www.cs.berkeley.edu/~daw/papers/setuid-usenix02.pdf

"Setuid Demystified"

On the other hand, it may just be an unusual "safety feature" in RH Linux.

Anyway, it works the way you showed be here in HP-UX.
Highlighted
A. Clay Stephenson
Acclaimed Contributor

Re: Getting error codes from system calls, in C

This is one of the things that HP-UX does very wrong and thus leaves a big security hole. It allows setuid scripts (as opposed to setuid executables). You should think of shell scripts not as executables but rather as data files for the shell. Linux (and other flavor of UNIX) takes this view so that the idea of a setuid data file is anathema. The "fix" for all versions is to do your setuid in the program and then call system(). Make your C program a setuid program (chmod 4555) and owned by root and you are good to go.

#include
#include

#define assign_errno(x) ((errno != 0) ? errno : (x))

#define ROOT_USER 0


int call_system(char *cmd)
{
int status = 0;

status = setuid(ROOT_USER);
if (status == 0)
{
status = system(cmd);
if (status != 0) (void) fprintf(stderr,"Command '%s' failed; status %d\n",cmd,status);
}
else
{
status = assign_errno(-1);
(void) fprintf(stderr,"Setuid failed (%d)\n",status);
}
return(status);
} /* call_system */


If it ain't broke, I can fix that.
Highlighted
James R. Ferguson
Acclaimed Contributor

Re: Getting error codes from system calls, in C

Hi (again) Michael:

For a long time, 'setuid' shell scripts have been allowed on HP-UX. As you now know, this is not the case for all Unix variations. Fortunately, beginning with 11iv2, you have the ability to allow/disallow them with the kernel tunable 'secure_sid_scripts'.

If you must have a 'setuid' script, create a C-wrapper for it and set the 'setuid' bit for the wrapper.

http://www.docs.hp.com/en/B2355-60105/secure_sid_scripts.5.html

Regards!

...JRF...
Highlighted
Michael D. Zorn
Regular Advisor

Re: Getting error codes from system calls, in C

It turns out the Red Hat Linux won't let 'dump' run as setUID=root. You have to really be root. They're keeping the Bad Guys from dumping things to a remote host.

The original problem was that the database did its backup to disk files, then I wanted to copy the files to tape, as root.

I fell back to a slightly less elegant solution.