mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 06:00:54 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			285 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * compat.c - compatibiltiy routines for the deprived
 | |
|  *
 | |
|  * This file is part of zsh, the Z shell.
 | |
|  *
 | |
|  * Copyright (c) 1992-1997 Paul Falstad
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, without written agreement and without
 | |
|  * license or royalty fees, to use, copy, modify, and distribute this
 | |
|  * software and to distribute modified versions of this software for any
 | |
|  * purpose, provided that the above copyright notice and the following
 | |
|  * two paragraphs appear in all copies of this software.
 | |
|  *
 | |
|  * In no event shall Paul Falstad or the Zsh Development Group be liable
 | |
|  * to any party for direct, indirect, special, incidental, or consequential
 | |
|  * damages arising out of the use of this software and its documentation,
 | |
|  * even if Paul Falstad and the Zsh Development Group have been advised of
 | |
|  * the possibility of such damage.
 | |
|  *
 | |
|  * Paul Falstad and the Zsh Development Group specifically disclaim any
 | |
|  * warranties, including, but not limited to, the implied warranties of
 | |
|  * merchantability and fitness for a particular purpose.  The software
 | |
|  * provided hereunder is on an "as is" basis, and Paul Falstad and the
 | |
|  * Zsh Development Group have no obligation to provide maintenance,
 | |
|  * support, updates, enhancements, or modifications.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "zsh.mdh"
 | |
| #include "compat.pro"
 | |
| 
 | |
| /* Return pointer to first occurence of string t *
 | |
|  * in string s.  Return NULL if not present.     */
 | |
| 
 | |
| #ifndef HAVE_STRSTR
 | |
| char *
 | |
| strstr(const char *s, const char *t)
 | |
