/* * IvyDaemon, an Ivy gateway for short-lived agents * * Copyright (C) 1999 * Centre d'Études de la Navigation Aérienne * * Main file for the client ivyecho * * Author(s): Stephane Chatty * from code by Patrick Amar * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software * */ #include #include #include #include #include #include #include #include #include #include #include #include "ivyd.h" const char* const servicename = "ivyd"; const char* const port_env_variable = "INIVYD_PORT"; const int default_port = DEFAULT_INIVYD_PORT; int debug = 0; void Usage (const char* progname) { fprintf (stderr, "Usage: %s [-b bus (ignored)][-s server] text\n", progname); exit (1); } /* Get in touch with super-server and retrieve server's port number */ int GetPort (long addr) { struct servent *serv; u_short serv_port; struct sockaddr_in sin; struct connmsg msg; int sock; int len; /* get service port number */ serv = getservbyname (servicename, 0); if (! serv) { char *pp = getenv (port_env_variable); serv_port = htons (pp ? atoi (pp) : default_port); if (serv_port <= 0) exit (0); } else serv_port = serv -> s_port; /* create and bind socket */ sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock == -1) { perror ("Can't create socket: "); return 0; } memset (&sin, 0, sizeof sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; if (-1 == bind (sock, &sin, sizeof sin)) { perror ("Can't bind socket: "); goto failed; } sin.sin_port = serv_port; sin.sin_addr.s_addr = addr; /* build request */ msg.msg_uid = getuid (); msg.msg_port = 0; msg.msg_type = MSG_CLIENT; /* send it */ if (-1 == sendto (sock, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&sin, sizeof sin)) { perror ("Can't send on socket: "); goto failed; } /* wait for reply */ len = sizeof sin; if (-1 == recvfrom (sock, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&sin, &len)) { perror ("Can't receive on socket: "); goto failed; } /* OK, we're done, return reply */ (void) close (sock); return (int) msg.msg_port; failed: (void) close (sock); return 0; } int ServerOpen (const char *host) { int sock; static struct sockaddr_in addr; struct hostent *hp; /* determine host name and address */ if (!host) host = getenv ("IVYD"); if (!host) host = "localhost"; hp = gethostbyname (host); if (hp == 0) { fprintf (stderr, "Unknown host %s\n", host); return 0; } /* create socket */ sock = socket (AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror ("Can't create socket: "); return 0; } /* build address from host addr, asking port number to super-server */ memcpy (&addr.sin_addr, hp->h_addr, hp->h_length); addr.sin_family = AF_INET; addr.sin_port = GetPort (addr.sin_addr.s_addr); if (! addr.sin_port) return 0; /* connect socket on address */ if (connect (sock, &addr, sizeof (addr)) < 0) { perror ("Can't connect socket: "); return 0; } return sock; } int SendMsg (int sock, const char* s) { request req; /* build request */ strcpy (req.buffer, s); /* send request */ /* we should handle return value more finely */ if (write (sock, &req, sizeof (request)) != sizeof (request)) { fprintf (stderr, "Unable to write %d bytes: ", sizeof (request)); perror (""); } #if 0 answer ans; register char *p = (char *) &ans; register int n, l; /* retrieve answer (useless) */ for (n = sizeof (answer); n > 0; p += l) { n -= (l = read (sock, p, n)); if (l <= 0) { perror ("Error retrieving answer from server: "); return 0; } } return ans.ok; #endif return 1; } void HandleArgs (int sock, int index, int argc, char** argv) { char buf [BUFSIZE]; int space = 0; int nbchars = 0; /* slice arguments into buffer */ buf [0] = '\0'; while (index < argc) { const char* p = argv[index++]; int l = strlen (p); /* while we have pending chars for this arg... */ while (l + space > 0) { /* first try and fit space if needed */ if (space) { if (nbchars + space <= BUFSIZE - 1) { strcat (buf, " "); nbchars += space; space = 0; } else { goto bufferfull; } } /* then look if we can fit all the chars we have */ if (nbchars + l <= BUFSIZE - 1) { /* if yes, go ahead */ strcat (buf, p); nbchars += l; /* we'll need to insert space if there are other args */ space = 1; /* but let's make sure we don't keep looping */ l = -1; /* if buffer is full, handle it */ if (nbchars == BUFSIZE - 1) goto bufferfull; /* otherwise, we're done anyway */ else continue; /* if not enough room, first fit what we can */ } else { int fitting = (BUFSIZE - 1) - nbchars; if (fitting > 0) { strncat (buf, p, fitting); nbchars += fitting; l -= fitting; p += fitting; } } bufferfull: /* now we have a full buffer */ /* send it */ if (debug) printf ("Sending [%s]\n", buf); SendMsg (sock, buf); /* and prepare for next round */ nbchars = 0; buf [0] = '\0'; } } if (nbchars > 0) { if (debug) printf ("Sending [%s]\n", buf); SendMsg (sock, buf); } } /* * Demande un numero de port au super-serveur de la machine addr */ int main (int argc, char** argv) { char busbuf [128]; const char* bus = 0; char serverhostbuf [128]; const char* serverhost = 0; const struct option options [] = { {"bus", required_argument, 0, 'b'}, {"debug", no_argument, 0, 'd'}, {"server", required_argument, 0, 's'}, {0, 0, 0, 0} }; char c; int servfd; #if 0 if (strlen (argv0) >= 4 && !strcmp (argv0+strlen (argv0)-4, "wait")) wflag = 1; #endif /* handle options */ while ((c = getopt_long (argc, argv, "+b:s:d", options, 0)) != EOF) { switch (c) { case 'b': strcpy (busbuf, optarg) ; bus = busbuf; break; case 's': strcpy (serverhostbuf, optarg) ; serverhost = serverhostbuf; break; case 'd': debug = 1; break; } } /* Se connecter au serveur. */ servfd = ServerOpen (serverhost); if (!servfd) { fprintf (stderr, "No server.\n"); return 0; } HandleArgs (servfd, optind, argc, argv); return 1; }