Initial import of the ircii-pana-1.1-final source tree.
git-svn-id: svn://svn.code.sf.net/p/bitchx/code/tags/ircii-pana-1.1-final@1 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
649
source/scr-bx.c
Normal file
649
source/scr-bx.c
Normal file
@@ -0,0 +1,649 @@
|
||||
|
||||
/*
|
||||
* Copyright Colten Edwards (July 1/1998).
|
||||
* This code is for the purpose of re-attaching to a detached BitchX session.
|
||||
* The idea for this program was by kasper@efnet after I mentioned the trouble
|
||||
* I was having reconnecting to a detached terminal.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Version 1.0 released with BitchX 75
|
||||
* $Id: scr-bx.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
#include "struct.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#ifdef USING_CURSES
|
||||
#include <curses.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "ircterm.h"
|
||||
#include "screen.h"
|
||||
#include "ircaux.h"
|
||||
|
||||
#if defined(_ALL_SOURCE) || defined(__EMX__) || defined(__QNX__)
|
||||
#include <termios.h>
|
||||
#else
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TRANSLATE
|
||||
char translation = 0;
|
||||
unsigned char transToClient[256]; /* Server to client translation. */
|
||||
#endif
|
||||
|
||||
int dumb_mode = 0;
|
||||
int already_detached = 1;
|
||||
int do_check_pid = 0;
|
||||
char socket_path[500];
|
||||
char attach_ttyname[500];
|
||||
|
||||
|
||||
struct param
|
||||
{
|
||||
pid_t pgrp,
|
||||
pid;
|
||||
uid_t uid;
|
||||
int cols;
|
||||
int rows;
|
||||
char tty[80];
|
||||
char cookie[30];
|
||||
char password[80];
|
||||
char termid[81];
|
||||
};
|
||||
|
||||
struct param parm;
|
||||
char *old_pass = NULL;
|
||||
Screen *output_screen = NULL, *last_input_screen = NULL, *main_screen = NULL;
|
||||
char empty_string[] = "";
|
||||
int foreground = 0;
|
||||
int use_input = 1;
|
||||
int use_flow_control = 0;
|
||||
static int displays = 0;
|
||||
|
||||
#define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
|
||||
|
||||
#ifdef CLOAKED
|
||||
extern char proctitlestr[140];
|
||||
extern char **Argv; /* pointer to argument vector */
|
||||
extern char *LastArgv; /* end of argv */
|
||||
#endif
|
||||
|
||||
|
||||
char *n_m_strdup (const char *str, const char *module, const char *file, const int line)
|
||||
{
|
||||
char *ptr;
|
||||
if (!str)
|
||||
str = empty_string;
|
||||
ptr = (char *)malloc(strlen(str) + 1);
|
||||
return strcpy(ptr, str);
|
||||
}
|
||||
|
||||
void ircpanic(char *string, ...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int get_int_var(int var)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ltoa (long foo)
|
||||
{
|
||||
static char buffer[BIG_BUFFER_SIZE/8+1];
|
||||
char *pos = buffer + BIG_BUFFER_SIZE/8-1;
|
||||
unsigned long absv;
|
||||
int negative;
|
||||
|
||||
absv = (foo < 0) ? (unsigned long)-foo : (unsigned long)foo;
|
||||
negative = (foo < 0) ? 1 : 0;
|
||||
|
||||
buffer[BIG_BUFFER_SIZE/8] = 0;
|
||||
for (; absv > 9; absv /= 10)
|
||||
*pos-- = (absv % 10) + '0';
|
||||
*pos = (absv) + '0';
|
||||
|
||||
if (negative)
|
||||
*--pos = '-';
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
char *lower(char *str)
|
||||
{
|
||||
register char *ptr = NULL;
|
||||
|
||||
if (str)
|
||||
{
|
||||
ptr = str;
|
||||
for (; *str; str++)
|
||||
{
|
||||
if (isupper(*str))
|
||||
*str = tolower(*str);
|
||||
}
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
#ifndef HAVE_GETPASS
|
||||
char *getpass(char *);
|
||||
char *get_string_var(int var)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WINNT
|
||||
void refresh_screen(int i, char *u)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *find_tty_name(char *name)
|
||||
{
|
||||
static char tty[20];
|
||||
char *q, *s;
|
||||
*tty = 0;
|
||||
if ((q = strrchr(name, '/')))
|
||||
{
|
||||
q++;
|
||||
if ((q = strchr(q, '.')))
|
||||
{
|
||||
q++;
|
||||
if ((s = strchr(q, '.')))
|
||||
strncpy(tty, q, s-q);
|
||||
}
|
||||
}
|
||||
return tty;
|
||||
}
|
||||
|
||||
char *find_tty_path(char *name)
|
||||
{
|
||||
static char ttypath[200];
|
||||
char *q;
|
||||
*ttypath = 0;
|
||||
if ((q = strrchr(name, '/')))
|
||||
strncpy(ttypath, name, q - name);
|
||||
return ttypath;
|
||||
}
|
||||
|
||||
void display_socket_list(char *path, int unl, char *arg)
|
||||
{
|
||||
DIR *dptr;
|
||||
struct dirent *dir;
|
||||
struct stat st;
|
||||
char buffer[2000];
|
||||
char *new_path, *p;
|
||||
int count = 0;
|
||||
int doit = 0;
|
||||
|
||||
new_path = alloca(strlen(path)+1);
|
||||
strcpy(new_path, path);
|
||||
if ((p = strrchr(new_path, '/')))
|
||||
*p = 0;
|
||||
if (!(dptr = opendir(new_path)))
|
||||
{
|
||||
fprintf(stderr, "No such directory %s\r\n ", new_path);
|
||||
exit(1);
|
||||
}
|
||||
while ((dir = readdir(dptr)))
|
||||
{
|
||||
doit = 0;
|
||||
if (!dir->d_ino)
|
||||
continue;
|
||||
if (dir->d_name[0] == '.')
|
||||
continue;
|
||||
sprintf(buffer, "%s/%s", new_path, dir->d_name);
|
||||
if ((stat(buffer, &st) == -1))
|
||||
continue;
|
||||
if (arg && strstr(dir->d_name, arg))
|
||||
doit++;
|
||||
if (!count && !unl)
|
||||
fprintf(stderr, "There is more than one sockets available - \r\n");
|
||||
else if (!count)
|
||||
fprintf(stderr, "unlinking the following\r\n");
|
||||
count++;
|
||||
if (unl)
|
||||
{
|
||||
if (!((st.st_mode & 0700) == 0600) || doit)
|
||||
{
|
||||
fprintf(stderr, "%30s\r\n", dir->d_name);
|
||||
unlink(buffer);
|
||||
}
|
||||
}
|
||||
else if ((!doit && !arg) || (doit && arg))
|
||||
fprintf(stderr, "%30s %s\r\n", dir->d_name, ((st.st_mode & 0700) == 0600) ? "detached":"Attached or dead");
|
||||
}
|
||||
if (!count)
|
||||
fprintf(stderr, "No sockets to attach too\r\n");
|
||||
closedir(dptr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *find_detach_socket(char *path, char *name)
|
||||
{
|
||||
char *new_path;
|
||||
DIR *dptr;
|
||||
struct dirent *dir;
|
||||
struct stat st;
|
||||
char *ret = NULL, *p;
|
||||
int count = 0;
|
||||
new_path = alloca(strlen(path)+1);
|
||||
strcpy(new_path, path);
|
||||
if ((p = strrchr(new_path, '/')))
|
||||
*p = 0;
|
||||
else
|
||||
return NULL;
|
||||
if (!(dptr = opendir(new_path)))
|
||||
return NULL;
|
||||
ret = malloc(2000);
|
||||
*ret = 0;
|
||||
while ((dir = readdir(dptr)))
|
||||
{
|
||||
*ret = 0;
|
||||
if (!dir->d_ino)
|
||||
continue;
|
||||
if (dir->d_name[0] == '.')
|
||||
continue;
|
||||
sprintf(ret, "%s/%s", new_path, dir->d_name);
|
||||
p = strrchr(ret, '/'); p++;
|
||||
if ((stat(ret, &st) == -1) || (st.st_uid != getuid()) || S_ISDIR(st.st_mode))
|
||||
{
|
||||
*ret = 0;
|
||||
continue;
|
||||
}
|
||||
if (name)
|
||||
{
|
||||
char *pid, *n_tty, *h_name;
|
||||
pid = alloca(strlen(p)+1);
|
||||
strcpy(pid, p);
|
||||
n_tty = strchr(pid, '.'); *n_tty++ = 0;
|
||||
h_name = strchr(n_tty, '.'); *h_name++ = 0;
|
||||
if (strcmp(name, pid))
|
||||
{
|
||||
if (strcmp(n_tty, name))
|
||||
{
|
||||
if (strcmp(h_name, name))
|
||||
{
|
||||
if (strcmp(p, name))
|
||||
{
|
||||
if (!strstr(p, name))
|
||||
{
|
||||
*ret = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((st.st_mode & 0700) == 0600)
|
||||
break;
|
||||
count++;
|
||||
*ret = 0;
|
||||
}
|
||||
closedir(dptr);
|
||||
if (ret && !*ret)
|
||||
{
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
display_socket_list(path, 0, name);
|
||||
if (ret) free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void charset_ibmpc (void)
|
||||
{
|
||||
fwrite("\033(U", 3, 1, stdout); /* switch to IBM code page 437 */
|
||||
}
|
||||
|
||||
SIGNAL_HANDLER(handle_pipe)
|
||||
{
|
||||
|
||||
term_cr();
|
||||
term_clear_to_eol();
|
||||
term_reset2();
|
||||
fprintf(stdout, "\rdetached from %s. To re-attach type scr-bx %s\n\r", attach_ttyname, old_pass? "password":"");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
SIGNAL_HANDLER(handle_hup)
|
||||
{
|
||||
term_cr();
|
||||
term_clear_to_eol();
|
||||
term_reset2();
|
||||
fprintf(stdout, "\r");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
volatile int ctrl_c = 0;
|
||||
|
||||
SIGNAL_HANDLER(handle_ctrlc)
|
||||
{
|
||||
ctrl_c++;
|
||||
}
|
||||
|
||||
/* set's socket options */
|
||||
void set_socket_options (int s)
|
||||
{
|
||||
int opt = 1;
|
||||
int optlen = sizeof(opt);
|
||||
#ifndef NO_STRUCT_LINGER
|
||||
struct linger lin;
|
||||
|
||||
lin.l_onoff = lin.l_linger = 0;
|
||||
setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&lin, optlen);
|
||||
#endif
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, optlen);
|
||||
opt = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, optlen);
|
||||
}
|
||||
|
||||
|
||||
char *get_cookie(char *name)
|
||||
{
|
||||
static char cookie[80];
|
||||
FILE *fp = NULL;
|
||||
*cookie = 0;
|
||||
if ((fp = fopen(name, "r")))
|
||||
{
|
||||
fread(cookie, 40, 1, fp);
|
||||
fclose(fp);
|
||||
if (*cookie)
|
||||
cookie[strlen(cookie)-1] = 0;
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void reattach_tty(char *tty, char *password)
|
||||
{
|
||||
int s = -1;
|
||||
char *name;
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *hp;
|
||||
int len = 0;
|
||||
fd_set rd_fd;
|
||||
struct timeval tm = {0};
|
||||
char chr_c[] = "\003";
|
||||
|
||||
/*
|
||||
* this buffer has to be big enough to handle a full screen of
|
||||
* information from the detached process.
|
||||
*/
|
||||
unsigned char buffer[6 * BIG_BUFFER_SIZE+1];
|
||||
char *p;
|
||||
int port = 0;
|
||||
#if defined (TIOCGWINSZ)
|
||||
struct winsize window;
|
||||
#endif
|
||||
memset(&parm, 0, sizeof(struct param));
|
||||
|
||||
if (!(name = find_detach_socket(socket_path, tty)))
|
||||
{
|
||||
fprintf(stderr, "No detached process to attach too\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
strcpy(parm.cookie, get_cookie(name));
|
||||
if (!*parm.cookie)
|
||||
_exit(1);
|
||||
if ((p = strrchr(name, '/')))
|
||||
p++;
|
||||
sscanf(p, "%d.%*s.%*s", &port);
|
||||
displays = 1;
|
||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
displays = 0;
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
chmod(name, SOCKMODE);
|
||||
set_socket_options(s);
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_family = AF_INET;
|
||||
if((hp = gethostbyname("localhost")))
|
||||
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
else
|
||||
inet_aton("127.0.0.1", (struct in_addr *)&addr.sin_addr);
|
||||
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
fprintf(stderr, "connection refused for %s\r\n", name);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
parm.pid = getpid();
|
||||
parm.pgrp = getpgrp();
|
||||
parm.uid = getuid();
|
||||
strcpy(parm.tty, ttyname(0));
|
||||
strncpy(parm.termid, getenv("TERM"), 80);
|
||||
if (password)
|
||||
strncpy(parm.password, password, 60);
|
||||
fprintf(stderr, "attempting to wakeup %s\r\n", find_tty_name(name));
|
||||
#if defined (TIOCGWINSZ)
|
||||
if (ioctl(0, TIOCGWINSZ, &window) > -1)
|
||||
{
|
||||
parm.cols = window.ws_col;
|
||||
parm.rows = window.ws_row;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
parm.cols = 79;
|
||||
parm.rows = 25;
|
||||
}
|
||||
write(s, &parm, sizeof(struct param));
|
||||
sleep(2);
|
||||
alarm(15);
|
||||
len = read(s, &parm, sizeof(struct param));
|
||||
alarm(0);
|
||||
if (len <= 0)
|
||||
{
|
||||
fprintf(stderr, "[1;37merror[0;37m reconnecting to %s\r\n", find_tty_name(name));
|
||||
displays = 0;
|
||||
chmod(name, SOCKMODE);
|
||||
exit(1);
|
||||
}
|
||||
unlink(name);
|
||||
|
||||
term_init(parm.termid);
|
||||
set_term_eight_bit(1);
|
||||
charset_ibmpc();
|
||||
term_clear_screen();
|
||||
term_resize();
|
||||
term_move_cursor(0,0);
|
||||
|
||||
my_signal(SIGPIPE, handle_pipe, 0);
|
||||
my_signal(SIGINT, handle_ctrlc, 0);
|
||||
my_signal(SIGHUP, handle_hup, 0);
|
||||
|
||||
/*
|
||||
* according to MHacker we need to set errno to 0 under BSD.
|
||||
* for some reason we get a address in use from a socket
|
||||
*
|
||||
*/
|
||||
errno = 0;
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&rd_fd);
|
||||
FD_SET(0, &rd_fd);
|
||||
FD_SET(s, &rd_fd);
|
||||
tm.tv_sec = 2;
|
||||
|
||||
switch(select(s+1, &rd_fd, NULL, NULL, &tm))
|
||||
{
|
||||
case -1:
|
||||
if (ctrl_c)
|
||||
{
|
||||
write(s, chr_c, 1);
|
||||
ctrl_c = 0;
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
close(s);
|
||||
_exit(1);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (FD_ISSET(0, &rd_fd))
|
||||
{
|
||||
len = read(0, buffer, sizeof(buffer)-1);
|
||||
write(s, buffer, len);
|
||||
}
|
||||
if (FD_ISSET(s, &rd_fd))
|
||||
{
|
||||
len = read(s, buffer, sizeof(buffer)-1);
|
||||
write(1, buffer, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
fprintf(stderr, "Never should have got here");
|
||||
_exit(1);
|
||||
|
||||
return; /* error return */
|
||||
}
|
||||
|
||||
char *stripdev(char *ttynam)
|
||||
{
|
||||
if (ttynam == NULL)
|
||||
return NULL;
|
||||
#ifdef SVR4
|
||||
/* unixware has /dev/pts012 as synonym for /dev/pts/12 */
|
||||
if (!strncmp(ttynam, "/dev/pts", 8) && ttynam[8] >= '0' && ttynam[8] <= '9')
|
||||
{
|
||||
static char b[13];
|
||||
sprintf(b, "pts/%d", atoi(ttynam + 8));
|
||||
return b;
|
||||
}
|
||||
#endif /* SVR4 */
|
||||
if (!strncmp(ttynam, "/dev/", 5))
|
||||
return ttynam + 5;
|
||||
return ttynam;
|
||||
}
|
||||
|
||||
|
||||
void init_socketpath(void)
|
||||
{
|
||||
#if !defined(__EMX__) && !defined(WINNT)
|
||||
struct stat st;
|
||||
extern char socket_path[], attach_ttyname[];
|
||||
|
||||
sprintf(socket_path, "%s/.BitchX/screens", getenv("HOME"));
|
||||
if (access(socket_path, F_OK))
|
||||
return;
|
||||
if (stat(socket_path, &st) != -1)
|
||||
{
|
||||
char host[BIG_BUFFER_SIZE+1];
|
||||
char *ap;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return;
|
||||
gethostname(host, BIG_BUFFER_SIZE);
|
||||
if ((ap = strchr(host, '.')))
|
||||
*ap = 0;
|
||||
ap = &socket_path[strlen(socket_path)];
|
||||
sprintf(ap, "/%%d.%s.%s", stripdev(attach_ttyname), host);
|
||||
ap++;
|
||||
for ( ; *ap; ap++)
|
||||
if (*ap == '/')
|
||||
*ap = '-';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
char *old_tty = NULL;
|
||||
void parse_args(int argc, char **argv)
|
||||
{
|
||||
int ac = 1;
|
||||
int disp_sock = 0;
|
||||
|
||||
for (; ac < argc; ac++)
|
||||
{
|
||||
|
||||
if (!strncasecmp(argv[ac], "tty", 3))
|
||||
{
|
||||
old_tty = malloc(strlen(argv[ac])+1);
|
||||
strcpy(old_tty, argv[ac]);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'p')
|
||||
{
|
||||
char *pass;
|
||||
pass = getpass("Enter password : ");
|
||||
old_pass = malloc(strlen(pass)+1);
|
||||
strcpy(old_pass, pass);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'h')
|
||||
{
|
||||
char *p;
|
||||
if ((p = strrchr(argv[0], '/')))
|
||||
p++;
|
||||
else
|
||||
p = argv[0];
|
||||
fprintf(stderr, "Usage %s: [tty] [-p] [-h] [-l]\r\n\t\ttty is the name of a tty\r\n\t\t-p to specify a password\r\n\t\t-l to list available sockets\r\n\t\t-w to wipe out dead sockets\r\n", p);
|
||||
exit(0);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'l')
|
||||
disp_sock = 1;
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'w')
|
||||
disp_sock = 2;
|
||||
else if (!old_tty)
|
||||
{
|
||||
old_tty = malloc(strlen(argv[ac])+1);
|
||||
strcpy(old_tty, argv[ac]);
|
||||
}
|
||||
}
|
||||
if (disp_sock)
|
||||
display_socket_list(socket_path, disp_sock - 1, old_tty);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
dmalloc_debug(0x1df47dfb);
|
||||
#endif
|
||||
*socket_path = 0;
|
||||
strcpy(attach_ttyname, ttyname(0));
|
||||
init_socketpath();
|
||||
parse_args(argc, argv);
|
||||
chdir(getenv("HOME"));
|
||||
reattach_tty(old_tty, old_pass);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user