1 /*
2 * (c) 1998-2002 Gerd Knorr
3 *
4 * functions to handle ftp uploads using the ftp utility
5 *
6 */
7 #include "config.h"
8 #define _GNU_SOURCE 1
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <stdarg.h>
17 #include <signal.h>
18
19 #include "ftp.h"
20
21 /* ---------------------------------------------------------------------- */
22 /* FTP stuff */
23
24 struct ftp_state {
25 char *name;
26 int connected;
27 int debug;
28 int pty, pid;
29 char tty_name[32];
30 };
31
32 static
33 int open_pty(struct ftp_state *s)
34 {
35 #ifdef HAVE_GETPT
36 int master;
37 char *slave;
38
39 if (-1 == (master = getpt()))
40 return -1;
41 if (-1 == grantpt(master) ||
42 -1 == unlockpt(master) ||
43 NULL == (slave = ptsname(master))) {
44 close(master);
45 return -1;
46 }
47 strcpy(s->tty_name,slave);
48 return master;
49 #else
50 static char pty_name[32];
51 static char s1[] = "pqrs";
52 static char s2[] = "0123456789abcdef";
53
54 char *p1,*p2;
55 int pty;
56
57 for (p1 = s1; *p1; p1++) {
58 for (p2 = s2; *p2; p2++) {
59 sprintf(pty_name,"/dev/pty%c%c",*p1,*p2);
60 sprintf(s->tty_name,"/dev/tty%c%c",*p1,*p2);
61 if (-1 == access(s->tty_name,R_OK|W_OK))
62 continue;
63 if (-1 != (pty = open(pty_name,O_RDWR)))
64 return pty;
65 }
66 }
67 return -1;
68 #endif
69 }
70
71 struct ftp_state* ftp_init(char *name, int autologin, int passive, int debug)
72 {
73 static char *doauto[] = { "ftp", NULL }; /* allow autologin via ~/.netrc */
74 static char *noauto[] = { "ftp", "-n", NULL };
75 struct ftp_state *s;
76
77 s = malloc(sizeof(*s));
78 memset(s,0,sizeof(*s));
79 s->name = name;
80 s->debug = debug;
81 if (-1 == (s->pty = open_pty(s))) {
82 fprintf(stderr,"can't grab pty\n");
83 exit(1);
84 }
85 switch (s->pid = fork()) {
86 case -1:
87 perror("fork");
88 exit(1);
89 case 0:
90 /* child */
91 close(s->pty);
92 close(0); close(1); close(2);
93 setsid();
94 open(s->tty_name,O_RDWR); dup(0); dup(0);
95
96 /* need english messages from ftp */
97 setenv("LC_ALL","C",1);
98
99 if (autologin)
100 execvp(doauto[0],doauto);
101 else
102 execvp(noauto[0],noauto);
103 perror("execvp");
104 exit(1);
105 default:
106 /* parent */
107 break;
108 }
109 ftp_recv(s);
110
111 /* initialisation */
112 if (passive) {
113 ftp_send(s,1,"pass");
114 ftp_recv(s);
115 }
116 return s;
117 }
118
119 void
120 ftp_send(struct ftp_state *s, int argc, ...)
121 {
122 va_list ap;
123 char line[256],*arg;
124 int length,i;
125
126 va_start(ap,argc);
127 memset(line,0,256);
128 length = 0;
129 for (i = 0; i < argc; i++) {
130 if (i)
131 line[length++] = ' ';
132 arg = va_arg(ap,char*);
133 length += strlen(arg);
134 strcat(line,arg);
135 }
136 line[length++] = '\n';
137 va_end (ap);
138
139 if (s->debug)
140 fprintf(stderr,"[%s]>> %s",s->name,line);
141 if (length != write(s->pty,line,length)) {
142 fprintf(stderr,"ftp: write error\n");
143 exit(1);
144 }
145 }
146
147 int
148 ftp_recv(struct ftp_state *s)
149 {
150 char line[512],*p,*n;
151 int length, done, status, ret=0;
152 fd_set set;
153
154 for (done = 0; !done;) {
155 FD_ZERO(&set);
156 FD_SET(s->pty,&set);
157 select(s->pty+1,&set,NULL,NULL,NULL);
158
159 switch (length = read(s->pty,line,511)) {
160 case -1:
161 perror("ftp: read error");
162 exit(1);
163 case 0:
164 fprintf(stderr,"ftp: EOF\n");
165 exit(1);
166 }
167 line[length] = 0;
168
169 for (p=line; p && *p; p = n) {
170 /* split into lines */
171 if (NULL != (n = strchr(p,'\n')) || NULL != (n = strchr(p,'\r')))
172 *(n++) = 0;
173 else
174 n = NULL;
175 if (s->debug)
176 fprintf(stderr,"[%s]<< %s\n",s->name,p);
177
178 /* prompt? */
179 if (NULL != strstr(p,"ftp>")) {
180 done = 1;
181 }
182
183 /* line dropped ? */
184 if (NULL != strstr(p,"closed connection")) {
185 fprintf(stderr,"ftp: lost connection\n");
186 s->connected = 0;
187 }
188 if (NULL != strstr(p,"Not connected")) {
189 if (!ftp_connected(s))
190 fprintf(stderr,"ftp: lost connection\n");
191 s->connected = 0;
192 }
193
194 /* status? */
195 if (1 == sscanf(p,"%d",&status)) {
196 ret = status;
197 }
198 }
199 }
200 return ret;
201 }
202
203 void
204 ftp_connect(struct ftp_state *s, char *host, char *user, char *pass, char *dir)
205 {
206 int delay = 0, status;
207
208 for (;;) {
209 /* Wiederholungsversuche mit wachsendem Intervall, 10 min max. */
210 if (delay) {
211 fprintf(stderr,"ftp: connect failed, sleeping %d sec\n",delay);
212 sleep(delay);
213 delay *= 2;
214 if (delay > 600)
215 delay = 600;
216 } else {
217 delay = 5;
218 }
219
220 /* (re-) connect */
221 ftp_send(s,1,"close");
222 ftp_recv(s);
223 ftp_send(s,2,"open",host);
224 status = ftp_recv(s);
225 if (230 == status) {
226 fprintf(stderr,"ftp: connected to %s, login ok\n",host);
227 s->connected = 1;
228 goto login_ok;
229 }
230 if (220 != status && 530 != status)
231 continue;
232
233 fprintf(stderr,"ftp: connected to %s\n",host);
234 s->connected = 1;
235
236 /* login */
237 ftp_send(s,3,"user",user,pass);
238 if (230 != ftp_recv(s)) {
239 if (!ftp_connected(s))
240 continue;
241 fprintf(stderr,"ftp: login incorrect\n");
242 exit(1);
243 }
244
245 login_ok:
246 /* set directory */
247 ftp_send(s,2,"cd",dir);
248 if (250 != ftp_recv(s)) {
249 if (!s->connected)
250 continue;
251 fprintf(stderr,"ftp: cd %s failed\n",dir);
252 exit(1);
253 }
254
255 /* initialisation */
256 ftp_send(s,1,"bin");
257 ftp_recv(s);
258 ftp_send(s,1,"umask 022");
259 ftp_recv(s);
260
261 /* ok */
262 break;
263 }
264 }
265
266 int ftp_connected(struct ftp_state *s)
267 {
268 return s->connected;
269 }
270
271 void
272 ftp_upload(struct ftp_state *s, char *local, char *remote, char *tmp)
273 {
274 ftp_send(s,3,"put",local,tmp);
275 ftp_recv(s);
276 ftp_send(s,3,"rename",tmp,remote);
277 ftp_recv(s);
278 }
279
280 void ftp_fini(struct ftp_state *s)
281 {
282 ftp_send(s,1,"bye");
283 ftp_recv(s);
284 kill(s->pid,SIGTERM);
285 close(s->pty);
286 free(s);
287 }
288
|
This page was automatically generated by the
LXR engine.
|