[comp.lang.c] strcat/access question

jjk@astro.UMD.EDU (Jim Klavetter) (10/03/89)

Here is a section of code:

if((home=getenv("HOME"))==(char *) 0)
    perror("GETENV\n");
printf("%s:\n", home);
printf("%s:\n", strcpy(string,strcat(home, "/astro/data/obs.list")));
printf("%s:\n", string);
printf("%d:\n", access(string, 4));
printf("%d:\n", access(strcat(home, "/astro/data/obs.list"), 4));

And the associated output:

/a/jjk:
/a/jjk/astro/data/obs.list:
/a/jjk/astro/data/obs.list:
0:
-1:

The man page says that strcat returns a null-terminated string so that
the two calls to access (I think) should both give "0" but the second
is saying the file doesn't exist.  I've included the appropriate
files.  Any response to the above address would be appreciated (and
I will summarize the response if there is some good answer(s)).

jjk

ok@cs.mu.oz.au (Richard O'Keefe) (10/03/89)

In article <5409@umd5.umd.edu>, jjk@astro.UMD.EDU (Jim Klavetter) writes:
> if((home=getenv("HOME"))==(char *) 0) perror("GETENV\n");
> printf("%s:\n", home);
At this point, home points to "/a/jjk\0" followed by who knows what
> printf("%s:\n", strcpy(string,strcat(home, "/astro/data/obs.list")));
				^^^^^
At this point, home points to "/a/jjk/astro/data/obs.list\0" who knows what
strcat() copies its second argument into the same array that its first
argument points to, starting at the first NUL it finds there.
> printf("%d:\n", access(strcat(home, "/astro/data/obs.list"), 4));
At this point, home points to "/a/jjk/astro/data/obs.list/astro/data/obs.list"

> The man page says that strcat returns a null-terminated string so that
Yes it does; and the pointer it returns is the pointer you gave it as
its first argument.

Sometimes it is simpler to forget strcat() and so on and just use
sprintf:
	sprintf(work_string, "%s/astro/data/obs.list", home);
This is unlikely to be a performance bottleneck.

cpcahil@virtech.UUCP (Conor P. Cahill) (10/03/89)

In article <5409@umd5.umd.edu>, jjk@astro.UMD.EDU (Jim Klavetter) writes:
> Here is a section of code:
> 
> if((home=getenv("HOME"))==(char *) 0)
>     perror("GETENV\n");

Perror is useless here since getenv is not a system call.  In addition,
since you use home in later code, you should exit here.

> printf("%s:\n", home);
> printf("%s:\n", strcpy(string,strcat(home, "/astro/data/obs.list")));
	                              ^^^^^
This modifies home.  You should never do this to an environment pointer
since this will mess up your environment (or may cause the program to 
core dump if HOME is at the end of your environment and the end of your
address space).

Home now points to "/a/jjk/astro/data/obs.list"

> printf("%s:\n", string);
> printf("%d:\n", access(string, 4));
> printf("%d:\n", access(strcat(home, "/astro/data/obs.list"), 4));
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Home now points to "/a/jjk/astro/data/obs.list/astro/data/obs.list"  hence
the failure code from access(2).


> The man page says that strcat returns a null-terminated string so that
> the two calls to access (I think) should both give "0" but the second
> is saying the file doesn't exist.  I've included the appropriate
> files.  Any response to the above address would be appreciated (and
> I will summarize the response if there is some good answer(s)).

You must read the man page for any routine you want to use.  If you had
read the man page for strcat (string(3) or maybe strings(3)) you would have
seen that strcat appends the second string to the first string and returns
a pointer to the first string (in this case home).

Make sure you read the entire man page!!!!!!!
-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

john@chinet.chi.il.us (John Mundt) (10/03/89)

In article <5409@umd5.umd.edu> jjk@astro.UMD.EDU writes:
>Here is a section of code:
>
>if((home=getenv("HOME"))==(char *) 0)
>printf("%d:\n", access(strcat(home, "/astro/data/obs.list"), 4));

home is a char pointer, pointing to somewhere in the environmental
variable area that was passed to main since that is where getenv()
looks for things like HOME.  

	main(int argc, char **argv, char **env)


When you concatenated home with the rest of the path, it would have
to step on other environmental variables, probably one that was
needed by access().
-- 
---------------------
John Mundt   Teachers' Aide, Inc.  P.O. Box 1666  Highland Park, IL
john@chinet.chi.il.us
(312) 998-5007 (Day voice) || -432-8860 (Answer Mach) && -432-5386 Modem  

cpcahil@virtech.UUCP (Conor P. Cahill) (10/04/89)

In article <9733@chinet.chi.il.us>, john@chinet.chi.il.us (John Mundt) writes:
> home is a char pointer, pointing to somewhere in the environmental
> variable area that was passed to main since that is where getenv()
> looks for things like HOME.  
> 
> When you concatenated home with the rest of the path, it would have
> to step on other environmental variables, probably one that was
> needed by access().

The part about stepping on other environment variables is true, but the cause
of the problem is not that access() requires something in the environment.
access(2) is a system call and system calls don't use any such thing as an
environment variable (can you imagine the kernel searching through your
data space looking for some strings?)

The problem is that the original poster appended the path from his HOME 
directory to the file twice thereby generating a non-existent file name.



-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

mccaugh@s.cs.uiuc.edu (10/04/89)

> Here is a section of code:
> 
> if((home=getenv("HOME"))==(char *) 0)
>     perror("GETENV\n");
> printf("%s:\n", home);
> printf("%s:\n", strcpy(string,strcat(home, "/astro/data/obs.list")));
> printf("%s:\n", string);
> printf("%d:\n", access(string, 4));
> printf("%d:\n", access(strcat(home, "/astro/data/obs.list"), 4));
> 
> And the associated output:
> 
> /a/jjk:
> /a/jjk/astro/data/obs.list:
> /a/jjk/astro/data/obs.list:
> 0:
> -1:
> 
> The man page says that strcat returns a null-terminated string so that
> the two calls to access (I think) should both give "0" but the second
> is saying the file doesn't exist.  

 Actually, I recall the 'man' page stating that strcat returns a pointer
 (char-type) to the null-terminated string, but in any case I suspect
 that the last printf contains a call to strcat which assigns to your
 string-variable 'home' the name of a truly non-existent file, namely:
 "/a/jjk/astro/data/obs.list/astro/data/obs.list", so a redundant 'strcat'
 appears to have occurred in variable 'home'.