Append to char *

M

Marcia Hon

Hi,

I would like to recursively force to empty and delete a directory. As
such I would like to append the char *.

Here is the code:

char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

Following this, I would like to do the system command:

if(system(command) == 0)
{
printf("Successfully removed directory\n");
}

Thanks,
Marcia
 
R

Richard Heathfield

Marcia said:
char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

char command[FILENAME_MAX + sizeof "rm -rf "] = "rm -rf ";
strcat(command, directory);
 
J

Johan Lindh

Duff said:
Just include <string.h> header file, and use "strcat()" function:

char * directory = "Directory";
char * command = "rm -rf ";
strcat(command,directory);
system(command);

That's a pretty good way to make demons fly out your nose, anyway...

/J
 
P

Peter Pichler

Marcia Hon said:
I would like to recursively force to empty and delete a directory.

See the replies to your first post regarding this.
As such I would like to append the char *.

Here is the code:

char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

Allocate enough memory to hold both strings, like this:

#include <stdlib.h> /* for malloc */
#include <string.h> /* for strlen, strcpy and strcat */

/* presumably, more code follows here */

char * concat = malloc(strlen(command) + strlen(directory) + 1);
if (concat)
{
strcpy(concat, command);
strcat(concat, directory);
/* do your other stuff here */
free(concat);
}
else
{
/* complain about not enough memory or some such */
)

You can get away without malloc, if you have a buffer (in other words, an
array of char) big enough to contain the concatenated string. You can also
use sprintf instead of strcpy and strcat. What you cannot do, is concatenate
strings like you do in BASIC or some script languages. In C, you have to
spell it out exactly what you want to do.
Following this, I would like to do the system command:

if(system(command) == 0)
{
printf("Successfully removed directory\n");
}

I am not sure your condition is guaranteed to do what you expect it to do:
"If the argument is not a null pointer, and the system function does return,
it returns an implementation-defined value". So, it may return 0, but just
as well it may return 42 or not return at all.

Peter
 
D

Duff

Just include <string.h> header file, and use "strcat()" function:

char * directory = "Directory";
char * command = "rm -rf ";
strcat(command,directory);
system(command);
 
D

Derk Gwen

(e-mail address removed) (Marcia Hon) wrote:
# Hi,
#
# I would like to recursively force to empty and delete a directory. As
# such I would like to append the char *.
#
# Here is the code:
#
# char * directory = "Directory";
# char * command = "rm -rf ";

char * commandformat = "rm -rf '%s'";

# How can I append the two to get: "rm -rf Directory"???

char * command = malloc(strlen(directory)+strlen(commandformat)+1);
sprintf(command,commandformat,directory);

The command string is passed to a shell; putting single quotes around
the directory name protects it from shell interpretation if you happen
to have spaces or other shell-interpretted characters in the name.

# if(system(command) == 0)
# {
# printf("Successfully removed directory\n");
# }

free(command);
 
K

Keith Thompson

Marcia Hon said:
Thanks!!!
[33 lines deleted]

Marcia, a couple of tips.

A: Because it makes it difficult to follow the discussion.
Q: Why is top-posting bad?

First, please don't top-post. The convention here (and in most
newsgroups) is for new text to follow quoted text.

Second, quoting an entire article and adding a single word is also
considered poor style. If you want to post a followup, trim anything
from the original article that's not directly relevant to what you're
writing.
 
N

Nils Petter Vaskinn

That's a pretty good way to make demons fly out your nose, anyway...

Marcia:
"Nasal demons" is a standing joke about what could happen when someone
invokes undefined behavior.

What is undefined behavior?
In one word "Bad" it means that your program does something that might
make it:
1: Crash
2: Give incorrect results
3: Apparently work correctly (which is the worst because it could decide
to fail at the most inconvenient moment)
4: Format you harddrive (unlikely but it could happen)
5: Make demons fly out your nose (again: unlikely)
6: Anything

Ok, we've established that undefined behavior is bad, so why does Duffs
code invoke undefined behavior.

directory is now a pointer to some place in memory where there's reserved
enough space to hold 10 chars. (Length of directory plus one for a
terminating nul character)

command similarly points to 8 bytes of memory.

