openenvutils/commandshell/shell/src/modules/system.c
changeset 0 2e3d3ce01487
child 1 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // sysread.c - interface to system read/write
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1998-2003 Peter Stephenson
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Peter Stephenson or the Zsh Development
       
    18  * Group be liable to any party for direct, indirect, special, incidental,
       
    19  * or consequential damages arising out of the use of this software and
       
    20  * its documentation, even if Peter Stephenson, and the Zsh
       
    21  * Development Group have been advised of the possibility of such damage.
       
    22  *
       
    23  * Peter Stephenson and the Zsh Development Group specifically
       
    24  * disclaim any warranties, including, but not limited to, the implied
       
    25  * warranties of merchantability and fitness for a particular purpose.  The
       
    26  * software provided hereunder is on an "as is" basis, and Peter Stephenson
       
    27  * and the Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 #include "system.mdh"
       
    32 #include "system.pro"
       
    33 
       
    34 #ifdef __SYMBIAN32__
       
    35 #include "dummy.h" //poll
       
    36 #endif //__SYMBIAN32__
       
    37 
       
    38 #ifdef HAVE_POLL_H
       
    39 #ifndef __SYMBIAN32__
       
    40 # include <sys/poll.h> 
       
    41 #else 
       
    42 #include "poll.h"
       
    43 #endif
       
    44 #endif
       
    45 #if defined(HAVE_POLL) && !defined(POLLIN)
       
    46 # undef HAVE_POLL
       
    47 #endif
       
    48 
       
    49 #ifdef __SYMBIAN32__
       
    50 #ifdef __WINSCW__
       
    51 #pragma warn_unusedarg off
       
    52 #endif//__WINSCW__
       
    53 #endif//__SYMBIAN32__
       
    54 
       
    55 #define SYSREAD_BUFSIZE	8192
       
    56 
       
    57 /**/
       
    58 static int
       
    59 getposint(char *instr, char *nam)
       
    60 {
       
    61     char *eptr;
       
    62     int ret;
       
    63 
       
    64     ret = (int)zstrtol(instr, &eptr, 10);
       
    65     if (*eptr || ret < 0) {
       
    66 	zwarnnam(nam, "integer expected: %s", instr, 0);
       
    67 	return -1;
       
    68     }
       
    69 
       
    70     return ret;
       
    71 }
       
    72 
       
    73 
       
    74 /*
       
    75  * Return values of bin_sysread:
       
    76  *	0	Successfully read (and written if appropriate)
       
    77  *	1	Error in parameters to command
       
    78  *	2	Error on read, or polling read fd ) ERRNO set by
       
    79  *      3	Error on write			  ) system
       
    80  *	4	Timeout on read
       
    81  *	5       Zero bytes read, end of file
       
    82  */
       
    83 
       
    84 /**/
       
    85 static int
       
    86 bin_sysread(char *nam, char **args, Options ops, UNUSED(int func))
       
    87 {
       
    88     int infd = 0, outfd = -1, bufsize = SYSREAD_BUFSIZE, count;
       
    89     char *outvar = NULL, *countvar = NULL, *inbuf;
       
    90 
       
    91     /* -i: input file descriptor if not stdin */
       
    92     if (OPT_ISSET(ops, 'i')) {
       
    93 	infd = getposint(OPT_ARG(ops, 'i'), nam);
       
    94 	if (infd < 0)
       
    95 	    return 1;
       
    96     }
       
    97 
       
    98     /* -o: output file descriptor, else store in REPLY */
       
    99     if (OPT_ISSET(ops, 'o')) {
       
   100 	if (*args) {
       
   101 	    zwarnnam(nam, "no argument allowed with -o", NULL, 0);
       
   102 	    return 1;
       
   103 	}
       
   104 	outfd = getposint(OPT_ARG(ops, 'o'), nam);
       
   105 	if (outfd < 0)
       
   106 	    return 1;
       
   107     }
       
   108 
       
   109     /* -s: buffer size if not default SYSREAD_BUFSIZE */
       
   110     if (OPT_ISSET(ops, 's')) {
       
   111 	bufsize = getposint(OPT_ARG(ops, 's'), nam);
       
   112 	if (bufsize < 0)
       
   113 	    return 1;
       
   114     }
       
   115 
       
   116     /* -c: name of variable to store count of transferred bytes */
       
   117     if (OPT_ISSET(ops, 'c')) {
       
   118 	countvar = OPT_ARG(ops, 'c');
       
   119 	if (!isident(countvar)) {
       
   120 	    zwarnnam(nam, "not an identifier: %s", countvar, 0);
       
   121 	    return 1;
       
   122 	}
       
   123     }
       
   124 
       
   125     if (*args) {
       
   126 	/*
       
   127 	 * Variable in which to store result if doing a plain read.
       
   128 	 * Default variable if not specified is REPLY.
       
   129 	 * If writing, only stuff we couldn't write is stored here,
       
   130 	 * no default in that case (we just discard it if no variable).
       
   131 	 */
       
   132 	outvar = *args;
       
   133 	if (!isident(outvar)) {
       
   134 	    zwarnnam(nam, "not an identifier: %s", outvar, 0);
       
   135 	    return 1;
       
   136 	}
       
   137     }
       
   138 
       
   139     inbuf = zhalloc(bufsize);
       
   140 
       
   141 #if defined(HAVE_POLL) || defined(HAVE_SELECT)
       
   142     /* -t: timeout */
       
   143     if (OPT_ISSET(ops, 't'))
       
   144     {
       
   145 # ifdef HAVE_POLL
       
   146 	struct pollfd poll_fd;
       
   147 	mnumber to_mn;
       
   148 	int to_int, ret;
       
   149 
       
   150 	poll_fd.fd = infd;
       
   151 	poll_fd.events = POLLIN;
       
   152 
       
   153 	to_mn = matheval(OPT_ARG(ops, 't'));
       
   154 	if (errflag)
       
   155 	    return 1;
       
   156 	if (to_mn.type == MN_FLOAT)
       
   157 	    to_int = (int) (1000 * to_mn.u.d);
       
   158 	else
       
   159 	    to_int = 1000 * (int)to_mn.u.l;
       
   160 
       
   161 	while ((ret = poll(&poll_fd, 1, to_int)) < 0) {
       
   162 	    if (errno != EINTR || errflag || retflag || breaks || contflag)
       
   163 		break;
       
   164 	}
       
   165 	if (ret <= 0) {
       
   166 	    /* treat non-timeout error as error on read */
       
   167 	    return ret ? 2 : 4;
       
   168 	}
       
   169 # else
       
   170 	/* using select */
       
   171 	struct timeval select_tv;
       
   172 	fd_set fds;
       
   173 	mnumber to_mn;
       
   174 	int ret;
       
   175 
       
   176 	FD_ZERO(&fds);
       
   177 	FD_SET(infd, &fds);
       
   178 	to_mn = matheval(OPT_ARG(ops, 't'));
       
   179 	if (errflag)
       
   180 	    return 1;
       
   181 
       
   182 	if (to_mn.type == MN_FLOAT) {
       
   183 	    select_tv.tv_sec = (int) to_mn.u.d;
       
   184 	    select_tv.tv_usec =
       
   185 		(int) ((to_mn.u.d - select_tv.tv_sec) * 1e6);
       
   186 	} else {
       
   187 	    select_tv.tv_sec = (int) to_mn.u.l;
       
   188 	    select_tv.tv_usec = 0;
       
   189 	}
       
   190 
       
   191 	while ((ret = select(infd+1, (SELECT_ARG_2_T) &fds, 
       
   192 			     NULL, NULL,&select_tv)) < 1) {
       
   193 	    if (errno != EINTR || errflag || retflag || breaks || contflag)
       
   194 		break;
       
   195 	}
       
   196 	if (ret <= 0) {
       
   197 	    /* treat non-timeout error as error on read */
       
   198 	    return ret ? 2 : 4;
       
   199 	}
       
   200 # endif
       
   201     }
       
   202 #endif
       
   203 
       
   204     while ((count = read(infd, inbuf, bufsize)) < 0) {
       
   205 	if (errno != EINTR || errflag || retflag || breaks || contflag)
       
   206 	    break;
       
   207     }
       
   208     if (countvar)
       
   209 	setiparam(countvar, count);
       
   210     if (count < 0)
       
   211 	return 2;
       
   212 
       
   213     if (outfd >= 0) {
       
   214 	if (!count)
       
   215 	    return 5;
       
   216 	while (count > 0) {
       
   217 	    int ret;
       
   218 
       
   219 	    ret = write(outfd, inbuf, count);
       
   220 	    if (ret < 0) {
       
   221 		if (errno == EINTR && !errflag &&
       
   222 		    !retflag && !breaks && !contflag)
       
   223 		    continue;
       
   224 		if (outvar)
       
   225 		    setsparam(outvar, metafy(inbuf, count, META_DUP));
       
   226 		if (countvar)
       
   227 		    setiparam(countvar, count);
       
   228 		return 3;
       
   229 	    }
       
   230 	    inbuf += ret;
       
   231 	    count -= ret;
       
   232 	}
       
   233 	return 0;
       
   234     }
       
   235 
       
   236     if (!outvar)
       
   237 	    outvar = "REPLY";
       
   238     /* do this even if we read zero bytes */
       
   239     setsparam(outvar, metafy(inbuf, count, META_DUP));
       
   240 
       
   241     return count ? 0 : 5;
       
   242 }
       
   243 
       
   244 
       
   245 /*
       
   246  * Return values of bin_syswrite:
       
   247  *	0	Successfully written
       
   248  *	1	Error in parameters to command
       
   249  *	2	Error on write, ERRNO set by system
       
   250  */
       
   251 
       
   252 /**/
       
   253 static int
       
   254 bin_syswrite(char *nam, char **args, Options ops, UNUSED(int func))
       
   255 {
       
   256     int outfd = 1, len, count, totcount;
       
   257     char *countvar = NULL;
       
   258 
       
   259     /* -o: output file descriptor if not stdout */
       
   260     if (OPT_ISSET(ops, 'o')) {
       
   261 	outfd = getposint(OPT_ARG(ops, 'o'), nam);
       
   262 	if (outfd < 0)
       
   263 	    return 1;
       
   264     }
       
   265 
       
   266     /* -c: variable in which to store count of bytes written */
       
   267     if (OPT_ISSET(ops, 'c')) {
       
   268 	countvar = OPT_ARG(ops, 'c');
       
   269 	if (!isident(countvar)) {
       
   270 	    zwarnnam(nam, "not an identifier: %s", countvar, 0);
       
   271 	    return 1;
       
   272 	}
       
   273     }
       
   274 
       
   275     totcount = 0;
       
   276     unmetafy(*args, &len);
       
   277     while (len) {
       
   278 	while ((count = write(outfd, *args, len)) < 0) {
       
   279 	    if (errno != EINTR || errflag || retflag || breaks || contflag)
       
   280 	    {
       
   281 		if (countvar)
       
   282 		    setiparam(countvar, totcount);
       
   283 		return 2;
       
   284 	    }
       
   285 	}
       
   286 	*args += count;
       
   287 	totcount += count;
       
   288 	len -= count;
       
   289     }
       
   290     if (countvar)
       
   291 	setiparam(countvar, totcount);
       
   292 
       
   293     return 0;
       
   294 }
       
   295 
       
   296 
       
   297 /*
       
   298  * Return values of bin_syserror:
       
   299  *	0	Successfully processed error
       
   300  *		(although if the number was invalid the string
       
   301  *		may not be useful)
       
   302  *	1	Error in parameters
       
   303  *	2	Name of error not recognised.
       
   304  */
       
   305 
       
   306 /**/
       
   307 static int
       
   308 bin_syserror(char *nam, char **args, Options ops, UNUSED(int func))
       
   309 {
       
   310     int num = 0;
       
   311     char *errvar = NULL, *msg, *pfx = "", *str;
       
   312 
       
   313     /* variable in which to write error message */
       
   314     if (OPT_ISSET(ops, 'e')) {
       
   315 	errvar = OPT_ARG(ops, 'e');
       
   316 	if (!isident(errvar)) {
       
   317 	    zwarnnam(nam, "not an identifier: %s", errvar, 0);
       
   318 	    return 1;
       
   319 	}
       
   320     }
       
   321     /* prefix for error message */
       
   322     if (OPT_ISSET(ops, 'p'))
       
   323 	pfx = OPT_ARG(ops, 'p');
       
   324 
       
   325     if (!*args)
       
   326 	num = errno;
       
   327     else {
       
   328 	char *ptr = *args;
       
   329 	while (*ptr && idigit(*ptr))
       
   330 	    ptr++;
       
   331 	if (!*ptr && ptr > *args)
       
   332 	    num = atoi(*args);
       
   333 	else {
       
   334 	    const char **eptr;
       
   335 	    for (eptr = sys_errnames; *eptr; eptr++) {
       
   336 		if (!strcmp(*eptr, *args)) {
       
   337 		    num = (eptr - sys_errnames) + 1;
       
   338 		    break;
       
   339 		}
       
   340 	    }
       
   341 	    if (!*eptr)
       
   342 		return 2;
       
   343 	}
       
   344     }
       
   345 
       
   346     msg = strerror(num);
       
   347     if (errvar) {
       
   348 	str = (char *)zalloc(strlen(msg) + strlen(pfx) + 1);
       
   349 	sprintf(str, "%s%s", pfx, msg);
       
   350 	setsparam(errvar, str);
       
   351     } else {
       
   352 	fprintf(stderr, "%s%s\n", pfx, msg);
       
   353     }
       
   354 
       
   355     return 0;
       
   356 }
       
   357 
       
   358 
       
   359 /* Functions for the errnos special parameter. */
       
   360 
       
   361 /**/
       
   362 static char **
       
   363 errnosgetfn(UNUSED(Param pm))
       
   364 {
       
   365     /* arrdup etc. should really take const pointers as arguments */
       
   366     return arrdup((char **)sys_errnames);
       
   367 }
       
   368 
       
   369 
       
   370 static struct builtin bintab[] = {
       
   371     BUILTIN("syserror", 0, bin_syserror, 0, 1, 0, "e:p:", NULL),
       
   372     BUILTIN("sysread", 0, bin_sysread, 0, 1, 0, "c:i:o:s:t:", NULL),
       
   373     BUILTIN("syswrite", 0, bin_syswrite, 1, 1, 0, "c:o:", NULL),
       
   374 };
       
   375 
       
   376 static const struct gsu_array errnos_gsu =
       
   377 { errnosgetfn, arrsetfn, stdunsetfn };
       
   378 
       
   379 /* The load/unload routines required by the zsh library interface */
       
   380 
       
   381 /**/
       
   382 int
       
   383 setup_(UNUSED(Module m))
       
   384 {
       
   385     return 0;
       
   386 }
       
   387 
       
   388 /**/
       
   389 static void
       
   390 tidyparam(Param pm)
       
   391 {
       
   392     if (!pm)
       
   393 	return;
       
   394     pm->flags &= ~PM_READONLY;
       
   395     unsetparam_pm(pm, 0, 1);
       
   396 }
       
   397 
       
   398 
       
   399 /**/
       
   400 int
       
   401 boot_(Module m)
       
   402 {
       
   403     Param pm_nos;
       
   404 
       
   405     /* this takes care of an autoload on errnos */
       
   406     unsetparam("errnos");
       
   407     if (!(pm_nos = createparam("errnos", PM_ARRAY|PM_SPECIAL|PM_READONLY|
       
   408 			       PM_HIDE|PM_HIDEVAL|PM_REMOVABLE)))
       
   409 	return 1;
       
   410     pm_nos->gsu.a = &errnos_gsu;
       
   411 
       
   412     if (!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) {
       
   413 	tidyparam(pm_nos);
       
   414 	return 1;
       
   415     }
       
   416     return 0;
       
   417 }
       
   418 
       
   419 
       
   420 /**/
       
   421 int
       
   422 cleanup_(Module m)
       
   423 {
       
   424     tidyparam((Param)paramtab->getnode(paramtab, "errnos"));
       
   425 
       
   426     deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
       
   427     return 0;
       
   428 }
       
   429 
       
   430 /**/
       
   431 int
       
   432 finish_(UNUSED(Module m))
       
   433 {
       
   434     return 0;
       
   435 }