Permalink
Browse files

SOL - Added network check for URL, and (localurl="...")

  • Loading branch information...
Sam Lantinga
Sam Lantinga committed Dec 1, 1999
1 parent e039e64 commit 51da9148b679f1c20344a544056c9be0942e1bbd
Showing with 329 additions and 3 deletions.
  1. +1 −0 CHANGES
  2. +1 −1 Makefile
  3. +3 −0 README.xml
  4. +24 −2 install.c
  5. +8 −0 install.h
  6. +264 −0 network.c
  7. +28 −0 network.h
@@ -4,6 +4,7 @@ SOL - Added license file support (eula="license.txt" option for install XML)
SOL - Added support for <script> elements in options
SOL - Added preinstall and postinstall script support
SOL - Added web browser launch support (url="http://....")
SOL - Added network check for URL, and (localurl="...")
SOL - Added -c command line option to change working directory
SOL - Added the "path" attribute to the install element
SOL - The console ui now checks for write permissions on install path
@@ -19,7 +19,7 @@ endif
CFLAGS += $(OPTIMIZE) $(HEADERS) $(OPTIONS)
OBJS = main.o install.o detect.o copy.o file.o log.o install_log.o
OBJS = main.o install.o detect.o copy.o file.o network.o log.o install_log.o
CONSOLE_OBJS = $(OBJS) console_ui.o
GUI_OBJS = $(OBJS) gtk_ui.o
@@ -52,6 +52,9 @@ There are several optional attributes of the install element:
the web site in a new netscape window, then falls back to
using lynx if that fails for some reason.
localurl This is the local HTML file that is loaded if the network
is down, or the web site cannot be reached.
The OPTION element:
@@ -1,4 +1,4 @@
/* $Id: install.c,v 1.22 1999-12-01 15:57:26 hercules Exp $ */
/* $Id: install.c,v 1.23 1999-12-01 20:40:25 hercules Exp $ */
#include <sys/types.h>
#include <sys/stat.h>
@@ -13,6 +13,7 @@
#include "detect.h"
#include "log.h"
#include "copy.h"
#include "network.h"
extern char *rpm_root;
@@ -47,6 +48,10 @@ const char *GetProductURL(install_info *info)
{
return xmlGetProp(info->config->root, "url");
}
const char *GetLocalURL(install_info *info)
{
return xmlGetProp(info->config->root, "localurl");
}
const char *GetPreInstall(install_info *info)
{
return xmlGetProp(info->config->root, "preinstall");
@@ -109,6 +114,13 @@ install_info *create_install(const char *configfile, int log_level)
GetProductName(info));
strcpy(info->symlinks_path, DEFAULT_SYMLINKS);
/* Start a network lookup for any URL */
if ( GetProductURL(info) ) {
info->lookup = open_lookup(info, GetProductURL(info));
} else {
info->lookup = NULL;
}
/* That was easy.. :) */
return(info);
}
@@ -328,6 +340,9 @@ void delete_install(install_info *info)
free(elem->path);
free(elem);
}
if ( info->lookup ) {
close_lookup(info->lookup);
}
if ( info->log ) {
destroy_log(info->log);
}
@@ -483,7 +498,14 @@ int launch_browser(install_info *info)
const char *url;
int retval;
url = GetProductURL(info);
url = NULL;
if ( info->lookup ) {
if ( poll_lookup(info->lookup) ) {
url = GetProductURL(info);
} else {
url = GetLocalURL(info);
}
}
retval = 0;
if ( url ) {
char command[4096];
@@ -5,6 +5,7 @@
#include <limits.h>
#include <gnome-xml/parser.h>
/* Conversion macro for bytes to megabytes */
#define BYTES2MB(bytes) ((bytes/(1024*1024))+1)
@@ -40,6 +41,9 @@ typedef enum {
/* Forward declaration (used by UI) */
struct UI_data;
/* Forward declaration */
typedef struct _URLlookup URLlookup;
/* Forward declaration */
typedef struct _install_log install_log;
@@ -118,6 +122,9 @@ typedef struct {
/* Arguments to the game when launching it */
const char *args;
/* URL lookup handle */
URLlookup *lookup;
/* Unspecified UI data */
struct UI_data *uidata;
@@ -130,6 +137,7 @@ extern const char *GetProductDesc(install_info *info);
extern const char *GetProductVersion(install_info *info);
extern const char *GetProductEULA(install_info *info);
extern const char *GetProductURL(install_info *info);
extern const char *GetLocalURL(install_info *info);
extern const char *GetPreInstall(install_info *info);
extern const char *GetPostInstall(install_info *info);
extern const char *GetRuntimeArgs(install_info *info);
264 network.c
@@ -0,0 +1,264 @@
/* Network functions for the Loki Setup program */
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#ifndef TEST_MAIN
#include "install.h"
#include "install_log.h"
#endif
#include "network.h"
/* This is the structure we pass back as a lookup handle */
struct _URLlookup {
int pid;
int fd;
};
/* Utility function to connect to a URL and return a status */
int connect_url(const char *url)
{
char *proto;
char *host;
char *string;
char *bufp;
int sock;
struct sockaddr_in socka;
short portnum;
/* Copy the string */
string = strdup(url);
/* Check for protocol and set default ports */
proto = NULL;
bufp = strstr(string, "://");
portnum = 0;
if ( bufp ) {
proto = string;
*bufp = '\0';
string = bufp+3;
if ( strcasecmp(proto, "ftp") == 0 ) {
portnum = 21;
}
}
/* We can always read files ... */
if ( (string[0] == '/') ||
(proto && (strcasecmp(proto, "file") == 0)) ) {
return(0);
}
/* Strip the file part of the URL */
bufp = strchr(string, '/');
if ( bufp ) {
*bufp = '\0';
}
/* Extract any port number */
bufp = strchr(string, ':');
if ( bufp ) {
*bufp++ = '\0';
portnum = atoi(bufp);
}
if ( portnum == 0 ) {
portnum = 80;
}
/* The rest of the string should be the hostname - resolve it */
host = string;
#ifdef TEST_MAIN
printf("Resolving %s port %d\n", host, portnum);
#endif
socka.sin_addr.s_addr = inet_addr(host);
if ( socka.sin_addr.s_addr == INADDR_NONE ) {
struct hostent *hp;
hp = gethostbyname(host);
if ( hp ) {
memcpy(&socka.sin_addr.s_addr,hp->h_addr,hp->h_length);
} else {
#ifdef TEST_MAIN
printf("Resolving failed!\n");
#endif
return(-1);
}
}
socka.sin_port = htons(portnum);
socka.sin_family = AF_INET;
/* Now try to create a socket and connect */
#ifdef TEST_MAIN
printf("Connecting to remote host\n");
#endif
sock = socket(AF_INET, SOCK_STREAM, 0);
if ( sock < 0 ) {
return(-1);
}
if ( connect(sock, (struct sockaddr *)&socka, sizeof(socka)) < 0 ) {
#ifdef TEST_MAIN
printf("Connect failed!\n");
#endif
return(-1);
}
close(sock);
/* Hey, we successfully connected! */
#ifdef TEST_MAIN
printf("Connect succeeded!\n");
#endif
return(0);
}
/* This does a non-blocking network check of a URL
It returns a socket file descriptor which is passed to wait_network(),
or -1 if an error occurred while setting up the network check.
*/
#ifdef TEST_MAIN
URLlookup *open_lookup(const char *url)
#else
URLlookup *open_lookup(install_info *info, const char *url)
#endif
{
URLlookup *lookup;
int pipe_fds[2];
/* Allocate a network lookup handle */
lookup = (URLlookup *)malloc(sizeof *lookup);
if ( lookup == NULL ) {
#ifdef TEST_MAIN
fprintf(stderr, "Out of memory, no network check\n");
#else
log_warning(info, "Out of memory, no network check");
#endif
return(NULL);
}
/* Create a pipe for IPC */
if ( pipe(pipe_fds) < 0 ) {
#ifdef TEST_MAIN
fprintf(stderr, "Unable to create pipe, no network check\n");
#else
log_warning(info, "Unable to create pipe, no network check");
#endif
free(lookup);
return(NULL);
}
lookup->fd = pipe_fds[0];
/* Fork and do a lookup and connect */
lookup->pid = fork();
switch (lookup->pid) {
case -1: /* Error... */
#ifdef TEST_MAIN
fprintf(stderr, "Fork failed, no network check\n");
#else
log_warning(info, "Fork failed, no network check");
#endif
close(pipe_fds[0]);
close(pipe_fds[1]);
lookup->fd = -1;
break;
case 0: /* Child, do lookup and connect */
close(pipe_fds[0]);
if ( connect_url(url) < 0 ) {
write(pipe_fds[1], "n", 1);
} else {
write(pipe_fds[1], "y", 1);
}
exit(0);
default: /* Parent, return okay */
close(pipe_fds[1]);
break;
}
if ( lookup->fd < 0 ) {
free(lookup);
lookup = NULL;
}
return lookup;
}
/* This checks the status of a URL lookup */
int poll_lookup(URLlookup *handle)
{
char response;
fd_set fdset;
struct timeval tv;
int ready;
int status;
/* Check to see if the child process is ready */
FD_ZERO(&fdset);
FD_SET(handle->fd, &fdset);
memset(&tv, 0, (sizeof tv));
if ( select(handle->fd+1, &fdset, NULL, NULL, &tv) == 1 ) {
ready = 1;
} else {
ready = 0;
}
#ifdef TEST_MAIN
printf("URL check is %s\n", ready ? "ready" : "not ready");
#endif
status = 0;
/* See whether the lookup has succeeded */
if ( ready ) {
if ( read(handle->fd, &response, 1) == 1 ) {
if ( response == 'y' ) {
status = 1;
}
}
}
return status;
}
/* This closes a previously opened URL lookup */
void close_lookup(URLlookup *handle)
{
close(handle->fd);
kill(handle->pid, SIGTERM);
wait(NULL);
free(handle);
}
#ifdef TEST_MAIN
int main(int argc, char *argv[])
{
URLlookup *lookup;
if ( argc != 3 ) {
fprintf(stderr, "Usage: %s <delay> <url>\n", argv[0]);
exit(1);
}
lookup = open_lookup(argv[2]);
if ( lookup == NULL ) {
fprintf(stderr, "Couldn't set up network check\n");
exit(2);
}
sleep(atoi(argv[1]));
printf("Checking URL... \n");
if ( poll_lookup(lookup) ) {
printf("URL okay\n");
} else {
printf("URL not okay\n");
}
close_lookup(lookup);
exit(0);
}
#endif
Oops, something went wrong.

0 comments on commit 51da914

Please sign in to comment.