12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256 |
- /* Supporting routines which may sometimes be missing.
- Copyright (C) 1988, 1992 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 2, 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. */
- #include <stdio.h>
- #include <sys/types.h>
- #include <signal.h>
- #include <errno.h>
- #ifndef STDC_HEADERS
- extern int errno;
- #endif
- #ifdef BSD42
- #include <sys/file.h>
- #else
- #ifndef V7
- #include <fcntl.h>
- #endif
- #endif
- #include "tar.h"
- #include "port.h"
- extern long baserec;
- /* All machine-dependent #ifdefs should appear here, instead of
- being scattered through the file. For UN*X systems, it is better to
- figure out what is needed in the configure script, for most of the
- features. */
- #ifdef __MSDOS__
- char TTY_NAME[] = "con";
- #define HAVE_STRSTR
- #define HAVE_RENAME
- #define HAVE_MKDIR
- #else
- char TTY_NAME[] = "/dev/tty";
- #endif
- /* End of system-dependent #ifdefs */
- #ifndef HAVE_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;
- {
- return (malloc (size));
- }
- #endif /* !HAVE_VALLOC */
- #ifndef HAVE_MKDIR
- /*
- * Written by Robert Rother, Mariah Corporation, August 1985.
- *
- * 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.
- */
- int
- mkdir (dpath, dmode)
- char *dpath;
- int dmode;
- {
- int cpid, status;
- struct stat statbuf;
- 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 (WIFSIGNALED (status) || WEXITSTATUS (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;
- 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 (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
- {
- errno = EIO; /* We don't know why, but */
- return -1; /* /bin/mkdir failed */
- }
- return 0;
- }
- #endif /* !HAVE_MKDIR */
- #ifndef HAVE_RENAME
- /* Rename file FROM to file TO.
- Return 0 if successful, -1 if not. */
- int
- rename (from, to)
- char *from;
- char *to;
- {
- struct stat from_stats;
- if (stat (from, &from_stats))
- return -1;
- if (unlink (to) && errno != ENOENT)
- return -1;
- if (link (from, to))
- return -1;
- if (unlink (from) && errno != ENOENT)
- {
- unlink (to);
- return -1;
- }
- return 0;
- }
- #endif /* !HAVE_RENAME */
- #ifdef minix
- /* 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;
- 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 (!S_ISREG (statbuf.st_mode))
- 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 /* minix */
- #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;
- {
- 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 /* EMUL_OPEN3 */
- #ifndef HAVE_MKNOD
- #ifdef __MSDOS__
- typedef int dev_t;
- #endif
- /* Fake mknod by complaining */
- int
- mknod (path, mode, dev)
- char *path;
- unsigned short mode;
- dev_t dev;
- {
- 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 /* !HAVE_MKNOD */
- #ifdef __TURBOC__
- #include <time.h>
- #include <fcntl.h>
- #include <io.h>
- struct utimbuf
- {
- time_t actime; /* Access time. */
- time_t modtime; /* Modification time. */
- };
- int
- utime (char *filename, struct utimbuf *utb)
- {
- struct tm *tm;
- struct ftime filetime;
- time_t when;
- int fd;
- int status;
- if (utb == 0)
- when = time (0);
- else
- when = utb->modtime;
- fd = _open (filename, O_RDWR);
- if (fd == -1)
- return -1;
- tm = localtime (&when);
- if (tm->tm_year < 80)
- filetime.ft_year = 0;
- else
- filetime.ft_year = tm->tm_year - 80;
- filetime.ft_month = tm->tm_mon + 1;
- filetime.ft_day = tm->tm_mday;
- if (tm->tm_hour < 0)
- filetime.ft_hour = 0;
- else
- filetime.ft_hour = tm->tm_hour;
- filetime.ft_min = tm->tm_min;
- filetime.ft_tsec = tm->tm_sec / 2;
- status = setftime (fd, &filetime);
- _close (fd);
- return status;
- }
- #endif /* __TURBOC__ */
- /* 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);
- }
- PTR
- ck_malloc (size)
- size_t size;
- {
- PTR ret;
- if (!size)
- size++;
- ret = malloc (size);
- if (ret == 0)
- panic ("Couldn't allocate memory");
- return ret;
- }
- /* Used by alloca.c and bison.simple. */
- char *
- xmalloc (size)
- size_t size;
- {
- return (char *) ck_malloc (size);
- }
- PTR
- ck_realloc (ptr, size)
- PTR ptr;
- size_t size;
- {
- PTR ret;
- 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 = b->length + n + MIN_ALLOCATE;
- 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;
- }
- }
- if (*to_there)
- *to_there++ = '\0';
- return ret;
- }
- #ifndef __MSDOS__
- void
- ck_pipe (pipes)
- int *pipes;
- {
- if (pipe (pipes) < 0)
- {
- msg_perror ("can't open a pipe");
- exit (EX_SYSTEM);
- }
- }
- #endif /* !__MSDOS__ */
- #ifndef HAVE_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;
- if (*wanted == '\0')
- return (char *) 0;
- /*
- * 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 /* !HAVE_STRSTR */
- #ifndef HAVE_FTRUNCATE
- #ifdef F_CHSIZE
- int
- ftruncate (fd, length)
- int fd;
- off_t length;
- {
- return fcntl (fd, F_CHSIZE, length);
- }
- #else /* !F_CHSIZE */
- #ifdef F_FREESP
- /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
- int
- ftruncate (fd, length)
- int fd; /* file descriptor */
- off_t length; /* length to set file to */
- {
- struct flock fl;
- fl.l_whence = 0;
- fl.l_len = 0;
- fl.l_start = length;
- fl.l_type = F_WRLCK; /* write lock on file space */
- /*
- * This relies on the UNDOCUMENTED F_FREESP argument to
- * fcntl(2), which truncates the file so that it ends at the
- * position indicated by fl.l_start.
- *
- * Will minor miracles never cease?
- */
- if (fcntl (fd, F_FREESP, &fl) < 0)
- return -1;
- return 0;
- }
- #else /* !F_FREESP */
- int
- ftruncate (fd, length)
- int fd;
- off_t length;
- {
- errno = EIO;
- return -1;
- }
- #endif /* !F_FREESP */
- #endif /* !F_CHSIZE */
- #endif /* !HAVE_FTRUNCATE */
- extern FILE *msg_file;
- #if defined (HAVE_VPRINTF) && __STDC__
- #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;
- 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 /* HAVE_VPRINTF and __STDC__ */
- #if defined(HAVE_VPRINTF) && !__STDC__
- #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;
- 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 /* HAVE_VPRINTF and not __STDC__ */
- #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
- 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 args;
- {
- int save_e;
- 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 /* !HAVE_VPRINTF and HAVE_DOPRNT */
- #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
- 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;
- 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 /* !HAVE_VPRINTF and !HAVE_DOPRNT */
|