From: Eric Sosman on
On 5/12/2010 3:30 PM, barncat wrote:
>
> Thanks John. I was not sure how much code to post. I did not want to
> post too much. i am trying to figure this out with your and Eric's
> suggestions. i will post all code if I can't get it working.

General suggestion, not just for your current problem: Begin
by getting rid of the inessentials and distractions, to put the
mystery into the foreground. In your code, for example, you could
jettison the space-squeezing stuff, and perhaps more. How do you
know what's relevant and what isn't? If the reduced program still
shows the same mystifying behavior, the relevant pieces are still
there. (If it suddenly starts behaving, chances are good -- but not,
alas, certain -- that the last thing you threw out had something to
do with the problem.)

Ideally, you'll distill the program down to an SSCCE: a Short,
Self-Contained, Complete Example (some people prefer Correct or
Compilable for the second C): <http://sscce.org/>. All of these
attributes are important when you're asking for volunteer help, so
give the exercise some attention. There's a bonus: It quite often
happens that the distillation process itself will reveal the problem
to you and enable you to solve it yourself!

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: David Schwartz on
On May 12, 10:41 am, barncat <thebarn...(a)gmail.com> wrote:

> if (send(socket, string, strlen(string), 0) == -1)
>         perror("Writing String to client");

What is the protocol you are using over this socket? Do you have a
specification for it?

Without a specification, if something goes wrong, there is no way to
know who to blame. With a specification, use this logic:

1) Check if the program that is having trouble follows the
specification. If not, it is broken.

2) Check if the program on the other end follows the specification. If
not, it is broken.

3) If you get to this step, the specification is broken.

See, your 'send' provides no obvious way for the program on the other
end to determine whether or not it got the whole message. To know if
this is correct or the cause of your problem, we need to check the
specification to see if it was supposed to. And to write the other end
correctly, it will need to follow the specification to know how to
know whether to process the message or wait for more data.

DS
From: barncat on
On May 12, 3:53 pm, Eric Sosman <esos...(a)ieee-dot-org.invalid> wrote:
> On 5/12/2010 3:30 PM, barncat wrote:
>
>
>      General suggestion, not just for your current problem: Begin
> by getting rid of the inessentials and distractions, to put the
> mystery into the foreground.  In your code, for example, you could
> jettison the space-squeezing stuff, and perhaps more.  How do you
> know what's relevant and what isn't?  If the reduced program still
> shows the same mystifying behavior, the relevant pieces are still
> there.  (If it suddenly starts behaving, chances are good -- but not,
> alas, certain -- that the last thing you threw out had something to
> do with the problem.)
>
>      Ideally, you'll distill the program down to an SSCCE: a Short,
> Self-Contained, Complete Example (some people prefer Correct or
> Compilable for the second C): <http://sscce.org/>.  All of these
> attributes are important when you're asking for volunteer help, so
> give the exercise some attention.  There's a bonus: It quite often
> happens that the distillation process itself will reveal the problem
> to you and enable you to solve it yourself!
>


i got it to "work" but probably not the correct way. any comments on
better ways to do this are appreciated. i hope this is not too much
cod but it does compile and returns the expected output:
-bash-2.05b$ ./client INFO server
Type:Dedicated
Mode:Capped
--------------------------

server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>

#define PORT 3490
#define BACKLOG 5
#define BUFLEN 1024

int squeeze(char *s) {
char *t = s;
for(;*s;(*s != ' ') ? *t++ = *s++ : *s++)
continue;
*t = '\0';
}

int sendInfo(int socket) {
FILE *FP;
char string[128];
char buf[64];
int len;
bzero(string,128);
FP = popen("lparstat -i | head -5 | tail -2","r");
while(fgets(buf,64,FP) != NULL) {
strcat(string,buf);
squeeze(string);
}
pclose(FP);

len = strlen(string);
string[len] = '\0';

if (send(socket, string, strlen(string) + 1, 0) == -1)
perror("Writing String to client");

return(1);
}

int main(void)
{
int sockfd, new_fd;
int len;
int yes=1;
pid_t pid;
socklen_t sin_size;
struct sockaddr_in serv_addr, cli_addr;
struct hostent *h;
struct sigaction sa;

char request[BUFLEN+1];
char* pc;
int rc;
char c[32]; /* client ip string buffer */

/* set sock addrs info */
memset(&serv_addr, 0, sizeof serv_addr);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);

if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("server:socket");
exit(1);
}

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}

/* bind 32 bit adr and 16 bit port to unamed sock */
if (bind(sockfd, (struct sockaddr*)&serv_addr,
sizeof(serv_addr)) < 0) {
perror("server: bind");
exit(1);
}

/* convert unconnected sock to a passive sock */
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}

/* Accept requests and create file desc for each cli conn
*/
while(1) {
sin_size = sizeof cli_addr;
new_fd = accept(sockfd, (struct sockaddr *)&cli_addr,
&sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}

inet_ntop(AF_INET, &cli_addr.sin_addr, c, sizeof c);
printf("got connection from %s\n", c);
pid = fork();
if (pid == 0) { // child
close(sockfd); // child doesn't need the
listener

/* Read data from cli socket into request */
pc = request;
while (rc = read(new_fd, pc, BUFLEN - (pc-
request))) {
pc += rc;
}
*pc = '\0';

if (strcmp(request,"INFO") == 0)
sendInfo(new_fd);

close(new_fd);
exit(0);

} /* end fork */

} /* end of while loop */

} /* end of main body */
--

client:

#include <stdio.h> /* Basic I/O routines */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> /* standard system types */
#include <netinet/in.h> /* Internet address structures */
#include <sys/socket.h> /* socket interface functions */
#include <netdb.h> /* host to IP resolution */
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>

