Init
This commit is contained in:
460
usr.etc/admin/sysIDtool.c
Normal file
460
usr.etc/admin/sysIDtool.c
Normal file
@@ -0,0 +1,460 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)sysIDtool.c 1.1 94/10/31 SMI";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* sysIDtool - semi-automatic installation tool for diskful desktop systems.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "admin_amcl.h"
|
||||
#include "sys_param_names.h"
|
||||
#include "admin_messages.h"
|
||||
|
||||
#define TIMEZONE_MAP_NAME "timezone.byname"
|
||||
#define UNCONFIGURED "/etc/.UNCONFIGURED"
|
||||
#define YPBIND "/usr/etc/ypbind"
|
||||
#define IFCONFIG "/usr/etc/ifconfig -au netmask + broadcast + >/dev/null 2>&1"
|
||||
#define TIMEHOST "timehost"
|
||||
#define RETURN_KEY '\n'
|
||||
#define ESC_KEY '\033'
|
||||
#define INPUT_CHAR 0
|
||||
#define INPUT_LINE 1
|
||||
|
||||
extern int gethostname();
|
||||
extern char *inet_ntoa();
|
||||
extern int admin_add_argp();
|
||||
extern void admin_write_err();
|
||||
extern char *admin_make_errbuf();
|
||||
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
|
||||
static void fail_dialog();
|
||||
static void kill_ypbind();
|
||||
static void save_modes();
|
||||
static void restore_modes();
|
||||
static void canon_input();
|
||||
static void get_input();
|
||||
static void admin_perror();
|
||||
|
||||
static struct termios ttyb;
|
||||
static unsigned long flags;
|
||||
static char min_chars; /* VMIN control character */
|
||||
static char time; /* VTIME control character */
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
Admin_arg *argp; /* Argument list for admin methods */
|
||||
char hostname[MAXHOSTNAMELEN]; /* Hostname to configure */
|
||||
char domain[MAXDOMAINLEN]; /* Domain to configure */
|
||||
struct ifreq ifr; /* ioctl interface request struct */
|
||||
char ether_name[10]; /* name of ethernet interface */
|
||||
int s; /* socket for ioctl */
|
||||
int i; /* counter while waiting for ypbind */
|
||||
int status; /* status from various calls */
|
||||
char *tzdata; /* timezone entry from map */
|
||||
int timezonelen;
|
||||
char timezone[MAXPATHLEN]; /* timezone name */
|
||||
char *ipaddr; /* ip address to configure */
|
||||
struct sockaddr_in *sinp;
|
||||
char *outbuf; /* Pointer to stdout buf from amcl */
|
||||
char *errbuf; /* Pointer to stderr buf from amcl */
|
||||
char *msgbuf; /* Error message buffer */
|
||||
char tmpbuf[4096]; /* Temp msg buffer */
|
||||
int ypbind_pid;
|
||||
|
||||
/*
|
||||
* Retrieve name of first ethernet interface, make sure it's up,
|
||||
* which means ifconfig with rarp worked, then get address.
|
||||
*/
|
||||
if (get_ether0name(ether_name, sizeof(ether_name)) == -1) {
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS,
|
||||
SYS_ERR_NO_ETHER0);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
sprintf(ifr.ifr_name, "%s0", ether_name);
|
||||
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
|
||||
admin_perror(tmpbuf, "ioctl");
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS, tmpbuf);
|
||||
fail_dialog(msgbuf);
|
||||
} else if (!(ifr.ifr_flags & IFF_UP)) {
|
||||
fail_dialog(IP_FAIL_REASONS);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Parameters for system as determined by sysIDtool\n");
|
||||
#endif
|
||||
sprintf(ifr.ifr_name, "%s0", ether_name);
|
||||
if (ioctl(s, SIOCGIFADDR, &ifr) == -1) {
|
||||
admin_perror(tmpbuf, "ioctl");
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS, tmpbuf);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
(void) close(s);
|
||||
sinp = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||
ipaddr = inet_ntoa(sinp->sin_addr);
|
||||
#ifdef DEBUG
|
||||
printf("\tIP addr is %s\n", ipaddr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get hostname, NIS domain. These are set in the kernel by
|
||||
* hostconfig which is called from rc.boot.
|
||||
*/
|
||||
if (gethostname(hostname, sizeof(hostname)) == -1) {
|
||||
admin_perror(tmpbuf, "gethostname");
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS, tmpbuf);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("\tHostname is %s\n", hostname);
|
||||
#endif
|
||||
if (strlen(hostname) == 0)
|
||||
fail_dialog(HOSTNAME_FAIL_REASONS);
|
||||
|
||||
if (getdomainname(domain, sizeof(domain)) == -1) {
|
||||
admin_perror(tmpbuf, "getdomainname");
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS, tmpbuf);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("\tdomain is %s\n", domain);
|
||||
#endif
|
||||
if (strlen(domain) == 0)
|
||||
fail_dialog(DOMAINNAME_FAIL_REASONS);
|
||||
|
||||
/*
|
||||
* Start ypbind for the purposes of sysIDtool.
|
||||
* We'll later kill this and let it start through normal
|
||||
* channels (i.e. rc.local)
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("starting ypbind\n");
|
||||
#endif DEBUG
|
||||
switch(ypbind_pid = fork()) {
|
||||
|
||||
case -1:
|
||||
admin_make_errbuf(&msgbuf, "sysIDtool: %s", SYS_ERR_YPBIND);
|
||||
fail_dialog(msgbuf);
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* This is the child - starts ypbind
|
||||
*/
|
||||
if(system(YPBIND) != 0) {
|
||||
admin_write_err(SYS_ERR_YPBIND);
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("parent: ypbind_pid = %d\n",ypbind_pid);
|
||||
#endif DEBUG
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait a bit for the ypbind to start and then
|
||||
* do an NIS call to force the binding
|
||||
*/
|
||||
for (i = 0; i < 20; i++) {
|
||||
sleep(1);
|
||||
if ((status = yp_master(domain, TIMEZONE_MAP_NAME,
|
||||
&tzdata)) == 0)
|
||||
break;
|
||||
else if (status == YPERR_YPBIND) {
|
||||
#ifdef DEBUG
|
||||
printf("waiting for ypbind\n");
|
||||
#endif DEBUG
|
||||
continue;
|
||||
} else if (status == YPERR_MAP) {
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(TIMEZONE_MAP_REASON);
|
||||
} else if (status != 0) {
|
||||
admin_make_errbuf(&msgbuf, "yp_master: %s.\n",
|
||||
yperr_string(status));
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
}
|
||||
|
||||
if ( i >= 20 && status != 0 ) {
|
||||
/*
|
||||
* the ypbind never worked, for some reason...
|
||||
*/
|
||||
admin_make_errbuf(&msgbuf, TIMEZONE_FAIL_REASONS,
|
||||
yperr_string(status));
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Retrieve timezone name for our system from NIS map created for
|
||||
* just this purpose. Look first for entry for our system, if none
|
||||
* found then look for a domain-wide entry.
|
||||
*/
|
||||
if ((status = yp_match(domain, TIMEZONE_MAP_NAME, hostname,
|
||||
strlen(hostname), &tzdata, &timezonelen)) == YPERR_KEY) {
|
||||
if ((status = yp_match(domain, TIMEZONE_MAP_NAME, domain,
|
||||
strlen(domain), &tzdata, &timezonelen)) == YPERR_KEY) {
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(TIMEZONE_KEY_REASON);
|
||||
}
|
||||
}
|
||||
if (status != 0) {
|
||||
admin_make_errbuf(&msgbuf, TIMEZONE_FAIL_REASONS,
|
||||
yperr_string(status));
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
|
||||
sscanf(tzdata, "%s %*s", timezone);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("\ttimezone is %s\n", timezone);
|
||||
#endif
|
||||
/*
|
||||
* Do an ifconfig of netmask so if 'timehost' is on another (sub)net
|
||||
* we can reach it with 'rdate'.
|
||||
*/
|
||||
if (system(IFCONFIG) != 0) {
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS,
|
||||
SYS_ERR_IFCONFIG);
|
||||
fail_dialog(msgbuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Now build the argument list for the method invocation
|
||||
*/
|
||||
argp = NULL;
|
||||
(void) admin_add_argp(&argp, HOSTNAME_PARAM, ADMIN_STRING,
|
||||
strlen(hostname), hostname);
|
||||
(void) admin_add_argp(&argp, DOMAIN_PARAM, ADMIN_STRING,
|
||||
strlen(domain), domain);
|
||||
(void) admin_add_argp(&argp, IPADDR_PARAM, ADMIN_STRING,
|
||||
strlen(ipaddr), ipaddr);
|
||||
(void) admin_add_argp(&argp, TIMEZONE_PARAM, ADMIN_STRING,
|
||||
strlen(timezone), timezone);
|
||||
(void) admin_add_argp(&argp, TIMESERVER_PARAM, ADMIN_STRING,
|
||||
strlen(TIMEHOST), TIMEHOST);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Attempting system add method\n");
|
||||
#endif
|
||||
if ((status =
|
||||
admin_perf_method(SYSTEM_CLASS_PARAM, SYS_ADD_METHOD,
|
||||
ADMIN_LOCAL, NULL, argp, &outbuf, &errbuf, ADMIN_END_OPTIONS)) !=
|
||||
SUCCESS) {
|
||||
admin_make_errbuf(&msgbuf, SETUP_FAIL_REASONS, errbuf);
|
||||
kill_ypbind(ypbind_pid);
|
||||
fail_dialog(msgbuf);
|
||||
} else if ((unlink(UNCONFIGURED) != 0) && (errno != ENOENT)) {
|
||||
perror("unlink");
|
||||
admin_write_err(SYS_ERR_PLS_RM, UNCONFIGURED);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(outbuf);
|
||||
printf("status = %d\n",status);
|
||||
#endif
|
||||
kill_ypbind(ypbind_pid);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void kill_ypbind(child_pid)
|
||||
int child_pid;
|
||||
{
|
||||
char pid[20];
|
||||
char line[MAXPATHLEN];
|
||||
char program[MAXPATHLEN];
|
||||
FILE *fp, *popen();
|
||||
|
||||
/*
|
||||
* Find the process ID of ypbind. Note, we have to do it
|
||||
* this way because ypbind forks a child to do the real
|
||||
* work and we have no way to get the child's pid
|
||||
*/
|
||||
if((fp = popen("ps ax","r")) == NULL ) {
|
||||
}
|
||||
|
||||
while(fgets(line,MAXPATHLEN,fp) != NULL) {
|
||||
|
||||
/* The STAT could be different, so scan this line twice */
|
||||
sscanf(line,"%s %*s %*s %*s %s %*s %*s %*s",pid,program);
|
||||
|
||||
if(!strcmp(program,YPBIND)) {
|
||||
#ifdef DEBUG
|
||||
printf("found ypbind - killing %s!\n",pid);
|
||||
#endif DEBUG
|
||||
kill(atoi(pid),SIGKILL);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
||||
sscanf(line,"%s %*s %*s %*s %*s %s %*s %*s %*s",pid,program);
|
||||
if(!strcmp(program,YPBIND)) {
|
||||
#ifdef DEBUG
|
||||
printf("found ypbind - killing %s!\n",pid);
|
||||
#endif DEBUG
|
||||
kill(atoi(pid),SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Also kill the child that exec-ed ypbind - if it's still around
|
||||
*/
|
||||
kill(child_pid,SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
* fail_dialog(msgbuf) - Walk user through failure reasons & possible courses
|
||||
* action. Never returns, we either exit or halt the system, user's choice.
|
||||
*/
|
||||
static void fail_dialog(msgbuf)
|
||||
char *msgbuf;
|
||||
{
|
||||
char ib[80];
|
||||
|
||||
save_modes(0);
|
||||
canon_input(0);
|
||||
disp_menu:
|
||||
printf(FAIL_MENU);
|
||||
fflush(stdout);
|
||||
for (;;) {
|
||||
printf(ENTER_CHOICE);
|
||||
fflush(stdout);
|
||||
get_input(INPUT_LINE, ib);
|
||||
switch (ib[0]) {
|
||||
case '1':
|
||||
printf(msgbuf);
|
||||
fflush(stdout);
|
||||
get_input(INPUT_CHAR);
|
||||
goto disp_menu;
|
||||
case '2':
|
||||
printf(MANUAL_INTRO);
|
||||
fflush(stdout);
|
||||
for (;;) {
|
||||
get_input(INPUT_CHAR, ib);
|
||||
if (ib[0] == RETURN_KEY) {
|
||||
restore_modes(0);
|
||||
exit(1);
|
||||
} else if (ib[0] == ESC_KEY)
|
||||
goto disp_menu;
|
||||
else
|
||||
printf(BAD_CHOICE_2);
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
restore_modes(0);
|
||||
printf(HALTING_MESSAGE);
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
reboot(RB_HALT);
|
||||
default:
|
||||
printf(BAD_CHOICE);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_input(key, buf) - Get input from user, either a single key or a complete
|
||||
* line depending on the value of 'key'. Input is returned in 'buf'. In line
|
||||
* input mode, we ignore whitespace so that the caller is guaranteed that the
|
||||
* significant input is at the beginning of the buffer.
|
||||
*/
|
||||
static void get_input(key, buf)
|
||||
int key;
|
||||
char *buf;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
cp = buf;
|
||||
for (;;) {
|
||||
(void) read(0, cp, 1);
|
||||
if (key == INPUT_CHAR)
|
||||
return;
|
||||
else if (*cp == RETURN_KEY)
|
||||
return;
|
||||
else if (isspace(*cp))
|
||||
continue;
|
||||
else
|
||||
++cp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine turns off canonical mode so that characters
|
||||
* can be received as typed
|
||||
*/
|
||||
static void canon_input(file_des)
|
||||
int file_des;
|
||||
{
|
||||
|
||||
ttyb.c_lflag &= ~ICANON;
|
||||
ttyb.c_cc[VMIN] = 1;
|
||||
ttyb.c_cc[VTIME] = 0;
|
||||
(void) ioctl(file_des, TCSETSF, &ttyb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the terminal modes in the static storage
|
||||
*/
|
||||
static void save_modes(file_des)
|
||||
int file_des;
|
||||
{
|
||||
|
||||
/* Save current terminal modes */
|
||||
(void) ioctl(file_des, TCGETS, &ttyb);
|
||||
flags = ttyb.c_lflag;
|
||||
min_chars = ttyb.c_cc[VMIN];
|
||||
time = ttyb.c_cc[VTIME];
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore terminal modes from values saved in static storage
|
||||
*/
|
||||
static void restore_modes(file_des)
|
||||
int file_des;
|
||||
{
|
||||
ttyb.c_lflag = flags;
|
||||
ttyb.c_cc[VMIN] = min_chars;
|
||||
ttyb.c_cc[VTIME] = time;
|
||||
(void) ioctl(file_des, TCSETSW, &ttyb);
|
||||
}
|
||||
|
||||
|
||||
static void admin_perror(buf, name)
|
||||
char *buf;
|
||||
char *name;
|
||||
{
|
||||
|
||||
if (errno > sys_nerr)
|
||||
sprintf(buf, "%s: Error code %d\n", name, errno);
|
||||
else
|
||||
sprintf(buf, "%s: %s\n", name, sys_errlist[errno]);
|
||||
}
|
||||
Reference in New Issue
Block a user