home *** CD-ROM | disk | FTP | other *** search
- /* Supporting routines which may sometimes be missing.
- Copyright (C) 1988 Free Software Foundation
-
- This file is part of GNU Tar.
-
- GNU Tar is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU Tar is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Tar; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /*
- * @(#)port.c 1.15 87/11/05 by John Gilmore, 1986
- *
- * These are routines not available in all environments.
- *
- * I know this introduces an extra level of subroutine calls and is
- * slightly slower. Frankly, my dear, I don't give a damn. Let the
- * Missed-Em Vee losers suffer a little. This software is proud to
- * have been written on a BSD system.
- */
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <errno.h>
-
- #ifdef MSDOS
- #include <fcntl.h>
- #else
- #include <sys/file.h>
- #endif
-
- #include "tar.h"
- #include "port.h"
-
- #ifdef USG
- #include <string.h>
- #else
- extern size_t strlen();
- #endif
-
- extern long baserec;
- /*
- * Some people (e.g. V7) don't have a #define for these.
- */
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
- #ifndef O_RDONLY
- #define O_RDONLY 0
- #endif
- #ifndef NULL
- #define NULL 0
- #endif
-
- /* JF: modified so all configuration information can appear here, instead of
- being scattered through the file. Add all the machine-dependent #ifdefs
- here */
- #undef WANT_DUMB_GETDATE/* WANT_DUMB_GETDATE --> getdate() */
- #undef WANT_VALLOC /* WANT_VALLOC --> valloc() */
- #undef WANT_MKDIR /* WANT_MKDIR --> mkdir() rmdir() */
- #undef WANT_STRING /* WANT_STRING --> index() bcopy() bzero() bcmp() */
- #undef WANT_BZERO /* WANT_BZERO --> bzero() bcmp() execlp() */
- /* EMUL_OPEN3 --> open3() */
- #undef WANT_MKNOD /* WANT_MKNOD --> mknod() link() chown() geteuid() */
- #undef WANT_UTILS /* WANT_UTILS --> panic() ck_*() *_buffer()
- merge_sort() quote_copy_string() un_quote_string() */
- #undef WANT_CK_PIPE /* WANT_CK_PIPE --> ck_pipe() */
- #undef WANT_GETWD /* WANT_GETWD --> getwd() */
- #undef WANT_STRSTR /* WANT_STRSTR --> strstr() */
- #undef WANT_FTRUNCATE /* WANT_FTRUNCATE --> frtruncate() */
-
- /* Define only ONE of these four . . . */
- /* #undef DOPRNT_MSG /* Define this one if you have _doprnt() and
- no varargs support */
- /* #undef VARARGS_MSG /* Define this one if you have varargs.h and
- vfprintf() */
- /* #undef STDC_MSG /* Define this one if you are using ANSI C and
- and have vfprintf() */
- /* #undef LOSING_MSG /* Define this one if you don't have any of the
- above */
-
- #ifdef AMIGA
- #define WANT_DUMB_GETDATE/* WANT_DUMB_GETDATE --> getdate() */
- #define WANT_VALLOC /* WANT_VALLOC --> valloc() */
- #define WANT_MKNOD /* WANT_MKNOD --> mknod() link() chown() geteuid() */
- #endif
-
-
- #ifdef USG
- #define WANT_STRING
- #define WANT_VALLOC
-
- #if defined(sgi) && defined(mips)
- #define WANT_GETWD
- #endif
-
- #if defined(i386)
- #define WANT_FTRUNCATE
- #endif
-
- #endif
-
- #ifdef MINIX
- #define WANT_BZERO
- #endif
-
- #ifdef MSDOS
- char TTY_NAME[] = "con";
-
- #define WANT_STRING
- #define WANT_MKNOD
- #define WANT_UTILS
- #define WANT_VALLOC
-
- #if (!defined(STDC_MSG) && !defined(DOPRNT_MSG) && !defined(VARARGS_MSG) && !defined(LOSING_MSG))
- #ifdef __STDC__
- #define STDC_MSG
- #else
- #define LOSING_MSG
- #endif
- #endif
-
- #else /* not MSDOS */
- char TTY_NAME[] ="/dev/tty";
-
- #define WANT_UTILS
- #define WANT_CK_PIPE
- #define WANT_STRSTR
-
- #if (!defined(STDC_MSG) && !defined(DOPRNT_MSG) && !defined(VARARGS_MSG) && !defined(LOSING_MSG))
- #ifdef BSD42
- /* BSD systems should do this even if __STDC__, because
- we might be using an ANSI compiler without an ANSI library. (sigh) */
- #ifdef sparc
- #define LOSING_MSG
- #else
- #define DOPRNT_MSG
- #endif
- #else /* not BSD */
- #ifdef __STDC__
- #define STDC_MSG
- #else /* not ANSI C */
- #define LOSING_MSG
- #endif /* not ANSI C */
- #endif /* not BSD */
- #endif /* Need to define some form of _MSG */
- #endif /* not MSDOS */
-
- /* End of system-dependent #ifdefs */
-
- #ifdef WANT_DUMB_GETDATE
- /* JF a getdate() routine takes a date/time/etc and turns it into a time_t */
- /* This one is a quick hack I wrote in about five minutes to see if the N
- option works. Someone should replace it with one that works */
-
- /* This getdate takes an arg of the form mm/dd/yyyy hh:mm:ss and turns it
- into a time_t . Its not well tested or anything. . . */
- /* In general, you should use the getdate() supplied in getdate.y */
-
- #define OFF_FROM GMT 18000 /* Change for your time zone! */
-
- time_t
- getdate(str)
- char *str;
- {
- int month,day,year,hour,minute,second;
- time_t ret;
- int n;
-
- #define SECS_PER_YEAR (365L*SECS_PER_DAY)
- #define SECS_PER_LEAP_YEAR (366L*SECS_PER_DAY)
-
- #define SECS_PER_DAY (24L*60*60)
- static int days_per_month[2][12] = {
- 31,28,31,30,31,30,31,31,30,31,30,31,
- 31,29,31,30,31,30,31,31,30,31,30,31
- };
-
- static int days_per_year[2]={365,366};
-
- month=day=year=hour=minute=second=0;
- n=sscanf(str,"%d/%d/%d %d:%d:%d",&month,&day,&year,&hour,&minute,&second);
- if(n<3)
- return 0;
- if(year<100)
- year+=1900;
- if(year<1970)
- return 0;
- ret=0;
-
- #ifndef AMIGA
- ret+=OFF_FROM_GMT;
- #endif
-
- for(n=1970;n<year;n++)
- if(n%4==0 && n%400!=0)
- ret+=SECS_PER_LEAP_YEAR;
- else
- ret+=SECS_PER_YEAR;
-
- month--;
- for(n=0;n<month;n++) {
- if(year%4==0 && year%400!=0)
- ret+=SECS_PER_DAY*days_per_month[1][n];
- else
- ret+=SECS_PER_DAY*days_per_month[0][n];
- }
- ret+=SECS_PER_DAY*(day-1);
- ret+=second+minute*60+hour*60*60;
- return ret;
- }
- #endif
-
- #ifdef WANT_VALLOC
- /*
- * valloc() does a malloc() on a page boundary. On some systems,
- * this can make large block I/O more efficient.
- */
- char *
- valloc (size)
- unsigned size;
- {
- extern char *malloc ();
- return (malloc (size));
- }
- #endif
- /*
- * NMKDIR.C
- *
- * Written by Robert Rother, Mariah Corporation, August 1985.
- *
- * I wrote this out of shear disgust with myself because I couldn't
- * figure out how to do this in /bin/sh.
- *
- * If you want it, it's yours. All I ask in return is that if you
- * figure out how to do this in a Bourne Shell script you send me
- * a copy.
- * sdcsvax!rmr or rmr@uscd
- *
- * Severely hacked over by John Gilmore to make a 4.2BSD compatible
- * subroutine. 11Mar86; hoptoad!gnu
- *
- * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
- * subroutine didn't return EEXIST. It does now.
- */
-
- /*
- * Make a directory. Compatible with the mkdir() system call on 4.2BSD.
- */
- #ifdef WANT_MKDIR
- int
- mkdir(dpath, dmode)
- char *dpath;
- int dmode;
- {
- int cpid, status;
- struct stat statbuf;
- extern int errno;
-
- if (stat(dpath,&statbuf) == 0) {
- errno = EEXIST; /* Stat worked, so it already exists */
- return -1;
- }
-
- /* If stat fails for a reason other than non-existence, return error */
- if (errno != ENOENT) return -1;
-
- switch (cpid = fork()) {
-
- case -1: /* Error in fork() */
- return(-1); /* Errno is set already */
-
- case 0: /* Child process */
- /*
- * Cheap hack to set mode of new directory. Since this
- * child process is going away anyway, we zap its umask.
- * FIXME, this won't suffice to set SUID, SGID, etc. on this
- * directory. Does anybody care?
- */
- status = umask(0); /* Get current umask */
- status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
- execl("/bin/mkdir", "mkdir", dpath, (char *)0);
- _exit(-1); /* Can't exec /bin/mkdir */
-
- default: /* Parent process */
- while (cpid != wait(&status)) ; /* Wait for kid to finish */
- }
-
- if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
- errno = EIO; /* We don't know why, but */
- return -1; /* /bin/mkdir failed */
- }
-
- return 0;
- }
- int
- rmdir(dpath)
- char *dpath;
- {
- int cpid, status;
- struct stat statbuf;
- extern int errno;
-
- if (stat(dpath,&statbuf) != 0) {
- /* Stat just set errno. We don't have to */
- return -1;
- }
-
- switch (cpid = fork()) {
-
- case -1: /* Error in fork() */
- return(-1); /* Errno is set already */
-
- case 0: /* Child process */
- execl("/bin/rmdir", "rmdir", dpath, (char *)0);
- _exit(-1); /* Can't exec /bin/mkdir */
-
- default: /* Parent process */
- while (cpid != wait(&status)) ; /* Wait for kid to finish */
- }
-
- if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
- errno = EIO; /* We don't know why, but */
- return -1; /* /bin/mkdir failed */
- }
-
- return 0;
- }
- #endif
-
- #ifdef WANT_STRING
- /*
- * Translate V7 style into Sys V style.
- */
- #include <string.h>
- #include <memory.h>
-
- char *
- index (s, c)
- char *s;
- int c;
- {
- return (strchr (s, c));
- }
-
- char *
- rindex(s,c)
- char *s;
- int c;
- {
- return strrchr(s,c);
- }
-
- void
- bcopy (s1, s2, n)
- char *s1, *s2;
- int n;
- {
- (void) memcpy (s2, s1, n);
- }
-
- void
- bzero (s1, n)
- char *s1;
- int n;
- {
- (void) memset(s1, 0, n);
- }
-
- int
- bcmp(s1, s2, n)
- char *s1, *s2;
- int n;
- {
- return memcmp(s1, s2, n);
- }
- #endif
-
- #ifdef WANT_BZERO
- /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
- void
- bzero (s1, n)
- register char *s1;
- register int n;
- {
- while (n--) *s1++ = '\0';
- }
-
- /* It also has no bcmp() */
- int
- bcmp (s1, s2, n)
- register char *s1,*s2;
- register int n;
- {
- for ( ; n-- ; ++s1, ++s2) {
- if (*s1 != *s2) return *s1 - *s2;
- }
- return 0;
- }
-
- /*
- * Groan, Minix doesn't have execlp either!
- *
- * execlp(file,arg0,arg1...argn,(char *)NULL)
- * exec a program, automatically searching for the program through
- * all the directories on the PATH.
- *
- * This version is naive about variable argument lists, it assumes
- * a straightforward C calling sequence. If your system has odd stacks
- * *and* doesn't have execlp, YOU get to fix it.
- */
- int
- execlp(filename, arg0)
- char *filename, *arg0;
- {
- register char *p, *path;
- register char *fnbuffer;
- char **argstart = &arg0;
- struct stat statbuf;
- extern char **environ;
- extern int errno;
- extern char *malloc(), *getenv(), *index();
-
- if ((p = getenv("PATH")) == NULL) {
- /* couldn't find path variable -- try to exec given filename */
- return execve(filename, argstart, environ);
- }
-
- /*
- * make a place to build the filename. We malloc larger than we
- * need, but we know it will fit in this.
- */
- fnbuffer = malloc( strlen(p) + 1 + strlen(filename) );
- if (fnbuffer == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- /*
- * try each component of the path to see if the file's there
- * and executable.
- */
- for (path = p ; path ; path = p) {
- /* construct full path name to try */
- if ((p = index(path,':')) == NULL) {
- strcpy(fnbuffer, path);
- } else {
- strncpy(fnbuffer, path, p-path);
- fnbuffer[p-path] = '\0';
- p++; /* Skip : for next time */
- }
- if (strlen(fnbuffer) != 0)
- strcat(fnbuffer,"/");
- strcat(fnbuffer,filename);
-
- /* check to see if file is there and is a normal file */
- if (stat(fnbuffer, &statbuf) < 0) {
- if (errno == ENOENT)
- continue; /* file not there,keep on looking */
- else
- goto fail; /* failed for some reason, return */
- }
- if ( (statbuf.st_mode & S_IFMT) != S_IFREG) continue;
-
- if (execve(fnbuffer, argstart, environ) < 0
- && errno != ENOENT
- && errno != ENOEXEC) {
- /* failed, for some other reason besides "file
- * not found" or "not a.out format"
- */
- goto fail;
- }
-
- /*
- * If we got error ENOEXEC, the file is executable but is
- * not an object file. Try to execute it as a shell script,
- * returning error if we can't execute /bin/sh.
- *
- * FIXME, this code is broken in several ways. Shell
- * scripts should not in general be executed by the user's
- * SHELL variable program. On more mature systems, the
- * script can specify with #!/bin/whatever. Also, this
- * code clobbers argstart[-1] if the exec of the shell
- * fails.
- */
- if (errno == ENOEXEC) {
- char *shell;
-
- /* Try to execute command "sh arg0 arg1 ..." */
- if ((shell = getenv("SHELL")) == NULL)
- shell = "/bin/sh";
- argstart[-1] = shell;
- argstart[0] = fnbuffer;
- execve(shell, &argstart[-1], environ);
- goto fail; /* Exec didn't work */
- }
-
- /*
- * If we succeeded, the execve() doesn't return, so we
- * can only be here is if the file hasn't been found yet.
- * Try the next place on the path.
- */
- }
-
- /* all attempts failed to locate the file. Give up. */
- errno = ENOENT;
-
- fail:
- free(fnbuffer);
- return -1;
- }
- #endif
-
-
- #ifdef EMUL_OPEN3
- #include "open3.h"
- /*
- * open3 -- routine to emulate the 3-argument open system
- * call that is present in most modern Unix systems.
- * This version attempts to support all the flag bits except for O_NDELAY
- * and O_APPEND, which are silently ignored. The emulation is not as efficient
- * as the real thing (at worst, 4 system calls instead of one), but there's
- * not much I can do about that.
- *
- * Written 6/10/87 by rmtodd@uokmax
- *
- * open3(path, flag, mode)
- * Attempts to open the file specified by
- * the given pathname. The following flag bits (#defined in tar.h)
- * specify options to the routine:
- * O_RDONLY file open for read only
- * O_WRONLY file open for write only
- * O_RDWR file open for both read & write
- * (Needless to say, you should only specify one of the above).
- * O_CREAT file is created with specified mode if it needs to be.
- * O_TRUNC if file exists, it is truncated to 0 bytes
- * O_EXCL used with O_CREAT--routine returns error if file exists
- * Function returns file descriptor if successful, -1 and errno if not.
- */
-
- /*
- * array to give arguments to access for various modes
- * FIXME, this table depends on the specific integer values of O_XXX,
- * and also contains integers (args to 'access') that should be #define's.
- */
- static int modes[] =
- {
- 04, /* O_RDONLY */
- 02, /* O_WRONLY */
- 06, /* O_RDWR */
- 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
- };
-
- /* Shut off the automatic emulation of open(), we'll need it. */
- #undef open
-
- int
- open3(path, flags, mode)
- char *path;
- int flags, mode;
- {
- extern int errno;
- int exists = 1;
- int call_creat = 0;
- int fd;
- /*
- * We actually do the work by calling the open() or creat() system
- * call, depending on the flags. Call_creat is true if we will use
- * creat(), false if we will use open().
- */
-
- /*
- * See if the file exists and is accessible in the requested mode.
- *
- * Strictly speaking we shouldn't be using access, since access checks
- * against real uid, and the open call should check against euid.
- * Most cases real uid == euid, so it won't matter. FIXME.
- * FIXME, the construction "flags & 3" and the modes table depends
- * on the specific integer values of the O_XXX #define's. Foo!
- */
- if (access(path,modes[flags & 3]) < 0) {
- if (errno == ENOENT) {
- /* the file does not exist */
- exists = 0;
- } else {
- /* probably permission violation */
- if (flags & O_EXCL) {
- /* Oops, the file exists, we didn't want it. */
- /* No matter what the error, claim EEXIST. */
- errno = EEXIST;
- }
- return -1;
- }
- }
-
- /* if we have the O_CREAT bit set, check for O_EXCL */
- if (flags & O_CREAT) {
- if ((flags & O_EXCL) && exists) {
- /* Oops, the file exists and we didn't want it to. */
- errno = EEXIST;
- return -1;
- }
- /*
- * If the file doesn't exist, be sure to call creat() so that
- * it will be created with the proper mode.
- */
- if (!exists) call_creat = 1;
- } else {
- /* If O_CREAT isn't set and the file doesn't exist, error. */
- if (!exists) {
- errno = ENOENT;
- return -1;
- }
- }
-
- /*
- * If the O_TRUNC flag is set and the file exists, we want to call
- * creat() anyway, since creat() guarantees that the file will be
- * truncated and open()-for-writing doesn't.
- * (If the file doesn't exist, we're calling creat() anyway and the
- * file will be created with zero length.)
- */
- if ((flags & O_TRUNC) && exists) call_creat = 1;
- /* actually do the call */
- if (call_creat) {
- /*
- * call creat. May have to close and reopen the file if we
- * want O_RDONLY or O_RDWR access -- creat() only gives
- * O_WRONLY.
- */
- fd = creat(path,mode);
- if (fd < 0 || (flags & O_WRONLY)) return fd;
- if (close(fd) < 0) return -1;
- /* Fall out to reopen the file we've created */
- }
-
- /*
- * calling old open, we strip most of the new flags just in case.
- */
- return open(path, flags & (O_RDONLY|O_WRONLY|O_RDWR|O_BINARY));
- }
- #endif
-
- #ifdef WANT_MKNOD
- /* Fake mknod by complaining */
- int
- mknod(path, mode, dev)
- char *path;
- unsigned short mode;
- dev_t dev;
- {
- extern int errno;
- int fd;
-
- errno = ENXIO; /* No such device or address */
- return -1; /* Just give an error */
- }
-
- /* Fake links by copying */
- int
- link(path1, path2)
- char *path1;
- char *path2;
- {
- char buf[256];
- int ifd, ofd;
- int nrbytes;
- int nwbytes;
-
- fprintf(stderr, "%s: %s: cannot link to %s, copying instead\n",
- tar, path1, path2);
- if ((ifd = open(path1, O_RDONLY|O_BINARY)) < 0)
- return -1;
- if ((ofd = creat(path2, 0666)) < 0)
- return -1;
- setmode(ofd, O_BINARY);
- while ((nrbytes = read(ifd, buf, sizeof(buf))) > 0) {
- if ((nwbytes = write(ofd, buf, nrbytes)) != nrbytes) {
- nrbytes = -1;
- break;
- }
- }
- /* Note use of "|" rather than "||" below: we want to close
- * the files even if an error occurs.
- */
- if ((nrbytes < 0) | (0 != close(ifd)) | (0 != close(ofd))) {
- unlink(path2);
- return -1;
- }
- return 0;
- }
-
- /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
- int
- chown(path, uid, gid)
- char *path;
- int uid;
- int gid;
- {
- return 0;
- }
-
- int
- geteuid()
- {
- return 0;
- }
- #endif /* WANT_MKNOD */
-
- #ifdef WANT_UTILS
- /* Stash argv[0] here so panic will know what the program is called */
- char *myname = 0;
-
- void
- panic(s)
- char *s;
- {
- if(myname)
- fprintf(stderr,"%s:",myname);
- fprintf(stderr,s);
- putc('\n',stderr);
- exit(12);
- }
-
-
- char *
- ck_malloc(size)
- size_t size;
- {
- char *ret;
- char *malloc();
-
- if(!size)
- size++;
- ret=malloc(size);
- if(ret==0)
- panic("Couldn't allocate memory");
- return ret;
- }
-
- char *
- ck_realloc(ptr,size)
- char *ptr;
- size_t size;
- {
- char *ret;
- char *realloc();
-
- if(!ptr)
- ret=ck_malloc(size);
- else
- ret=realloc(ptr,size);
- if(ret==0)
- panic("Couldn't re-allocate memory");
- return ret;
- }
-
- /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
- nor do we care, as long as it doesn't mind being aligned on a char boundry.
- */
-
- struct buffer {
- int allocated;
- int length;
- char *b;
- };
-
- #define MIN_ALLOCATE 50
-
- char *
- init_buffer()
- {
- struct buffer *b;
-
- b=(struct buffer *)ck_malloc(sizeof(struct buffer));
- b->allocated=MIN_ALLOCATE;
- b->b=(char *)ck_malloc(MIN_ALLOCATE);
- b->length=0;
- return (char *)b;
- }
-
- void
- flush_buffer(bb)
- char *bb;
- {
- struct buffer *b;
-
- b=(struct buffer *)bb;
- free(b->b);
- b->b=0;
- b->allocated=0;
- b->length=0;
- free((void *)b);
- }
-
- void
- add_buffer(bb,p,n)
- char *bb;
- char *p;
- int n;
- {
- struct buffer *b;
-
- b=(struct buffer *)bb;
- if(b->length+n>b->allocated) {
- b->allocated*=2;
- b->b=(char *)ck_realloc(b->b,b->allocated);
- }
- bcopy(p,b->b+b->length,n);
- b->length+=n;
- }
-
- char *
- get_buffer(bb)
- char *bb;
- {
- struct buffer *b;
-
- b=(struct buffer *)bb;
- return b->b;
- }
-
- char *
- merge_sort(list,n,off,cmp)
- char *list;
- int (*cmp)();
- unsigned n;
- int off;
- {
- char *ret;
-
- char *alist,*blist;
- unsigned alength,blength;
-
- char *tptr;
- int tmp;
- char **prev;
- #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
- if(n==1)
- return list;
- if(n==2) {
- if((*cmp)(list,NEXTOF(list))>0) {
- ret=NEXTOF(list);
- NEXTOF(ret)=list;
- NEXTOF(list)=0;
- return ret;
- }
- return list;
- }
- alist=list;
- alength=(n+1)/2;
- blength=n/2;
- for(tptr=list,tmp=(n-1)/2;tmp;tptr=NEXTOF(tptr),tmp--)
- ;
- blist=NEXTOF(tptr);
- NEXTOF(tptr)=0;
-
- alist=merge_sort(alist,alength,off,cmp);
- blist=merge_sort(blist,blength,off,cmp);
- prev = &ret;
- for(;alist && blist;) {
- if((*cmp)(alist,blist)<0) {
- tptr=NEXTOF(alist);
- *prev = alist;
- prev = &(NEXTOF(alist));
- alist=tptr;
- } else {
- tptr=NEXTOF(blist);
- *prev = blist;
- prev = &(NEXTOF(blist));
- blist=tptr;
- }
- }
- if(alist)
- *prev = alist;
- else
- *prev = blist;
-
- return ret;
- }
-
- void
- ck_close(fd)
- int fd;
- {
- if(close(fd)<0) {
- msg_perror("can't close a file #%d",fd);
- exit(EX_SYSTEM);
- }
- }
-
- #include <ctype.h>
-
- /* Quote_copy_string is like quote_string, but instead of modifying the
- string in place, it malloc-s a copy of the string, and returns that.
- If the string does not have to be quoted, it returns the NULL string.
- The allocated copy can, of course, be freed with free() after the
- caller is done with it.
- */
- char *
- quote_copy_string(string)
- char *string;
- {
- char *from_here;
- char *to_there = 0;
- char *copy_buf = 0;
- int c;
- int copying = 0;
-
- from_here=string;
- while(*from_here) {
- c= *from_here++;
- if(c=='\\') {
- if(!copying) {
- int n;
-
- n=(from_here-string)-1;
- copying++;
- copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
- if(!copy_buf)
- return 0;
- bcopy(string,copy_buf,n);
- to_there=copy_buf+n;
- }
- *to_there++='\\';
- *to_there++='\\';
- } else if(isprint(c)) {
- if(copying)
- *to_there++= c;
- } else {
- if(!copying) {
- int n;
-
- n=(from_here-string)-1;
- copying++;
- copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
- if(!copy_buf)
- return 0;
- bcopy(string,copy_buf,n);
- to_there=copy_buf+n;
- }
- *to_there++='\\';
- if(c=='\n') *to_there++='n';
- else if(c=='\t') *to_there++='t';
- else if(c=='\f') *to_there++='f';
- else if(c=='\b') *to_there++='b';
- else if(c=='\r') *to_there++='r';
- else if(c=='\177') *to_there++='?';
- else {
- to_there[0]=(c>>6)+'0';
- to_there[1]=((c>>3)&07)+'0';
- to_there[2]=(c&07)+'0';
- to_there+=3;
- }
- }
- }
- if(copying) {
- *to_there='\0';
- return copy_buf;
- }
- return (char *)0;
- }
-
-
- /* Un_quote_string takes a quoted c-string (like those produced by
- quote_string or quote_copy_string and turns it back into the
- un-quoted original. This is done in place.
- */
-
- /* There is no un-quote-copy-string. Write it yourself */
-
- char *un_quote_string(string)
- char *string;
- {
- char *ret;
- char *from_here;
- char *to_there;
- int tmp;
-
- ret=string;
- to_there=string;
- from_here=string;
- while(*from_here) {
- if(*from_here!='\\') {
- if(from_here!=to_there)
- *to_there++= *from_here++;
- else
- from_here++,to_there++;
- continue;
- }
- switch(*++from_here) {
- case '\\':
- *to_there++= *from_here++;
- break;
- case 'n':
- *to_there++= '\n';
- from_here++;
- break;
- case 't':
- *to_there++= '\t';
- from_here++;
- break;
- case 'f':
- *to_there++= '\f';
- from_here++;
- break;
- case 'b':
- *to_there++= '\b';
- from_here++;
- break;
- case 'r':
- *to_there++= '\r';
- from_here++;
- break;
- case '?':
- *to_there++= 0177;
- from_here++;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- tmp= *from_here - '0';
- from_here++;
- if(*from_here<'0' || *from_here>'7') {
- *to_there++= tmp;
- break;
- }
- tmp= tmp*8 + *from_here-'0';
- from_here++;
- if(*from_here<'0' || *from_here>'7') {
- *to_there++= tmp;
- break;
- }
- tmp=tmp*8 + *from_here-'0';
- from_here++;
- *to_there=tmp;
- break;
- default:
- ret=0;
- *to_there++='\\';
- *to_there++= *from_here++;
- break;
- }
- }
- *to_there++='\0';
- return ret;
- }
- #endif
-
- #ifdef WANT_CK_PIPE
- void ck_pipe(pipes)
- int *pipes;
- {
- if(pipe(pipes)<0) {
- msg_perror("can't open a pipe");
- exit(EX_SYSTEM);
- }
- }
-
- #endif
-
- #ifdef WANT_GETWD
- char *
- getwd(path)
- char *path;
- {
- FILE *fp;
- FILE *popen();
-
- fp=popen("pwd","r");
- if(!fp)
- return 0;
- if(!fgets(path,100,fp))
- return 0;
- if(!pclose(fp))
- return 0;
- return path;
- }
- #endif /* WANT_CK_PIPE */
-
-
- #ifdef WANT_STRSTR
-
- /*
- * strstr - find first occurrence of wanted in s
- */
-
- char * /* found string, or NULL if none */
- strstr(s, wanted)
- char *s;
- char *wanted;
- {
- register char *scan;
- register size_t len;
- register char firstc;
- extern int strcmp();
-
- /*
- * The odd placement of the two tests is so "" is findable.
- * Also, we inline the first char for speed.
- * The ++ on scan has been moved down for optimization.
- */
- firstc = *wanted;
- len = strlen(wanted);
- for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
- if (*scan++ == '\0')
- return (char *)0;
- return scan;
- }
- #endif
-
- #ifdef WANT_FTRUNCATE
-
- int
- ftruncate(fd, length)
- int fd;
- off_t length;
- {
- errno = EIO;
- return -1;
- }
-
- #endif
-
-
-
-
- extern FILE *msg_file;
-
- #ifdef STDC_MSG
- #include <stdarg.h>
-
- void
- msg(char *str,...)
- {
- va_list args;
-
- va_start(args,str);
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- vfprintf(stderr,str,args);
- va_end(args);
- putc('\n',stderr);
- fflush(stderr);
- }
-
- void
- msg_perror(char *str,...)
- {
- va_list args;
- int save_e;
- extern int errno;
-
- save_e=errno;
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- va_start(args,str);
- vfprintf(stderr,str,args);
- va_end(args);
- errno=save_e;
- perror(" ");
- fflush(stderr);
- }
- #endif
-
- #ifdef VARARGS_MSG
- #include <varargs.h>
- void msg(str,va_alist)
- char *str;
- va_dcl
- {
- va_list args;
-
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- va_start(args);
- vfprintf(stderr,str,args);
- va_end(args);
- putc('\n',stderr);
- fflush(stderr);
- }
-
- void msg_perror(str,va_alist)
- char *str;
- va_dcl
- {
- va_list args;
- int save_e;
- extern int errno;
-
- save_e=errno;
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- va_start(args);
- vfprintf(stderr,str,args);
- va_end(args);
- errno=save_e;
- perror(" ");
- fflush(stderr);
- }
- #endif
-
- #ifdef DOPRNT_MSG
- void msg(str,args)
- char *str;
- int args;
- {
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- _doprnt(str, &args, stderr);
- putc('\n',stderr);
- fflush(stderr);
- }
-
- void msg_perror(str,args)
- char *str;
- {
- int save_e;
- extern int errno;
-
- save_e=errno;
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- _doprnt(str, &args, stderr);
- errno=save_e;
- perror(" ");
- fflush(stderr);
- }
-
- #endif
- #ifdef LOSING_MSG
- void msg(str,a1,a2,a3,a4,a5,a6)
- char *str;
- {
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
- putc('\n',stderr);
- fflush(stderr);
- }
-
- void msg_perror(str,a1,a2,a3,a4,a5,a6)
- char *str;
- {
- int save_e;
- extern int errno;
-
- save_e=errno;
- fflush(msg_file);
- fprintf(stderr,"%s: ",tar);
- if(f_sayblock)
- fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
- fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
- fprintf(stderr,": ");
- errno=save_e;
- perror(" ");
- }
-
- #endif
-