How JustAnswer Works:

  • Ask an Expert
    Experts are full of valuable knowledge and are ready to help with any question. Credentials confirmed by a Fortune 500 verification firm.
  • Get a Professional Answer
    Via email, text message, or notification as you wait on our site.
    Ask follow up questions if you need to.
  • 100% Satisfaction Guarantee
    Rate the answer you receive.

Ask ATLPROG Your Own Question

ATLPROG
ATLPROG, Computer Software Engineer
Category: Programming
Satisfied Customers: 7677
Experience:  MS in IT.Several years of programming experience in Java C++ C C# Python VB Javascript HTML
44910485
Type Your Programming Question Here...
ATLPROG is online now
A new question is answered every 9 seconds

I'm trying to redirect the output of a specific 'system'

Customer Question

I'm trying to redirect the output of a specific 'system' command and I can't get the redirection to work:
// This works: -hashfile command completed successfully.
memset(&tchar[0], 0, sizeof(tchar));
sprintf(tchar, "certutil -hashfile \"\%s\"\ MD5", output_filename);
system(tchar);
This doesn't --> Error: Expected no more than 2 args, received 4
sprintf(tchar, "certutil -hashfile \"\%s\"\ MD5 ^> \"\C:\\TEMP\\image.cksm\"\"", output_filename);
ANY suggestions would be greatly appreciated!
Submitted: 3 months ago.
Category: Programming
Expert:  Bruce Wilner replied 3 months ago.

First question: why are you bothering to memset() the zeroth char when you immediately overwrite the string?

Second question: exactly what command line are you trying to get to run? I want it verbatim, free of %s and \" and such.

Third question: could you please stick to three-letter suffixes? File extensions like '.cksm' can cause trouble.

Expert:  Bruce Wilner replied 3 months ago.

You also have a \ in front of the % which is going to turn off the special interpretation of %s as "insert the string argument into the format string in this position." Nor can I see why you have a circumflex (^) in front of the >.

What you need is:

sprintf( tchar, "certutil -hashfile \"%s\" MD5 >C:\\temp\\image.cks", output_filename );

Don't go hog-wild with unncessary extra backslashes. Notice each \ in the output pathname is doubled.

Expert:  Bruce Wilner replied 3 months ago.

If you have questions, I will be at the veterinarian for approximately the next hour. I will be back immediately after that. Again,

sprintf( tchar, "certutil -hashfile \"%s\" MD5 >C:\\temp\\image.cks", output_filename );

Expert:  Bruce Wilner replied 3 months ago.

Also, you can redirect standard output by yourself and put it back after the command:

int stdo = dup( 1 );

close( stdo );

creat( "C:\\temp\\image.cks", 0666 );

sprintf( tchar, "certutil -hashfile \"%s\" MD5", output_filename );

system( tchar );

close( 1 );

dup( stdo );

Expert:  Bruce Wilner replied 3 months ago.

WHOOPS! CORRECTING ERROR IN THE SECOND LINE!

int stdo = dup( 1 );

close( 1 );

creat( "C:\\temp\\image.cks", 0666 );

sprintf( tchar, "certutil -hashfile \"%s\" MD5", output_filename );

system( tchar );

close( 1 );

dup( stdo );

Expert:  Bruce Wilner replied 3 months ago.

Back from vet!

The idea of the dup() close() creat() jazz is for your program to deal with redirecting standard output so that you don't overcomplicate the call to system().

dup() duplicates a file descriptor. Whenever a file is opened, the lowest possible descriptor is assigned. Thus, we make a "copy" of standard output, so to speak; close standard output; and create the temp file, which will be assigned file descriptor #1 and therefore be "standard output" when system() runs the certutil command. After the command, we close the temp file (again freeing file descriptor #1) and make a copy of our original copy of standard output, which will--guess what--be assigned back to the lowest available slot, i.e., slot #1. We basically stuck the original standard output in the hopper; set up an alternative standard output for your command, going to the new temp file; and then restored the original standard output afterwards.

Customer: replied 3 months ago.
This does not work - same error --> Expected no more than 2 args, received 4
sprintf( tchar, "certutil -hashfile \"%s\" MD5 >C:\\temp\\image.cks", output_filename );
so I think I need to try redirecting standard output like you suggest,
I'm working in Nat. Instruments CVI environment, and popen is not supported, otherwise I would have done that.
I'll let you know how it goes.
Thanks
Expert:  Bruce Wilner replied 3 months ago.

By the way, unless you're mistyping that sprintf() statement, I don't see more than three arguments. I see tchar, the string constant, and output_filename. I have programmed in C for 30+ years, so I'm not readily fooled.

Are you sure tchar is properly defined as a char array, as in:

