Skip to content

Commit

Permalink
SOL - Added network check for URL, and (localurl="...")
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Lantinga committed Dec 1, 1999
1 parent e039e64 commit 51da914
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions README.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
26 changes: 24 additions & 2 deletions install.c
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -13,6 +13,7 @@
#include "detect.h"
#include "log.h"
#include "copy.h"
#include "network.h"

extern char *rpm_root;

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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];
Expand Down
8 changes: 8 additions & 0 deletions install.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down
264 changes: 264 additions & 0 deletions network.c
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 51da914

Please sign in to comment.