Xinu7/contrib/distodt/src/download.c
/*
* download.c - version 1 - copies a.out file to backend mach
*
* Author: Jim Griffioen
* Dept. of Computer Sciences
* Purdue University
* Date: Wed Mar 2 11:08:01 1988
*
* Copyright (c) 1988 Jim Griffioen
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sgtty.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <setjmp.h>
#include <errno.h>
#include "../h/utils.h"
#include "../h/bed.h"
#include "../h/bmutils.h"
#include "../h/netutils.h"
#include "../h/downloadd.h"
extern char *getlogin(); /* get user id */
jmp_buf env; /* used to return from read time-outs */
int errno; /* error number when system err */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
typedef int Bool;
#endif
/*
*---------------------------------------------------------------------------
* main (csb, rgsb)
*---------------------------------------------------------------------------
*/
main (csb, rgsb)
int csb;
char *rgsb[];
{
int i;
int sock;
struct bm bm;
int fdTcp;
int len;
char *sb;
int remoteport;
char class[16]; /* class of machine desired */
char femachine[MAXMACHINENAME]; /* front end machine to use */
char bemachine[MAXMACHINENAME]; /* back end machine to use */
char filename[256]; /* file to download */
struct genericreq *dnreq; /* download request struct */
char unspecifiedclass; /* user specified class? */
if (csb > 4) {
fprintf(stderr, "usage: download [-cCLASS] [-mBACKENDMACHINE] file\n");
exit(1);
}
strcpy(class, DEFAULTCLASS);
strcpy(femachine, "");
strcpy(bemachine, "");
unspecifiedclass = TRUE;
for (i = 1; i < csb; i++) {
if (strncmp(rgsb[i], "-c", 2) == 0) {
strcpy(class, (char *) (rgsb[i]+2));
unspecifiedclass = FALSE;
}
else if (strncmp(rgsb[i], "-m", 2) == 0) {
strcpy(bemachine, (char *) (rgsb[i]+2));
}
else if (i != (csb-1)) {
fprintf(stderr,"unexpected arguement '%s'\n", rgsb[i]);
exit(1);
}
}
if (obtainlock(class,femachine,bemachine,unspecifiedclass) != SYSOK) {
if (strlen(bemachine) > 0)
fprintf(stderr, "machine %s is unavailable\n", bemachine);
else if (strlen(class) > 0)
fprintf(stderr, "no machines in class %s available\n",
class);
exit(1);
}
printf("using front end '%s': Using backend '%s'\n",
femachine, bemachine);
bm.ver = CURVER;
sprintf(bm.cmd, "%d", REQ_DNLD_CONNECT);
dnreq = (struct genericreq *) bm.detail;
sb = getlogin();
strcpy(dnreq->uid, sb);
if (gethostname(dnreq->hostid, MAXMACHINENAME) != 0) {
strcpy(dnreq->hostid, "dunno");
fprintf(stderr, "error getting local host name\n");
}
strcpy(dnreq->bename, bemachine);
sock = ConnectUdp (femachine, KNOWN_UDP_PORT);
if (bmsend (sock, &bm, lbm, 0) <= 0) {
fprintf(stderr,"error sending connection request\n");
exit(1);
}
len = bmrecv (sock, &bm, lbm, 0);
if (len<=0) {
fprintf(stderr, "receive error: trying to establish a connection\n");
exit(1);
}
if (atoi(bm.cmd) != RESP_OK) {
fprintf(stderr, "recv(): bad response (%s) from daemon: '%s'\n",bm.cmd,bm.detail);
exit(1);
}
/* get the TCP port to use */
remoteport = atoi(bm.detail);
fdTcp = ConnectTcp(femachine, remoteport);
if ((*(rgsb[csb-1]) == '-') || (csb == 1)) {
strcpy(filename, "a.out");
}
else {
strcpy(filename, rgsb[csb-1]);
}
printf("downloading file: %s\n", filename);
download(fdTcp, filename);
printf("download completeted\n");
exit(0);
}
/*
*---------------------------------------------------------------------------
* download
* this routine sends the a.out file to the front end machine so that
* it can store it in /tftpboot/a.out for the backend machine to boot
* with
*---------------------------------------------------------------------------
*/
download(fdTcp, aoutfile)
int fdTcp;
char *aoutfile;
{
int fdaout; /* file descriptor of a.out file */
char buff[BIGBUFSIZE]; /* big buffer to read into and out of */
char sblen[SMALLSTR]; /* string form of length */
struct stat statbuf; /* file status structure */
long aoutsize; /* size of a.out file */
int packetnum; /* number of packets sent */
long bytessent; /* number of bytes sent */
if ((fdaout=open(aoutfile, O_RDONLY, 0400)) < 0) {
fprintf(stderr, "error opening file %s\n", aoutfile);
exit(1);
}
/* Get name of the machine you are using */
if (sockgetstr(fdTcp, buff, STIMEOUT) == NULL) {
fprintf(stderr, "Error reading machine name during downloading");
exit(1);
}
if (fstat(fdaout,&statbuf) != 0) {
fprintf(stderr, "error finding status info about %s\n", aoutfile);
exit(1);
}
aoutsize = (long) statbuf.st_size;
sprintf(sblen,"%ld", (long) aoutsize);
if (write(fdTcp, sblen, strlen(sblen)+1) != (strlen(sblen)+1)) {
fprintf(stderr, "error writing file len to front end machine\n");
exit(1);
}
bytessent = 0;
packetnum = 1;
while (aoutsize > sizeof(buff)) {
if (read(fdaout, buff, sizeof(buff)) != sizeof(buff)) {
fprintf(stderr, "error read from %s\n", aoutfile);
exit(1);
}
if (write(fdTcp, buff, sizeof(buff)) != sizeof(buff)) {
fprintf(stderr, "error writing to front end\n");
exit(1);
}
packetnum++;
bytessent += sizeof(buff);
aoutsize -= sizeof(buff);
printf("Sent %ldk bytes\r", bytessent/1000);
}
if (read(fdaout, buff, aoutsize) != aoutsize) {
fprintf(stderr, "error read from %s\n", aoutfile);
exit(1);
}
if (write(fdTcp, buff, aoutsize) != aoutsize) {
fprintf(stderr, "error writing to front end\n");
exit(1);
}
bytessent += aoutsize;
printf("Sent %ldk bytes\n", bytessent/1000);
close(fdTcp);
close(fdaout);
}
/*
*---------------------------------------------------------------------------
* sockgetstr(sock, str, timeout) - get str from tcp socket-ret NULL if error
*---------------------------------------------------------------------------
*/
char *sockgetstr(sock, str, timeout)
int sock; /* socket descriptor handle */
char *str;
int timeout;
{
char *sb;
settimer(timeout);
if (setjmp(env) == EINTR) {
canceltimer();
return(NULL);
}
sb = str;
if (recv(sock, sb, 1, 0) < 1) {
canceltimer();
return(NULL);
}
while (*sb++ != '\0') {
if (recv(sock, sb, 1, 0) <1) {
canceltimer();
return(NULL);
}
}
canceltimer();
return(str);
}