1 /* @(#)edit.c 1.40 19/04/27 Copyright 2006-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)edit.c 1.40 19/04/27 Copyright 2006-2019 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 2006-2019 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 * A copy of the CDDL is also available via the Internet at
18 * http://www.opensource.org/licenses/cddl1.txt
19 *
20 * When distributing Covered Code, include this CDDL HEADER in each
21 * file and include the License file CDDL.Schily.txt from this distribution.
22 */
23
24 #include <schily/unistd.h>
25 #include <schily/varargs.h>
26 #include <schily/fcntl.h>
27 #include <schily/stat.h>
28 #include <schily/stdio.h>
29 #include "bsh.h"
30 #include "strsubs.h"
31 #include <schily/fstream.h>
32 #include <schily/shedit.h>
33 #define toint shell_toint
34
35 LOCAL fstream *instrm = (fstream *) NULL; /* Aliasexpanded input stream */
36 LOCAL fstream *rawstrm = (fstream *) NULL; /* Unexpanded input stream */
37
38 LOCAL void einit __PR((void));
39 LOCAL int readchar __PR((fstream *fsp));
40 EXPORT int shedit_egetc __PR((void));
41 EXPORT int shedit_getdelim __PR((void));
42 EXPORT void shedit_treset __PR((void));
43 EXPORT void shedit_bhist __PR((int **ctlcpp));
44 EXPORT void shedit_bshist __PR((int **ctlcpp));
45 LOCAL int lstatat __PR((char *name, struct stat *buf, int flag));
46
47 /*
48 * Set up file from where the inout should be read,
49 * returns the old FILE * value.
50 */
51 EXPORT FILE *
setinput(f)52 setinput(f)
53 FILE *f;
54 {
55 if (rawstrm == (fstream *) NULL)
56 rawstrm = mkfstream(f,
57 (fstr_fun)0, readchar, (fstr_efun)berror);
58 else
59 f = fssetfile(rawstrm, f);
60
61 if (instrm == (fstream *) NULL) /* Pfusch in sgetc */
62 instrm = mkfstream((FILE *)rawstrm,
63 NULL, (fstr_rfun)0, (fstr_efun)berror);
64 return (f);
65 }
66
67 extern char **environ;
68 extern int delim;
69 extern int prompt;
70 extern char *inithome;
71
72 #ifndef LIB_SHEDIT
73 int
main(ac,av,ev)74 main(ac, av, ev)
75 int ac;
76 char *av[];
77 char *ev[];
78 {
79 editloop();
80 }
81 #endif
82
83 LOCAL int __init;
84
85 LOCAL void
einit()86 einit()
87 {
88 char *p;
89 FILE *f;
90
91 gstd[0] = stdin;
92 gstd[1] = stdout;
93 gstd[2] = stderr;
94 evarray = environ;
95
96 p = getcurenv("HOME");
97 if (p)
98 inithome = p;
99
100 /*
101 * Use stdin only as a fallback if the input was not yet set.
102 */
103 f = setinput(stdin);
104 if (f != stdin)
105 setinput(f);
106 init_input();
107 read_init_history();
108 __init = TRUE;
109 }
110
111 LOCAL int
readchar(fsp)112 readchar(fsp)
113 register fstream *fsp;
114 {
115 #ifdef INTERACTIVE
116 extern int ttyflg;
117 extern int prflg;
118
119 prflg = ttyflg = isatty(fdown(fsp->fstr_file));
120 pushline(get_line(prompt++, fsp->fstr_file));
121 return (fsgetc(fsp));
122 #else
123 return (getc(fsp->fstr_file)); /* read from FILE */
124 #endif
125 }
126
127 EXPORT int
shedit_egetc()128 shedit_egetc()
129 {
130 if (!__init)
131 einit();
132 return (fsgetc(rawstrm));
133 }
134
135 EXPORT size_t
shedit_getlen()136 shedit_getlen()
137 {
138 if (!__init)
139 einit();
140 return (fsgetlen(rawstrm));
141 }
142
143 EXPORT int
shedit_getdelim()144 shedit_getdelim()
145 {
146 return (delim);
147 }
148
149 #ifndef LIB_SHEDIT
editloop()150 editloop()
151 {
152 int c;
153 int i = 0;
154
155 while (c = shedit_egetc()) {
156 printf("%c %o\n", c, c);
157 if (c == '\r' || c == '\n') {
158 printf("prompt %d\n", prompt);
159 prompt = 0;
160 }
161 if (++i > 100)
162 break;
163 }
164 exitbsh(0);
165 return (0);
166 }
167 #endif
168
169 EXPORT BOOL
toint(std,s,i)170 toint(std, s, i)
171 FILE *std[];
172 char *s;
173 int *i;
174 {
175 if (*s == '\0' || *astoi(s, i)) {
176 fprintf(std[2], "Not a number: %s.\n", s);
177 ex_status = 1;
178 return (FALSE);
179 }
180 return (TRUE);
181 }
182
183 char *
myhome()184 myhome()
185 {
186 return (makestr(inithome));
187 }
188
189 #ifdef PROTOTYPES
190 EXPORT int
berror(const char * s,...)191 berror(const char *s, ...)
192 #else
193 /* VARARGS1 */
194 EXPORT int
195 berror(s, va_alist)
196 char *s;
197 va_dcl
198 #endif
199 {
200 va_list args;
201 int ret;
202
203 #ifdef PROTOTYPES
204 va_start(args, s);
205 #else
206 va_start(args);
207 #endif
208 ret = fprintf(stderr, "%r\n", s, args);
209 va_end(args);
210 (void) fflush(stderr);
211 return (ret);
212 }
213
214
215 #if defined(__BEOS__) || defined(__HAIKU__)
216 #define silent_error(e) ((e) < 0 && (e) >= -1024)
217 #else
218 #define silent_error(e) ((e) < 0)
219 #endif
220
221 EXPORT char *
errstr(err)222 errstr(err)
223 int err;
224 {
225 static char errbuf[12];
226 char *estr;
227
228 if (silent_error(err)) {
229 return ("");
230 } else {
231 estr = errmsgstr(err);
232 if (estr == NULL) {
233 sprintf(errbuf, "%d", err);
234 estr = errbuf;
235 }
236 return (estr);
237 }
238 }
239
240 /*
241 * Push back a complete line
242 */
243 EXPORT void
pushline(s)244 pushline(s)
245 char *s;
246 {
247 if (s && rawstrm != (fstream *) NULL) {
248 fspushcha(rawstrm, delim);
249 fspushstr(rawstrm, s);
250 }
251 }
252
253 /*
254 * Check the current environment array against name and tval.
255 */
256 EXPORT BOOL
ev_eql(name,tval)257 ev_eql(name, tval)
258 char *name;
259 char *tval;
260 {
261 char *val;
262
263 if ((val = getcurenv(name)) != NULL)
264 return (streql(val, tval));
265 return (FALSE);
266 }
267
268 EXPORT BOOL
is_dir(name)269 is_dir(name)
270 char *name;
271 {
272 struct stat buf;
273
274 if (lstatat(name, &buf, 0) < 0)
275 return (FALSE);
276
277 return ((buf.st_mode & S_IFMT) == S_IFDIR);
278 }
279
280
281 EXPORT void
exitbsh(excode)282 exitbsh(excode)
283 int excode;
284 {
285 int sflg = 1;
286
287 if (sflg) {
288 /* see if its a top level */
289 /* run final file */
290 #ifdef INTERACTIVE
291 save_history(HI_NOINTR);
292 #endif
293 }
294
295 #ifdef INTERACTIVE
296 reset_tty_modes();
297 reset_line_disc(); /* Line discipline */
298 reset_tty_pgrp();
299 #endif
300 exit(excode);
301 }
302
303 EXPORT void
shedit_treset()304 shedit_treset()
305 {
306 save_history(HI_NOINTR);
307 reset_tty_modes();
308 reset_line_disc(); /* Line discipline */
309 reset_tty_pgrp();
310 }
311
312 EXPORT void
shedit_bhist(ctlcpp)313 shedit_bhist(ctlcpp)
314 int **ctlcpp;
315 {
316 if (ctlcpp)
317 *ctlcpp = &ctlc;
318 ctlc = 0;
319 put_history(gstd[1], HI_INTR, 0, 0, NULL);
320 }
321
322 EXPORT int
shedit_history(f,ctlcpp,flags,first,last,subst)323 shedit_history(f, ctlcpp, flags, first, last, subst)
324 FILE *f;
325 int **ctlcpp;
326 int flags;
327 int first;
328 int last;
329 char *subst;
330 {
331 if (ctlcpp)
332 *ctlcpp = &ctlc;
333 ctlc = 0;
334 return (put_history(f?f:gstd[1], flags, first, last, subst));
335 }
336
337 EXPORT int
shedit_search_history(ctlcpp,flags,first,pat)338 shedit_search_history(ctlcpp, flags, first, pat)
339 int **ctlcpp;
340 int flags;
341 int first;
342 char *pat;
343 {
344 if (ctlcpp)
345 *ctlcpp = &ctlc;
346 ctlc = 0;
347 return (search_history(flags, first, pat));
348 }
349
350 EXPORT int
shedit_remove_history(ctlcpp,flags,first,pat)351 shedit_remove_history(ctlcpp, flags, first, pat)
352 int **ctlcpp;
353 int flags;
354 int first;
355 char *pat;
356 {
357 if (ctlcpp)
358 *ctlcpp = &ctlc;
359 ctlc = 0;
360 return (remove_history(flags, first, pat));
361 }
362
363 EXPORT int
shedit_read_history(f,ctlcpp,flags)364 shedit_read_history(f, ctlcpp, flags)
365 FILE *f;
366 int **ctlcpp;
367 int flags;
368 {
369 if (ctlcpp)
370 *ctlcpp = &ctlc;
371 ctlc = 0;
372 shell_readhistory(f);
373 return (0);
374 }
375
376 EXPORT void
shedit_bshist(ctlcpp)377 shedit_bshist(ctlcpp)
378 int **ctlcpp;
379 {
380 if (ctlcpp)
381 *ctlcpp = &ctlc;
382 ctlc = 0;
383 save_history(HI_INTR);
384 }
385
386 EXPORT char *
shell_getenv(name)387 shell_getenv(name)
388 char *name;
389 {
390 extern char *(*__get_env) __PR((char *__name));
391
392 if (name == NULL)
393 return ((char *)NULL);
394 if (__get_env != NULL)
395 return (__get_env(name));
396 return (getenv(name));
397 }
398
399 EXPORT void
shell_putenv(name)400 shell_putenv(name)
401 char *name;
402 {
403 extern void (*__put_env) __PR((char *__name));
404
405 if (name == NULL)
406 return;
407 if (__put_env != NULL)
408 __put_env(name);
409 else
410 putenv(name);
411 }
412
413 EXPORT void
414 shedit_getenv(genv)
415 char *(*genv) __PR((char *name));
416 {
417 extern char *(*__get_env) __PR((char *__name));
418
419 __get_env = genv;
420 }
421
422 EXPORT void
423 shedit_putenv(penv)
424 void (*penv) __PR((char *name));
425 {
426 extern void (*__put_env) __PR((char *__name));
427
428 __put_env = penv;
429 }
430
431 EXPORT void
432 shedit_igneof(ieof)
433 BOOL (*ieof) __PR((void));
434 {
435 extern BOOL (*__ign_eof) __PR((void));
436
437 __ign_eof = ieof;
438 }
439
440 EXPORT void
shedit_setprompts(promptidx,nprompts,newprompts)441 shedit_setprompts(promptidx, nprompts, newprompts)
442 int promptidx;
443 int nprompts;
444 char *newprompts[];
445 {
446 int i;
447
448 prompt = promptidx;
449
450 if (nprompts > SHEDIT_NPROMPTS)
451 nprompts = SHEDIT_NPROMPTS;
452
453 for (i = 0; i < nprompts; i++)
454 prompts[i] = newprompts[i];
455 }
456
457 EXPORT void
shedit_spromptidx(promptidx)458 shedit_spromptidx(promptidx)
459 int promptidx;
460 {
461 prompt = promptidx;
462
463 if (prompt >= SHEDIT_NPROMPTS)
464 prompt = SHEDIT_NPROMPTS-1;
465 }
466
467 EXPORT int
shedit_gpromptidx()468 shedit_gpromptidx()
469 {
470 return (prompt);
471 }
472
473 LOCAL int
lstatat(name,buf,flag)474 lstatat(name, buf, flag)
475 char *name;
476 struct stat *buf;
477 int flag;
478 {
479 #ifdef HAVE_FCHDIR
480 char *p;
481 int fd;
482 int err;
483 #endif
484 int ret;
485
486 if ((ret = fstatat(AT_FDCWD, name, buf, flag)) < 0 &&
487 geterrno() != ENAMETOOLONG) {
488 return (ret);
489 }
490
491 #ifdef HAVE_FCHDIR
492 if (ret >= 0)
493 return (ret);
494
495 fd = bsh_hop_dirs(name, &p);
496 ret = fstatat(fd, p, buf, flag);
497 err = geterrno();
498 close(fd);
499 seterrno(err);
500 #endif
501 return (ret);
502 }
503