Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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)
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)
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.