Now plop the contents pointed to by directory over the end of the
contens pointed to by command. Because command isn't made big enough to
hold then length of both "rm -rf " and "Directory" the memory immediately
following command will be overwritten with "irectory" and a null
character. (The 'D' occupies the space previously held by command's null
character.

Depending on what/if the memory after command was used for the program may
appear to work, or behave in unpredicatable ways. If it crashes it may
crash at a later time when that memory is used, and if nothing goes wrong
now it may do in a future version of the program (if something else uses
the moemory, or perhaps a different compiler version uses the memory
differently)

How to fix this? (untested code typed right in)

char * directory = "Directory";
char * command = "rm -rf ";

char * completed_command = malloc(strlen(directory)+strlen(command)+1);
if (!char) {
printf("Out of memory\n");
/* replace with error handling */
exit(1);
}
strcpy(completed_command,command);
strcat(completed_command,directory);
system(completed_command);

free(completed_command);
 
I

Irrwahn Grausewitz

[Snipped great explanation why

invokes undefined behavior.]

Just for completeness: both character pointers point to
memory which must not be modified (C99 6.4.5.#6), so that
even something like

char *s1 = "I'm a string literal.";
char *s2 = "Free nasal demons, if modified!";
strcpy( s2, s1 );

would invoke UB. Even worse, in

char *s1 = "Hello, world!";
char *s2 = "Hello, world!";

s1 and s2 might refer to the same memory location (the
standard explicitly allows literals to be shared, same
C&V).
How to fix this? (untested code typed right in)

char * directory = "Directory";
char * command = "rm -rf ";

char * completed_command = malloc(strlen(directory)+strlen(command)+1);
if (!char) {
ITYM:
if (!completed_command) {
printf("Out of memory\n");
/* replace with error handling */
exit(1);
*shudder* 8^)
}
strcpy(completed_command,command);
strcat(completed_command,directory);
system(completed_command);

free(completed_command);


Regards
 
A

Al Bowers

Nils said:
.......snip.....

Ok, we've established that undefined behavior is bad, so why does Duffs
code invoke undefined behavior.




directory is now a pointer to some place in memory where there's reserved
enough space to hold 10 chars. (Length of directory plus one for a
terminating nul character)




command similarly points to 8 bytes of memory.




Now plop the contents pointed to by directory over the end of the
contens pointed to by command. Because command isn't made big enough to
hold then length of both "rm -rf " and "Directory" the memory immediately
following command will be overwritten with "irectory" and a null
character. (The 'D' occupies the space previously held by command's null
character.

Memory space size is not the only issue here. Even if one had enough
storage, ex.

char *command = "rm -rf ";
strcpy(command+7,directory); /* Unsafe */

The Standard states that the space pointed to by the
variable(command) may be read-only. Writing to this space
is unsafe. The FAQ mentions this in question 1.32
http://www.eskimo.com/~scs/C-faq/q1.32.html

How to fix this? (untested code typed right in)

The code appears to be correct except for:
char * directory = "Directory";
char * command = "rm -rf ";

char * completed_command = malloc(strlen(directory)+strlen(command)+1);
if (!char) {

if( !completed_command) {
 
J

Jeremy Yallop

Richard said:
Marcia said:
char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

char command[FILENAME_MAX + sizeof "rm -rf "] = "rm -rf ";
strcat(command, directory);

FILENAME_MAX is either too large or too small here. Too small,
because there's no guarantee (as far as I know) that it's large enough
for the buffer to hold "Directory"; it's certainly not large enough
for arbitrary user input, which will overflow the buffer. Too large,
because if this code is supposed to only handle the specific string
"Directory" then FILENAME_MAX is unnecessarily large on the
implementations I'm aware of.

Dynamic memory allocation is the only sensible strategy here.

Jeremy.
 
J

Jeremy Yallop

Derk said:
(e-mail address removed) (Marcia Hon) wrote:
# Hi,
#
# I would like to recursively force to empty and delete a directory. As
# such I would like to append the char *.
#
# Here is the code:
#
# char * directory = "Directory";
# char * command = "rm -rf ";

char * commandformat = "rm -rf '%s'";

# How can I append the two to get: "rm -rf Directory"???

char * command = malloc(strlen(directory)+strlen(commandformat)+1);
sprintf(command,commandformat,directory);

The command string is passed to a shell; putting single quotes around
the directory name protects it from shell interpretation if you happen
to have spaces or other shell-interpretted characters in the name.

That's only part of the job, though: the user input may contain single
quotes.

Jeremy.
 
R

Richard Heathfield

Jeremy said:
Richard said:
Marcia said:
char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

char command[FILENAME_MAX + sizeof "rm -rf "] = "rm -rf ";
strcat(command, directory);

FILENAME_MAX is either too large or too small here. Too small,
because there's no guarantee (as far as I know) that it's large enough
for the buffer to hold "Directory";

<shrug> The Standard guarantees it's big enough to hold any filename. I
agree that the Standard doesn't talk about directory names, but one would
have thought a directory name would have to fit into FILENAME_MAX, wouldn't
one?
it's certainly not large enough
for arbitrary user input, which will overflow the buffer. Too large,
because if this code is supposed to only handle the specific string
"Directory" then FILENAME_MAX is unnecessarily large on the
implementations I'm aware of.

Dynamic memory allocation is the only sensible strategy here.

That is /always/ a reasonable approach, in my opinion. (Call me lazy on this
occasion.)
 
E

E. Robert Tisdale

Johan said:
That's a pretty good way to make demons fly out your nose, anyway...

Nonsense!
The ANSI/ISO C [89]9 standard
does *not* specify anything about nasal demons.
According to my Linux man page:


STRCAT(3) Linux Programmer’s Manual STRCAT(3)

NAME
strcat, strncat - concatenate two strings
.
.
.

CONFORMING TO
SVID 3, POSIX, BSD 4.3, ISO 9899
.
.
.
 
K

Keith Thompson

Richard Heathfield said:
Jeremy said:
Richard said:
Marcia Hon wrote:

char * directory = "Directory";
char * command = "rm -rf ";

How can I append the two to get: "rm -rf Directory"???

char command[FILENAME_MAX + sizeof "rm -rf "] = "rm -rf ";
strcat(command, directory);

FILENAME_MAX is either too large or too small here. Too small,
because there's no guarantee (as far as I know) that it's large enough
for the buffer to hold "Directory";

<shrug> The Standard guarantees it's big enough to hold any filename. I
agree that the Standard doesn't talk about directory names, but one would
have thought a directory name would have to fit into FILENAME_MAX, wouldn't
one?

No, the Standard doesn't guarantee that it's big enough to hold any
filename. FILENAME_MAX is "the size needed for an array of char large
enough to hold the longest file name string that the implementation
guarantees can be opened". The implementation bay be able to
succesfully open files with names longer than FILENAME_MAX, and
there's no limit on the length of an *invalid* file name.

If you're writing real-world code, rather than a toy example, you
should at least check strlen(directory) before calling strcat().

If you're being lazy, you might as well have used 200 rather than
FILENAME_MAX; using FILENAME_MAX doesn't really buy you anything.

So what's FILENAME_MAX good for? A program that gets file names from
some external source can reasonably reject names longer than
FILENAME_MAX, but it needs to check explicitly rather than assuming
everything is ok.
 
K

Keith Thompson

E. Robert Tisdale said:
Johan Lindh wrote: [..]
That's a pretty good way to make demons fly out your nose, anyway...

Nonsense!
The ANSI/ISO C [89]9 standard
does *not* specify anything about nasal demons.
According to my Linux man page:
[snip]

ERT, you've been hanging around here long enough to know what the
whole "nasal demons" thing is about.
 
J

Joona I Palaste

Keith Thompson said:
E. Robert Tisdale said:
Johan Lindh wrote: [..]
That's a pretty good way to make demons fly out your nose, anyway...

Nonsense!
The ANSI/ISO C [89]9 standard
does *not* specify anything about nasal demons.
According to my Linux man page: [snip]

ERT, you've been hanging around here long enough to know what the
whole "nasal demons" thing is about.

Sinc when were Linux man pages an authoritative source of what the
ANSI/ISO C standard says, anyway?
 

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

No members online now.

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,352
Latest member
DianeKulik

Latest Threads

Top