#define BUFLEN 1024 /* maximum response size */
#define PORT 3490

int main(int argc, char *argv[])
{
int n, i;
int length;
char request[BUFLEN+1];
char hostname[64];
char ServerInfo[128];
int sockfd;
struct hostent *h;
struct sockaddr_in sin;

/* Address resolution of Server we are connecting to */
h = gethostbyname(argv[2]);
if (!h) { perror("couldn't resolve host name"); }

strcpy(request,argv[1]);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
memcpy(&sin.sin_addr,h->h_addr,h->h_length);

/* open a socket */
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("client:socket");
exit(1);
}

/* connect to the socket */
if (connect(sockfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
perror("client: connect");
exit(1);
}

/* Send request to host server OS,SerialNum,... */
if (n = write(sockfd, request, BUFLEN) < 0)
perror("writing request to socket");

/* Read back response from server */
if (read(sockfd, ServerInfo, 128), 0)
perror("Reading back server data");
printf("%s\n",ServerInfo);
close(sockfd);

}

From: Barry Margolin on
In article
<e9c77949-3250-4167-85d7-fe4bb39e248a(a)o8g2000yqo.googlegroups.com>,
barncat <thebarncat(a)gmail.com> wrote:

> hi
> I am reading data from a popen call (server) and sending the data to a
> client. It works fine except funny chars are prepended to the string
> sent and displayed at the client. here is the relevant code:

I think it's because of strcat(string, buf). You never initialized
string[], so it contains garbage, and then you append buf to that.

> --
> FILE *FP;
> char string[32];
> char buf[128];
> FP = popen("lparstat -i | head -5 | tail -2","r");
> while(fgets(buf,128,FP) != NULL) {
> strcat(string,buf);
> squeeze(string); //function to remove spaces
> }
> pclose(FP);
> if (send(socket, string, strlen(string), 0) == -1)
> perror("Writing String to client");
> --
> /* function to remove spaces */
> int squeeze(char *s) {
> char *t = s;
> for(;*s;(*s != ' ') ? *t++ = *s++ : *s++)
> continue;
> *t = '\0';
> }
> --
>
> Output from client:
>
> -bash-2.05b$ ./program
> received answer to query from server:
> /�,�/�,�Type:Dedicated
> Mode:Capped
> --
>
> Thanks,
> Jim

--
Barry Margolin, barmar(a)alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Eric Sosman on
On 5/12/2010 7:31 PM, barncat wrote:
>
> i got it to "work" but probably not the correct way. any comments on
> better ways to do this are appreciated. i hope this is not too much
> cod but it does compile and returns the expected output:
> -bash-2.05b$ ./client INFO server
> Type:Dedicated
> Mode:Capped
> --------------------------
>
> server:
> #include<sys/types.h>
> #include<sys/socket.h>
> #include<netinet/in.h>
> #include<netdb.h>
> #include<time.h>
> #include<signal.h>
> #include<stdio.h>
> #include<string.h>
> #include<strings.h>
> #include<unistd.h>
> #include<fcntl.h>
> #include<stdlib.h>
> #include<errno.h>
> #include<sys/wait.h>

You have not expended much effort toward reducing your program
to a minimal example. At a cursory look, you seem to be using *nothing*
that requires <time.h>, nor <signal.h>, nor <errno.h>, nor <strings.h>
(whatever the Hell *that* is), and I'd be there are yet more superfluous
relics here, whose only purpose is to give the would-be helper more
useless junk to wade through. Okay, fine: I'll set a limit on my
wading depth, and I'll count all these extraneous lines against that
limit, and at some point I'll reach my tolerance for sludge.

> #define PORT 3490
> #define BACKLOG 5
> #define BUFLEN 1024
>
> int squeeze(char *s) {
> char *t = s;
> for(;*s;(*s != ' ') ? *t++ = *s++ : *s++)
> continue;

This is still obfuscated and ugly -- but beauty is in the
eye of the beholder, and besides: it's a side-issue.

> *t = '\0';
> }
>
> int sendInfo(int socket) {
> FILE *FP;
> char string[128];
> char buf[64];
> int len;
> bzero(string,128);

Overkill. All you actually need is `string[0] = 0;'.

> FP = popen("lparstat -i | head -5 | tail -2","r");
> while(fgets(buf,64,FP) != NULL) {
> strcat(string,buf);

Still vulnerable to buffer overflow. Each individual chunk
will fit, yes, but what if the other end sends you a hundred of
them? How do you expect to fit 6301 characters in a 128-char
array?

> squeeze(string);

Wasteful. You squeeze the first chunk, then append a second
and squeeze them both (re-squeezing the first uselessly), then
append a third and squeeze all three (re-re-squeezing the first
and re-squeezing the second), then ...

> }
> pclose(FP);
>
> len = strlen(string);
> string[len] = '\0';

Utterly pointless, utterly. How do you suppose strlen()
determines its result? By locating the '\0', that's right. So,
what character is *already* at string[len]? (Now, let's not
always see the same hands ...)

> if (send(socket, string, strlen(string) + 1, 0) == -1)
> perror("Writing String to client");

Interesting that you carefully check for send() errors but
don't bother to check for popen() problems ...

> return(1);

Interesting, too, that you always return 1. Success? Return 1.
Failure? Return 1. 1 is 1 and all alone and ever more ... oh, sorry.

>[...]

Heck with it. Sludge tolerance reached. Going no further until
some evidence of cooperation appears, or until you start paying me.

--
Eric Sosman
esosman(a)ieee-dot-org.invalid