openenvutils/commandshell/shell/src/compat.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 //
       
     2 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     3 //
       
     4 /* 
       
     5  * compat.c - compatibility routines for the deprived
       
     6  *
       
     7  * This file is part of zsh, the Z shell.
       
     8  *
       
     9  * Copyright (c) 1992-1997 Paul Falstad
       
    10  * All rights reserved.
       
    11  *
       
    12  * Permission is hereby granted, without written agreement and without
       
    13  * license or royalty fees, to use, copy, modify, and distribute this
       
    14  * software and to distribute modified versions of this software for any
       
    15  * purpose, provided that the above copyright notice and the following
       
    16  * two paragraphs appear in all copies of this software.
       
    17  *
       
    18  * In no event shall Paul Falstad or the Zsh Development Group be liable
       
    19  * to any party for direct, indirect, special, incidental, or consequential
       
    20  * damages arising out of the use of this software and its documentation,
       
    21  * even if Paul Falstad and the Zsh Development Group have been advised of
       
    22  * the possibility of such damage.
       
    23  *
       
    24  * Paul Falstad and the Zsh Development Group specifically disclaim any
       
    25  * warranties, including, but not limited to, the implied warranties of
       
    26  * merchantability and fitness for a particular purpose.  The software
       
    27  * provided hereunder is on an "as is" basis, and Paul Falstad and the
       
    28  * Zsh Development Group have no obligation to provide maintenance,
       
    29  * support, updates, enhancements, or modifications.
       
    30  *
       
    31  */
       
    32 
       
    33 #include "zsh.mdh"
       
    34 #include "compat.pro"
       
    35 
       
    36 /* Return pointer to first occurence of string t *
       
    37  * in string s.  Return NULL if not present.     */
       
    38 
       
    39 #ifndef HAVE_STRSTR
       
    40 char *
       
    41 strstr(const char *s, const char *t)
       
    42 {
       
    43     char *p1, *p2;
       
    44 
       
    45     for (; *s; s++) {
       
    46         for (p1 = s, p2 = t; *p2; p1++, p2++)
       
    47             if (*p1 != *p2)
       
    48                 break;
       
    49         if (!*p2)
       
    50             return (char *)s;
       
    51     }
       
    52     return NULL;
       
    53 }
       
    54 #endif
       
    55 
       
    56 
       
    57 #ifndef HAVE_GETHOSTNAME
       
    58 int
       
    59 gethostname(char *name, size_t namelen)
       
    60 {
       
    61     struct utsname uts;
       
    62 
       
    63     uname(&uts);
       
    64     if(strlen(uts.nodename) >= namelen) {
       
    65 	errno = EINVAL;
       
    66 	return -1;
       
    67     }
       
    68     strcpy(name, uts.nodename);
       
    69     return 0;
       
    70 }
       
    71 #endif
       
    72 
       
    73 
       
    74 #ifndef HAVE_GETTIMEOFDAY
       
    75 int
       
    76 gettimeofday(struct timeval *tv, struct timezone *tz)
       
    77 {
       
    78     tv->tv_usec = 0;
       
    79     tv->tv_sec = (long)time((time_t) 0);
       
    80     return 0;
       
    81 }
       
    82 #endif
       
    83 
       
    84 
       
    85 /* compute the difference between two calendar times */
       
    86 
       
    87 #ifndef HAVE_DIFFTIME
       
    88 double
       
    89 difftime(time_t t2, time_t t1)
       
    90 {
       
    91     return ((double)t2 - (double)t1);
       
    92 }
       
    93 #endif
       
    94 
       
    95 
       
    96 #ifndef HAVE_STRERROR
       
    97 extern char *sys_errlist[];
       
    98 
       
    99 /* Get error message string associated with a particular  *
       
   100  * error number, and returns a pointer to that string.    *
       
   101  * This is not a particularly robust version of strerror. */
       
   102 
       
   103 char *
       
   104 strerror(int errnum)
       
   105 {
       
   106     return (sys_errlist[errnum]);
       
   107 }
       
   108 #endif
       
   109 
       
   110 
       
   111 #if 0
       
   112 /* pathconf(_PC_PATH_MAX) is not currently useful to zsh.  The value *
       
   113  * returned varies depending on a number of factors, e.g. the amount *
       
   114  * of memory available to the operating system at a given time; thus *
       
   115  * it can't be used for buffer allocation, or even as an indication  *
       
   116  * of whether an attempt to use or create a given pathname may fail  *
       
   117  * at any future time.                                               *
       
   118  *                                                                   *
       
   119  * The call is also permitted to fail if the argument path is not an *
       
   120  * existing directory, so even to make sense of that one must search *
       
   121  * for a valid directory somewhere in the path and adjust.  Even if  *
       
   122  * it succeeds, the return value is relative to the input directory, *
       
   123  * and therefore potentially relative to the length of the shortest  *
       
   124  * path either to that directory or to our working directory.        *
       
   125  *                                                                   *
       
   126  * Finally, see the note below for glibc; detection of pathconf() is *
       
   127  * not by itself an indication that it works reliably.               */
       
   128 
       
   129 /* The documentation for pathconf() says something like:             *
       
   130  *     The limit is returned, if one exists.  If the system  does    *
       
   131  *     not  have  a  limit  for  the  requested  resource,  -1 is    *
       
   132  *     returned, and errno is unchanged.  If there is  an  error,    *
       
   133  *     -1  is returned, and errno is set to reflect the nature of    *
       
   134  *     the error.                                                    *
       
   135  *                                                                   *
       
   136  * System calls are not permitted to set errno to 0; but we must (or *
       
   137  * some other flag value) in order to determine that the resource is *
       
   138  * unlimited.  What use is leaving errno unchanged?  Instead, define *
       
   139  * a wrapper that resets errno to 0 and returns 0 for "the system    *
       
   140  * does not have a limit," so that -1 always means a real error.     */
       
   141 
       
   142 /**/
       
   143 mod_export long
       
   144 zpathmax(char *dir)
       
   145 {
       
   146 #ifdef HAVE_PATHCONF
       
   147     long pathmax;
       
   148 
       
   149     errno = 0;
       
   150     if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
       
   151 	/* Some versions of glibc pathconf return a hardwired value! */
       
   152 	return pathmax;
       
   153     } else if (errno == EINVAL || errno == ENOENT || errno == ENOTDIR) {
       
   154 	/* Work backward to find a directory, until we run out of path. */
       
   155 	char *tail = strrchr(dir, '/');
       
   156 	while (tail > dir && tail[-1] == '/')
       
   157 	    --tail;
       
   158 	if (tail > dir) {
       
   159 	    *tail = 0;
       
   160 	    pathmax = zpathmax(dir);
       
   161 	    *tail = '/';
       
   162 	} else {
       
   163 	    errno = 0;
       
   164 	    if (tail)
       
   165 		pathmax = pathconf("/", _PC_PATH_MAX);
       
   166 	    else
       
   167 		pathmax = pathconf(".", _PC_PATH_MAX);
       
   168 	}
       
   169 	if (pathmax > 0) {
       
   170 	    long taillen = (tail ? strlen(tail) : (strlen(dir) + 1));
       
   171 	    if (taillen < pathmax)
       
   172 		return pathmax - taillen;
       
   173 	    else
       
   174 		errno = ENAMETOOLONG;
       
   175 	}
       
   176     }
       
   177     if (errno)
       
   178 	return -1;
       
   179     else
       
   180 	return 0; /* pathmax should be considered unlimited */
       
   181 #else
       
   182     long dirlen = strlen(dir);
       
   183 
       
   184     /* The following is wrong if dir is not an absolute path. */
       
   185     return ((long) ((dirlen >= PATH_MAX) ?
       
   186 		    ((errno = ENAMETOOLONG), -1) :
       
   187 		    ((errno = 0), PATH_MAX - dirlen)));
       
   188 #endif
       
   189 }
       
   190 #endif /* 0 */
       
   191 
       
   192 #ifdef HAVE_SYSCONF
       
   193 /* This is replaced by a macro from system.h if not HAVE_SYSCONF.    *
       
   194  * 0 is returned by sysconf if _SC_OPEN_MAX is unavailable;          *
       
   195  * -1 is returned on error                                           *
       
   196  *                                                                   *
       
   197  * Neither of these should happen, but resort to OPEN_MAX rather     *
       
   198  * than return 0 or -1 just in case.                                 */
       
   199 
       
   200 /**/
       
   201 mod_export long
       
   202 zopenmax(void)
       
   203 {
       
   204     static long openmax = 0;
       
   205 
       
   206     if (openmax < 1) {
       
   207 	if ((openmax = sysconf(_SC_OPEN_MAX)) < 1) {
       
   208 	    openmax = OPEN_MAX;
       
   209 	} else if (openmax > OPEN_MAX) {
       
   210 	    /* On some systems, "limit descriptors unlimited" or the  *
       
   211 	     * equivalent will set openmax to a huge number.  Unless  *
       
   212 	     * there actually is a file descriptor > OPEN_MAX already *
       
   213 	     * open, nothing in zsh requires the true maximum, and in *
       
   214 	     * fact it causes inefficiency elsewhere if we report it. *
       
   215 	     * So, report the maximum of OPEN_MAX or the largest open *
       
   216 	     * descriptor (is there a better way to find that?).      */
       
   217 	    long i, j = OPEN_MAX;
       
   218 	    for (i = j; i < openmax; i += (errno != EINTR)) {
       
   219 		errno = 0;
       
   220 		if (fcntl(i, F_GETFL, 0) < 0 &&
       
   221 		    (errno == EBADF || errno == EINTR))
       
   222 		    continue;
       
   223 		j = i;
       
   224 	    }
       
   225 	    openmax = j;
       
   226 	}
       
   227     }
       
   228 
       
   229     return (max_zsh_fd > openmax) ? max_zsh_fd : openmax;
       
   230 }
       
   231 #endif
       
   232 
       
   233 /**/
       
   234 mod_export char *
       
   235 zgetdir(struct dirsav *d)
       
   236 {
       
   237     char nbuf[PATH_MAX+3];
       
   238     char *buf;
       
   239     int bufsiz, pos;
       
   240     struct stat sbuf;
       
   241     ino_t pino;
       
   242     dev_t pdev;
       
   243 #if !defined(__CYGWIN__) && !defined(USE_GETCWD)
       
   244     struct dirent *de;
       
   245     DIR *dir;
       
   246     dev_t dev;
       
   247     ino_t ino;
       
   248     int len;
       
   249 #endif
       
   250 
       
   251     buf = zhalloc(bufsiz = PATH_MAX);
       
   252     pos = bufsiz - 1;
       
   253     buf[pos] = '\0';
       
   254     strcpy(nbuf, "../");
       
   255     if (stat(".", &sbuf) < 0) {
       
   256 	if (d)
       
   257 	    return NULL;
       
   258 	buf[0] = '.';
       
   259 	buf[1] = '\0';
       
   260 	return buf;
       
   261     }
       
   262 
       
   263     pino = sbuf.st_ino;
       
   264     pdev = sbuf.st_dev;
       
   265     if (d)
       
   266 	d->ino = pino, d->dev = pdev;
       
   267 #ifdef HAVE_FCHDIR
       
   268     else
       
   269 #endif
       
   270 #if !defined(__CYGWIN__) && !defined(USE_GETCWD)
       
   271 	holdintr();
       
   272 
       
   273     for (;;) {
       
   274 	if (stat("..", &sbuf) < 0)
       
   275 	    break;
       
   276 
       
   277 	ino = pino;
       
   278 	dev = pdev;
       
   279 	pino = sbuf.st_ino;
       
   280 	pdev = sbuf.st_dev;
       
   281 
       
   282 	if (ino == pino && dev == pdev) {
       
   283 	    /*if (!buf[pos])
       
   284 		buf[--pos] = '\\';*/
       
   285 	    if (d) {
       
   286 #ifndef HAVE_FCHDIR
       
   287 		zchdir(buf + pos);
       
   288 		noholdintr();
       
   289 #endif
       
   290 		return d->dirname = ztrdup(buf + pos);
       
   291 	    }
       
   292 	    zchdir(buf + pos);
       
   293 	    noholdintr();
       
   294 	    return buf + pos;
       
   295 	}
       
   296 
       
   297 	if (!(dir = opendir("..")))
       
   298 	    break;
       
   299 
       
   300 	while ((de = readdir(dir))) {
       
   301 	    char *fn = de->d_name;
       
   302 	    /* Ignore `.' and `..'. */
       
   303 	    if (fn[0] == '.' &&
       
   304 		(fn[1] == '\0' ||
       
   305 		 (fn[1] == '.' && fn[2] == '\0')))
       
   306 		continue;
       
   307 #ifdef HAVE_STRUCT_DIRENT_D_STAT
       
   308 	    if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
       
   309 		strncpy(nbuf + 3, fn, PATH_MAX);
       
   310 		break;
       
   311 	    }
       
   312 #else /* !HAVE_STRUCT_DIRENT_D_STAT */
       
   313 # ifdef HAVE_STRUCT_DIRENT_D_INO
       
   314 	    if (dev != pdev || (ino_t) de->d_ino == ino)
       
   315 # endif /* HAVE_STRUCT_DIRENT_D_INO */
       
   316 	    {
       
   317 		strncpy(nbuf + 3, fn, PATH_MAX);
       
   318 		lstat(nbuf, &sbuf);
       
   319 		if (sbuf.st_dev == dev && sbuf.st_ino == ino)
       
   320 		    break;
       
   321 	    }
       
   322 #endif /* !HAVE_STRUCT_DIRENT_D_STAT */
       
   323 	}
       
   324 	closedir(dir);
       
   325 	if (!de)
       
   326 	    break;
       
   327 	len = strlen(nbuf + 2);
       
   328 	pos -= len;
       
   329 	while (pos <= 1) {
       
   330 	    char *newbuf = zhalloc(2*bufsiz);
       
   331 	    memcpy(newbuf + bufsiz, buf, bufsiz);
       
   332 	    buf = newbuf;
       
   333 	    pos += bufsiz;
       
   334 	    bufsiz *= 2;
       
   335 	}
       
   336 	memcpy(buf + pos, nbuf + 2, len);
       
   337 #ifdef HAVE_FCHDIR
       
   338 	if (d)
       
   339 	    return d->dirname = ztrdup(buf + pos + 1);
       
   340 #endif
       
   341 	if (chdir(".."))
       
   342 	    break;
       
   343     }
       
   344     if (d) {
       
   345 #ifndef HAVE_FCHDIR
       
   346 	if (*buf)
       
   347 	    zchdir(buf + pos + 1);
       
   348 	noholdintr();
       
   349 #endif
       
   350 	return NULL;
       
   351     }
       
   352     if (*buf)
       
   353 	zchdir(buf + pos + 1);
       
   354     noholdintr();
       
   355 
       
   356 #else  /* __CYGWIN__, USE_GETCWD cases */
       
   357 
       
   358     if (!getcwd(buf, bufsiz)) {
       
   359 	if (d) {
       
   360 	    return NULL;
       
   361 	}
       
   362     } else {
       
   363 	if (d) {
       
   364 	    return d->dirname = ztrdup(buf);
       
   365 	}
       
   366 	return buf;
       
   367     }
       
   368 #endif
       
   369 
       
   370     buf[0] = '.';
       
   371     buf[1] = '\0';
       
   372     return buf;
       
   373 }
       
   374 
       
   375 /**/
       
   376 char *
       
   377 zgetcwd(void)
       
   378 {
       
   379     return zgetdir(NULL);
       
   380 }
       
   381 
       
   382 /* chdir with arbitrary long pathname.  Returns 0 on success, -1 on normal *
       
   383  * failure and -2 when chdir failed and the current directory is lost.  */
       
   384 
       
   385 /**/
       
   386 mod_export int
       
   387 zchdir(char *dir)
       
   388 {
       
   389     char *s;
       
   390     int currdir = -2;
       
   391 #ifdef __SYMBIAN32__
       
   392 	if(dir==NULL || !*dir)
       
   393 		{
       
   394 		return -1; //denote failure	
       
   395 		}
       
   396 #endif		
       
   397 
       
   398     for (;;) {
       
   399 	if (!*dir || chdir(dir) == 0) {
       
   400 #ifdef HAVE_FCHDIR
       
   401            if (currdir >= 0)
       
   402                close(currdir);
       
   403 #endif
       
   404 	    return 0;
       
   405 	}
       
   406 	if ((errno != ENAMETOOLONG && errno != ENOMEM) ||
       
   407 	    strlen(dir) < PATH_MAX)
       
   408 	    break;
       
   409 	for (s = dir + PATH_MAX - 1; s > dir && *s != '/'; s--)
       
   410 	    ;
       
   411 	if (s == dir)
       
   412 	    break;
       
   413 #ifdef HAVE_FCHDIR
       
   414 	if (currdir == -2)
       
   415 	    currdir = open(".", O_RDONLY|O_NOCTTY);
       
   416 #endif
       
   417 	*s = '\0';
       
   418 	if (chdir(dir) < 0) {
       
   419 	    *s = '/';
       
   420 	    break;
       
   421 	}
       
   422 #ifndef HAVE_FCHDIR
       
   423 	currdir = -1;
       
   424 #endif
       
   425 	*s = '/';
       
   426 	while (*++s == '/')
       
   427 	    ;
       
   428 	dir = s;
       
   429     }
       
   430 #ifdef HAVE_FCHDIR
       
   431     if (currdir >= 0) {
       
   432 	if (fchdir(currdir) < 0) {
       
   433 	    close(currdir);
       
   434 	    return -2;
       
   435 	}
       
   436 	close(currdir);
       
   437 	return -1;
       
   438     }
       
   439 #endif
       
   440     return currdir == -2 ? -1 : -2;
       
   441 }
       
   442 
       
   443 /*
       
   444  * How to print out a 64 bit integer.  This isn't needed (1) if longs
       
   445  * are 64 bit, since ordinary %ld will work (2) if we couldn't find a
       
   446  * 64 bit type anyway.
       
   447  */
       
   448 /**/
       
   449 #ifdef ZSH_64_BIT_TYPE
       
   450 /**/
       
   451 mod_export char *
       
   452 output64(zlong val)
       
   453 {
       
   454     static char llbuf[DIGBUFSIZE];
       
   455     convbase(llbuf, val, 0);
       
   456     return llbuf;
       
   457 }
       
   458 /**/
       
   459 #endif /* ZSH_64_BIT_TYPE */