Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ie/editlib.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1984-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* Pat Sullivan *
19
* *
20
***********************************************************************/
21
/*
22
* Miscellaneous routine needed for standalone library for edit modes
23
*/
24
25
#define read ______read
26
27
#include "io.h"
28
#include "terminal.h"
29
#include "history.h"
30
31
#undef read
32
33
#include "edit.h"
34
#ifdef LDYNAMIC
35
# include "dlldefs.h"
36
#endif
37
#ifdef TIOCLBIC
38
# undef TIOCLBIC
39
# ifdef _sys_ioctl
40
# include <sys/ioctl.h>
41
# endif /* _sys_ioctl */
42
#endif /* TIOCLBIC */
43
44
#undef read
45
46
#ifdef __EXPORT__
47
# define extern __EXPORT__
48
#endif
49
50
#define e_create "cannot create"
51
52
char opt_flag = 0;
53
char ed_errbuf[IOBSIZE+1] = { 0 };
54
struct fileblk *io_ftable[NFILE+USERIO] = { 0 };
55
static struct fileblk outfile = { ed_errbuf, ed_errbuf, ed_errbuf+IOBSIZE, 2, IOWRT};
56
static int editfd;
57
static int output = 0;
58
static char beenhere;
59
60
#if 0 /* almost always false. Makes a good block comment */
61
**********************************************************************
62
* There are two scenarios here.
63
*
64
* 1) We ALWAYS want ksh-editing on the terminal input.
65
* 2) We SOMETIMES want ksh-editing on the terminal input.
66
*
67
* If you are running with case 1, then just call read() in the usual
68
* manner and be happy.
69
*
70
* If you want to only have line-editing sometimes, and the very first
71
* read() is not one of those times, then you must perform the
72
* initialization first, turn OFF editing, perform your read(), and
73
* so forth. An example of this is in a curses application in which
74
* single characters are read in RAW mode and acted upon immediately.
75
* Line editing here will not work.
76
*
77
* Do the following:
78
* edit_Init();
79
* SAVopt_flag = set_edit(0,0); /* fd=0 set to NO editing */
80
* read(0,buffer,1); /* do your single char read */
81
* set_edit(0,SAVopt_flag); /* restore editing on fd=0 */
82
**********************************************************************
83
#endif /* 0 */
84
85
int edit_Init()
86
{
87
register char *sp;
88
if(!beenhere)
89
{
90
beenhere = 1;
91
hist_open();
92
if(!(sp = getenv("VISUAL")))
93
sp = getenv("EDITOR");
94
if(sp)
95
{
96
if(strrchr(sp,'/'))
97
sp = strrchr(sp,'/')+1;
98
if(strcmp(sp,"vi") == 0)
99
opt_flag = EDITVI;
100
else if(strcmp(sp,"emacs")==0)
101
opt_flag = EMACS;
102
else if(strcmp(sp,"gmacs")==0)
103
opt_flag = GMACS;
104
}
105
}
106
return(1);
107
}
108
/*
109
* read routine with edit modes
110
*/
111
112
#ifdef LDYNAMIC
113
#ifdef __STDC__
114
typedef ssize_t (*Read_f)(int, void*, size_t);
115
#else
116
typedef ssize_t (*Read_f)();
117
#endif
118
119
ssize_t rEAd(fd,buf,n)
120
int fd;
121
void *buf;
122
size_t n;
123
{
124
ssize_t r;
125
126
static Read_f readfn;
127
static int here;
128
static int loop;
129
static void* dll;
130
131
static char msg[] = "ie: cannot intercept read() system call\n";
132
133
/*
134
* on some systems read() is globally bound by the
135
* runtime linker which may get us into a loop if
136
* another library intercepts read() between us and
137
* the system library
138
* on these systems the (dllnext)() call bypasses
139
* any intermediate libraries and gets directly to
140
* the system library
141
*/
142
143
if (here++)
144
{
145
if (loop++)
146
return -1;
147
if (!(dll = (dllnext)(RTLD_LAZY)))
148
goto bad;
149
readfn = 0;
150
}
151
if (!readfn)
152
{
153
if (!dll && !(dll = dllnext(RTLD_LAZY)))
154
goto bad;
155
if (!(readfn = (Read_f)dlsym(dll, "_read")) && !(readfn = (Read_f)dlsym(dll, "read")))
156
goto bad;
157
}
158
r = (*readfn)(fd, buf, n);
159
here--;
160
return r;
161
bad:
162
write(2, msg, sizeof(msg) - 1);
163
return -1;
164
}
165
#endif /* LDYNAMIC */
166
167
extern ssize_t read(fd,buf,n)
168
int fd;
169
void *buf;
170
size_t n;
171
{
172
register int r, flag;
173
char *buff = (char*)buf;
174
if(fd==editfd && !beenhere)
175
edit_Init();
176
flag = (fd==editfd?opt_flag&EDITMASK:0);
177
switch(flag)
178
{
179
case EMACS:
180
case GMACS:
181
tty_set(-1);
182
r = emacs_read(fd,buff,n);
183
break;
184
185
case VIRAW:
186
case EDITVI:
187
tty_set(-1);
188
r = vi_read(fd,buff,n);
189
break;
190
default:
191
{
192
#ifdef SYSCALL
193
r = syscall(3,fd,buff,n);
194
#else
195
r = rEAd(fd,buff,n);
196
#endif /* SYSCALL */
197
}
198
}
199
if(fd==editfd && hist_ptr && (opt_flag&NOHIST)==0 && r>0)
200
{
201
/* write and flush history */
202
int c = buff[r];
203
buff[r] = 0;
204
hist_eof();
205
p_setout(hist_ptr->fixfd);
206
p_str(buff,0);
207
hist_flush();
208
buff[r] = c;
209
}
210
return(r);
211
}
212
213
#ifndef __EXPORT__
214
215
extern ssize_t _read(fd,buf,n)
216
int fd;
217
void *buf;
218
size_t n;
219
{
220
return(read(fd,buf,n));
221
}
222
223
extern ssize_t __read(fd,buf,n)
224
int fd;
225
void *buf;
226
size_t n;
227
{
228
return(read(fd,buf,n));
229
}
230
231
extern ssize_t _libc_read(fd,buf,n)
232
int fd;
233
void *buf;
234
size_t n;
235
{
236
return(read(fd,buf,n));
237
}
238
239
extern ssize_t __libc_read(fd,buf,n)
240
int fd;
241
void *buf;
242
size_t n;
243
{
244
return(read(fd,buf,n));
245
}
246
247
#endif
248
249
/*
250
* enable edit mode <mode> on file number <fd>
251
* the NOHIST bit can also be set to avoid writing the history file
252
* <fd> cannot be file two
253
*/
254
255
int set_edit(fd,mode)
256
int fd;
257
int mode;
258
{
259
int retval = opt_flag;
260
opt_flag = mode;
261
if(fd==2)
262
return(-1);
263
editfd = fd;
264
return(retval);
265
}
266
267
/*
268
* flush the output queue and reset the output stream
269
*/
270
271
void p_setout(fd)
272
register int fd;
273
{
274
register struct fileblk *fp;
275
if(!io_ftable[fd])
276
io_ftable[fd] = &outfile;
277
fp = io_ftable[fd];
278
fp->last = fp->base + IOBSIZE;
279
fp->flag &= ~(IOREAD|IOERR|IOEOF);
280
if(output==fd)
281
return;
282
if(io_ftable[fd]==io_ftable[output])
283
p_flush();
284
output = fd;
285
}
286
287
/*
288
* flush the output if necessary and null terminate the buffer
289
*/
290
291
void p_flush()
292
{
293
register struct fileblk *fp = io_ftable[output];
294
register int count;
295
if(fp && (count=fp->ptr-fp->base))
296
{
297
if(write(output,fp->base,count) < 0)
298
fp->flag |= IOERR;
299
/* leave previous buffer as a null terminated string */
300
*fp->ptr = 0;
301
fp->ptr = fp->base;
302
}
303
}
304
305
/*
306
* print a given character
307
*/
308
309
void p_char(c)
310
register int c;
311
{
312
register struct fileblk *fp = io_ftable[output];
313
if(fp->ptr >= fp->last)
314
p_flush();
315
*fp->ptr++ = c;
316
}
317
318
/*
319
* print a string optionally followed by a character
320
*/
321
322
void p_str(string,c)
323
register char *string;
324
int c;
325
{
326
register struct fileblk *fp = io_ftable[output];
327
register int cc;
328
while(1)
329
{
330
if((cc= *string)==0)
331
cc = c,c = 0;
332
else
333
string++;
334
if(cc==0)
335
break;
336
if(fp->ptr >= fp->last)
337
p_flush();
338
*fp->ptr++ = cc;
339
}
340
}
341
342
/*
343
* copy string a to string b and return pointer to end of string b
344
*/
345
346
char *ed_movstr(a,b)
347
register const char *a;
348
register char *b;
349
{
350
while(*b++ = *a++);
351
return(--b);
352
}
353
354
/*
355
* print and error message and exit
356
*/
357
358
void ed_failed(name,message)
359
char *name,*message;
360
{
361
p_setout(ERRIO);
362
p_str(name,' ');
363
p_char(':');
364
p_char(' ');
365
p_str(message,'\n');
366
exit(2);
367
}
368
369
/*
370
* print a prompt
371
*/
372
void pr_prompt(string)
373
register char *string;
374
{
375
register int c;
376
register char *dp = editb.e_prbuff;
377
#ifdef TIOCLBIC
378
int mode;
379
mode = LFLUSHO;
380
ioctl(ERRIO,TIOCLBIC,&mode);
381
#endif /* TIOCLBIC */
382
p_setout(ERRIO);
383
while(c= *string++)
384
{
385
if(dp < editb.e_prbuff+PRSIZE)
386
*dp++ = c;
387
p_char(c);
388
}
389
*dp = 0;
390
if (!(opt_flag&EDITMASK))
391
p_flush();
392
393
}
394
395
396