Скачиваний:
16
Добавлен:
01.05.2014
Размер:
4.38 Кб
Скачать
#include <iostream.h>
#include <fstream.h>
#include <strstream.h>
#include <stdio.h>
#include <netdir.h>
#include <rpc/rpc.h>
#include <string.h>
#include "mshell.h"
#include <thread.h>
#include "RPC.h"

#define MAXHOSTS   30
#define TMPFILE    "/tmp/hosts"

static char  *hostlist[MAXHOSTS];
static int   numhosts;
extern rwlock_t    rwlck;

int exec_host( const char* cmd, char* host )
{
    static int    res=0;
    RPC_cls cl( host, SHELLPROG, SHELLVER, "netpath");
    if (!cl.good()) return 1; 

    cl.set_auth( AUTH_SYS );

    if (cl.call( EXECSHELL, (xdrproc_t)xdr_string, (caddr_t)&cmd,
            (xdrproc_t)xdr_int, (caddr_t)&res) != RPC_SUCCESS)
       return 2;

    if (res!=0) {
       cerr << "clnt: exec cmd fails\n"; 
       return 4;
    }
    return 0;
}


/* check if a host has service defined */
int check_host( const char* hostnm )
{
    if (rw_rdlock(&rwlck)) perror("rw_rdlock");

    int i;
    for (i=0; i < numhosts; i++)
       if (!strcmp(hostlist[i],hostnm)) break;

    if (rw_unlock(&rwlck)) perror("rw_unlock");

    return  (i < numhosts) ? 1 : 0;
}

/* execute a command on a host */
void* exec_shell( void* argp )
{
    static int rc = 0;
    char* cmd = (char*)argp;
    /* the input string syntax is: <cmd>'/'<host> */
    char* host = strrchr(cmd,'/');
    *host++ = '\0';
    if (!check_host(host)) {
       cout << "Invalid host: '" << host << "'\n" << flush;
       rc = 1;
       thr_exit(&rc);
    }
    rc = exec_host( cmd, host );
    thr_exit(&rc);
    return 0;
}

/* display all available hosts to an output stream */
void* display_hosts( void* argp )
{
    int rc = 0;

    if (rw_tryrdlock(&rwlck)) { 
       cout << "Host table in processed. please waite...\n";

       if (rw_rdlock(&rwlck)) perror("rw_rdlock");
    }

    if (!numhosts)  {
        cout << "Host table is empty!\n" << flush;
        cout << "please select 'Collect hosts info' option\n" << flush;
        rc = -1;
    }
    else {
       char buf[256];
       ostrstream(buf,256) << TMPFILE << "." << thr_self();
       ofstream ofs (buf);
       if (!ofs) 
           cerr << "Create temp file '" << buf << "' failed\n";
       else {
	   int i;
           for ( i=0; i < numhosts; i++)
              ofs << i << ":   " <<  hostlist[i] << endl;
           ofs.close();
           char cmd[256];
           ostrstream(cmd,256) << "xterm -title Hosts -e view " << buf;
           if (system(cmd)) perror("system");
           if (unlink(buf)) perror("unlink");
       }
    }

    if (rw_unlock(&rwlck)) perror("rw_unlock");
    thr_exit(&rc);
    return 0;
}

/* record a remote host */
int add_host( const char* hostnm )
{
    int new_entry = 1;
    if (rw_wrlock(&rwlck)) perror("rw_wrlock");

    int i;
    for ( i=0; i < numhosts; i++)
       if (!strcmp(hostlist[i],hostnm)) break;

    if (i >= numhosts) {
       if (numhosts >= MAXHOSTS) 
          cerr << "Too many remote hosts detected\n";
       else {
          hostlist[numhosts] = new char[strlen(hostnm)+1];
          strcpy(hostlist[numhosts++],hostnm);
       }
    }
    else new_entry = 0;
    if (rw_unlock(&rwlck)) perror("rw_unlock");
    return new_entry;
}
 
/* client's braodcast call back function */
bool_t callme (caddr_t res_p, struct netbuf* addr, struct netconfig *nconf)
{
    int i;
    struct nd_hostservlist *servp;
    if (netdir_getbyaddr(nconf,&servp,addr))
       perror("netdir_getbyaddr");
    else for ( i=0; i < servp->h_cnt; i++)
       if (!add_host( servp->h_hostservs[i].h_host )) 
          return TRUE;   /* end broadcast if found a host twice */

    return FALSE; /* get more responses */
}


/* collect remote hosts that have server running on it */
void* collect_hosts( void* argp )
{
    /* client sends a broadcast request and waits for responses */
    int rc = RPC_cls::broadcast( SHELLPROG, SHELLVER, 0, (resultproc_t)callme, 
               (xdrproc_t)xdr_void, (caddr_t)NULL,
               (xdrproc_t)xdr_void, (caddr_t)NULL);

    switch (rc) {
       case RPC_SUCCESS:     
          break;
       case RPC_TIMEDOUT:
          if (numhosts) break;
       default:
          cerr << "RPC broadcast failed\n";
          rc = 1;
    }


    thr_exit(&rc);
    return 0;
}
Соседние файлы в папке main_shell