Commit | Line | Data |
---|---|---|
53102063 C |
1 | /* ftp_lib.c - FTP subroutines */ |
2 | ||
3 | /* | |
4 | * $Header: /f/osi/ftam-ftp/RCS/ftp_lib.c,v 7.2 91/02/22 09:23:29 mrose Interim $ | |
5 | * | |
6 | * | |
7 | * $Log: ftp_lib.c,v $ | |
8 | * Revision 7.2 91/02/22 09:23:29 mrose | |
9 | * Interim 6.8 | |
10 | * | |
11 | * Revision 7.1 90/12/23 18:39:51 mrose | |
12 | * update | |
13 | * | |
14 | * Revision 7.0 89/11/23 21:55:06 mrose | |
15 | * Release 6.0 | |
16 | * | |
17 | */ | |
18 | ||
19 | /* | |
20 | * NOTICE | |
21 | * | |
22 | * The MITRE Corporation (hereafter MITRE) makes this software available | |
23 | * on an "as is" basis. No guarantees, either explicit or implied, are | |
24 | * given as to performance or suitability. | |
25 | * | |
26 | */ | |
27 | ||
28 | /* | |
29 | * Library interface routines. Design of routines is specific for | |
30 | * FTAM. | |
31 | */ | |
32 | ||
33 | /* | |
34 | * FTP User Program -- Command Routines. | |
35 | */ | |
36 | #include "config.h" | |
37 | #include <sys/param.h> | |
38 | #include <sys/stat.h> | |
39 | #include <sys/socket.h> | |
40 | ||
41 | #include <arpa/ftp.h> | |
42 | ||
43 | #include <signal.h> | |
44 | #include <stdio.h> | |
45 | #include <errno.h> | |
46 | #include <netdb.h> | |
47 | ||
48 | #include "ftp_var.h" | |
49 | #include "general.h" | |
50 | #include "logger.h" | |
51 | ||
52 | void advise (); | |
53 | #ifndef NULLCP | |
54 | #define NULLCP ((char *) 0) | |
55 | #endif | |
56 | ||
57 | #define FTP_PORT 21 | |
58 | ||
59 | /* Virtual filesystem file types */ | |
60 | ||
61 | #define VFS_UBF 0 /* offset to FTAM-3 */ | |
62 | #define VFS_UTF 1 /* .. FTAM-1 */ | |
63 | #define VFS_FDF 2 /* .. NBS-9 */ | |
64 | ||
65 | #ifndef NOTOK | |
66 | #define NOTOK (-1) | |
67 | #define OK 0 | |
68 | #define DONE 1 | |
69 | #endif /* NOTOK */ | |
70 | ||
71 | ||
72 | /* | |
73 | * ftp_login: establish command connection with remote host | |
74 | * then execute login process. | |
75 | */ | |
76 | int | |
77 | ftp_login(host,user,passwd,acct) | |
78 | char *host, *user, *passwd, *acct; | |
79 | { | |
80 | ||
81 | if (connected) return NOTOK; /* already connected */ | |
82 | ||
83 | ftp_init(); /* initialize control state structures */ | |
84 | if (hookup(host,FTP_PORT) == NOTOK) return NOTOK; | |
85 | ||
86 | ||
87 | /* execute login process */ | |
88 | if (login(user,passwd,acct) == NOTOK) return NOTOK; | |
89 | ||
90 | return OK; | |
91 | } | |
92 | ||
93 | /* | |
94 | * ftp_quit: send quit command and shutdown communications link. | |
95 | */ | |
96 | int | |
97 | ftp_quit() | |
98 | { | |
99 | ||
100 | extern FILE *cout; | |
101 | extern int data; | |
102 | int n; | |
103 | ||
104 | if (!connected) return OK; | |
105 | n = command("QUIT"); | |
106 | (void) fclose(cout); | |
107 | connected = 0; | |
108 | data = -1; | |
109 | ||
110 | if (n == 0 || n == COMPLETE) return OK; | |
111 | return NOTOK; | |
112 | } | |
113 | ||
114 | /* | |
115 | * ftp_abort: send abort command | |
116 | */ | |
117 | int | |
118 | ftp_abort() | |
119 | { | |
120 | int n; | |
121 | ||
122 | if (!connected) return NOTOK; | |
123 | n = command("ABOR"); | |
124 | ||
125 | if (n == COMPLETE) return OK; | |
126 | return NOTOK; | |
127 | ||
128 | } | |
129 | ||
130 | /* | |
131 | * ftp_exist: perform NLST command and count number of records in data | |
132 | * stream. If 0 or reply code is failure, file does not exist. If 1 | |
133 | * or more and reply code is COMPLETE, file exists. ftp_directory is | |
134 | * a global flag. It is set if more than 1 record in data stream and | |
135 | * reply code is COMPLETE. Yes this is hokey but it works for all the | |
136 | * test systems and is faster than trying a case sensitive, then case | |
137 | * insensitive scan then falling back on record counts in the case of | |
138 | * directories. | |
139 | */ | |
140 | int | |
141 | ftp_exist(filename) | |
142 | char *filename; | |
143 | { | |
144 | int n, count; | |
145 | int fd; | |
146 | FILE *fp, *fdopen(); | |
147 | char lineX[BUFSIZ]; | |
148 | ||
149 | ftp_directory = 0; | |
150 | ||
151 | if (!connected) return NOTOK; | |
152 | ||
153 | /* set ascii transfer */ | |
154 | if (ftp_type(VFS_FDF) != OK) return NOTOK; | |
155 | ||
156 | /* begin list transfer */ | |
157 | if ((fd = recvrequest("NLST",filename)) == NOTOK) return NOTOK; | |
158 | if ((fp = fdopen(fd,"r")) == NULL){ | |
159 | (void)close(fd); | |
160 | (void) getreply(0); | |
161 | (void)sprintf(ftp_error,"Out of memory"); | |
162 | return NOTOK; | |
163 | } | |
164 | ||
165 | /* count number of records (lines) in data transfer */ | |
166 | for(count=0; fgets(lineX,BUFSIZ,fp)!=NULL; count++); | |
167 | (void)fclose(fp); | |
168 | ||
169 | /* transfer complete reply */ | |
170 | n = getreply(0); | |
171 | ||
172 | if (n != COMPLETE) /* directory command not accepted */ | |
173 | return NOTOK; | |
174 | ||
175 | /* if more than one record in reply, guess that it is a directory */ | |
176 | if (count > 1) { | |
177 | ftp_directory = 1; | |
178 | if (verbose) | |
179 | advise (LLOG_DEBUG, NULLCP, "directory found"); | |
180 | } | |
181 | ||
182 | /* if any records in reply, assume that file existed */ | |
183 | if (count) return OK; | |
184 | ||
185 | return NOTOK; | |
186 | ||
187 | } | |
188 | ||
189 | /* Basicly set transfer type to ascii and issue NLST command | |
190 | * and returning the socket descriptor for the data stream. | |
191 | */ | |
192 | int | |
193 | ftp_ls(dir) | |
194 | char *dir; | |
195 | { | |
196 | int fd; | |
197 | ||
198 | if (!connected) return NOTOK; | |
199 | ||
200 | /* set ascii transfer */ | |
201 | if (ftp_type(VFS_FDF) != OK) return NOTOK; | |
202 | ||
203 | /* begin list transfer */ | |
204 | if ((fd = recvrequest("NLST",dir)) == NOTOK) return NOTOK; | |
205 | ||
206 | return(fd); | |
207 | } | |
208 | int | |
209 | ftp_delete(file) | |
210 | char *file; | |
211 | { | |
212 | ||
213 | ||
214 | if (!connected) return NOTOK; | |
215 | ||
216 | /* send delete command, return OK if complete, NOTOK otherwise */ | |
217 | if (command("DELE %s", file) == COMPLETE) return OK; | |
218 | /* Hummm, try directory delete */ | |
219 | if (command("XRMD %s", file) == COMPLETE) return OK; | |
220 | /* No dice, return error */ | |
221 | return NOTOK; | |
222 | ||
223 | } | |
224 | ||
225 | int | |
226 | ftp_mkdir(dir) | |
227 | char *dir; | |
228 | { | |
229 | ||
230 | if (!connected) return NOTOK; | |
231 | ||
232 | /* send MKDIR command, return OK if complete, NOTOK otherwise */ | |
233 | if (command("XMKD %s", dir) == COMPLETE) return OK; | |
234 | return NOTOK; | |
235 | ||
236 | } | |
237 | ||
238 | int | |
239 | ftp_rename(from,to) | |
240 | char *from, *to; | |
241 | { | |
242 | int n; | |
243 | ||
244 | if (!connected) return NOTOK; | |
245 | ||
246 | /* send RNFR command followed by RNTO if successful */ | |
247 | if ((n = command("RNFR %s",from)) == CONTINUE) | |
248 | n = command("RNTO %s",to); | |
249 | if (n == COMPLETE) return OK; | |
250 | return NOTOK; | |
251 | ||
252 | } | |
253 | ||
254 | int | |
255 | ftp_write(file) | |
256 | char *file; | |
257 | { | |
258 | ||
259 | if (!connected) return NOTOK; | |
260 | ||
261 | return(sendrequest("STOR",file)); | |
262 | } | |
263 | int | |
264 | ftp_append(file) | |
265 | char *file; | |
266 | { | |
267 | if (!connected) return NOTOK; | |
268 | ||
269 | return(sendrequest("APPE",file)); | |
270 | } | |
271 | ||
272 | int | |
273 | ftp_read(file) | |
274 | char *file; | |
275 | { | |
276 | ||
277 | if (!connected) return NOTOK; | |
278 | ||
279 | return(recvrequest("RETR", file)); | |
280 | } | |
281 | ||
282 | int | |
283 | ftp_type(modeX) | |
284 | int modeX; | |
285 | { | |
286 | int n; | |
287 | char cmd[10]; | |
288 | ||
289 | /* The current transfer type is stored in ``type''. | |
290 | * The TYPE command is issued if the type changes. | |
291 | * (this cuts down on the number of FTP transactions). | |
292 | */ | |
293 | if (!connected) return NOTOK; | |
294 | n = COMPLETE; | |
295 | ||
296 | switch(modeX) { | |
297 | /* unstructured binary file */ | |
298 | case VFS_UBF: | |
299 | if (type == TYPE_L) break; | |
300 | (void)sprintf(cmd, "TYPE L %s", bytename); | |
301 | type = TYPE_L; | |
302 | n = command(cmd,0); | |
303 | break; | |
304 | /* unstructured text file */ | |
305 | case VFS_UTF: | |
306 | /* directory file */ | |
307 | case VFS_FDF: | |
308 | default: | |
309 | if (type == TYPE_A) break; | |
310 | (void)sprintf(cmd, "TYPE A"); | |
311 | type = TYPE_A; | |
312 | n = command(cmd,0); | |
313 | } | |
314 | ||
315 | if (n == COMPLETE) return OK; | |
316 | return NOTOK; | |
317 | ||
318 | } | |
319 | ||
320 | int | |
321 | ftp_reply() | |
322 | { | |
323 | int n; | |
324 | ||
325 | /* process an FTP response */ | |
326 | ||
327 | n = getreply(0); | |
328 | if (n == COMPLETE) return OK; | |
329 | return NOTOK; | |
330 | } | |
331 | ||
332 | int | |
333 | ftp_create(filename) | |
334 | char *filename; | |
335 | { | |
336 | int fd,n; | |
337 | ||
338 | if (!connected) return NOTOK; | |
339 | ||
340 | /* open file */ | |
341 | fd = sendrequest("STOR",filename); | |
342 | if (fd == NOTOK) return NOTOK; | |
343 | ||
344 | /* close file (create empty file) */ | |
345 | (void)close(fd); | |
346 | n = getreply(0); | |
347 | if (n == COMPLETE) return OK; | |
348 | return NOTOK; | |
349 | ||
350 | } | |
351 |