/* * rexec: remote exec */ /* * Copyright (c) 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include "rexec.h" const char usagemsg[] = "usage: rexec -i [IP] -c [command] <args>\n" "\n" "options:\n" " -i IP connect to host with address IP\n" " -c command execute command on host\n" " also: rexec -v show version\n" " rexec -h display this help\n" " rexec -l display (BSD) license\n" ; const char versionmsg[] = "rexec 0.2\n"; void usage(void); void version(void); void license(void); int main ( int argc, char* argv[] ) { int localargsparsed = 0; int i; int sock; int tmp; int child; char buff; char *command = NULL; in_addr_t remote_addr = 0; struct sockaddr_in *remote_host_addr = NULL; while ( !localargsparsed && (tmp = getopt(argc, argv, "i:c:hlv")) != -1 ) { switch ( tmp ) { case 'h': usage(); exit(0); case 'l': license(); exit(0); case 'v': version(); exit(0); case 'i': remote_addr = inet_addr(optarg); if ( command != NULL ) { localargsparsed = 1; } break; case 'c': command = optarg; if ( remote_addr != 0 ) { localargsparsed = 1; } break; } } if ( (remote_addr == 0) || (command == NULL) ) { usage(); exit(-1); } remote_host_addr = malloc(sizeof(struct sockaddr_in)); remote_host_addr->sin_family = AF_INET; remote_host_addr->sin_addr.s_addr = remote_addr; remote_host_addr->sin_port = REXEC_PORT; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( sock < 0 ) { printf("error: %s\n", strerror(errno)); exit(-1); } tmp = connect(sock, (struct sockaddr*)remote_host_addr, sizeof(struct sockaddr_in)); free(remote_host_addr); if ( tmp < 0 ) { printf("error: %s\n", strerror(errno)); exit(-1); } /* send command with args and a final \n */ write(sock, command, strlen(command)+1); for ( i = optind; i < argc; i++ ) { write(sock, argv[i], strlen(argv[i])+1); } write(sock, "\n", 1); if ( (child = fork()) == 0 ) { while ( tmp > -1 ) { if ( (tmp = read(sock, &buff, 1)) == 1 ) { printf("%c", buff); } else { usleep(200000); } } } else { while ( feof(stdin) == 0 ) { if ( buff = (char)getchar() ) { write(sock, &buff, 1); } else { usleep(200000); } } } tmp = shutdown(sock, SHUT_RDWR); if ( tmp < 0 ) { printf("error: %s\n", strerror(errno)); exit(-1); } tmp = close(sock); if ( tmp < 0 ) { printf("error: %s\n", strerror(errno)); exit(-1); } while ( wait(&tmp) > 0 ) { } exit(0); } void usage(void) { fprintf(stdout, "%s", usagemsg); } void version(void) { fprintf(stdout, "%s", versionmsg); } void license(void) { fprintf(stdout, "%s", licensemsg); }