1 /*
2 ** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $
3 ** Standard I/O (and system) library
4 ** See Copyright Notice in lua.h
5 */
6 
7 #define liolib_c
8 #define LUA_LIB
9 
10 #include "lprefix.h"
11 
12 
13 #include <ctype.h>
14 #include <errno.h>
15 #include <locale.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #include "lua.h"
21 
22 #include "lauxlib.h"
23 #include "lualib.h"
24 
25 
26 #if !defined(l_checkmode)
27 
28 /*
29 ** Check whether 'mode' matches '[rwa]%+?b?'.
30 ** Change this macro to accept other modes for 'fopen' besides
31 ** the standard ones.
32 */
33 #define l_checkmode(mode) \
34 	(*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&	\
35 	(*mode != '+' || ++mode) &&  /* skip if char is '+' */	\
36 	(*mode != 'b' || ++mode) &&  /* skip if char is 'b' */	\
37 	(*mode == '\0'))
38 
39 #endif
40 
41 /*
42 ** {======================================================
43 ** l_popen spawns a new process connected to the current
44 ** one through the file streams.
45 ** =======================================================
46 */
47 
48 #if !defined(l_popen)		/* { */
49 
50 #if defined(LUA_USE_POSIX)	/* { */
51 
52 #define l_popen(L,c,m)		(fflush(NULL), popen(c,m))
53 #define l_pclose(L,file)	(pclose(file))
54 
55 #elif defined(LUA_USE_WINDOWS)	/* }{ */
56 
57 #define l_popen(L,c,m)		(_popen(c,m))
58 #define l_pclose(L,file)	(_pclose(file))
59 
60 #else				/* }{ */
61 
62 /* ISO C definitions */
63 #define l_popen(L,c,m)  \
64 	  ((void)((void)c, m), \
65 	  luaL_error(L, "'popen' not supported"), \
66 	  (FILE*)0)
67 #define l_pclose(L,file)		((void)L, (void)file, -1)
68 
69 #endif				/* } */
70 
71 #endif				/* } */
72 
73 /* }====================================================== */
74 
75 
76 #if !defined(l_getc)		/* { */
77 
78 #if defined(LUA_USE_POSIX)
79 #define l_getc(f)		getc_unlocked(f)
80 #define l_lockfile(f)		flockfile(f)
81 #define l_unlockfile(f)		funlockfile(f)
82 #else
83 #define l_getc(f)		getc(f)
84 #define l_lockfile(f)		((void)0)
85 #define l_unlockfile(f)		((void)0)
86 #endif
87 
88 #endif				/* } */
89 
90 
91 /*
92 ** {======================================================
93 ** l_fseek: configuration for longer offsets
94 ** =======================================================
95 */
96 
97 #if !defined(l_fseek)		/* { */
98 
99 #if defined(LUA_USE_POSIX)	/* { */
100 
101 #include <sys/types.h>
102 
103 #define l_fseek(f,o,w)		fseeko(f,o,w)
104 #define l_ftell(f)		ftello(f)
105 #define l_seeknum		off_t
106 
107 #elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
108    && defined(_MSC_VER) && (_MSC_VER >= 1400)	/* }{ */
109 
110 /* Windows (but not DDK) and Visual C++ 2005 or higher */
111 #define l_fseek(f,o,w)		_fseeki64(f,o,w)
112 #define l_ftell(f)		_ftelli64(f)
113 #define l_seeknum		__int64
114 
115 #else				/* }{ */
116 
117 /* ISO C definitions */
118 #define l_fseek(f,o,w)		fseek(f,o,w)
119 #define l_ftell(f)		ftell(f)
120 #define l_seeknum		long
121 
122 #endif				/* } */
123 
124 #endif				/* } */
125 
126 /* }====================================================== */
127 
128 
129 #define IO_PREFIX	"_IO_"
130 #define IOPREF_LEN	(sizeof(IO_PREFIX)/sizeof(char) - 1)
131 #define IO_INPUT	(IO_PREFIX "input")
132 #define IO_OUTPUT	(IO_PREFIX "output")
133 
134 
135 typedef luaL_Stream LStream;
136 
137 
138 #define tolstream(L)	((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
139 
140 #define isclosed(p)	((p)->closef == NULL)
141 
142 
io_type(lua_State * L)143 static int io_type (lua_State *L) {
144   LStream *p;
145   luaL_checkany(L, 1);
146   p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
147   if (p == NULL)
148     lua_pushnil(L);  /* not a file */
149   else if (isclosed(p))
150     lua_pushliteral(L, "closed file");
151   else
152     lua_pushliteral(L, "file");
153   return 1;
154 }
155 
156 
f_tostring(lua_State * L)157 static int f_tostring (lua_State *L) {
158   LStream *p = tolstream(L);
159   if (isclosed(p))
160     lua_pushliteral(L, "file (closed)");
161   else
162     lua_pushfstring(L, "file (%p)", p->f);
163   return 1;
164 }
165 
166 
tofile(lua_State * L)167 static FILE *tofile (lua_State *L) {
168   LStream *p = tolstream(L);
169   if (isclosed(p))
170     luaL_error(L, "attempt to use a closed file");
171   lua_assert(p->f);
172   return p->f;
173 }
174 
175 
176 /*
177 ** When creating file handles, always creates a 'closed' file handle
178 ** before opening the actual file; so, if there is a memory error, the
179 ** file is not left opened.
180 */
newprefile(lua_State * L)181 static LStream *newprefile (lua_State *L) {
182   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
183   p->closef = NULL;  /* mark file handle as 'closed' */
184   luaL_setmetatable(L, LUA_FILEHANDLE);
185   return p;
186 }
187 
188 
189 /*
190 ** Calls the 'close' function from a file handle. The 'volatile' avoids
191 ** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
192 ** 32 bits).
193 */
aux_close(lua_State * L)194 static int aux_close (lua_State *L) {
195   LStream *p = tolstream(L);
196   volatile lua_CFunction cf = p->closef;
197   p->closef = NULL;  /* mark stream as closed */
198   return (*cf)(L);  /* close it */
199 }
200 
201 
io_close(lua_State * L)202 static int io_close (lua_State *L) {
203   if (lua_isnone(L, 1))  /* no argument? */
204     lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
205   tofile(L);  /* make sure argument is an open stream */
206   return aux_close(L);
207 }
208 
209 
f_gc(lua_State * L)210 static int f_gc (lua_State *L) {
211   LStream *p = tolstream(L);
212   if (!isclosed(p) && p->f != NULL)
213     aux_close(L);  /* ignore closed and incompletely open files */
214   return 0;
215 }
216 
217 
218 /*
219 ** function to close regular files
220 */
io_fclose(lua_State * L)221 static int io_fclose (lua_State *L) {
222   LStream *p = tolstream(L);
223   int res = fclose(p->f);
224   return luaL_fileresult(L, (res == 0), NULL);
225 }
226 
227 
newfile(lua_State * L)228 static LStream *newfile (lua_State *L) {
229   LStream *p = newprefile(L);
230   p->f = NULL;
231   p->closef = &io_fclose;
232   return p;
233 }
234 
235 
opencheck(lua_State * L,const char * fname,const char * mode)236 static void opencheck (lua_State *L, const char *fname, const char *mode) {
237   LStream *p = newfile(L);
238   p->f = fopen(fname, mode);
239   if (p->f == NULL)
240     luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
241 }
242 
243 
io_open(lua_State * L)244 static int io_open (lua_State *L) {
245   const char *filename = luaL_checkstring(L, 1);
246   const char *mode = luaL_optstring(L, 2, "r");
247   LStream *p = newfile(L);
248   const char *md = mode;  /* to traverse/check mode */
249   luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
250   p->f = fopen(filename, mode);
251   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
252 }
253 
254 
255 /*
256 ** function to close 'popen' files
257 */
io_pclose(lua_State * L)258 static int io_pclose (lua_State *L) {
259   LStream *p = tolstream(L);
260   return luaL_execresult(L, l_pclose(L, p->f));
261 }
262 
263 
io_popen(lua_State * L)264 static int io_popen (lua_State *L) {
265   const char *filename = luaL_checkstring(L, 1);
266   const char *mode = luaL_optstring(L, 2, "r");
267   LStream *p = newprefile(L);
268   p->f = l_popen(L, filename, mode);
269   p->closef = &io_pclose;
270   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
271 }
272 
273 
io_tmpfile(lua_State * L)274 static int io_tmpfile (lua_State *L) {
275   LStream *p = newfile(L);
276   p->f = tmpfile();
277   return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
278 }
279 
280 
getiofile(lua_State * L,const char * findex)281 static FILE *getiofile (lua_State *L, const char *findex) {
282   LStream *p;
283   lua_getfield(L, LUA_REGISTRYINDEX, findex);
284   p = (LStream *)lua_touserdata(L, -1);
285   if (isclosed(p))
286     luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
287   return p->f;
288 }
289 
290 
g_iofile(lua_State * L,const char * f,const char * mode)291 static int g_iofile (lua_State *L, const char *f, const char *mode) {
292   if (!lua_isnoneornil(L, 1)) {
293     const char *filename = lua_tostring(L, 1);
294     if (filename)
295       opencheck(L, filename, mode);
296     else {
297       tofile(L);  /* check that it's a valid file handle */
298       lua_pushvalue(L, 1);
299     }
300     lua_setfield(L, LUA_REGISTRYINDEX, f);
301   }
302   /* return current value */
303   lua_getfield(L, LUA_REGISTRYINDEX, f);
304   return 1;
305 }
306 
307 
io_input(lua_State * L)308 static int io_input (lua_State *L) {
309   return g_iofile(L, IO_INPUT, "r");
310 }
311 
312 
io_output(lua_State * L)313 static int io_output (lua_State *L) {
314   return g_iofile(L, IO_OUTPUT, "w");
315 }
316 
317 
318 static int io_readline (lua_State *L);
319 
320 
aux_lines(lua_State * L,int toclose)321 static void aux_lines (lua_State *L, int toclose) {
322   int n = lua_gettop(L) - 1;  /* number of arguments to read */
323   lua_pushinteger(L, n);  /* number of arguments to read */
324   lua_pushboolean(L, toclose);  /* close/not close file when finished */
325   lua_rotate(L, 2, 2);  /* move 'n' and 'toclose' to their positions */
326   lua_pushcclosure(L, io_readline, 3 + n);
327 }
328 
329 
f_lines(lua_State * L)330 static int f_lines (lua_State *L) {
331   tofile(L);  /* check that it's a valid file handle */
332   aux_lines(L, 0);
333   return 1;
334 }
335 
336 
io_lines(lua_State * L)337 static int io_lines (lua_State *L) {
338   int toclose;
339   if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */
340   if (lua_isnil(L, 1)) {  /* no file name? */
341     lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);  /* get default input */
342     lua_replace(L, 1);  /* put it at index 1 */
343     tofile(L);  /* check that it's a valid file handle */
344     toclose = 0;  /* do not close it after iteration */
345   }
346   else {  /* open a new file */
347     const char *filename = luaL_checkstring(L, 1);
348     opencheck(L, filename, "r");
349     lua_replace(L, 1);  /* put file at index 1 */
350     toclose = 1;  /* close it after iteration */
351   }
352   aux_lines(L, toclose);
353   return 1;
354 }
355 
356 
357 /*
358 ** {======================================================
359 ** READ
360 ** =======================================================
361 */
362 
363 
364 /* maximum length of a numeral */
365 #define MAXRN		200
366 
367 /* auxiliary structure used by 'read_number' */
368 typedef struct {
369   FILE *f;  /* file being read */
370   int c;  /* current character (look ahead) */
371   int n;  /* number of elements in buffer 'buff' */
372   char buff[MAXRN + 1];  /* +1 for ending '\0' */
373 } RN;
374 
375 
376 /*
377 ** Add current char to buffer (if not out of space) and read next one
378 */
nextc(RN * rn)379 static int nextc (RN *rn) {
380   if (rn->n >= MAXRN) {  /* buffer overflow? */
381     rn->buff[0] = '\0';  /* invalidate result */
382     return 0;  /* fail */
383   }
384   else {
385     rn->buff[rn->n++] = rn->c;  /* save current char */
386     rn->c = l_getc(rn->f);  /* read next one */
387     return 1;
388   }
389 }
390 
391 
392 /*
393 ** Accept current char if it is in 'set' (of size 1 or 2)
394 */
test2(RN * rn,const char * set)395 static int test2 (RN *rn, const char *set) {
396   if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0'))
397     return nextc(rn);
398   else return 0;
399 }
400 
401 
402 /*
403 ** Read a sequence of (hex)digits
404 */
readdigits(RN * rn,int hex)405 static int readdigits (RN *rn, int hex) {
406   int count = 0;
407   while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
408     count++;
409   return count;
410 }
411 
412 
413 /* access to locale "radix character" (decimal point) */
414 #if !defined(l_getlocaledecpoint)
415 #define l_getlocaledecpoint()     (localeconv()->decimal_point[0])
416 #endif
417 
418 
419 /*
420 ** Read a number: first reads a valid prefix of a numeral into a buffer.
421 ** Then it calls 'lua_stringtonumber' to check whether the format is
422 ** correct and to convert it to a Lua number
423 */
read_number(lua_State * L,FILE * f)424 static int read_number (lua_State *L, FILE *f) {
425   RN rn;
426   int count = 0;
427   int hex = 0;
428   char decp[2] = ".";
429   rn.f = f; rn.n = 0;
430   decp[0] = l_getlocaledecpoint();  /* get decimal point from locale */
431   l_lockfile(rn.f);
432   do { rn.c = l_getc(rn.f); } while (isspace(rn.c));  /* skip spaces */
433   test2(&rn, "-+");  /* optional signal */
434   if (test2(&rn, "0")) {
435     if (test2(&rn, "xX")) hex = 1;  /* numeral is hexadecimal */
436     else count = 1;  /* count initial '0' as a valid digit */
437   }
438   count += readdigits(&rn, hex);  /* integral part */
439   if (test2(&rn, decp))  /* decimal point? */
440     count += readdigits(&rn, hex);  /* fractional part */
441   if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) {  /* exponent mark? */
442     test2(&rn, "-+");  /* exponent signal */
443     readdigits(&rn, 0);  /* exponent digits */
444   }
445   ungetc(rn.c, rn.f);  /* unread look-ahead char */
446   l_unlockfile(rn.f);
447   rn.buff[rn.n] = '\0';  /* finish string */
448   if (lua_stringtonumber(L, rn.buff))  /* is this a valid number? */
449     return 1;  /* ok */
450   else {  /* invalid format */
451    lua_pushnil(L);  /* "result" to be removed */
452    return 0;  /* read fails */
453   }
454 }
455 
456 
test_eof(lua_State * L,FILE * f)457 static int test_eof (lua_State *L, FILE *f) {
458   int c = getc(f);
459   ungetc(c, f);  /* no-op when c == EOF */
460   lua_pushlstring(L, NULL, 0);
461   return (c != EOF);
462 }
463 
464 
read_line(lua_State * L,FILE * f,int chop)465 static int read_line (lua_State *L, FILE *f, int chop) {
466   luaL_Buffer b;
467   int c = '\0';
468   luaL_buffinit(L, &b);
469   while (c != EOF && c != '\n') {  /* repeat until end of line */
470     char *buff = luaL_prepbuffer(&b);  /* pre-allocate buffer */
471     int i = 0;
472     l_lockfile(f);  /* no memory errors can happen inside the lock */
473     while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
474       buff[i++] = c;
475     l_unlockfile(f);
476     luaL_addsize(&b, i);
477   }
478   if (!chop && c == '\n')  /* want a newline and have one? */
479     luaL_addchar(&b, c);  /* add ending newline to result */
480   luaL_pushresult(&b);  /* close buffer */
481   /* return ok if read something (either a newline or something else) */
482   return (c == '\n' || lua_rawlen(L, -1) > 0);
483 }
484 
485 
read_all(lua_State * L,FILE * f)486 static void read_all (lua_State *L, FILE *f) {
487   size_t nr;
488   luaL_Buffer b;
489   luaL_buffinit(L, &b);
490   do {  /* read file in chunks of LUAL_BUFFERSIZE bytes */
491     char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE);
492     nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
493     luaL_addsize(&b, nr);
494   } while (nr == LUAL_BUFFERSIZE);
495   luaL_pushresult(&b);  /* close buffer */
496 }
497 
498 
read_chars(lua_State * L,FILE * f,size_t n)499 static int read_chars (lua_State *L, FILE *f, size_t n) {
500   size_t nr;  /* number of chars actually read */
501   char *p;
502   luaL_Buffer b;
503   luaL_buffinit(L, &b);
504   p = luaL_prepbuffsize(&b, n);  /* prepare buffer to read whole block */
505   nr = fread(p, sizeof(char), n, f);  /* try to read 'n' chars */
506   luaL_addsize(&b, nr);
507   luaL_pushresult(&b);  /* close buffer */
508   return (nr > 0);  /* true iff read something */
509 }
510 
511 
g_read(lua_State * L,FILE * f,int first)512 static int g_read (lua_State *L, FILE *f, int first) {
513   int nargs = lua_gettop(L) - 1;
514   int success;
515   int n;
516   clearerr(f);
517   if (nargs == 0) {  /* no arguments? */
518     success = read_line(L, f, 1);
519     n = first+1;  /* to return 1 result */
520   }
521   else {  /* ensure stack space for all results and for auxlib's buffer */
522     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
523     success = 1;
524     for (n = first; nargs-- && success; n++) {
525       if (lua_type(L, n) == LUA_TNUMBER) {
526         size_t l = (size_t)luaL_checkinteger(L, n);
527         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
528       }
529       else {
530         const char *p = luaL_checkstring(L, n);
531         if (*p == '*') p++;  /* skip optional '*' (for compatibility) */
532         switch (*p) {
533           case 'n':  /* number */
534             success = read_number(L, f);
535             break;
536           case 'l':  /* line */
537             success = read_line(L, f, 1);
538             break;
539           case 'L':  /* line with end-of-line */
540             success = read_line(L, f, 0);
541             break;
542           case 'a':  /* file */
543             read_all(L, f);  /* read entire file */
544             success = 1; /* always success */
545             break;
546           default:
547             return luaL_argerror(L, n, "invalid format");
548         }
549       }
550     }
551   }
552   if (ferror(f))
553     return luaL_fileresult(L, 0, NULL);
554   if (!success) {
555     lua_pop(L, 1);  /* remove last result */
556     lua_pushnil(L);  /* push nil instead */
557   }
558   return n - first;
559 }
560 
561 
io_read(lua_State * L)562 static int io_read (lua_State *L) {
563   return g_read(L, getiofile(L, IO_INPUT), 1);
564 }
565 
566 
f_read(lua_State * L)567 static int f_read (lua_State *L) {
568   return g_read(L, tofile(L), 2);
569 }
570 
571 
io_readline(lua_State * L)572 static int io_readline (lua_State *L) {
573   LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
574   int i;
575   int n = (int)lua_tointeger(L, lua_upvalueindex(2));
576   if (isclosed(p))  /* file is already closed? */
577     return luaL_error(L, "file is already closed");
578   lua_settop(L , 1);
579   luaL_checkstack(L, n, "too many arguments");
580   for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
581     lua_pushvalue(L, lua_upvalueindex(3 + i));
582   n = g_read(L, p->f, 2);  /* 'n' is number of results */
583   lua_assert(n > 0);  /* should return at least a nil */
584   if (lua_toboolean(L, -n))  /* read at least one value? */
585     return n;  /* return them */
586   else {  /* first result is nil: EOF or error */
587     if (n > 1) {  /* is there error information? */
588       /* 2nd result is error message */
589       return luaL_error(L, "%s", lua_tostring(L, -n + 1));
590     }
591     if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
592       lua_settop(L, 0);
593       lua_pushvalue(L, lua_upvalueindex(1));
594       aux_close(L);  /* close it */
595     }
596     return 0;
597   }
598 }
599 
600 /* }====================================================== */
601 
602 
g_write(lua_State * L,FILE * f,int arg)603 static int g_write (lua_State *L, FILE *f, int arg) {
604   int nargs = lua_gettop(L) - arg;
605   int status = 1;
606   for (; nargs--; arg++) {
607     if (lua_type(L, arg) == LUA_TNUMBER) {
608       /* optimization: could be done exactly as for strings */
609       int len = lua_isinteger(L, arg)
610                 ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
611                 : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
612       status = status && (len > 0);
613     }
614     else {
615       size_t l;
616       const char *s = luaL_checklstring(L, arg, &l);
617       status = status && (fwrite(s, sizeof(char), l, f) == l);
618     }
619   }
620   if (status) return 1;  /* file handle already on stack top */
621   else return luaL_fileresult(L, status, NULL);
622 }
623 
624 
io_write(lua_State * L)625 static int io_write (lua_State *L) {
626   return g_write(L, getiofile(L, IO_OUTPUT), 1);
627 }
628 
629 
f_write(lua_State * L)630 static int f_write (lua_State *L) {
631   FILE *f = tofile(L);
632   lua_pushvalue(L, 1);  /* push file at the stack top (to be returned) */
633   return g_write(L, f, 2);
634 }
635 
636 
f_seek(lua_State * L)637 static int f_seek (lua_State *L) {
638   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
639   static const char *const modenames[] = {"set", "cur", "end", NULL};
640   FILE *f = tofile(L);
641   int op = luaL_checkoption(L, 2, "cur", modenames);
642   lua_Integer p3 = luaL_optinteger(L, 3, 0);
643   l_seeknum offset = (l_seeknum)p3;
644   luaL_argcheck(L, (lua_Integer)offset == p3, 3,
645                   "not an integer in proper range");
646   op = l_fseek(f, offset, mode[op]);
647   if (op)
648     return luaL_fileresult(L, 0, NULL);  /* error */
649   else {
650     lua_pushinteger(L, (lua_Integer)l_ftell(f));
651     return 1;
652   }
653 }
654 
655 
f_setvbuf(lua_State * L)656 static int f_setvbuf (lua_State *L) {
657   static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
658   static const char *const modenames[] = {"no", "full", "line", NULL};
659   FILE *f = tofile(L);
660   int op = luaL_checkoption(L, 2, NULL, modenames);
661   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
662   int res = setvbuf(f, NULL, mode[op], (size_t)sz);
663   return luaL_fileresult(L, res == 0, NULL);
664 }
665 
666 
667 
io_flush(lua_State * L)668 static int io_flush (lua_State *L) {
669   return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
670 }
671 
672 
f_flush(lua_State * L)673 static int f_flush (lua_State *L) {
674   return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
675 }
676 
677 
678 /*
679 ** functions for 'io' library
680 */
681 static const luaL_Reg iolib[] = {
682   {"close", io_close},
683   {"flush", io_flush},
684   {"input", io_input},
685   {"lines", io_lines},
686   {"open", io_open},
687   {"output", io_output},
688   {"popen", io_popen},
689   {"read", io_read},
690   {"tmpfile", io_tmpfile},
691   {"type", io_type},
692   {"write", io_write},
693   {NULL, NULL}
694 };
695 
696 
697 /*
698 ** methods for file handles
699 */
700 static const luaL_Reg flib[] = {
701   {"close", io_close},
702   {"flush", f_flush},
703   {"lines", f_lines},
704   {"read", f_read},
705   {"seek", f_seek},
706   {"setvbuf", f_setvbuf},
707   {"write", f_write},
708   {"__gc", f_gc},
709   {"__tostring", f_tostring},
710   {NULL, NULL}
711 };
712 
713 
createmeta(lua_State * L)714 static void createmeta (lua_State *L) {
715   luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
716   lua_pushvalue(L, -1);  /* push metatable */
717   lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
718   luaL_setfuncs(L, flib, 0);  /* add file methods to new metatable */
719   lua_pop(L, 1);  /* pop new metatable */
720 }
721 
722 
723 /*
724 ** function to (not) close the standard files stdin, stdout, and stderr
725 */
io_noclose(lua_State * L)726 static int io_noclose (lua_State *L) {
727   LStream *p = tolstream(L);
728   p->closef = &io_noclose;  /* keep file opened */
729   lua_pushnil(L);
730   lua_pushliteral(L, "cannot close standard file");
731   return 2;
732 }
733 
734 
createstdfile(lua_State * L,FILE * f,const char * k,const char * fname)735 static void createstdfile (lua_State *L, FILE *f, const char *k,
736                            const char *fname) {
737   LStream *p = newprefile(L);
738   p->f = f;
739   p->closef = &io_noclose;
740   if (k != NULL) {
741     lua_pushvalue(L, -1);
742     lua_setfield(L, LUA_REGISTRYINDEX, k);  /* add file to registry */
743   }
744   lua_setfield(L, -2, fname);  /* add file to module */
745 }
746 
747 
luaopen_io(lua_State * L)748 LUAMOD_API int luaopen_io (lua_State *L) {
749   luaL_newlib(L, iolib);  /* new module */
750   createmeta(L);
751   /* create (and set) default files */
752   createstdfile(L, stdin, IO_INPUT, "stdin");
753   createstdfile(L, stdout, IO_OUTPUT, "stdout");
754   createstdfile(L, stderr, NULL, "stderr");
755   return 1;
756 }
757 
758