char tchar[ 100 ];

THE NEXT PROBLEM: are you using the CERTUTIL command properly? I see a flag and two arguments for a total of three.

The error isn't coming from system(), it's coming from CERTUTIL. Make sure you have the proper command syntax for CERTUTIL.

Expert:  Bruce Wilner replied 3 months ago.

If there is any blank space in the value of the string output_filename, that would explain why CERTUTIL is seeing four arguments. For example, suppose the value of output_filename was "hello dolly", then certutil would be invoked as follows:

certutil -hashfile hello dolly MD5

with or without the redirection (>), which has nothing to do with the certutil command per se, it's a syntax feature of the DOS shell.

Expert:  Bruce Wilner replied 3 months ago.

I hate to go on and on, but . . .

in your original example, your string argument to sprintf() still has that nasty ^ in front of the >.

As a result of that, CERTUTIL would receive the '^' and think it's an argument. Triple-check that that ^ isn't actually in the string!

Expert:  Bruce Wilner replied 3 months ago.

You can test out what CERTUTIL command is actually being issued--what arguments CERTUTIL is actually being passed--by changing the sprintf string so that in place of certutil you have echo certutil (two independent words, spaced apart). When system() runs that command, it will merely PRINT OUT the certutil command. If you have the redirection, the certutil command will be printed out to the temp file--instead of RUNNING the certutil command and sending its output there.

Customer: replied 3 months ago.
Like I said, this works:
sprintf(tchar, "certutil -hashfile \"\%s\"\ MD5", output_filename);
And this doesn't (modified slightly due to a sourceforge suggestion):
sprintf(tchar, "certutil -hashfile \"%s\" MD5 > \"C:\\TEMP\\image.cksm\"", output_filename);
And I STILL have the same error: Expected no more than 2 args, received 4.
FYI I don't think my Windows NI CVI environment supports dup() and close() (would fclose() work?)
Expert:  Bruce Wilner replied 3 months ago.

Did you, by any chance, try to follow my instructions, as in changing CERTUTIL to ECHO CERTUTIL so that you could print out what CERTUTIL is actually receiving and trying to execute?

I can't see from here what arguments are being passed to CERTUTIL, nor do I know what's in the string output_filename.

I also believe I said, like, three times to remove the pointless \" from before and after the temp file name.

Expert:  Bruce Wilner replied 3 months ago.

You also have backslash space MD5 i the first sprintf() statement and no backslash space MD5 in the second.

Not that that would hurt--backslash space will be mapped into just a space by the compiler--but I can't divine from the ether if you can't even precisely type into the chat stream what statements are or aren't working for you.

Customer: replied 3 months ago.
OK. I'll try the echo and remove the extra backslashes
Expert:  Bruce Wilner replied 3 months ago.

When you have done so, please type EXACTLY what the output of ECHO CERTUTIL blah blah blah was. Remember, if you redirect it, you'll have to type out the contents of C:\temp\blahblahblah to get the information.

Customer: replied 3 months ago.
I just logged char tchar[150] to my logfile, and it is:echo certutil -hashfile "c:\\MK54\\IMG\\8megallzeros.img" MD5 > C:\MK54\TEMP\temp.md5
Customer: replied 3 months ago.
When I execute this on the command line,
certutil -hashfile "c:\\MK54\\IMG\\8megallzeros.img" MD5 > C:\MK54\TEMP\temp.md5
It works perfectly
Expert:  Bruce Wilner replied 3 months ago.

I don't recall asking you to log tchar, but to copy the command "echo certutil . . ." into tchar and then system() it. It's difficult to diagnose if you don't follow the directions really precisely.

If that's what it's executing, then it should run correctly, unless we're having a MAJOR miscommunication here.

Expert:  Bruce Wilner replied 3 months ago.

I will be honestly with you: this is a profoundly trivial situation, and all it takes is following directions to the letter.

Customer: replied 3 months ago.
I'm running NI Test Stand, and there is no command output window that I know of to capture the echo output.
The major problem is the NI CVI environment - it doesn't support popen(), dup(), close(), ...
The following command: sprintf(tchar, "certutil -hashfile \"%s\" MD5 > \"C:\\TEMP\\image.cksm\"", output_file);
Works when compiled it using VStudio21k0 and ran it on Win10, but NOT for Windows 7 with a National Instruments LabWindows CVI compiler. So the LabWindows CVI system() command works differently too!
Bruce, whether we get a solution or not, I appreciate your effort.
Expert:  Bruce Wilner replied 3 months ago.

It's not about "get a solution or not," obeying simple directions will give you a solution. There is nothing magical about using system() to execute a certutil command with various arguments unless the arguments are screwed up or system() doesn't work.