programi parsing question - Unix
This is a discussion on programi parsing question - Unix ; In the following code snippet, I misplaced one of the parenthesis in
read() and as a result, the program outputs junk. The question is why
does the misplaced parenthesin read() cause the program to print junk?
I guess I probably ...
-
programi parsing question
In the following code snippet, I misplaced one of the parenthesis in
read() and as a result, the program outputs junk. The question is why
does the misplaced parenthesin read() cause the program to print junk?
I guess I probably don't understand how read() gets parsed or read in
by the compiler
#include
#include
#include
#include
#include
int main(void)
{
int fd;
struct utmp log;
if((fd=open(_PATH_UTMP, O_RDONLY)) < 0){
fprintf(stderr, "can't open file\n");
exit(1);
}
while( read(fd, &log, sizeof(log) == sizeof(log) ) ){
printf("%s\n", log.ut_user);
}
close(fd);
return 0;
}
-
Re: programi parsing question
K-mart Cashier writes:
> In the following code snippet, I misplaced one of the parenthesis in
> read() and as a result, the program outputs junk. The question is why
> does the misplaced parenthesin read() cause the program to print junk?
> I guess I probably don't understand how read() gets parsed or read in
> by the compiler
[...]
> struct utmp log;
[...]
> while( read(fd, &log, sizeof(log) == sizeof(log) ) ){
> printf("%s\n", log.ut_user);
> }
The comparison used as third argument is always true and its value is
therefore one. Your call is equivalent to
read(fd, &log, 1);
which means that you read the file byte-by-byte, dumping each into the
first byte occupied by log and then trying to interpret some part of
the structure as C-string.
-
Re: programi parsing question
K-mart Cashier wrote:
> while( read(fd, &log, sizeof(log) == sizeof(log) ) ){
The expression 42 == 42 returns 1, so that's the number of bytes read() reads.
> printf("%s\n", log.ut_user);
Then the ut_user element never got initialized or written on, so it contains
stack garbage, and this prints out.
All this is "undefined behavior", so nearly anything could happen, in theory!
Now switch to a softer language, like Ruby, so you can start actually writing
real programs, sooner, and get back to C after you actually need it for something!
--
Phlip
-
Re: programi parsing question
On 2 aug, 17:21, K-mart Cashier wrote:
> if((fd=open(_PATH_UTMP, O_RDONLY)) < 0){
The manual (http://www.gnu.org/software/libtool/manual/libc/User-
Accounting-Database.html) says:
The user accounting database typically lives in /etc/utmp, /var/adm/
utmp or /var/run/utmp. However, these files should *never* be accessed
directly. For reading information from and writing information to the
user accounting database, the functions described in this section
should be used.
This implies that you should not use open() and read(), but rather
getutent().
On 2 aug, 17:28, Phlip wrote:
> Now switch to a softer language, like Ruby, so you can start actually writing
> real programs, sooner, and get back to C after you actually need it for something!
I think you are putting your Ruby evangelism forward a bit harsh.
Besides, Ruby does not seem to have the utmp functions provided by
libc (although the poster does not use them in his example). There
does seem to be a python-utmp package, however.
-
Re: programi parsing question
Sjoerd wrote:
>> Now switch to a softer language, like Ruby, so you can start actually writing
>> real programs, sooner, and get back to C after you actually need it for something!
> I think you are putting your Ruby evangelism forward a bit harsh.
Sorry. I thought I was representing my decades of experience with C.
--
Phlip
-
Re: programi parsing question
In comp.unix.programmer Phlip wrote:
| Sjoerd wrote:
|
|>> Now switch to a softer language, like Ruby, so you can start actually writing
|>> real programs, sooner, and get back to C after you actually need it for something!
|
|> I think you are putting your Ruby evangelism forward a bit harsh.
|
| Sorry. I thought I was representing my decades of experience with C.
The "start actually writing real programs" part is what suggested evangelism.
AFAICT, both languages let you write real programs. Which is the best choice
depends on a lot of factors such as what kind application you are developing,
your experiences, and whether it impacts continuing your employment.
--
|WARNING: Due to extreme spam, googlegroups.com is blocked. Due to ignorance |
| by the abuse department, bellsouth.net is blocked. If you post to |
| Usenet from these places, find another Usenet provider ASAP. |
| Phil Howard KA9WGN (email for humans: first name in lower case at ipal.net) |
-
Re: programi parsing question
>In the following code snippet, I misplaced one of the parenthesis in
>read() and as a result, the program outputs junk. The question is why
>does the misplaced parenthesin read() cause the program to print junk?
>I guess I probably don't understand how read() gets parsed or read in
>by the compiler
The length argument to read() was the constant 1, as others have
pointed out.
> while( read(fd, &log, sizeof(log)) == sizeof(log) ){
/* parens fixed above */
> printf("%s\n", log.ut_user);
> }
HOWEVER, even if that problem is corrected, I see no guarantee that
what is read is '\0'-terminated. read() makes no such guarantee,
and I doubt that the file format does either. Ensure that strings
are terminated before trying to print them with %s.
-
Re: programi parsing question
On Aug 2, 10:40 am, Sjoerd wrote:
> On 2 aug, 17:21, K-mart Cashier wrote:
>
> > if((fd=open(_PATH_UTMP, O_RDONLY)) < 0){
>
> The manual (http://www.gnu.org/software/libtool/manual/libc/User-
> Accounting-Database.html) says:
> The user accounting database typically lives in /etc/utmp, /var/adm/
> utmp or /var/run/utmp. However, these files should *never* be accessed
> directly. For reading information from and writing information to the
> user accounting database, the functions described in this section
> should be used.
>
> This implies that you should not use open() and read(), but rather
> getutent().
>
There are some *nix variants that don't have getutent().
-
Re: programi parsing question
On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
> >In the following code snippet, I misplaced one of the parenthesis in
> >read() and as a result, the program outputs junk. The question is why
> >does the misplaced parenthesin read() cause the program to print junk?
> >I guess I probably don't understand how read() gets parsed or read in
> >by the compiler
>
> The length argument to read() was the constant 1, as others have
> pointed out.
>
> > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>
> /* parens fixed above */
>
> > printf("%s\n", log.ut_user);
> > }
>
> HOWEVER, even if that problem is corrected, I see no guarantee that
> what is read is '\0'-terminated. read() makes no such guarantee,
> and I doubt that the file format does either. Ensure that strings
> are terminated before trying to print them with %s.
So should I have done something like
memset(&log, 0, sizeof (log));
before the call to read()?
-
Re: programi parsing question
On Aug 2, 6:12 pm, Chad wrote:
> On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
>
>
>
> > >In the following code snippet, I misplaced one of the parenthesis in
> > >read() and as a result, the program outputs junk. The question is why
> > >does the misplaced parenthesin read() cause the program to print junk?
> > >I guess I probably don't understand how read() gets parsed or read in
> > >by the compiler
>
> > The length argument to read() was the constant 1, as others have
> > pointed out.
>
> > > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>
> > /* parens fixed above */
>
> > > printf("%s\n", log.ut_user);
> > > }
>
> > HOWEVER, even if that problem is corrected, I see no guarantee that
> > what is read is '\0'-terminated. read() makes no such guarantee,
> > and I doubt that the file format does either. Ensure that strings
> > are terminated before trying to print them with %s.
>
> So should I have done something like
>
> memset(&log, 0, sizeof (log));
>
> before the call to read()?
Now that I think about it, I have a second question. How come doesn't
get checked for a return value (on error)?
-
Re: programi parsing question
On Aug 2, 6:12 pm, Chad wrote:
> On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
>
>
>
> > >In the following code snippet, I misplaced one of the parenthesis in
> > >read() and as a result, the program outputs junk. The question is why
> > >does the misplaced parenthesin read() cause the program to print junk?
> > >I guess I probably don't understand how read() gets parsed or read in
> > >by the compiler
>
> > The length argument to read() was the constant 1, as others have
> > pointed out.
>
> > > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>
> > /* parens fixed above */
>
> > > printf("%s\n", log.ut_user);
> > > }
>
> > HOWEVER, even if that problem is corrected, I see no guarantee that
> > what is read is '\0'-terminated. read() makes no such guarantee,
> > and I doubt that the file format does either. Ensure that strings
> > are terminated before trying to print them with %s.
>
> So should I have done something like
>
> memset(&log, 0, sizeof (log));
>
> before the call to read()?
No, that's not good enough, because you're reading sizeof(log) bytes.
All those zeros will get overwritten. If you want to printf with %s,
you would probably want to copy the whole thing into a buffer that's
one byte larger, so you can put the zero byte there. Alternatively,
use a precision specifier for printf, so that it won't try to read
more than the appropriate number of bytes.
But I don't understand why you're trying to print out a struct utmp as
ASCII anyway when it's got binary data in it. Wouldn't you rather be
printing the fields one at a time, with appropriate formatting?
I think maybe what you want to be doing is
while (read(fd, log, sizeof(log)) == sizeof(log)) {
time_t t = log.ut_time;
printf("Line %.*s, name %.*s, host %.*s, time %s\n", UT_LINESIZE,
ut.ut_line, UT_NAMESIZE, ut.ut_name, UT_HOSTSIZE, ut.ut_host,
ctime(&t));
}
-
Re: programi parsing question
On Aug 2, 7:27 pm, K-mart Cashier wrote:
> On Aug 2, 6:12 pm, Chad wrote:
>
>
>
> > On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
>
> > > >In the following code snippet, I misplaced one of the parenthesis in
> > > >read() and as a result, the program outputs junk. The question is why
> > > >does the misplaced parenthesin read() cause the program to print junk?
> > > >I guess I probably don't understand how read() gets parsed or read in
> > > >by the compiler
>
> > > The length argument to read() was the constant 1, as others have
> > > pointed out.
>
> > > > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>
> > > /* parens fixed above */
>
> > > > printf("%s\n", log.ut_user);
> > > > }
>
> > > HOWEVER, even if that problem is corrected, I see no guarantee that
> > > what is read is '\0'-terminated. read() makes no such guarantee,
> > > and I doubt that the file format does either. Ensure that strings
> > > are terminated before trying to print them with %s.
>
> > So should I have done something like
>
> > memset(&log, 0, sizeof (log));
>
> > before the call to read()?
>
> Now that I think about it, I have a second question. How come doesn't
> get checked for a return value (on error)?
How come *what* doesn't get checked?
-
Re: programi parsing question
phil-news-nospam@ipal.net wrote:
> |>> Now switch to a softer language, like Ruby, so you can start actually writing
> |>> real programs, sooner, and get back to C after you actually need it for something!
> |
> |> I think you are putting your Ruby evangelism forward a bit harsh.
> |
> | Sorry. I thought I was representing my decades of experience with C.
>
> The "start actually writing real programs" part is what suggested evangelism.
You snipped "sooner".
I think if two groups were learning programming, from scratch, the first ones
writing real programs that do useful things would be the ones using a soft
language, such as Javascript, Python, or Ruby. The ones that take longer to
learn the basics (and all the Gotchas) would be using harder languages, such as
BASIC, C, C++, Java, or Pascal.
You read too much into "real" programs...
-
Re: programi parsing question
On Aug 2, 9:36 pm, fjbl...@yahoo.com wrote:
> On Aug 2, 7:27 pm, K-mart Cashier wrote:
>
>
>
> > On Aug 2, 6:12 pm, Chad wrote:
>
> > > On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
>
> > > > >In the following code snippet, I misplaced one of the parenthesis in
> > > > >read() and as a result, the program outputs junk. The question is why
> > > > >does the misplaced parenthesin read() cause the program to print junk?
> > > > >I guess I probably don't understand how read() gets parsed or read in
> > > > >by the compiler
>
> > > > The length argument to read() was the constant 1, as others have
> > > > pointed out.
>
> > > > > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>
> > > > /* parens fixed above */
>
> > > > > printf("%s\n", log.ut_user);
> > > > > }
>
> > > > HOWEVER, even if that problem is corrected, I see no guarantee that
> > > > what is read is '\0'-terminated. read() makes no such guarantee,
> > > > and I doubt that the file format does either. Ensure that strings
> > > > are terminated before trying to print them with %s.
>
> > > So should I have done something like
>
> > > memset(&log, 0, sizeof (log));
>
> > > before the call to read()?
>
> > Now that I think about it, I have a second question. How come doesn't
> > get checked for a return value (on error)?
>
> How come *what* doesn't get checked?
memset()
-
Re: programi parsing question
K-mart Cashier said:
> On Aug 2, 9:36 pm, fjbl...@yahoo.com wrote:
>> On Aug 2, 7:27 pm, K-mart Cashier wrote:
>>
>>
>>
>> > On Aug 2, 6:12 pm, Chad wrote:
>>
>> > > On Aug 2, 3:04 pm, gordonb.0c...@burditt.org (Gordon Burditt) wrote:
>>
>> > > > >In the following code snippet, I misplaced one of the parenthesis
>> > > > >in read() and as a result, the program outputs junk. The question
>> > > > >is why does the misplaced parenthesin read() cause the program to
>> > > > >print junk? I guess I probably don't understand how read() gets
>> > > > >parsed or read in by the compiler
>>
>> > > > The length argument to read() was the constant 1, as others have
>> > > > pointed out.
>>
>> > > > > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>>
>> > > > /* parens fixed above */
>>
>> > > > > printf("%s\n", log.ut_user);
>> > > > > }
>>
>> > > > HOWEVER, even if that problem is corrected, I see no guarantee
>> > > > that
>> > > > what is read is '\0'-terminated. read() makes no such guarantee,
>> > > > and I doubt that the file format does either. Ensure that strings
>> > > > are terminated before trying to print them with %s.
>>
>> > > So should I have done something like
>>
>> > > memset(&log, 0, sizeof (log));
>>
>> > > before the call to read()?
>>
>> > Now that I think about it, I have a second question. How come doesn't
>> > get checked for a return value (on error)?
>>
>> How come *what* doesn't get checked?
>
> memset()
What are you going to check it against? memset() has no error return. It
always returns the same pointer you give to it.
But in fact you don't need the memset call anyway, since every byte is
written. Rather more useful would be a way of storing and checking the
result of read().
And in any case, if you really want to set every element of a struct to 0
on initialisation, memset isn't the best way to do it. Instead, take
advantage of the default initialiser rule:
struct utmp log = {0};
sets every element of log (except the first) to 0 (because of the partial
initialisation, which it observes, making the first element get set to 0
too because that's what you told it to do).
Given the frequency with which comp.lang.c gets off-topic questions, I find
it amusing that a question that - for once - would have been bang on-topic
in clc for several reasons, has ended up in c.p and c.u.p instead.
--
Richard Heathfield
Email: -http://www. +rjh@
Google users:
"Usenet is a strange place" - dmr 29 July 1999
-
Re: programi parsing question
Phlip wrote:
> phil-news-nospam@ipal.net wrote:
>
>> |>> Now switch to a softer language, like Ruby, so you can start
>> |>> actually writing real programs, sooner, and get back to C after
>> |>> you actually need it for something!
>> |
>> |> I think you are putting your Ruby evangelism forward a bit harsh.
>> |
>> | Sorry. I thought I was representing my decades of experience with
>> | C.
>>
>> The "start actually writing real programs" part is what suggested
>> evangelism.
>
> You snipped "sooner".
>
> I think if two groups were learning programming, from scratch, the
> first ones writing real programs that do useful things would be the
> ones using a soft language, such as Javascript, Python, or Ruby. The
> ones that take longer to learn the basics (and all the Gotchas) would
> be using harder languages, such as BASIC, C, C++, Java, or Pascal.
>
> You read too much into "real" programs...
I'm rather surprised that you classify Java as a "hard" language.
-
Re: programi parsing question
>> >In the following code snippet, I misplaced one of the parenthesis in
>> >read() and as a result, the program outputs junk. The question is why
>> >does the misplaced parenthesin read() cause the program to print junk?
>> >I guess I probably don't understand how read() gets parsed or read in
>> >by the compiler
>>
>> The length argument to read() was the constant 1, as others have
>> pointed out.
>>
>> > while( read(fd, &log, sizeof(log)) == sizeof(log) ){
>>
>> /* parens fixed above */
>>
>> > printf("%s\n", log.ut_user);
>> > }
My system (FreeBSD) seems to have a ut_name, not a ut_user structure
member.
>> HOWEVER, even if that problem is corrected, I see no guarantee that
>> what is read is '\0'-terminated. read() makes no such guarantee,
>> and I doubt that the file format does either. Ensure that strings
>> are terminated before trying to print them with %s.
>
>
>So should I have done something like
>
>memset(&log, 0, sizeof (log));
>
>before the call to read()?
That is insufficient. Consider a system in which the administrator
insists that all names (well, perhaps not including root) MUST be
UT_NAMESIZE characters long (NOT including the '\0', because there
isn't room for one) to make them hard to guess.
This is one application where strncpy() can be put to good use:
You need to declare dest somewhere, and make sure it's at
least sizeof(src.ut_name)+1 large.
strncpy(dest, src.ut_name, sizeof(src.ut_name));
dest[sizeof(src.ut_name)] = '\0';
If you also want to use ut_host and ut_line, you have the same issues
with them. These fields are not guaranteed to be '\0' terminated
and there isn't room to put one there.
-
Re: programi parsing question
Phlip writes:
> phil-news-nospam@ipal.net wrote:
>> |>> Now switch to a softer language, like Ruby, so you can start actually writing
>> |>> real programs, sooner, and get back to C after you actually need it for something!
>> | |> I think you are putting your Ruby evangelism forward a bit
>> harsh.
>> | | Sorry. I thought I was representing my decades of experience
>> with C.
>> The "start actually writing real programs" part is what suggested
>> evangelism.
>
> You snipped "sooner".
>
> I think if two groups were learning programming, from scratch, the
> first ones writing real programs that do useful things would be the
> ones using a soft language, such as Javascript, Python, or Ruby.
I don't think that people who consider 'programming language grammar
and syntax' to be 'a really hard problem' will ever write a useful
program. That would be close to expecting first-graders struggling
with expressing themselves in writing to publish enlightening treaties
on epistemology. Programming languages are tools (or toys :-). The
world is a complex thing and most of the (unsolved) problems that
spring from it are hard problems in their own right. Solving them
requires use of suitable tools, not necessarily familiar ones.
-
Re: programi parsing question
Phlip wrote:
) phil-news-nospam@ipal.net wrote:
)
)> |>> Now switch to a softer language, like Ruby, so you can start actually writing
)> |>> real programs, sooner, and get back to C after you actually need it for something!
)> |
)> |> I think you are putting your Ruby evangelism forward a bit harsh.
)> |
)> | Sorry. I thought I was representing my decades of experience with C.
)>
)> The "start actually writing real programs" part is what suggested evangelism.
)
) You snipped "sooner".
It's still there. However, there is a comma between "writing real
programs" and "sooner", which gives it a different meaning.
Just a comment, though.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
-
Re: programi parsing question
santosh wrote:
> I'm rather surprised that you classify Java as a "hard" language.
This is what happens when someone cross-posts between two technical newsgroups -
the introductions go around!
Java is amazingly hard, despite its brochure. To get a useful project going,
like a website, you often find yourself managing a thousand lines of
configuration, spread out over several files, before finally clawing your way to
the "hello, world".
Further, Java uses static typing, which tends to require a huge number of extra
lines just to "fill out forms" and prove that various objects have the right to
interact with each other.
--
Phlip