]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/athttpd/v2_0/src/jim-aio.c
Cleanup CVS ipmorted branch
[karo-tx-redboot.git] / packages / net / athttpd / v2_0 / src / jim-aio.c
1 /* Jim - ANSI I/O extension
2  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
3  *
4  * $Id: jim-aio.c,v 1.1.1.1 2008/07/31 20:44:21 mmahesh Exp $
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * A copy of the license is also included in the source distribution
13  * of Jim, as a TXT file name called LICENSE.
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include <pkgconf/athttpd.h>
27 #ifndef JIM_STATICEXT
28 #define JIM_EXTENSION
29 #endif
30 #include <cyg/athttpd/jim.h>
31
32 #define AIO_CMD_LEN 128
33 #define AIO_BUF_LEN 1024
34
35 typedef struct AioFile {
36     FILE *fp;
37     int keepOpen; /* If set, the file is not fclosed on cleanup (stdin, ...) */
38 } AioFile;
39
40 static void JimAioSetError(Jim_Interp *interp)
41 {
42     Jim_SetResultString(interp, strerror(errno), -1);
43 }
44
45 static void JimAioDelProc(Jim_Interp *interp, void *privData)
46 {
47     AioFile *af = privData;
48     JIM_NOTUSED(interp);
49
50     if (!af->keepOpen)
51         fclose(af->fp);
52     Jim_Free(af);
53 }
54
55 /* Calls to [aio.file] create commands that are implemented by this
56  * C command. */
57 static int JimAioHandlerCommand(Jim_Interp *interp, int argc,
58         Jim_Obj *const *argv)
59 {
60     AioFile *af = Jim_CmdPrivData(interp);
61     int option;
62     const char *options[] = {
63         "close", "seek", "tell", "gets", "read", "puts", "flush", "eof", NULL
64     };
65     enum {OPT_CLOSE, OPT_SEEK, OPT_TELL, OPT_GETS, OPT_READ, OPT_PUTS,
66           OPT_FLUSH, OPT_EOF};
67
68     if (argc < 2) {
69         Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
70         return JIM_ERR;
71     }
72     if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method",
73                 JIM_ERRMSG) != JIM_OK)
74         return JIM_ERR;
75     /* CLOSE */
76     if (option == OPT_CLOSE) {
77         if (argc != 2) {
78             Jim_WrongNumArgs(interp, 2, argv, "");
79             return JIM_ERR;
80         }
81         Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL));
82         return JIM_OK;
83     } else if (option == OPT_SEEK) {
84     /* SEEK */
85         int orig = SEEK_SET;
86         long offset;
87
88         if (argc != 3 && argc != 4) {
89             Jim_WrongNumArgs(interp, 2, argv, "offset ?origin?");
90             return JIM_ERR;
91         }
92         if (argc == 4) {
93             if (Jim_CompareStringImmediate(interp, argv[3], "start"))
94                 orig = SEEK_SET;
95             else if (Jim_CompareStringImmediate(interp, argv[3], "current"))
96                 orig = SEEK_CUR;
97             else if (Jim_CompareStringImmediate(interp, argv[3], "end"))
98                 orig = SEEK_END;
99             else {
100                 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
101                 Jim_AppendStrings(interp, Jim_GetResult(interp),
102                         "bad origin \"", Jim_GetString(argv[3], NULL),
103                         "\" must be: start, current, or end", NULL);
104                 return JIM_ERR;
105             }
106         }
107         if (Jim_GetLong(interp, argv[2], &offset) != JIM_OK)
108             return JIM_ERR;
109         if (fseek(af->fp, offset, orig) == -1) {
110             JimAioSetError(interp);
111             return JIM_ERR;
112         }
113         return JIM_OK;
114     } else if (option == OPT_TELL) {
115     /* TELL */
116         long position;
117
118         if (argc != 2) {
119             Jim_WrongNumArgs(interp, 2, argv, "");
120             return JIM_ERR;
121         }
122         position = ftell(af->fp);
123         Jim_SetResult(interp, Jim_NewIntObj(interp, position));
124         return JIM_OK;
125     } else if (option == OPT_GETS) {
126     /* GETS */
127         char buf[AIO_BUF_LEN];
128         Jim_Obj *objPtr;
129
130         if (argc != 2 && argc != 3) {
131             Jim_WrongNumArgs(interp, 2, argv, "?varName?");
132             return JIM_ERR;
133         }
134         objPtr = Jim_NewStringObj(interp, NULL, 0);
135         while (1) {
136             int more = 0;
137             buf[AIO_BUF_LEN-1] = '_';
138             if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
139                 break;
140             if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN-2] == '\n')
141                 more = 1;
142             if (more) {
143                 Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1);
144             } else {
145                 /* strip "\n" */
146                 Jim_AppendString(interp, objPtr, buf, strlen(buf)-1);
147             }
148             if (!more)
149                 break;
150         }
151         if (ferror(af->fp)) {
152             /* I/O error */
153             Jim_IncrRefCount(objPtr);
154             Jim_DecrRefCount(interp, objPtr);
155             JimAioSetError(interp);
156             return JIM_ERR;
157         }
158         /* On EOF returns -1 if varName was specified, or the empty string. */
159         if (feof(af->fp) && Jim_Length(objPtr) == 0) {
160             Jim_IncrRefCount(objPtr);
161             Jim_DecrRefCount(interp, objPtr);
162             if (argc == 3)
163                 Jim_SetResult(interp, Jim_NewIntObj(interp, -1));
164             return JIM_OK;
165         }
166         if (argc == 3) {
167             int totLen;
168
169             Jim_GetString(objPtr, &totLen);
170             if (Jim_SetVariable(interp, argv[2], objPtr) != JIM_OK) {
171                 Jim_IncrRefCount(objPtr);
172                 Jim_DecrRefCount(interp, objPtr);
173                 return JIM_ERR;
174             }
175             Jim_SetResult(interp, Jim_NewIntObj(interp, totLen));
176         } else {
177             Jim_SetResult(interp, objPtr);
178         }
179         return JIM_OK;
180     } else if (option == OPT_READ) {
181     /* READ */
182         char buf[AIO_BUF_LEN];
183         Jim_Obj *objPtr;
184         int nonewline = 0;
185         int neededLen = -1; /* -1 is "read as much as possible" */
186
187         if (argc != 2 && argc != 3) {
188             Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? ?len?");
189             return JIM_ERR;
190         }
191         if (argc == 3 &&
192             Jim_CompareStringImmediate(interp, argv[2], "-nonewline"))
193         {
194             nonewline = 1;
195             argv++;
196             argc--;
197         }
198         if (argc == 3) {
199             jim_wide wideValue;
200             if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK)
201                 return JIM_ERR;
202             if (wideValue < 0) {
203                 Jim_SetResultString(interp, "invalid parameter: negative len",
204                         -1);
205                 return JIM_ERR;
206             }
207             neededLen = (int) wideValue;
208         }
209         objPtr = Jim_NewStringObj(interp, NULL, 0);
210         while (neededLen != 0) {
211             int retval;
212             int readlen;
213            
214             if (neededLen == -1) {
215                 readlen = AIO_BUF_LEN;
216             } else {
217                 readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
218             }
219             retval = fread(buf, 1, readlen, af->fp);
220             if (retval > 0) {
221                 Jim_AppendString(interp, objPtr, buf, retval);
222                 if (neededLen != -1) {
223                     neededLen -= retval;
224                 }
225             }
226             if (retval != readlen) break;
227         }
228         /* Check for error conditions */
229         if (ferror(af->fp)) {
230             /* I/O error */
231             Jim_FreeNewObj(interp, objPtr);
232             JimAioSetError(interp);
233             return JIM_ERR;
234         }
235         if (nonewline) {
236             int len;
237             const char *s = Jim_GetString(objPtr, &len);
238
239             if (len > 0 && s[len-1] == '\n') {
240                 objPtr->length--;
241                 objPtr->bytes[objPtr->length] = '\0';
242             }
243         }
244         Jim_SetResult(interp, objPtr);
245         return JIM_OK;
246     } else if (option == OPT_PUTS) {
247     /* PUTS */
248         int wlen;
249         const char *wdata;
250
251         if (argc != 3 && (argc != 4 || !Jim_CompareStringImmediate(
252                         interp, argv[2], "-nonewline"))) {
253             Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? string");
254             return JIM_ERR;
255         }
256         wdata = Jim_GetString(argv[2+(argc==4)], &wlen);
257         if (fwrite(wdata, 1, wlen, af->fp) != (unsigned)wlen ||
258             (argc == 3 && fwrite("\n", 1, 1, af->fp) != 1)) {
259             JimAioSetError(interp);
260             return JIM_ERR;
261         }
262         return JIM_OK;
263     } else if (option  == OPT_FLUSH) {
264     /* FLUSH */
265         if (argc != 2) {
266             Jim_WrongNumArgs(interp, 2, argv, "");
267             return JIM_ERR;
268         }
269         if (fflush(af->fp) == EOF) {
270             JimAioSetError(interp);
271             return JIM_ERR;
272         }
273         return JIM_OK;
274     } else if (option  == OPT_EOF) {
275     /* EOF */
276         if (argc != 2) {
277             Jim_WrongNumArgs(interp, 2, argv, "");
278             return JIM_ERR;
279         }
280         Jim_SetResult(interp, Jim_NewIntObj(interp, feof(af->fp)));
281         return JIM_OK;
282     }
283     return JIM_OK;
284 }
285
286 static int JimAioOpenCommand(Jim_Interp *interp, int argc, 
287         Jim_Obj *const *argv)
288 {
289     FILE *fp;
290     AioFile *af;
291     char buf[AIO_CMD_LEN];
292     const char *mode = "r";
293     Jim_Obj *objPtr;
294     long fileId;
295     const char *options[] = {"input", "output", "error"};
296     enum {OPT_INPUT, OPT_OUTPUT, OPT_ERROR};
297     int keepOpen = 0, modeLen;
298
299     if (argc != 2 && argc != 3) {
300         Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
301         return JIM_ERR;
302     }
303     if (argc == 3)
304         mode = Jim_GetString(argv[2], &modeLen);
305     if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "standard") &&
306             modeLen >= 3) {
307             int option;
308         if (Jim_GetEnum(interp, argv[2], options, &option, "standard channel",
309                     JIM_ERRMSG) != JIM_OK)
310             return JIM_ERR;
311         keepOpen = 1;
312         switch (option) {
313         case OPT_INPUT: fp = stdin; break;
314         case OPT_OUTPUT: fp = stdout; break;
315         case OPT_ERROR: fp = stderr; break;
316         default: fp = NULL; Jim_Panic(interp,"default reached in JimAioOpenCommand()");
317                  break;
318         }
319     } else {
320         fp = fopen(Jim_GetString(argv[1], NULL), mode);
321         if (fp == NULL) {
322             JimAioSetError(interp);
323             return JIM_ERR;
324         }
325     }
326     /* Get the next file id */
327     if (Jim_EvalGlobal(interp,
328                 "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK)
329         return JIM_ERR;
330     objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG);
331     if (objPtr == NULL) return JIM_ERR;
332     if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR;
333
334     /* Create the file command */
335     af = Jim_Alloc(sizeof(*af));
336     af->fp = fp;
337     af->keepOpen = keepOpen;
338     sprintf(buf, "aio.handle%ld", fileId);
339     Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
340     Jim_SetResultString(interp, buf, -1);
341     return JIM_OK;
342 }
343
344 #ifndef JIM_STATICEXT
345 int Jim_OnLoad(Jim_Interp *interp)
346 #else
347 int Jim_AioInit(Jim_Interp *interp)
348 #endif
349 {
350     #ifndef JIM_STATICEXT
351     Jim_InitExtension(interp);
352     #endif
353     if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG) != JIM_OK)
354         return JIM_ERR;
355     Jim_CreateCommand(interp, "aio.open", JimAioOpenCommand, NULL, NULL);
356     return JIM_OK;
357 }