1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: file.c 1082 2008-06-12 18:39:50Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2015 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
18 * Program: High level file input and output routines
23 * The routines in this file
24 * handle the reading and writing of
25 * disk files. All of details about the
26 * reading and writing of the disk are
30 #include "../pith/charconv/filesys.h"
33 void init_insmsgchar_cbuf(void);
35 char *file_split(char *, size_t, char *, int);
38 * Read a file into the current
39 * buffer. This is really easy; all you do it
40 * find the name of the file, and call the standard
41 * "read a file into the current buffer" code.
45 fileread(int f
, int n
)
51 if ((s
=mlreply_utf8(_("Read file: "), fname
, NFILEN
, QNORML
, NULL
)) != TRUE
)
55 emlwrite(_("File reading disabled in secure mode"),NULL
);
59 if (strlen(fname
) == 0) {
60 emlwrite(_("No file name entered"),NULL
);
64 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
66 emlwrite(_("Can't read file from outside of %s"), &eml
);
70 return(readin(fname
, TRUE
, TRUE
));
75 static char *inshelptext
[] = {
76 /* TRANSLATORS: several lines of help text */
77 N_("Insert File Help Text"),
79 N_(" Type in a file name to have it inserted into your editing"),
80 N_(" buffer between the line that the cursor is currently on"),
81 N_(" and the line directly below it. You may abort this by "),
82 N_("~ typing the ~F~2 (~^~C) key after exiting help."),
84 N_("End of Insert File Help"),
89 static char *writehelp
[] = {
90 /* TRANSLATORS: several lines of help text */
91 N_("Write File Help Text"),
93 N_(" Type in a file name to have it written out, thus saving"),
94 N_(" your buffer, to a file. You can abort this by typing "),
95 N_("~ the ~F~2 (~^~C) key after exiting help."),
97 N_("End of Write File Help"),
105 * Insert a file into the current
106 * buffer. This is really easy; all you do it
107 * find the name of the file, and call the standard
108 * "insert a file into the current buffer" code.
109 * Bound to "C-X C-I".
112 insfile(int f
, int n
)
115 char fname
[NLINE
], dir
[NLINE
];
116 int retval
, bye
= 0, msg
= 0;
117 char prompt
[64], *infile
;
118 EXTRAKEYS menu_ins
[5];
121 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
122 return(rdonly()); /* we are in read only mode */
124 fname
[0] = dir
[0] = '\0';
126 /* set up keymenu stuff */
130 menu_ins
[last_menu
].name
= "^T";
131 menu_ins
[last_menu
].key
= (CTRL
|'T');
132 menu_ins
[last_menu
].label
= N_("To Files");
133 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
135 if(Pmaster
&& Pmaster
->msgntext
){
136 menu_ins
[++last_menu
].name
= "^W";
137 menu_ins
[last_menu
].key
= (CTRL
|'W');
138 /* TRANSLATORS: Insert File is a key label for a command
139 that inserts a file into a message being composed.
140 InsertMsg means Insert Message and it inserts a different
141 message into the message being composed. */
142 menu_ins
[last_menu
].label
= msg
? N_("InsertFile") : N_("InsertMsg");
143 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
146 #if !defined(DOS) && !defined(MAC)
147 if(Pmaster
&& Pmaster
->upload
){
148 menu_ins
[++last_menu
].name
= "^Y";
149 menu_ins
[last_menu
].key
= (CTRL
|'Y');
150 menu_ins
[last_menu
].label
= "RcvUpload";
151 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
153 #endif /* !(DOS || MAC) */
156 menu_ins
[++last_menu
].name
= msg
? "" : "TAB";
157 menu_ins
[last_menu
].key
= (CTRL
|'I');
158 menu_ins
[last_menu
].label
= msg
? "" : N_("Complete");
159 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
162 menu_ins
[++last_menu
].name
= NULL
;
165 snprintf(prompt
, sizeof(prompt
), "%s to insert from %s %s: ",
166 msg
? "Number of message" : "File",
167 (msg
|| (gmode
&MDCURDIR
))
169 : ((gmode
& MDTREE
) || opertree
[0]) ? opertree
: "home",
170 msg
? "folder" : "directory");
171 s
= mlreplyd_utf8(prompt
, fname
, NLINE
, QDEFLT
, msg
? NULL
: menu_ins
);
172 /* something to read and it was edited or the default accepted */
173 if(fname
[0] && (s
== TRUE
|| s
== FALSE
)){
176 init_insmsgchar_cbuf();
177 if((*Pmaster
->msgntext
)(atol(fname
), insmsgchar
)){
179 emlwrite(_("Message %s included"), &eml
);
185 emlwrite(_("Can't insert file in restricted mode"),NULL
);
189 && !compresspath(opertree
, fname
, sizeof(fname
))){
192 _("Can't insert file from outside of %s: too many ..'s"), &eml
);
195 fixpath(fname
, sizeof(fname
));
197 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
199 emlwrite(_("Can't insert file from outside of %s"), &eml
);
202 retval
= ifile(fname
);
214 fn
= file_split(dir
, sizeof(dir
), fname
, 0);
216 if(!pico_fncomplete(dir
, fn
, sizeof(fname
)-(fn
-fname
)))
222 msg
= !msg
; /* toggle what to insert */
226 emlwrite(_("Can't select messages yet!"), NULL
);
231 fn
= file_split(dir
, sizeof(dir
), fname
, 1);
232 if(!isdir(dir
, NULL
, NULL
)){
233 strncpy(dir
, (gmode
&MDCURDIR
)
234 ? (browse_dir
[0] ? browse_dir
: ".")
235 : ((gmode
& MDTREE
) || opertree
[0])
237 : (browse_dir
[0] ? browse_dir
238 :gethomedir(NULL
)), sizeof(dir
));
239 dir
[sizeof(dir
)-1] = '\0';
245 dirlen
= strlen(dir
);
246 if(dirlen
&& dir
[dirlen
- 1] != C_FILESEP
){
247 strncat(dir
, S_FILESEP
, sizeof(dir
)-strlen(dir
)-1);
248 dir
[sizeof(dir
)-1] = '\0';
251 strncat(dir
, fn
, sizeof(dir
)-strlen(dir
)-1);
252 dir
[sizeof(dir
)-1] = '\0';
253 if(!isdir(dir
, NULL
, NULL
))
254 dir
[MIN(dirlen
,sizeof(dir
)-1)] = '\0';
259 if((s
= FileBrowse(dir
, sizeof(dir
), fname
, sizeof(fname
),
260 NULL
, 0, FB_READ
, NULL
)) == 1){
262 emlwrite(_("Can't insert in restricted mode"),
269 len
= strlen(dir
)+strlen(S_FILESEP
)+strlen(fname
);
270 if ((infile
= (char *)malloc((len
+1)*sizeof(char))) != NULL
){
271 strncpy(infile
, dir
, len
);
273 strncat(infile
, S_FILESEP
, len
+1-1-strlen(infile
));
275 strncat(infile
, fname
, len
+1-1-strlen(infile
));
277 retval
= ifile(infile
);
278 free((char *) infile
);
281 emlwrite("Trouble allocating space for insert!"
291 pico_refresh(FALSE
, 1);
293 update(); /* redraw on return */
300 #if !defined(DOS) && !defined(MAC)
302 if(Pmaster
&& Pmaster
->upload
){
307 _("\007Restricted mode disallows uploaded command"),
313 retval
= (*Pmaster
->upload
)(tfname
, sizeof(tfname
), NULL
);
315 pico_refresh(FALSE
, 1);
319 retval
= ifile(tfname
);
323 sleep(3); /* problem, show error! */
325 if(tfname
[0]) /* clean up temp file */
329 (*term
.t_beep
)(); /* what? */
332 #endif /* !(DOS || MAC) */
335 VARS_TO_SAVE
*saved_state
;
337 saved_state
= save_pico_state();
338 (*Pmaster
->helper
)(msg
? Pmaster
->ins_m_help
340 _("Help for Insert File"), 1);
342 restore_pico_state(saved_state
);
343 free_pico_state(saved_state
);
347 pico_help(inshelptext
, _("Help for Insert File"), 1);
349 pico_refresh(FALSE
, 1);
359 curwp
->w_flag
|= WFMODE
|WFHARD
;
365 * split out the file name from the path.
366 * Copy path into dirbuf, return filename,
367 * which is a pointer into orig_fname.
368 * is_for_browse - use browse dir if possible
369 * don't want to use it for TAB-completion
372 file_split(char *dirbuf
, size_t dirbuflen
, char *orig_fname
, int is_for_browse
)
377 if(*orig_fname
&& (p
= strrchr(orig_fname
, C_FILESEP
))){
379 dirlen
= p
- orig_fname
;
381 strncpy(dirbuf
, S_FILESEP
, dirbuflen
);
382 dirbuf
[dirbuflen
-1] = '\0';
385 else if(orig_fname
[0] == C_FILESEP
386 || (isalpha((unsigned char)orig_fname
[0])
387 && orig_fname
[1] == ':')){
388 if(orig_fname
[1] == ':' && p
== orig_fname
+2)
389 dirlen
= fn
- orig_fname
;
391 dirlen
= MIN(dirlen
, dirbuflen
-1);
392 strncpy(dirbuf
, orig_fname
, dirlen
);
393 dirbuf
[dirlen
] = '\0';
396 else if (orig_fname
[0] == C_FILESEP
|| orig_fname
[0] == '~'){
397 dirlen
= MIN(dirlen
, dirbuflen
-1);
398 strncpy(dirbuf
, orig_fname
, dirlen
);
399 dirbuf
[dirlen
] = '\0';
403 snprintf(dirbuf
, dirbuflen
, "%s%c%.*s",
405 ? ((is_for_browse
&& browse_dir
[0]) ? browse_dir
: ".")
406 : ((gmode
& MDTREE
) || opertree
[0])
408 : ((is_for_browse
&& browse_dir
[0])
409 ? browse_dir
: gethomedir(NULL
)),
410 C_FILESEP
, p
- orig_fname
, orig_fname
);
414 strncpy(dirbuf
, (gmode
& MDCURDIR
)
415 ? ((is_for_browse
&& browse_dir
[0]) ? browse_dir
: ".")
416 : ((gmode
& MDTREE
) || opertree
[0])
418 : ((is_for_browse
&& browse_dir
[0])
419 ? browse_dir
: gethomedir(NULL
)), dirbuflen
);
420 dirbuf
[dirbuflen
-1] = '\0';
427 static CBUF_S insmsgchar_cb
;
430 init_insmsgchar_cbuf(void)
432 insmsgchar_cb
.cbuf
[0] = '\0';
433 insmsgchar_cb
.cbufp
= insmsgchar_cb
.cbuf
;
434 insmsgchar_cb
.cbufend
= insmsgchar_cb
.cbuf
;
439 * This is called with a stream of UTF-8 characters.
440 * We change that stream into UCS characters and insert
450 for(u
= glo_quote_str
; u
&& *u
; u
++)
454 else if(c
!= '\r'){ /* ignore CR (likely CR of CRLF) */
458 if((outchars
= utf8_to_ucs4_oneatatime(c
, &insmsgchar_cb
, &ucs
, NULL
)) != 0)
468 * Read file "fname" into the current
469 * buffer, blowing away any text found there. Called
470 * by both the read and find commands. Return the final
471 * status of the read. Also called by the mainline,
472 * to read in a file specified on the command line as
476 readin(char fname
[], /* name of file to read */
477 int lockfl
, /* check for file locks? */
478 int rename
) /* don't rename if reading from, say, alt speller */
480 UCS line
[NLINE
], *linep
;
482 int s
, done
, newline
;
484 curbp
->b_linecnt
= -1; /* Must be recalculated */
485 if ((s
= bclear(curbp
)) != TRUE
) /* Might be old. */
489 strncpy(curbp
->b_fname
, fname
, sizeof(curbp
->b_fname
));
490 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
493 if ((s
=ffropen(fname
)) != FIOSUC
){ /* Hard file open. */
494 if(s
== FIOFNF
) /* File not found. */
495 emlwrite(_("New file"), NULL
);
500 size_t charsread
= 0;
502 emlwrite(_("Reading file"), NULL
);
506 if((s
= ffgetline(line
, NLINE
, &charsread
, 1)) == FIOEOF
){
509 curbp
->b_flag
&= ~(BFTEMP
|BFCHG
);
512 snprintf(b
, sizeof(b
), _("Read %ld lines"), nline
);
514 snprintf(b
, sizeof(b
), _("Read 1 line"));
522 if(lnewline() == FALSE
){
535 for(linep
= line
; charsread
-- > 0; linep
++)
536 if(linsert(1, *linep
) == FALSE
) done
++;
546 ffclose(); /* Ignore errors. */
549 return(s
!= FIOERR
&& s
!= FIOFNF
); /* true if success */
554 * Ask for a file name, and write the
555 * contents of the current buffer to that file.
556 * Update the remembered file name and clear the
557 * buffer changed flag. This handling of file names
558 * is different from the earlier versions, and
559 * is more compatable with Gosling EMACS than
560 * with ITS EMACS. Bound to "C-X C-W".
563 filewrite(int f
, int n
)
568 char shows
[NLINE
], origshows
[NLINE
], *bufp
;
569 EXTRAKEYS menu_write
[3];
572 if(curbp
->b_fname
[0] != 0){
573 strncpy(fname
, curbp
->b_fname
, sizeof(curbp
->b_fname
));
574 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
579 menu_write
[0].name
= "^T";
580 menu_write
[0].label
= N_("To Files");
581 menu_write
[0].key
= (CTRL
|'T');
582 menu_write
[1].name
= "TAB";
583 menu_write
[1].label
= N_("Complete");
584 menu_write
[1].key
= (CTRL
|'I');
585 menu_write
[2].name
= NULL
;
586 for(;!(gmode
& MDTOOL
);){
587 /* TRANSLATORS: Asking for name of file to write data into */
588 s
= mlreplyd_utf8(_("File Name to write : "), fname
, NFILEN
,
589 QDEFLT
|QFFILE
, menu_write
);
593 if(!fname
[0]){ /* no file name to write to */
598 if((gmode
& MDTREE
) && !compresspath(opertree
, fname
, sizeof(fname
))){
600 emlwrite(_("Can't write outside of %s: too many ..'s"), &eml
);
605 fixpath(fname
, sizeof(fname
)); /* fixup ~ in file name */
606 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
608 emlwrite(_("Can't write outside of %s"), &eml
);
618 char *fn
, *p
, dir
[NFILEN
];
622 if(*fname
&& (p
= strrchr(fname
, C_FILESEP
))){
626 strncpy(dir
, S_FILESEP
, sizeof(dir
));
627 dir
[sizeof(dir
)-1] = '\0';
630 else if(fname
[0] == C_FILESEP
631 || (isalpha((unsigned char)fname
[0])
634 else if (fname
[0] == C_FILESEP
|| fname
[0] == '~')
637 strncpy(dir
, fname
, MIN(p
- fname
, sizeof(dir
)-1));
638 dir
[MIN(p
-fname
, sizeof(dir
)-1)] = '\0';
641 snprintf(dir
, sizeof(dir
), "%s%c%.*s",
644 : ((gmode
& MDTREE
) || opertree
[0])
645 ? opertree
: gethomedir(NULL
),
646 C_FILESEP
, p
- fname
, fname
);
650 strncpy(dir
, (gmode
& MDCURDIR
)
652 : ((gmode
& MDTREE
) || opertree
[0])
653 ? opertree
: gethomedir(NULL
), sizeof(dir
));
654 dir
[sizeof(dir
)-1] = '\0';
657 if(!pico_fncomplete(dir
, fn
, sizeof(fname
)-(fn
-fname
)))
664 /* If we have a file name, break up into path and file name.*/
667 if(isdir(fname
, NULL
, NULL
)) {
668 /* fname is a directory. */
669 strncpy(shows
, fname
, sizeof(shows
));
670 shows
[sizeof(shows
)-1] = '\0';
674 /* Find right most separator. */
675 bufp
= strrchr (fname
, C_FILESEP
);
677 /* Copy directory part to 'shows', and file
678 * name part to front of 'fname'. */
680 strncpy(shows
, fname
, sizeof(shows
));
681 shows
[sizeof(shows
)-1] = '\0';
682 strncpy(fname
, bufp
+1, MIN(strlen(bufp
+1)+1, sizeof(fname
)));
683 fname
[sizeof(fname
)-1] = '\0';
688 /* If we did not end up with a valid directory, use home. */
689 if (!*shows
|| !isdir (shows
, NULL
, NULL
)){
690 strncpy(shows
, ((gmode
& MDTREE
) || opertree
[0])
692 : (browse_dir
[0] ? browse_dir
693 : gethomedir(NULL
)), sizeof(shows
));
694 shows
[sizeof(shows
)-1] = '\0';
697 strncpy(origshows
, shows
, sizeof(origshows
));
698 origshows
[sizeof(origshows
)-1] = '\0';
699 if ((s
= FileBrowse(shows
, sizeof(shows
), fname
, sizeof(fname
), NULL
, 0,
700 FB_SAVE
, NULL
)) == 1) {
701 if (strlen(shows
)+strlen(S_FILESEP
)+strlen(fname
) < NLINE
){
702 strncat(shows
, S_FILESEP
, sizeof(shows
)-strlen(shows
)-1);
703 shows
[sizeof(shows
)-1] = '\0';
704 strncat(shows
, fname
, sizeof(shows
)-strlen(shows
)-1);
705 shows
[sizeof(shows
)-1] = '\0';
706 strncpy(fname
, shows
, sizeof(fname
));
707 fname
[sizeof(fname
)-1] = '\0';
710 emlwrite("Cannot write. File name too long!!",NULL
);
714 else if (s
== 0 && strcmp(shows
, origshows
)){
715 strncat(shows
, S_FILESEP
, sizeof(shows
)-strlen(shows
)-1);
716 shows
[sizeof(shows
)-1] = '\0';
717 strncat(shows
, fname
, sizeof(shows
)-strlen(shows
)-1);
718 shows
[sizeof(shows
)-1] = '\0';
719 strncpy(fname
, shows
, sizeof(fname
));
720 fname
[sizeof(fname
)-1] = '\0';
723 emlwrite("Cannot write. File name too long!!",NULL
);
727 pico_refresh(FALSE
, 1);
735 pico_help(writehelp
, "", 1);
737 pico_refresh(FALSE
, 1);
746 if(strcmp(fname
, curbp
->b_fname
) == 0)
749 if((s
=fexist(fname
, "w", (off_t
*)NULL
)) == FIOSUC
){
750 /*exists overwrite? */
752 snprintf(shows
, sizeof(shows
), _("File \"%s\" exists, OVERWRITE"), fname
);
753 if((s
=mlyesno_utf8(shows
, FALSE
)) == TRUE
)
756 else if(s
== FIOFNF
){
757 break; /* go write it */
759 else{ /* some error, can't write */
765 emlwrite("Writing...", NULL
);
767 if ((s
=writeout(fname
, 0)) != -1) {
769 strncpy(curbp
->b_fname
, fname
, sizeof(curbp
->b_fname
));
770 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
771 curbp
->b_flag
&= ~BFCHG
;
773 wp
= wheadp
; /* Update mode lines. */
775 if (wp
->w_bufp
== curbp
)
776 if((Pmaster
&& s
== TRUE
) || Pmaster
== NULL
)
777 wp
->w_flag
|= WFMODE
;
784 emlwrite(_("Wrote %s lines"), &eml
);
787 emlwrite(_("Wrote 1 line"), NULL
);
790 return ((s
== -1) ? FALSE
: TRUE
);
795 * Save the contents of the current
796 * buffer in its associatd file. No nothing
797 * if nothing has changed (this may be a bug, not a
798 * feature). Error if there is no remembered file
799 * name for the buffer. Bound to "C-X C-S". May
800 * get called by "C-Z".
803 filesave(int f
, int n
)
809 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
810 return(rdonly()); /* we are in read only mode */
811 if ((curbp
->b_flag
&BFCHG
) == 0) /* Return, no changes. */
813 if (curbp
->b_fname
[0] == 0) { /* Must have a name. */
814 emlwrite(_("No file name"), NULL
);
819 emlwrite("Writing...", NULL
);
820 if ((s
=writeout(curbp
->b_fname
, 0)) != -1) {
821 curbp
->b_flag
&= ~BFCHG
;
822 wp
= wheadp
; /* Update mode lines. */
824 if (wp
->w_bufp
== curbp
)
826 wp
->w_flag
|= WFMODE
;
831 emlwrite(_("Wrote %s lines"), &eml
);
834 emlwrite(_("Wrote 1 line"), NULL
);
841 * This function performs the details of file
842 * writing. Uses the file management routines in the
843 * "fileio.c" package. The number of lines written is
844 * displayed. Sadly, it looks inside a LINE; provide
845 * a macro for this. Most of the grief is error
846 * checking of some sort.
848 * If the argument readonly is set, the file is created with user read
849 * and write permission only if it doesn't already exist. Note that the
850 * word readonly is misleading. It is user r/w permission only.
852 * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
855 writeout(char *fn
, int readonly
)
862 if (!((s
= ffwopen(fn
, readonly
)) == FIOSUC
&& ffelbowroom()))
863 return (-1); /* Open writes message. */
865 lp
= lforw(curbp
->b_linep
); /* First line. */
866 nline
= 0; /* Number of lines. */
867 while (lp
!= curbp
->b_linep
) {
868 if ((s
=ffputline(&lp
->l_text
[0], llength(lp
))) != FIOSUC
)
874 t
= ffclose(); /* ffclose complains if error */
877 s
= t
; /* report worst case */
879 return ((s
== FIOSUC
) ? nline
: -1);
884 * writetmp - write a temporary file for message text, mindful of
885 * access restrictions and included text. If n is true, include
886 * lines that indicated included message text, otw forget them
887 * If dir is non-null, put the temp file in that directory.
890 writetmp(int n
, char *dir
)
892 static char fn
[NFILEN
];
900 /* Open writes message */
901 if (!fn
[0] || (s
=ffwopen(fn
, TRUE
)) != FIOSUC
){
908 lp
= lforw(curbp
->b_linep
); /* First line. */
909 nline
= 0; /* Number of lines. */
910 while (lp
!= curbp
->b_linep
) {
911 if(n
|| (!n
&& lp
->l_text
[0].c
!= '>'))
912 if ((s
=ffputline(&lp
->l_text
[0], llength(lp
))) != FIOSUC
)
919 t
= ffclose(); /* ffclose complains if error */
922 s
= t
; /* remember worst case */
924 if (s
!= FIOSUC
){ /* Some sort of error. */
934 * Insert file "fname" into the current
935 * buffer, Called by insert file command. Return the final
936 * status of the read.
941 UCS line
[NLINE
], *linep
;
943 int s
, done
, newline
;
944 size_t charsread
= 0;
947 if ((s
=ffropen(fname
)) != FIOSUC
){ /* Hard file open. */
954 curbp
->b_flag
|= BFCHG
; /* we have changed */
955 curbp
->b_flag
&= ~BFTEMP
; /* and are not temporary*/
956 curbp
->b_linecnt
= -1; /* must be recalculated */
959 emlwrite(_("Inserting %s."), &eml
);
963 if((s
= ffgetline(line
, NLINE
, &charsread
, 1)) == FIOEOF
){
966 if(llength(curwp
->w_dotp
) > curwp
->w_doto
)
972 snprintf(b
, sizeof(b
), _("Inserted %ld lines"), nline
);
974 snprintf(b
, sizeof(b
), _("Inserted 1 line"));
981 if(lnewline() == FALSE
){
989 case FIOSUC
: /* copy line into buf */
994 for(linep
= line
; charsread
-- > 0; linep
++)
995 if(linsert(1, *linep
) == FALSE
) done
++;
1004 ffclose(); /* Ignore errors. */
1006 return(s
!= FIOERR
);
1011 * pico_fncomplete - pico's function to complete the given file name
1014 pico_fncomplete(char *dirarg
, char *fn
, size_t fnlen
)
1016 char *p
, *dlist
, tmp
[NLINE
], dir
[NLINE
];
1017 int n
, i
, match
= -1;
1019 #define FILECMP(x, y) (toupper((unsigned char)(x))\
1020 == toupper((unsigned char)(y)))
1022 #define FILECMP(x, y) ((x) == (y))
1025 strncpy(dir
, dirarg
, sizeof(dir
));
1026 dir
[sizeof(dir
)-1] = '\0';
1027 pfnexpand(dir
, sizeof(dir
));
1028 if(*fn
&& (dlist
= p
= getfnames(dir
, fn
, &n
, NULL
, 0))){
1029 memset(tmp
, 0, sizeof(tmp
));
1030 while(n
--){ /* any names in it */
1031 for(i
= 0; i
< sizeof(tmp
)-1 && fn
[i
] && FILECMP(p
[i
], fn
[i
]); i
++)
1034 if(!fn
[i
]){ /* match or more? */
1036 for(; p
[i
] && FILECMP(p
[i
], tmp
[i
]); i
++)
1039 match
= !p
[i
] && !tmp
[i
];
1040 tmp
[i
] = '\0'; /* longest common string */
1043 match
= 1; /* may be it!?! */
1044 strncpy(tmp
, p
, sizeof(tmp
));
1045 tmp
[sizeof(tmp
)-1] = '\0';
1056 strncpy(fn
, tmp
, fnlen
);
1059 if ((strlen(dir
)+strlen(S_FILESEP
)+strlen(fn
)) < sizeof(dir
)){
1060 strncat(dir
, S_FILESEP
, sizeof(dir
)-strlen(dir
)-1);
1061 dir
[sizeof(dir
)-1] = '\0';
1062 strncat(dir
, fn
, sizeof(dir
)-strlen(dir
)-1);
1063 dir
[sizeof(dir
)-1] = '\0';
1064 if(isdir(dir
, NULL
, NULL
)){
1065 strncat(fn
, S_FILESEP
, fnlen
-strlen(fn
)-1);
1070 emlwrite("File name too BIG!!",0);
1083 * in_oper_tree - returns true if file "f" does reside in opertree
1086 in_oper_tree(char *f
)
1088 int end
= strlen(opertree
);
1090 return(!strncmp(opertree
, f
, end
)
1091 && (opertree
[end
-1] == '/'
1092 || opertree
[end
-1] == '\\'
1095 || f
[end
] == '\\'));