| {
 | |
|     char *p1, *p2;
 | |
|  
 | |
|     for (; *s; s++) {
 | |
|         for (p1 = s, p2 = t; *p2; p1++, p2++)
 | |
|             if (*p1 != *p2)
 | |
|                 break;
 | |
|         if (!*p2)
 | |
|             return (char *)s;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifndef HAVE_GETHOSTNAME
 | |
| int
 | |
| gethostname(char *name, size_t namelen)
 | |
| {
 | |
|     struct utsname uts;
 | |
| 
 | |
|     uname(&uts);
 | |
|     if(strlen(uts.nodename) >= namelen) {
 | |
| 	errno = EINVAL;
 | |
| 	return -1;
 | |
|     }
 | |
|     strcpy(name, uts.nodename);
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifndef HAVE_GETTIMEOFDAY
 | |
| int
 | |
| gettimeofday(struct timeval *tv, struct timezone *tz)
 | |
| {
 | |
|     tv->tv_usec = 0;
 | |
|     tv->tv_sec = (long)time((time_t) 0);
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* compute the difference between two calendar times */
 | |
| 
 | |
| #ifndef HAVE_DIFFTIME
 | |
| double
 | |
| difftime(time_t t2, time_t t1)
 | |
| {
 | |
|     return ((double)t2 - (double)t1);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifndef HAVE_STRERROR
 | |
| extern char *sys_errlist[];
 | |
| 
 | |
| /* Get error message string associated with a particular  *
 | |
|  * error number, and returns a pointer to that string.    *
 | |
|  * This is not a particularly robust version of strerror. */
 | |
| 
 | |
| char *
 | |
| strerror(int errnum)
 | |
| {
 | |
|     return (sys_errlist[errnum]);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /**/
 | |
| char *
 | |
| zgetdir(struct dirsav *d)
 | |
| {
 | |
|     char nbuf[PATH_MAX+3];
 | |
|     char *buf;
 | |
|     int bufsiz, pos, len;
 | |
|     struct stat sbuf;
 | |
|     struct dirent *de;
 | |
|     DIR *dir;
 | |
|     ino_t ino, pino;
 | |
|     dev_t dev, pdev;
 | |
| 
 | |
|     buf = halloc(bufsiz = PATH_MAX);
 | |
|     pos = bufsiz - 1;
 | |
|     buf[pos] = '\0';
 | |
|     strcpy(nbuf, "../");
 | |
|     if (stat(".", &sbuf) < 0) {
 | |
| 	if (d)
 | |
| 	    return NULL;
 | |
| 	buf[0] = '.';
 | |
| 	buf[1] = '\0';
 | |
| 	return buf;
 | |
|     }
 | |
| 
 | |
|     pino = sbuf.st_ino;
 | |
|     pdev = sbuf.st_dev;
 | |
|     if (d)
 | |
| 	d->ino = pino, d->dev = pdev;
 | |
| #ifdef HAVE_FCHDIR
 | |
|     else
 | |
| #endif
 | |
| 	holdintr();
 | |
| 
 | |
|     for (;;) {
 | |
| 	if (stat("..", &sbuf) < 0)
 | |
| 	    break;
 | |
| 
 | |
| 	ino = pino;
 | |
| 	dev = pdev;
 | |
| 	pino = sbuf.st_ino;
 | |
| 	pdev = sbuf.st_dev;
 | |
| 
 | |
| 	if (ino == pino && dev == pdev) {
 | |
| 	    if (!buf[pos])
 | |
| 		buf[--pos] = '/';
 | |
| 	    if (d) {
 | |
| #ifndef HAVE_FCHDIR
 | |
| 		zchdir(buf + pos);
 | |
| 		noholdintr();
 | |
| #endif
 | |
| 		return d->dirname = ztrdup(buf + pos);
 | |
| 	    }
 | |
| 	    zchdir(buf + pos);
 | |
| 	    noholdintr();
 | |
| 	    return buf + pos;
 | |
| 	}
 | |
| 
 | |
| 	if (!(dir = opendir("..")))
 | |
| 	    break;
 | |
| 
 | |
| 	while ((de = readdir(dir))) {
 | |
| 	    char *fn = de->d_name;
 | |
| 	    /* Ignore `.' and `..'. */
 | |
| 	    if (fn[0] == '.' &&
 | |
| 		(fn[1] == '\0' ||
 | |
| 		 (fn[1] == '.' && fn[2] == '\0')))
 | |
| 		continue;
 | |
| #ifdef HAVE_STRUCT_DIRENT_D_STAT
 | |
| 	    if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
 | |
| 		strncpy(nbuf + 3, fn, PATH_MAX);
 | |
| 		break;
 | |
| 	    }
 | |
| #else /* !HAVE_STRUCT_DIRENT_D_STAT */
 | |
| # ifdef HAVE_STRUCT_DIRENT_D_INO
 | |
| 	    if (dev != pdev || (ino_t) de->d_ino == ino)
 | |
| # endif /* HAVE_STRUCT_DIRENT_D_INO */
 | |
| 	    {
 | |
| 		strncpy(nbuf + 3, fn, PATH_MAX);
 | |
| 		lstat(nbuf, &sbuf);
 | |
| 		if (sbuf.st_dev == dev && sbuf.st_ino == ino)
 | |
| 		    break;
 | |
| 	    }
 | |
| #endif /* !HAVE_STRUCT_DIRENT_D_STAT */
 | |
| 	}
 | |
| 	closedir(dir);
 | |
| 	if (!de)
 | |
| 	    break;
 | |
| 	len = strlen(nbuf + 2);
 | |
| 	pos -= len;
 | |
| 	while (pos <= 1) {
 | |
| 	    char *newbuf = halloc(2*bufsiz);
 | |
| 	    memcpy(newbuf + bufsiz, buf, bufsiz);
 | |
| 	    buf = newbuf;
 | |
| 	    pos += bufsiz;
 | |
| 	    bufsiz *= 2;
 | |
| 	}
 | |
| 	memcpy(buf + pos, nbuf + 2, len);
 | |
| #ifdef HAVE_FCHDIR
 | |
| 	if (d)
 | |
| 	    return d->dirname = ztrdup(buf + pos + 1);
 | |
| #endif
 | |
| 	if (chdir(".."))
 | |
| 	    break;
 | |
|     }
 | |
|     if (d) {
 | |
| #ifndef HAVE_FCHDIR
 | |
| 	if (*buf)
 | |
| 	    zchdir(buf + pos + 1);
 | |
| 	noholdintr();
 | |
| #endif
 | |
| 	return NULL;
 | |
|     }
 | |
|     if (*buf)
 | |
| 	zchdir(buf + pos + 1);
 | |
|     noholdintr();
 | |
|     buf[0] = '.';
 | |
|     buf[1] = '\0';
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| /**/
 | |
| char *
 | |
| zgetcwd(void)
 | |
| {
 | |
|     return zgetdir(NULL);
 | |
| }
 | |
| 
 | |
| /* chdir with arbitrary long pathname.  Returns 0 on success, 0 on normal *
 | |
|  * faliliure and -2 when chdir failed and the current directory is lost.  */
 | |
| 
 | |
| /**/
 | |
| int
 | |
| zchdir(char *dir)
 | |
| {
 | |
|     char *s;
 | |
|     int currdir = -2;
 | |
| 
 | |
|     for (;;) {
 | |
| 	if (!*dir)
 | |
| 	    return 0;
 | |
| 	if (!chdir(dir))
 | |
| 	    return 0;
 | |
| 	if ((errno != ENAMETOOLONG && errno != ENOMEM) ||
 | |
| 	    strlen(dir) < PATH_MAX)
 | |
| 	    break;
 | |
| 	for (s = dir + PATH_MAX - 1; s > dir && *s != '/'; s--);
 | |
| 	if (s == dir)
 | |
| 	    break;
 | |
| #ifdef HAVE_FCHDIR
 | |
| 	if (currdir == -2)
 | |
| 	    currdir = open(".", O_RDONLY|O_NOCTTY);
 | |
| #endif
 | |
| 	*s = '\0';
 | |
| 	if (chdir(dir)) {
 | |
| 	    *s = '/';
 | |
| 	    break;
 | |
| 	}
 | |
| #ifndef HAVE_FCHDIR
 | |
| 	currdir = -1;
 | |
| #endif
 | |
| 	*s = '/';
 | |
| 	while (*++s == '/');
 | |
| 	dir = s;
 | |
|     }
 | |
| #ifdef HAVE_FCHDIR
 | |
|     if (currdir == -1 || (currdir >= 0 && fchdir(currdir))) {
 | |
| 	if (currdir >= 0)
 | |
| 	    close(currdir);
 | |
| 	return -2;
 | |
|     }
 | |
|     if (currdir >= 0)
 | |
| 	close(currdir);
 | |
|     return -1;
 | |
| #else
 | |
|     return currdir == -2 ? -1 : -2;
 | |
| #endif
 | |
| }
 |