#include #include #include #include #include #include #include #include "E-ScreenShoot_ftp.h" int ftp_connected; int ftp_debug; static int ftp_pty, ftp_pid; static char tty_name[32]; static void ftp_send(int argc, ...); static int ftp_recv(void); static int open_pty(void) { #ifdef HAVE_GETPT int master; char *slave; if (-1 == (master = getpt())) return -1; if (-1 == grantpt(master) || -1 == unlockpt(master) || !(slave = ptsname(master))) { close(master); return -1; } strcpy(tty_name, slave); return master; #else static char pty_name[32]; static char s1[] = "pqrs"; static char s2[] = "0123456789abcdef"; char *p1, *p2; int pty; for (p1 = s1; *p1; p1++) { for (p2 = s2; *p2; p2++) { sprintf(pty_name, "/dev/pty%c%c", *p1, *p2); sprintf(tty_name, "/dev/tty%c%c", *p1, *p2); if (-1 == access(tty_name, R_OK | W_OK)) continue; if (-1 != (pty = open(pty_name, O_RDWR))) return pty; } } return -1; #endif } void ftp_init(int passive) { static char *argv[] = { (char *)"ftp", (char *)"-n", NULL }; if (-1 == (ftp_pty = open_pty())) { fprintf(stderr, "can't grab pty\n"); exit(1); } switch (ftp_pid = fork()) { case -1: perror("fork"); exit(1); case 0: /* child */ close(ftp_pty); close(0); close(1); close(2); setsid(); open(tty_name, O_RDWR); dup(0); dup(0); unsetenv("LANG"); /* need english messages from ftp */ execvp(argv[0], argv); perror("execvp"); exit(1); default: /* parent */ break; } ftp_recv(); /* initialisation */ if (passive) { ftp_send(1, "pass"); ftp_recv(); } } void ftp_send(int argc, ...) { va_list ap; char line[256], *arg; int length, i; va_start(ap, argc); memset(line, 0, 256); length = 0; for (i = 0; i < argc; i++) { if (i) line[length++] = ' '; arg = va_arg(ap, char *); length += strlen(arg); strcat(line, arg); } line[length++] = '\n'; va_end(ap); if (ftp_debug) fprintf(stderr, ">> %s", line); if (length != write(ftp_pty, line, length)) { fprintf(stderr, "ftp: write error\n"); exit(1); } } int ftp_recv() { char line[512], *p, *n; int length, done, status, ret = 0; fd_set set; for (done = 0; !done;) { FD_ZERO(&set); FD_SET(ftp_pty, &set); select(ftp_pty + 1, &set, NULL, NULL, NULL); switch (length = read(ftp_pty, line, 511)) { case -1: perror("ftp: read error"); exit(1); case 0: fprintf(stderr, "ftp: EOF\n"); exit(1); } line[length] = 0; for (p = line; p && *p; p = n) { /* split into lines */ if ((n = strchr(p, '\n')) || (n = strchr(p, '\r'))) *(n++) = 0; else n = NULL; if (ftp_debug) fprintf(stderr, "<< %s\n", p); /* prompt? */ if (strstr(p, "ftp>")) { done = 1; } /* line dropped ? */ if (strstr(p, "closed connection")) { fprintf(stderr, "ftp: lost connection\n"); ftp_connected = 0; } if (strstr(p, "Not connected")) { if (ftp_connected) fprintf(stderr, "ftp: lost connection\n"); ftp_connected = 0; } /* status? */ if (1 == sscanf(p, "%d", &status)) { ret = status; } } } return ret; } void ftp_connect(char *host, char *user, char *pass, char *dir) { int delay = 0; for (;;) { /* Wiederholungsversuche mit wachsendem Intervall, 10 min max. */ if (delay) { fprintf(stderr, "ftp: connect failed, sleeping %d sec\n", delay); sleep(delay); delay *= 2; if (delay > 600) delay = 600; } else { delay = 5; } /* (re-) connect */ ftp_send(1, "close"); ftp_recv(); ftp_send(2, "open", host); if (220 != ftp_recv()) continue; /* fprintf(stderr,"ftp: connected to %s\n",host); */ ftp_connected = 1; /* login */ ftp_send(3, "user", user, pass); if (230 != ftp_recv()) { if (!ftp_connected) continue; fprintf(stderr, "ftp: login incorrect\n"); exit(1); } /* set directory */ ftp_send(2, "cd", dir); if (250 != ftp_recv()) { if (!ftp_connected) continue; fprintf(stderr, "ftp: cd %s failed\n", dir); exit(1); } /* initialisation */ ftp_send(1, "bin"); ftp_recv(); ftp_send(1, "umask 022"); ftp_recv(); /* ok */ break; } } void ftp_upload(char *local, char *remote, char *tmp) { ftp_send(3, "put", local, tmp); ftp_recv(); ftp_send(3, "rename", tmp, remote); ftp_recv(); }