00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
00039 #endif
00040
00041
00042
00043
00044
00045 #include <sys/types.h>
00046 #include <stdio.h>
00047 #include "shell.h"
00048 #include <fcntl.h>
00049 #include <errno.h>
00050 #include "syntax.h"
00051 #include "input.h"
00052 #include "output.h"
00053 #include "memalloc.h"
00054 #include "error.h"
00055
00056 #define EOF_NLEFT -99
00057
00058
00059
00060
00061
00062
00063
00064 MKINIT
00065 struct parsefile {
00066 int linno;
00067 int fd;
00068 int nleft;
00069 char *nextc;
00070 struct parsefile *prev;
00071 char *buf;
00072 };
00073
00074
00075 int plinno = 1;
00076 MKINIT int parsenleft;
00077 char *parsenextc;
00078 MKINIT struct parsefile basepf;
00079 char basebuf[BUFSIZ];
00080 struct parsefile *parsefile = &basepf;
00081 char *pushedstring;
00082 int pushednleft;
00083
00084 #if READLINE
00085 char *readline __P((const char *prompt));
00086 char *r_use_prompt = NULL;
00087 #endif
00088
00089 #ifdef __STDC__
00090 STATIC void pushfile(void);
00091 #else
00092 STATIC void pushfile();
00093 #endif
00094
00095
00096
00097 #ifdef mkinit
00098 INCLUDE "input.h"
00099 INCLUDE "error.h"
00100
00101 INIT {
00102 extern char basebuf[];
00103
00104 basepf.nextc = basepf.buf = basebuf;
00105 }
00106
00107 RESET {
00108 if (exception != EXSHELLPROC)
00109 parsenleft = 0;
00110 popallfiles();
00111 }
00112
00113 SHELLPROC {
00114 popallfiles();
00115 }
00116 #endif
00117
00118
00119
00120
00121
00122
00123 char *
00124 pfgets(line, len)
00125 char *line;
00126 {
00127 register char *p = line;
00128 int nleft = len;
00129 int c;
00130
00131 while (--nleft > 0) {
00132 c = pgetc_macro();
00133 if (c == PEOF) {
00134 if (p == line)
00135 return NULL;
00136 break;
00137 }
00138 *p++ = c;
00139 if (c == '\n')
00140 break;
00141 }
00142 *p = '\0';
00143 return line;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153 int
00154 pgetc() {
00155 return pgetc_macro();
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int
00171 preadbuffer() {
00172 register char *p, *q;
00173 register int i;
00174
00175 if (pushedstring) {
00176 parsenextc = pushedstring;
00177 pushedstring = NULL;
00178 parsenleft = pushednleft;
00179 if (--parsenleft >= 0)
00180 return *parsenextc++;
00181 }
00182 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
00183 return PEOF;
00184 flushout(&output);
00185 flushout(&errout);
00186 #if READLINE
00187
00188 if (r_use_prompt != NULL) {
00189 char *prompt;
00190 char *line;
00191
00192 p = parsenextc = parsefile->buf;
00193
00194 prompt = r_use_prompt;
00195 r_use_prompt = NULL;
00196
00197 if ((line = readline(prompt)) == NULL) {
00198 parsenleft = EOF_NLEFT;
00199 return PEOF;
00200 }
00201 strcpy(p, line);
00202 free(line);
00203 i = strlen(p);
00204 p[i++] = '\n';
00205 } else {
00206 #endif
00207 retry:
00208 p = parsenextc = parsefile->buf;
00209 i = read(parsefile->fd, p, BUFSIZ);
00210 if (i <= 0) {
00211 if (i < 0) {
00212 if (errno == EINTR)
00213 goto retry;
00214 #ifdef EWOULDBLOCK
00215 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
00216 int flags = fcntl(0, F_GETFL, 0);
00217 if (flags >= 0 && flags & O_NONBLOCK) {
00218 flags &=~ O_NONBLOCK;
00219 if (fcntl(0, F_SETFL, flags) >= 0) {
00220 out2str("sh: turning off NDELAY mode\n");
00221 goto retry;
00222 }
00223 }
00224 }
00225 #endif
00226 }
00227 parsenleft = EOF_NLEFT;
00228 return PEOF;
00229 }
00230 #if READLINE
00231 }
00232 #endif
00233 parsenleft = i - 1;
00234
00235
00236 for (;;) {
00237 if (*p++ == '\0')
00238 break;
00239 if (--i <= 0)
00240 return *parsenextc++;
00241 }
00242 q = p - 1;
00243 while (--i > 0) {
00244 if (*p != '\0')
00245 *q++ = *p;
00246 p++;
00247 }
00248 if (q == parsefile->buf)
00249 goto retry;
00250 parsenleft = q - parsefile->buf - 1;
00251 return *parsenextc++;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 void
00261 pungetc() {
00262 parsenleft++;
00263 parsenextc--;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272 void
00273 ppushback(string, length)
00274 char *string;
00275 {
00276 pushedstring = parsenextc;
00277 pushednleft = parsenleft;
00278 parsenextc = string;
00279 parsenleft = length;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289 void
00290 setinputfile(fname, push)
00291 char *fname;
00292 {
00293 int fd;
00294 int fd2;
00295
00296 INTOFF;
00297 if ((fd = open(fname, O_RDONLY)) < 0)
00298 error("Can't open %s", fname);
00299 if (fd < 10) {
00300 fd2 = copyfd(fd, 10);
00301 close(fd);
00302 if (fd2 < 0)
00303 error("Out of file descriptors");
00304 fd = fd2;
00305 }
00306 setinputfd(fd, push);
00307 INTON;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316 void
00317 setinputfd(fd, push) {
00318 (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
00319 if (push) {
00320 pushfile();
00321 parsefile->buf = ckmalloc(BUFSIZ);
00322 }
00323 if (parsefile->fd > 0)
00324 close(parsefile->fd);
00325 parsefile->fd = fd;
00326 if (parsefile->buf == NULL)
00327 parsefile->buf = ckmalloc(BUFSIZ);
00328 parsenleft = 0;
00329 plinno = 1;
00330 }
00331
00332
00333
00334
00335
00336
00337 void
00338 setinputstring(string, push)
00339 char *string;
00340 {
00341 INTOFF;
00342 if (push)
00343 pushfile();
00344 parsenextc = string;
00345 parsenleft = strlen(string);
00346 parsefile->buf = NULL;
00347 plinno = 1;
00348 INTON;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358 STATIC void
00359 pushfile() {
00360 struct parsefile *pf;
00361
00362 parsefile->nleft = parsenleft;
00363 parsefile->nextc = parsenextc;
00364 parsefile->linno = plinno;
00365 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
00366 pf->prev = parsefile;
00367 pf->fd = -1;
00368 parsefile = pf;
00369 }
00370
00371
00372 void
00373 popfile() {
00374 struct parsefile *pf = parsefile;
00375
00376 INTOFF;
00377 if (pf->fd >= 0)
00378 close(pf->fd);
00379 if (pf->buf)
00380 ckfree(pf->buf);
00381 parsefile = pf->prev;
00382 ckfree(pf);
00383 parsenleft = parsefile->nleft;
00384 parsenextc = parsefile->nextc;
00385 plinno = parsefile->linno;
00386 INTON;
00387 }
00388
00389
00390
00391
00392
00393
00394 void
00395 popallfiles() {
00396 while (parsefile != &basepf)
00397 popfile();
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407 void
00408 closescript() {
00409 popallfiles();
00410 if (parsefile->fd > 0) {
00411 close(parsefile->fd);
00412 parsefile->fd = 0;
00413 }
00414 }