mirror of https://github.com/dzavalishin/oskit/
256 lines
5.8 KiB
C
Executable File
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
|