complete.c (223308) | complete.c (223328) |
---|---|
1/* $NetBSD: complete.c,v 1.38 2000/05/01 10:35:17 lukem Exp $ */ | 1/* $NetBSD: complete.c,v 1.10 2009/05/20 12:53:47 lukem Exp $ */ 2/* from NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp */ |
2 3/*- | 3 4/*- |
4 * Copyright (c) 1997-2000 The NetBSD Foundation, Inc. | 5 * Copyright (c) 1997-2009 The NetBSD Foundation, Inc. |
5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. | 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Luke Mewburn. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. |
18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. | |
25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 | 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 |
33#include "tnftp.h" 34 35#if 0 /* tnftp */ 36 |
|
39#include <sys/cdefs.h> 40#ifndef lint | 37#include <sys/cdefs.h> 38#ifndef lint |
41__RCSID("$NetBSD: complete.c,v 1.38 2000/05/01 10:35:17 lukem Exp $"); | 39__RCSID(" NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp "); |
42#endif /* not lint */ 43 44/* 45 * FTP user program - command and file completion routines 46 */ 47 48#include <sys/stat.h> 49 50#include <ctype.h> 51#include <err.h> 52#include <dirent.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> 56 | 40#endif /* not lint */ 41 42/* 43 * FTP user program - command and file completion routines 44 */ 45 46#include <sys/stat.h> 47 48#include <ctype.h> 49#include <err.h> 50#include <dirent.h> 51#include <stdio.h> 52#include <stdlib.h> 53#include <string.h> 54 |
55#endif /* tnftp */ 56 |
|
57#include "ftp_var.h" 58 59#ifndef NO_EDITCOMPLETE 60 61static int comparstr (const void *, const void *); 62static unsigned char complete_ambiguous (char *, int, StringList *); 63static unsigned char complete_command (char *, int); 64static unsigned char complete_local (char *, int); 65static unsigned char complete_option (char *, int); 66static unsigned char complete_remote (char *, int); 67 68static int 69comparstr(const void *a, const void *b) 70{ | 57#include "ftp_var.h" 58 59#ifndef NO_EDITCOMPLETE 60 61static int comparstr (const void *, const void *); 62static unsigned char complete_ambiguous (char *, int, StringList *); 63static unsigned char complete_command (char *, int); 64static unsigned char complete_local (char *, int); 65static unsigned char complete_option (char *, int); 66static unsigned char complete_remote (char *, int); 67 68static int 69comparstr(const void *a, const void *b) 70{ |
71 return (strcmp(*(const char **)a, *(const char **)b)); | 71 return (strcmp(*(const char * const *)a, *(const char * const *)b)); |
72} 73 74/* 75 * Determine if complete is ambiguous. If unique, insert. 76 * If no choices, error. If unambiguous prefix, insert that. 77 * Otherwise, list choices. words is assumed to be filtered 78 * to only contain possible choices. 79 * Args: 80 * word word which started the match 81 * list list by default 82 * words stringlist containing possible matches 83 * Returns a result as per el_set(EL_ADDFN, ...) 84 */ 85static unsigned char 86complete_ambiguous(char *word, int list, StringList *words) 87{ 88 char insertstr[MAXPATHLEN]; 89 char *lastmatch, *p; | 72} 73 74/* 75 * Determine if complete is ambiguous. If unique, insert. 76 * If no choices, error. If unambiguous prefix, insert that. 77 * Otherwise, list choices. words is assumed to be filtered 78 * to only contain possible choices. 79 * Args: 80 * word word which started the match 81 * list list by default 82 * words stringlist containing possible matches 83 * Returns a result as per el_set(EL_ADDFN, ...) 84 */ 85static unsigned char 86complete_ambiguous(char *word, int list, StringList *words) 87{ 88 char insertstr[MAXPATHLEN]; 89 char *lastmatch, *p; |
90 int i, j; | 90 size_t i, j; |
91 size_t matchlen, wordlen; 92 93 wordlen = strlen(word); 94 if (words->sl_cur == 0) 95 return (CC_ERROR); /* no choices available */ 96 97 if (words->sl_cur == 1) { /* only once choice available */ 98 p = words->sl_str[0] + wordlen; --- 39 unchanged lines hidden (view full) --- 138static unsigned char 139complete_command(char *word, int list) 140{ 141 struct cmd *c; 142 StringList *words; 143 size_t wordlen; 144 unsigned char rv; 145 | 91 size_t matchlen, wordlen; 92 93 wordlen = strlen(word); 94 if (words->sl_cur == 0) 95 return (CC_ERROR); /* no choices available */ 96 97 if (words->sl_cur == 1) { /* only once choice available */ 98 p = words->sl_str[0] + wordlen; --- 39 unchanged lines hidden (view full) --- 138static unsigned char 139complete_command(char *word, int list) 140{ 141 struct cmd *c; 142 StringList *words; 143 size_t wordlen; 144 unsigned char rv; 145 |
146 words = xsl_init(); | 146 words = ftp_sl_init(); |
147 wordlen = strlen(word); 148 149 for (c = cmdtab; c->c_name != NULL; c++) { 150 if (wordlen > strlen(c->c_name)) 151 continue; 152 if (strncmp(word, c->c_name, wordlen) == 0) | 147 wordlen = strlen(word); 148 149 for (c = cmdtab; c->c_name != NULL; c++) { 150 if (wordlen > strlen(c->c_name)) 151 continue; 152 if (strncmp(word, c->c_name, wordlen) == 0) |
153 xsl_add(words, c->c_name); | 153 ftp_sl_add(words, ftp_strdup(c->c_name)); |
154 } 155 156 rv = complete_ambiguous(word, list, words); 157 if (rv == CC_REFRESH) { 158 if (el_insertstr(el, " ") == -1) 159 rv = CC_ERROR; 160 } | 154 } 155 156 rv = complete_ambiguous(word, list, words); 157 if (rv == CC_REFRESH) { 158 if (el_insertstr(el, " ") == -1) 159 rv = CC_ERROR; 160 } |
161 sl_free(words, 0); | 161 sl_free(words, 1); |
162 return (rv); 163} 164 165/* 166 * Complete a local file 167 */ 168static unsigned char 169complete_local(char *word, int list) --- 25 unchanged lines hidden (view full) --- 195 return (CC_ERROR); 196 (void)strlcpy(dir, p, sizeof(dir)); 197 free(p); 198 } 199 200 if ((dd = opendir(dir)) == NULL) 201 return (CC_ERROR); 202 | 162 return (rv); 163} 164 165/* 166 * Complete a local file 167 */ 168static unsigned char 169complete_local(char *word, int list) --- 25 unchanged lines hidden (view full) --- 195 return (CC_ERROR); 196 (void)strlcpy(dir, p, sizeof(dir)); 197 free(p); 198 } 199 200 if ((dd = opendir(dir)) == NULL) 201 return (CC_ERROR); 202 |
203 words = xsl_init(); | 203 words = ftp_sl_init(); |
204 len = strlen(file); 205 206 for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { 207 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 208 continue; 209 210#if defined(DIRENT_MISSING_D_NAMLEN) 211 if (len > strlen(dp->d_name)) 212 continue; 213#else 214 if (len > dp->d_namlen) 215 continue; 216#endif 217 if (strncmp(file, dp->d_name, len) == 0) { 218 char *tcp; 219 | 204 len = strlen(file); 205 206 for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { 207 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 208 continue; 209 210#if defined(DIRENT_MISSING_D_NAMLEN) 211 if (len > strlen(dp->d_name)) 212 continue; 213#else 214 if (len > dp->d_namlen) 215 continue; 216#endif 217 if (strncmp(file, dp->d_name, len) == 0) { 218 char *tcp; 219 |
220 tcp = xstrdup(dp->d_name); 221 xsl_add(words, tcp); | 220 tcp = ftp_strdup(dp->d_name); 221 ftp_sl_add(words, tcp); |
222 } 223 } 224 closedir(dd); 225 226 rv = complete_ambiguous(file, list, words); 227 if (rv == CC_REFRESH) { 228 struct stat sb; 229 char path[MAXPATHLEN]; --- 20 unchanged lines hidden (view full) --- 250static unsigned char 251complete_option(char *word, int list) 252{ 253 struct option *o; 254 StringList *words; 255 size_t wordlen; 256 unsigned char rv; 257 | 222 } 223 } 224 closedir(dd); 225 226 rv = complete_ambiguous(file, list, words); 227 if (rv == CC_REFRESH) { 228 struct stat sb; 229 char path[MAXPATHLEN]; --- 20 unchanged lines hidden (view full) --- 250static unsigned char 251complete_option(char *word, int list) 252{ 253 struct option *o; 254 StringList *words; 255 size_t wordlen; 256 unsigned char rv; 257 |
258 words = xsl_init(); | 258 words = ftp_sl_init(); |
259 wordlen = strlen(word); 260 261 for (o = optiontab; o->name != NULL; o++) { 262 if (wordlen > strlen(o->name)) 263 continue; 264 if (strncmp(word, o->name, wordlen) == 0) | 259 wordlen = strlen(word); 260 261 for (o = optiontab; o->name != NULL; o++) { 262 if (wordlen > strlen(o->name)) 263 continue; 264 if (strncmp(word, o->name, wordlen) == 0) |
265 xsl_add(words, o->name); | 265 ftp_sl_add(words, ftp_strdup(o->name)); |
266 } 267 268 rv = complete_ambiguous(word, list, words); 269 if (rv == CC_REFRESH) { 270 if (el_insertstr(el, " ") == -1) 271 rv = CC_ERROR; 272 } | 266 } 267 268 rv = complete_ambiguous(word, list, words); 269 if (rv == CC_REFRESH) { 270 if (el_insertstr(el, " ") == -1) 271 rv = CC_ERROR; 272 } |
273 sl_free(words, 0); | 273 sl_free(words, 1); |
274 return (rv); 275} 276 277/* 278 * Complete a remote file 279 */ 280static unsigned char 281complete_remote(char *word, int list) 282{ 283 static StringList *dirlist; 284 static char lastdir[MAXPATHLEN]; 285 StringList *words; 286 char dir[MAXPATHLEN]; 287 char *file, *cp; | 274 return (rv); 275} 276 277/* 278 * Complete a remote file 279 */ 280static unsigned char 281complete_remote(char *word, int list) 282{ 283 static StringList *dirlist; 284 static char lastdir[MAXPATHLEN]; 285 StringList *words; 286 char dir[MAXPATHLEN]; 287 char *file, *cp; |
288 int i; | 288 size_t i; |
289 unsigned char rv; | 289 unsigned char rv; |
290 char cmdbuf[MAX_C_NAME]; 291 char *dummyargv[3] = { NULL, NULL, NULL }; |
|
290 | 292 |
291 char *dummyargv[] = { "complete", NULL, NULL }; | 293 (void)strlcpy(cmdbuf, "complete", sizeof(cmdbuf)); 294 dummyargv[0] = cmdbuf; |
292 dummyargv[1] = dir; 293 294 if ((file = strrchr(word, '/')) == NULL) { 295 dir[0] = '\0'; 296 file = word; 297 } else { 298 cp = file; 299 while (*cp == '/' && cp > word) 300 cp--; 301 (void)strlcpy(dir, word, cp - word + 2); 302 file++; 303 } 304 305 if (dirchange || dirlist == NULL || 306 strcmp(dir, lastdir) != 0) { /* dir not cached */ | 295 dummyargv[1] = dir; 296 297 if ((file = strrchr(word, '/')) == NULL) { 298 dir[0] = '\0'; 299 file = word; 300 } else { 301 cp = file; 302 while (*cp == '/' && cp > word) 303 cp--; 304 (void)strlcpy(dir, word, cp - word + 2); 305 file++; 306 } 307 308 if (dirchange || dirlist == NULL || 309 strcmp(dir, lastdir) != 0) { /* dir not cached */ |
307 char *emesg; | 310 const char *emesg; |
308 309 if (dirlist != NULL) 310 sl_free(dirlist, 1); | 311 312 if (dirlist != NULL) 313 sl_free(dirlist, 1); |
311 dirlist = xsl_init(); | 314 dirlist = ftp_sl_init(); |
312 313 mflag = 1; 314 emesg = NULL; 315 while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) { 316 char *tcp; 317 318 if (!mflag) 319 continue; 320 if (*cp == '\0') { 321 mflag = 0; 322 continue; 323 } 324 tcp = strrchr(cp, '/'); 325 if (tcp) 326 tcp++; 327 else 328 tcp = cp; | 315 316 mflag = 1; 317 emesg = NULL; 318 while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) { 319 char *tcp; 320 321 if (!mflag) 322 continue; 323 if (*cp == '\0') { 324 mflag = 0; 325 continue; 326 } 327 tcp = strrchr(cp, '/'); 328 if (tcp) 329 tcp++; 330 else 331 tcp = cp; |
329 tcp = xstrdup(tcp); 330 xsl_add(dirlist, tcp); | 332 tcp = ftp_strdup(tcp); 333 ftp_sl_add(dirlist, tcp); |
331 } 332 if (emesg != NULL) { 333 fprintf(ttyout, "\n%s\n", emesg); 334 return (CC_REDISPLAY); 335 } 336 (void)strlcpy(lastdir, dir, sizeof(lastdir)); 337 dirchange = 0; 338 } 339 | 334 } 335 if (emesg != NULL) { 336 fprintf(ttyout, "\n%s\n", emesg); 337 return (CC_REDISPLAY); 338 } 339 (void)strlcpy(lastdir, dir, sizeof(lastdir)); 340 dirchange = 0; 341 } 342 |
340 words = xsl_init(); | 343 words = ftp_sl_init(); |
341 for (i = 0; i < dirlist->sl_cur; i++) { 342 cp = dirlist->sl_str[i]; 343 if (strlen(file) > strlen(cp)) 344 continue; 345 if (strncmp(file, cp, strlen(file)) == 0) | 344 for (i = 0; i < dirlist->sl_cur; i++) { 345 cp = dirlist->sl_str[i]; 346 if (strlen(file) > strlen(cp)) 347 continue; 348 if (strncmp(file, cp, strlen(file)) == 0) |
346 xsl_add(words, cp); | 349 ftp_sl_add(words, cp); |
347 } 348 rv = complete_ambiguous(file, list, words); 349 sl_free(words, 0); 350 return (rv); 351} 352 353/* 354 * Generic complete routine 355 */ 356unsigned char | 350 } 351 rv = complete_ambiguous(file, list, words); 352 sl_free(words, 0); 353 return (rv); 354} 355 356/* 357 * Generic complete routine 358 */ 359unsigned char |
357complete(EditLine *el, int ch) | 360complete(EditLine *cel, int ch) |
358{ 359 static char word[FTPBUFLEN]; | 361{ 362 static char word[FTPBUFLEN]; |
360 static int lastc_argc, lastc_argo; | 363 static size_t lastc_argc, lastc_argo; |
361 362 struct cmd *c; 363 const LineInfo *lf; | 364 365 struct cmd *c; 366 const LineInfo *lf; |
364 int celems, dolist, cmpltype; 365 size_t len; | 367 int dolist, cmpltype; 368 size_t celems, len; |
366 | 369 |
367 lf = el_line(el); | 370 lf = el_line(cel); |
368 len = lf->lastchar - lf->buffer; 369 if (len >= sizeof(line)) 370 return (CC_ERROR); 371 (void)strlcpy(line, lf->buffer, len + 1); 372 cursor_pos = line + (lf->cursor - lf->buffer); 373 lastc_argc = cursor_argc; /* remember last cursor pos */ 374 lastc_argo = cursor_argo; 375 makeargv(); /* build argc/argv of current line */ 376 377 if (cursor_argo >= sizeof(word)) 378 return (CC_ERROR); 379 380 dolist = 0; 381 /* if cursor and word is same, list alternatives */ 382 if (lastc_argc == cursor_argc && lastc_argo == cursor_argo 383 && strncmp(word, margv[cursor_argc] ? margv[cursor_argc] : "", 384 cursor_argo) == 0) 385 dolist = 1; | 371 len = lf->lastchar - lf->buffer; 372 if (len >= sizeof(line)) 373 return (CC_ERROR); 374 (void)strlcpy(line, lf->buffer, len + 1); 375 cursor_pos = line + (lf->cursor - lf->buffer); 376 lastc_argc = cursor_argc; /* remember last cursor pos */ 377 lastc_argo = cursor_argo; 378 makeargv(); /* build argc/argv of current line */ 379 380 if (cursor_argo >= sizeof(word)) 381 return (CC_ERROR); 382 383 dolist = 0; 384 /* if cursor and word is same, list alternatives */ 385 if (lastc_argc == cursor_argc && lastc_argo == cursor_argo 386 && strncmp(word, margv[cursor_argc] ? margv[cursor_argc] : "", 387 cursor_argo) == 0) 388 dolist = 1; |
386 else if (cursor_argc < margc) | 389 else if (cursor_argc < (size_t)margc) |
387 (void)strlcpy(word, margv[cursor_argc], cursor_argo + 1); 388 word[cursor_argo] = '\0'; 389 390 if (cursor_argc == 0) 391 return (complete_command(word, dolist)); 392 393 c = getcmd(margv[0]); 394 if (c == (struct cmd *)-1 || c == 0) --- 26 unchanged lines hidden (view full) --- 421 case 'R': 422 if (connected != -1) { 423 fputs("\nMust be logged in to complete.\n", 424 ttyout); 425 return (CC_REDISPLAY); 426 } 427 return (complete_remote(word, dolist)); 428 default: | 390 (void)strlcpy(word, margv[cursor_argc], cursor_argo + 1); 391 word[cursor_argo] = '\0'; 392 393 if (cursor_argc == 0) 394 return (complete_command(word, dolist)); 395 396 c = getcmd(margv[0]); 397 if (c == (struct cmd *)-1 || c == 0) --- 26 unchanged lines hidden (view full) --- 424 case 'R': 425 if (connected != -1) { 426 fputs("\nMust be logged in to complete.\n", 427 ttyout); 428 return (CC_REDISPLAY); 429 } 430 return (complete_remote(word, dolist)); 431 default: |
429 errx(1, "unknown complete type `%c'", cmpltype); | 432 errx(1, "complete: unknown complete type `%c'", 433 cmpltype); |
430 return (CC_ERROR); 431 } 432 /* NOTREACHED */ 433} 434 435#endif /* !NO_EDITCOMPLETE */ | 434 return (CC_ERROR); 435 } 436 /* NOTREACHED */ 437} 438 439#endif /* !NO_EDITCOMPLETE */ |