oskit/oskit-20020317/netdisk/main.c

256 lines
5.8 KiB
C
Executable File

/*
* Copyright (c) 1995-2001 University of Utah and the Flux Group.
* All rights reserved.
*
* This file is part of the Flux OSKit. The OSKit is free software, also known
* as "open source;" you can redistribute it and/or modify it under the terms
* of the GNU General Public License (GPL), version 2, as published by the Free
* Software Foundation (FSF). To explore alternate licensing terms, contact
* the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
*
* The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
* received a copy of the GPL along with the OSKit; see the file COPYING. If
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
*/
#include <ctype.h> /* isspace */
#include <stdlib.h> /* malloc */
#include <string.h> /* strcpy */
#include <stdio.h> /* printf */
#include <assert.h> /* assert */
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* ntohl */
#include <malloc.h> /* malloc_lmm */
#include <netdb.h>
#include <oskit/dev/dev.h>
#include <oskit/clientos.h>
#include <oskit/startup.h>
#ifdef PTHREADS
#include <oskit/threads/pthread.h>
#endif
#include "driver.h"
#include "timer.h"
#include "image.h"
#include "misc.h"
#ifdef UTAHTESTBED
static void bootinfo_ack(void);
#endif
#define CMD_LINE_LEN 512
extern char version[], build_info[];
/* Forward decls */
static void print_help(void);
static int runcommand(char *filename, char *diskname);
int
main(int argc, char *argv[])
{
char buf[BUFSIZ], input[BUFSIZ], prev_cmd[BUFSIZ];
#ifdef PTHREADS
oskit_clientos_init_pthreads();
start_clock();
start_pthreads();
#else
oskit_clientos_init();
start_clock();
#endif
printf("\n%s\n", version);
printf("%s\n", build_info);
osenv_process_lock();
start_net_devices();
start_blk_devices();
osenv_process_unlock();
start_fs_bmod();
heartbeat_init();
timer_init();
net_init();
/* Skip kernel name */
argc--;
argv++;
if (argc) {
/*
* Allow for several netdisk commands to specified.
*/
while (argc) {
if (argc < 2) {
print_help();
exit(1);
}
if (runcommand(argv[0], argv[1]))
goto bad;
argv += 2;
argc -= 2;
}
goto done;
}
/*
* Interactive mode
*/
strcpy(prev_cmd, "");
while (1) {
char *path, *disk;
showdisks();
printf("NetDisk> ");
fgets(input, BUFSIZ, stdin);
input[strlen(input) - 1] = '\0'; /* chop \n */
if (strcmp(input, "help") == 0 || strcmp(input, "?") == 0) {
print_help();
continue;
}
if (strcmp(input, "quit") == 0 || strcmp(input, "exit") == 0)
break;
if (input[0] == '\0')
continue;
if (strcmp(input, "!!") == 0) {
/* get the previous command */
strcpy(buf, prev_cmd);
} else {
/* save the command for next time round */
strcpy(prev_cmd, input);
strcpy(buf, input);
}
/*
* Input line consists of a path and a disk spec only.
*/
path = disk = buf;
while (*disk && !isspace(*disk))
disk++;
if (!*disk) {
printf("Bad command line, type \"help\" for help.\n");
continue;
}
*disk++ = NULL;
while (isspace(*disk))
disk++;
if (runcommand(path, disk))
continue;
}
done:
#ifdef UTAHTESTBED
bootinfo_ack();
#endif
bad:
net_shutdown();
timer_shutdown();
exit(0);
}
static int
runcommand(char *imagespec, char *diskname)
{
struct in_addr ip; /* ip of server host, in host order */
char *dirname; /* dir to mount */
char *filename; /* file within dir */
if (! parse_filespec(imagespec, &ip.s_addr, &dirname, &filename)) {
printf("usage: <IPaddr|host>:<path> <disk>[:part]\n");
return 1;
}
netprintf("Root server: %I, dir: %s, file: %s, disk/part %s\r\n",
ip.s_addr, dirname, filename, diskname);
if (writeimage(ip, dirname, filename, diskname))
return 1;
return 0;
}
static void
print_help(void)
{
printf("\n");
printf("%s\n", version);
printf("%s\n", build_info);
printf("\n");
printf("To copy over the disk image, tell me the disk file name and\n"
"the partition to which it should copied, in the form\n"
"\t<IPaddr|host>:<path> <partition>[:partition]\n"
"For example:\n"
"\t155.22.33.44:/home/foo/diskimage wd1"
"or\n"
"\tmyhost:/home/foo/diskimage wd1:b\n"
"The directory must be an NFS exported directory.\n"
"Hostnames are currently limited to \"marker\" and \"fast\".\n");
printf("\n");
}
#if defined(UTAHTESTBED)
#include <oskit/boot/bootwhat.h>
#include "socket.h"
/* XXX */
#define BOOTSERVER "boss.emulab.net"
static void
bootinfo_ack(void)
{
int i;
boot_info_t bootinfo;
oskit_socket_t *sock;
oskit_size_t got;
struct oskit_sockaddr sockaddr;
struct sockaddr_in *sin = (void *) &sockaddr;
/*
* Create a socket to talk to the server. Use that for
* all RPC request traffic.
*/
if (comsocket(OSKIT_AF_INET, OSKIT_SOCK_DGRAM, IPPROTO_UDP, &sock)) {
printf("bootinfo_ack: comsocket failed\n");
return;
}
/* Bind our side */
sin->sin_family = OSKIT_AF_INET;
sin->sin_addr.s_addr = htonl(INADDR_ANY);
sin->sin_port = htons(BOOTWHAT_SRCPORT);
if (oskit_socket_bind(sock, &sockaddr, sizeof(sockaddr))) {
oskit_socket_release(sock);
printf("bootinfo_ack: oskit_socket_bind failed\n");
return;
}
bootinfo.opcode = BIOPCODE_BOOTWHAT_ACK;
bootinfo.status = BISTAT_SUCCESS;
sin->sin_addr.s_addr = htonl(hostlookup(BOOTSERVER));
if (sin->sin_addr.s_addr == INADDR_ANY) {
printf("bootinfo_ack: Can not resolve %s\n", BOOTSERVER);
oskit_socket_release(sock);
return;
}
sin->sin_port = htons(BOOTWHAT_DSTPORT);
for (i = 0; i < 3; i++)
oskit_socket_sendto(sock, &bootinfo, sizeof(bootinfo), 0,
&sockaddr, sizeof(sockaddr), &got);
oskit_socket_release(sock);
}
#endif