sprintf a filename

R

Rudra Banerjee

I am trying to have something like:
Code:

char pdfinfo[1028];
sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);
g_print("%s", pdfinfo);
system((char *) pdfinfo);


This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.

I cannot open pdfinfo (in my knowledge) with fopen, as then,

sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);

will give error, as I am printing a FILE as char.
what is the way out?
 
K

Keith Thompson

Rudra Banerjee said:
I am trying to have something like:
Code:

char pdfinfo[1028];
sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);
g_print("%s", pdfinfo);
system((char *) pdfinfo);

The cast is unnecessary, and could be dangerous if you got it wrong.
Since pdfinfo is a char array, it's implicitly converted to a char*
in most contexts. If you're unclear on this, read section 6 of the
comp.lang.c FAQ said:
This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.

I cannot open pdfinfo (in my knowledge) with fopen, as then,

sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);

will give error, as I am printing a FILE as char.
what is the way out?

The behavior of system() is largely system-specific.

On Unix-like systems, it executes the given command by passing it as an
argument to /bin/sh. That means that, to run a command with certain
arguments using system(), the argument needs to be the same as what
you'd need to type at a shell prompt.

This is likely to work:

sprintf(pdfinfo, "pdfinfo '%s' >filout", pdfname);

But it's not a completely general solution; for example, it will
fail if pdfname contains a single-quote character.

If there's a general solution, you're more likely to find it on
comp.unix.programmer. (I'm assuming you're using a Unix-like system;
if you're not, then another newsgroup might be more helpful.)
 
R

Rudra Banerjee

Keith,
Thanks for your help. For my present situation, its working. For a "failsafe" way, I have asked comp.unix.programmer as per your advice.
 
J

James Kuyper

I am trying to have something like:
Code:

char pdfinfo[1028];
sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);
g_print("%s", pdfinfo);
system((char *) pdfinfo);


This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.

When you call system(), the host environment's command processor (if one
is available) is used to process the string. I believe that on Unix-like
systems it's usually
"/bin/sh -c", which on Linux systems is usually an alias for bash. The
problem is not the presence of a backslash, but the absence of one.

Try these two:
system("pdfinfo file with space");
system("pdfinfo file\\ with\\ space");

On my system, the first fails, the second succeeds. Keep in mind that
'\\' is a C escape sequence that only places a single backslash
character in the resulting string. A space character in bash normally
separates command line arguments. Escaping it with a backslash turns
that special meaning off, with the result that the entire file name,
including the embedded spaces, is parsed as a single command line
argument to be passed to pdfinfo. As Keith pointed out, the following
also works:
system("pdfinfo 'file with space'");
I cannot open pdfinfo (in my knowledge) with fopen, as then,

sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);

will give error, as I am printing a FILE as char.
what is the way out?

One way is to insert a backslash into the file name before any spaces,
or to surround it with single quotes, before calling system().

If you need to look at files with other unusual characters embedded in
them (such as backslashes, single quotes, etc.), you may need a more
complete solution. You might want to look at the exec*() family of POSIX
functions - they pass the specified list of arguments directly to the
program being executed, without any command line processing. You'll need
to use fork() before calling it, and only call the exec*() function in
the child processif there's anything you want the program to do after
calling it.
 
L

Lew Pitcher

I am trying to have something like:
Code:

char pdfinfo[1028];
sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);
g_print("%s", pdfinfo);
system((char *) pdfinfo);


This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.

Is there any particular reason why you restrict yourself to the system()
function here?

You mention that you are working on a Linux system, and you call a function
not defined in the C standard (g_print()), so it appears that you have no
reason /not/ to use Linux-specific functions (that is, the standard POSIX
process management functions) to run your "pdfinfo" program.

You might want to discuss your code, and the alternatives, in the
comp.os.linux.development.apps or comp.unix.programmer newsgroups. We can
help you there with examples of POSIX functions that would make easy work
of your problem here.
 
N

Nobody

I am trying to have something like:
Code:

char pdfinfo[1028];
sprintf(pdfinfo, "pdfinfo %s >filout", pdfname);
g_print("%s", pdfinfo);
system((char *) pdfinfo);


This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.

Don't use system().

For Unix, use fork() and one of the exec*() functions. This ensures
that the resulting program's argv[] will be exactly what you want it to
be. You'll need to implement redirection manually with dup2(). As a
starting point, you might consider using the sample system()
implementation given at:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html

Note that most of it is signal handling: in the parent, SIGINT and SIGQUIT
are ignored and SIGCHLD is blocked. This may or may not be appropriate for
your particular case (this behaviour results in Ctrl-C killing the child
process rather than the parent; this can be appropriate for long-running
programs, particularly interactive ones, but often isn't for simple
commands).

Windows doesn't have an equivalent; the underlying interface for passing
arguments between programs uses a single string rather than a list of
strings. For programs using C's main() interface, the executable is
responsible for parsing the command string into the argv[]. In theory
there's no reliable way to force the program's main() (if it even has one)
to receive a specific argument list. The best you can do is assume that
it uses the syntax documented at:

http://msdn.microsoft.com/en-us/library/17w5ykft.aspx

BTW: don't use the spawn*() functions. They have the correct interface,
but the wrong implementation; they just concatenate the arguments with
spaces in between, with no quoting. So you'll just get the existing
incorrect behaviour if the filename contains spaces or other
metacharacters.
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×œ×™×©×™, 18 בספטמבר 2012 22:01:14 UTC+1, מ×ת Rudra Banerjee:
I am trying to have something like:

This works fine when the filename choosen has no space. If it has space,
as linux reads it as "file\ with\ space", pdfinfo is giving error.
So you need quotes around the filename, so the shell expands it as one string
instead of two. (Embed quotes using the backslash to escape).
 
B

Ben Bacarisse

Malcolm McLean said:
בת×ריך ×™×•× ×©×œ×™×©×™, 18 בספטמבר 2012 22:01:14 UTC+1, מ×ת Rudra Banerjee:
So you need quotes around the filename, so the shell expands it as one string
instead of two. (Embed quotes using the backslash to escape).

In comp.lang.c you can't say what sort of quoting and/or escaping is
needed. If (as turns out to be the case) the OP can assume a certain
shell with be involved you can give a defintite answer (see
comp.unix.programmer for the definitive answer in this case).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top