]> Dogcows Code - chaz/tar/blob - src/port.c
Fix Solaris bug where chmod fails if we don't have PRIV_SYS_LINKDIR
[chaz/tar] / src / port.c
1 /* Supporting routines which may sometimes be missing.
2 Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <signal.h>
23 #include <errno.h>
24 #ifndef STDC_HEADERS
25 extern int errno;
26 #endif
27
28 #ifdef BSD42
29 #include <sys/file.h>
30 #else
31 #ifndef V7
32 #include <fcntl.h>
33 #endif
34 #endif
35
36 #include "tar.h"
37 #include "port.h"
38
39 extern long baserec;
40
41 /* All machine-dependent #ifdefs should appear here, instead of
42 being scattered through the file. For UN*X systems, it is better to
43 figure out what is needed in the configure script, for most of the
44 features. */
45
46 #ifdef __MSDOS__
47 char TTY_NAME[] = "con";
48 #define HAVE_STRSTR
49 #define HAVE_RENAME
50 #define HAVE_MKDIR
51 #else
52 char TTY_NAME[] = "/dev/tty";
53 #endif
54
55 /* End of system-dependent #ifdefs */
56
57
58 #ifndef HAVE_VALLOC
59 /*
60 * valloc() does a malloc() on a page boundary. On some systems,
61 * this can make large block I/O more efficient.
62 */
63 char *
64 valloc (size)
65 unsigned size;
66 {
67 return (malloc (size));
68 }
69
70 #endif /* !HAVE_VALLOC */
71
72 #ifndef HAVE_MKDIR
73 /*
74 * Written by Robert Rother, Mariah Corporation, August 1985.
75 *
76 * If you want it, it's yours. All I ask in return is that if you
77 * figure out how to do this in a Bourne Shell script you send me
78 * a copy.
79 * sdcsvax!rmr or rmr@uscd
80 *
81 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
82 * subroutine. 11Mar86; hoptoad!gnu
83 *
84 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
85 * subroutine didn't return EEXIST. It does now.
86 */
87
88 /*
89 * Make a directory.
90 */
91 int
92 mkdir (dpath, dmode)
93 char *dpath;
94 int dmode;
95 {
96 int cpid, status;
97 struct stat statbuf;
98
99 if (stat (dpath, &statbuf) == 0)
100 {
101 errno = EEXIST; /* Stat worked, so it already exists */
102 return -1;
103 }
104
105 /* If stat fails for a reason other than non-existence, return error */
106 if (errno != ENOENT)
107 return -1;
108
109 switch (cpid = fork ())
110 {
111
112 case -1: /* Error in fork() */
113 return (-1); /* Errno is set already */
114
115 case 0: /* Child process */
116 /*
117 * Cheap hack to set mode of new directory. Since this
118 * child process is going away anyway, we zap its umask.
119 * FIXME, this won't suffice to set SUID, SGID, etc. on this
120 * directory. Does anybody care?
121 */
122 status = umask (0); /* Get current umask */
123 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
124 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
125 _exit (-1); /* Can't exec /bin/mkdir */
126
127 default: /* Parent process */
128 while (cpid != wait (&status)); /* Wait for kid to finish */
129 }
130
131 if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
132 {
133 errno = EIO; /* We don't know why, but */
134 return -1; /* /bin/mkdir failed */
135 }
136
137 return 0;
138 }
139
140 int
141 rmdir (dpath)
142 char *dpath;
143 {
144 int cpid, status;
145 struct stat statbuf;
146
147 if (stat (dpath, &statbuf) != 0)
148 {
149 /* Stat just set errno. We don't have to */
150 return -1;
151 }
152
153 switch (cpid = fork ())
154 {
155
156 case -1: /* Error in fork() */
157 return (-1); /* Errno is set already */
158
159 case 0: /* Child process */
160 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
161 _exit (-1); /* Can't exec /bin/mkdir */
162
163 default: /* Parent process */
164 while (cpid != wait (&status)); /* Wait for kid to finish */
165 }
166
167 if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
168 {
169 errno = EIO; /* We don't know why, but */
170 return -1; /* /bin/mkdir failed */
171 }
172
173 return 0;
174 }
175
176 #endif /* !HAVE_MKDIR */
177
178 #ifndef HAVE_RENAME
179 /* Rename file FROM to file TO.
180 Return 0 if successful, -1 if not. */
181
182 int
183 rename (from, to)
184 char *from;
185 char *to;
186 {
187 struct stat from_stats;
188
189 if (stat (from, &from_stats))
190 return -1;
191
192 if (unlink (to) && errno != ENOENT)
193 return -1;
194
195 if (link (from, to))
196 return -1;
197
198 if (unlink (from) && errno != ENOENT)
199 {
200 unlink (to);
201 return -1;
202 }
203
204 return 0;
205 }
206
207 #endif /* !HAVE_RENAME */
208
209 #ifdef minix
210 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
211 void
212 bzero (s1, n)
213 register char *s1;
214 register int n;
215 {
216 while (n--)
217 *s1++ = '\0';
218 }
219
220 /* It also has no bcmp() */
221 int
222 bcmp (s1, s2, n)
223 register char *s1, *s2;
224 register int n;
225 {
226 for (; n--; ++s1, ++s2)
227 {
228 if (*s1 != *s2)
229 return *s1 - *s2;
230 }
231 return 0;
232 }
233
234 /*
235 * Groan, Minix doesn't have execlp either!
236 *
237 * execlp(file,arg0,arg1...argn,(char *)NULL)
238 * exec a program, automatically searching for the program through
239 * all the directories on the PATH.
240 *
241 * This version is naive about variable argument lists, it assumes
242 * a straightforward C calling sequence. If your system has odd stacks
243 * *and* doesn't have execlp, YOU get to fix it.
244 */
245 int
246 execlp (filename, arg0)
247 char *filename, *arg0;
248 {
249 register char *p, *path;
250 register char *fnbuffer;
251 char **argstart = &arg0;
252 struct stat statbuf;
253 extern char **environ;
254
255 if ((p = getenv ("PATH")) == NULL)
256 {
257 /* couldn't find path variable -- try to exec given filename */
258 return execve (filename, argstart, environ);
259 }
260
261 /*
262 * make a place to build the filename. We malloc larger than we
263 * need, but we know it will fit in this.
264 */
265 fnbuffer = malloc (strlen (p) + 1 + strlen (filename));
266 if (fnbuffer == NULL)
267 {
268 errno = ENOMEM;
269 return -1;
270 }
271
272 /*
273 * try each component of the path to see if the file's there
274 * and executable.
275 */
276 for (path = p; path; path = p)
277 {
278 /* construct full path name to try */
279 if ((p = index (path, ':')) == NULL)
280 {
281 strcpy (fnbuffer, path);
282 }
283 else
284 {
285 strncpy (fnbuffer, path, p - path);
286 fnbuffer[p - path] = '\0';
287 p++; /* Skip : for next time */
288 }
289 if (strlen (fnbuffer) != 0)
290 strcat (fnbuffer, "/");
291 strcat (fnbuffer, filename);
292
293 /* check to see if file is there and is a normal file */
294 if (stat (fnbuffer, &statbuf) < 0)
295 {
296 if (errno == ENOENT)
297 continue; /* file not there,keep on looking */
298 else
299 goto fail; /* failed for some reason, return */
300 }
301 if (!S_ISREG (statbuf.st_mode))
302 continue;
303
304 if (execve (fnbuffer, argstart, environ) < 0
305 && errno != ENOENT
306 && errno != ENOEXEC)
307 {
308 /* failed, for some other reason besides "file
309 * not found" or "not a.out format"
310 */
311 goto fail;
312 }
313
314 /*
315 * If we got error ENOEXEC, the file is executable but is
316 * not an object file. Try to execute it as a shell script,
317 * returning error if we can't execute /bin/sh.
318 *
319 * FIXME, this code is broken in several ways. Shell
320 * scripts should not in general be executed by the user's
321 * SHELL variable program. On more mature systems, the
322 * script can specify with #!/bin/whatever. Also, this
323 * code clobbers argstart[-1] if the exec of the shell
324 * fails.
325 */
326 if (errno == ENOEXEC)
327 {
328 char *shell;
329
330 /* Try to execute command "sh arg0 arg1 ..." */
331 if ((shell = getenv ("SHELL")) == NULL)
332 shell = "/bin/sh";
333 argstart[-1] = shell;
334 argstart[0] = fnbuffer;
335 execve (shell, &argstart[-1], environ);
336 goto fail; /* Exec didn't work */
337 }
338
339 /*
340 * If we succeeded, the execve() doesn't return, so we
341 * can only be here is if the file hasn't been found yet.
342 * Try the next place on the path.
343 */
344 }
345
346 /* all attempts failed to locate the file. Give up. */
347 errno = ENOENT;
348
349 fail:
350 free (fnbuffer);
351 return -1;
352 }
353
354 #endif /* minix */
355
356
357 #ifdef EMUL_OPEN3
358 #include "open3.h"
359 /*
360 * open3 -- routine to emulate the 3-argument open system
361 * call that is present in most modern Unix systems.
362 * This version attempts to support all the flag bits except for O_NDELAY
363 * and O_APPEND, which are silently ignored. The emulation is not as efficient
364 * as the real thing (at worst, 4 system calls instead of one), but there's
365 * not much I can do about that.
366 *
367 * Written 6/10/87 by rmtodd@uokmax
368 *
369 * open3(path, flag, mode)
370 * Attempts to open the file specified by
371 * the given pathname. The following flag bits (#defined in tar.h)
372 * specify options to the routine:
373 * O_RDONLY file open for read only
374 * O_WRONLY file open for write only
375 * O_RDWR file open for both read & write
376 * (Needless to say, you should only specify one of the above).
377 * O_CREAT file is created with specified mode if it needs to be.
378 * O_TRUNC if file exists, it is truncated to 0 bytes
379 * O_EXCL used with O_CREAT--routine returns error if file exists
380 * Function returns file descriptor if successful, -1 and errno if not.
381 */
382
383 /*
384 * array to give arguments to access for various modes
385 * FIXME, this table depends on the specific integer values of O_XXX,
386 * and also contains integers (args to 'access') that should be #define's.
387 */
388 static int modes[] =
389 {
390 04, /* O_RDONLY */
391 02, /* O_WRONLY */
392 06, /* O_RDWR */
393 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
394 };
395
396 /* Shut off the automatic emulation of open(), we'll need it. */
397 #undef open
398
399 int
400 open3 (path, flags, mode)
401 char *path;
402 int flags, mode;
403 {
404 int exists = 1;
405 int call_creat = 0;
406 int fd;
407 /*
408 * We actually do the work by calling the open() or creat() system
409 * call, depending on the flags. Call_creat is true if we will use
410 * creat(), false if we will use open().
411 */
412
413 /*
414 * See if the file exists and is accessible in the requested mode.
415 *
416 * Strictly speaking we shouldn't be using access, since access checks
417 * against real uid, and the open call should check against euid.
418 * Most cases real uid == euid, so it won't matter. FIXME.
419 * FIXME, the construction "flags & 3" and the modes table depends
420 * on the specific integer values of the O_XXX #define's. Foo!
421 */
422 if (access (path, modes[flags & 3]) < 0)
423 {
424 if (errno == ENOENT)
425 {
426 /* the file does not exist */
427 exists = 0;
428 }
429 else
430 {
431 /* probably permission violation */
432 if (flags & O_EXCL)
433 {
434 /* Oops, the file exists, we didn't want it. */
435 /* No matter what the error, claim EEXIST. */
436 errno = EEXIST;
437 }
438 return -1;
439 }
440 }
441
442 /* if we have the O_CREAT bit set, check for O_EXCL */
443 if (flags & O_CREAT)
444 {
445 if ((flags & O_EXCL) && exists)
446 {
447 /* Oops, the file exists and we didn't want it to. */
448 errno = EEXIST;
449 return -1;
450 }
451 /*
452 * If the file doesn't exist, be sure to call creat() so that
453 * it will be created with the proper mode.
454 */
455 if (!exists)
456 call_creat = 1;
457 }
458 else
459 {
460 /* If O_CREAT isn't set and the file doesn't exist, error. */
461 if (!exists)
462 {
463 errno = ENOENT;
464 return -1;
465 }
466 }
467
468 /*
469 * If the O_TRUNC flag is set and the file exists, we want to call
470 * creat() anyway, since creat() guarantees that the file will be
471 * truncated and open()-for-writing doesn't.
472 * (If the file doesn't exist, we're calling creat() anyway and the
473 * file will be created with zero length.)
474 */
475 if ((flags & O_TRUNC) && exists)
476 call_creat = 1;
477 /* actually do the call */
478 if (call_creat)
479 {
480 /*
481 * call creat. May have to close and reopen the file if we
482 * want O_RDONLY or O_RDWR access -- creat() only gives
483 * O_WRONLY.
484 */
485 fd = creat (path, mode);
486 if (fd < 0 || (flags & O_WRONLY))
487 return fd;
488 if (close (fd) < 0)
489 return -1;
490 /* Fall out to reopen the file we've created */
491 }
492
493 /*
494 * calling old open, we strip most of the new flags just in case.
495 */
496 return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
497 }
498
499 #endif /* EMUL_OPEN3 */
500
501 #ifndef HAVE_MKNOD
502 #ifdef __MSDOS__
503 typedef int dev_t;
504 #endif
505 /* Fake mknod by complaining */
506 int
507 mknod (path, mode, dev)
508 char *path;
509 unsigned short mode;
510 dev_t dev;
511 {
512 int fd;
513
514 errno = ENXIO; /* No such device or address */
515 return -1; /* Just give an error */
516 }
517
518 /* Fake links by copying */
519 int
520 link (path1, path2)
521 char *path1;
522 char *path2;
523 {
524 char buf[256];
525 int ifd, ofd;
526 int nrbytes;
527 int nwbytes;
528
529 fprintf (stderr, "%s: %s: cannot link to %s, copying instead\n",
530 tar, path1, path2);
531 if ((ifd = open (path1, O_RDONLY | O_BINARY)) < 0)
532 return -1;
533 if ((ofd = creat (path2, 0666)) < 0)
534 return -1;
535 setmode (ofd, O_BINARY);
536 while ((nrbytes = read (ifd, buf, sizeof (buf))) > 0)
537 {
538 if ((nwbytes = write (ofd, buf, nrbytes)) != nrbytes)
539 {
540 nrbytes = -1;
541 break;
542 }
543 }
544 /* Note use of "|" rather than "||" below: we want to close
545 * the files even if an error occurs.
546 */
547 if ((nrbytes < 0) | (0 != close (ifd)) | (0 != close (ofd)))
548 {
549 unlink (path2);
550 return -1;
551 }
552 return 0;
553 }
554
555 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
556 int
557 chown (path, uid, gid)
558 char *path;
559 int uid;
560 int gid;
561 {
562 return 0;
563 }
564
565 int
566 geteuid ()
567 {
568 return 0;
569 }
570
571 #endif /* !HAVE_MKNOD */
572
573 #ifdef __TURBOC__
574 #include <time.h>
575 #include <fcntl.h>
576 #include <io.h>
577
578 struct utimbuf
579 {
580 time_t actime; /* Access time. */
581 time_t modtime; /* Modification time. */
582 };
583
584 int
585 utime (char *filename, struct utimbuf *utb)
586 {
587 struct tm *tm;
588 struct ftime filetime;
589 time_t when;
590 int fd;
591 int status;
592
593 if (utb == 0)
594 when = time (0);
595 else
596 when = utb->modtime;
597
598 fd = _open (filename, O_RDWR);
599 if (fd == -1)
600 return -1;
601
602 tm = localtime (&when);
603 if (tm->tm_year < 80)
604 filetime.ft_year = 0;
605 else
606 filetime.ft_year = tm->tm_year - 80;
607 filetime.ft_month = tm->tm_mon + 1;
608 filetime.ft_day = tm->tm_mday;
609 if (tm->tm_hour < 0)
610 filetime.ft_hour = 0;
611 else
612 filetime.ft_hour = tm->tm_hour;
613 filetime.ft_min = tm->tm_min;
614 filetime.ft_tsec = tm->tm_sec / 2;
615
616 status = setftime (fd, &filetime);
617 _close (fd);
618 return status;
619 }
620
621 #endif /* __TURBOC__ */
622
623 /* Stash argv[0] here so panic will know what the program is called */
624 char *myname = 0;
625
626 void
627 panic (s)
628 char *s;
629 {
630 if (myname)
631 fprintf (stderr, "%s:", myname);
632 fprintf (stderr, s);
633 putc ('\n', stderr);
634 exit (12);
635 }
636
637
638 PTR
639 ck_malloc (size)
640 size_t size;
641 {
642 PTR ret;
643
644 if (!size)
645 size++;
646 ret = malloc (size);
647 if (ret == 0)
648 panic ("Couldn't allocate memory");
649 return ret;
650 }
651
652 /* Used by alloca.c and bison.simple. */
653 char *
654 xmalloc (size)
655 size_t size;
656 {
657 return (char *) ck_malloc (size);
658 }
659
660 PTR
661 ck_realloc (ptr, size)
662 PTR ptr;
663 size_t size;
664 {
665 PTR ret;
666
667 if (!ptr)
668 ret = ck_malloc (size);
669 else
670 ret = realloc (ptr, size);
671 if (ret == 0)
672 panic ("Couldn't re-allocate memory");
673 return ret;
674 }
675
676 /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
677 nor do we care, as long as it doesn't mind being aligned on a char boundry.
678 */
679
680 struct buffer
681 {
682 int allocated;
683 int length;
684 char *b;
685 };
686
687 #define MIN_ALLOCATE 50
688
689 char *
690 init_buffer ()
691 {
692 struct buffer *b;
693
694 b = (struct buffer *) ck_malloc (sizeof (struct buffer));
695 b->allocated = MIN_ALLOCATE;
696 b->b = (char *) ck_malloc (MIN_ALLOCATE);
697 b->length = 0;
698 return (char *) b;
699 }
700
701 void
702 flush_buffer (bb)
703 char *bb;
704 {
705 struct buffer *b;
706
707 b = (struct buffer *) bb;
708 free (b->b);
709 b->b = 0;
710 b->allocated = 0;
711 b->length = 0;
712 free ((void *) b);
713 }
714
715 void
716 add_buffer (bb, p, n)
717 char *bb;
718 char *p;
719 int n;
720 {
721 struct buffer *b;
722
723 b = (struct buffer *) bb;
724 if (b->length + n > b->allocated)
725 {
726 b->allocated = b->length + n + MIN_ALLOCATE;
727 b->b = (char *) ck_realloc (b->b, b->allocated);
728 }
729 bcopy (p, b->b + b->length, n);
730 b->length += n;
731 }
732
733 char *
734 get_buffer (bb)
735 char *bb;
736 {
737 struct buffer *b;
738
739 b = (struct buffer *) bb;
740 return b->b;
741 }
742
743 char *
744 merge_sort (list, n, off, cmp)
745 char *list;
746 int (*cmp) ();
747 unsigned n;
748 int off;
749 {
750 char *ret;
751
752 char *alist, *blist;
753 unsigned alength, blength;
754
755 char *tptr;
756 int tmp;
757 char **prev;
758 #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
759 if (n == 1)
760 return list;
761 if (n == 2)
762 {
763 if ((*cmp) (list, NEXTOF (list)) > 0)
764 {
765 ret = NEXTOF (list);
766 NEXTOF (ret) = list;
767 NEXTOF (list) = 0;
768 return ret;
769 }
770 return list;
771 }
772 alist = list;
773 alength = (n + 1) / 2;
774 blength = n / 2;
775 for (tptr = list, tmp = (n - 1) / 2; tmp; tptr = NEXTOF (tptr), tmp--)
776 ;
777 blist = NEXTOF (tptr);
778 NEXTOF (tptr) = 0;
779
780 alist = merge_sort (alist, alength, off, cmp);
781 blist = merge_sort (blist, blength, off, cmp);
782 prev = &ret;
783 for (; alist && blist;)
784 {
785 if ((*cmp) (alist, blist) < 0)
786 {
787 tptr = NEXTOF (alist);
788 *prev = alist;
789 prev = &(NEXTOF (alist));
790 alist = tptr;
791 }
792 else
793 {
794 tptr = NEXTOF (blist);
795 *prev = blist;
796 prev = &(NEXTOF (blist));
797 blist = tptr;
798 }
799 }
800 if (alist)
801 *prev = alist;
802 else
803 *prev = blist;
804
805 return ret;
806 }
807
808 void
809 ck_close (fd)
810 int fd;
811 {
812 if (close (fd) < 0)
813 {
814 msg_perror ("can't close a file #%d", fd);
815 exit (EX_SYSTEM);
816 }
817 }
818
819 #include <ctype.h>
820
821 /* Quote_copy_string is like quote_string, but instead of modifying the
822 string in place, it malloc-s a copy of the string, and returns that.
823 If the string does not have to be quoted, it returns the NULL string.
824 The allocated copy can, of course, be freed with free() after the
825 caller is done with it.
826 */
827 char *
828 quote_copy_string (string)
829 char *string;
830 {
831 char *from_here;
832 char *to_there = 0;
833 char *copy_buf = 0;
834 int c;
835 int copying = 0;
836
837 from_here = string;
838 while (*from_here)
839 {
840 c = *from_here++;
841 if (c == '\\')
842 {
843 if (!copying)
844 {
845 int n;
846
847 n = (from_here - string) - 1;
848 copying++;
849 copy_buf = (char *) malloc (n + 5 + strlen (from_here) * 4);
850 if (!copy_buf)
851 return 0;
852 bcopy (string, copy_buf, n);
853 to_there = copy_buf + n;
854 }
855 *to_there++ = '\\';
856 *to_there++ = '\\';
857 }
858 else if (isprint (c))
859 {
860 if (copying)
861 *to_there++ = c;
862 }
863 else
864 {
865 if (!copying)
866 {
867 int n;
868
869 n = (from_here - string) - 1;
870 copying++;
871 copy_buf = (char *) malloc (n + 5 + strlen (from_here) * 4);
872 if (!copy_buf)
873 return 0;
874 bcopy (string, copy_buf, n);
875 to_there = copy_buf + n;
876 }
877 *to_there++ = '\\';
878 if (c == '\n')
879 *to_there++ = 'n';
880 else if (c == '\t')
881 *to_there++ = 't';
882 else if (c == '\f')
883 *to_there++ = 'f';
884 else if (c == '\b')
885 *to_there++ = 'b';
886 else if (c == '\r')
887 *to_there++ = 'r';
888 else if (c == '\177')
889 *to_there++ = '?';
890 else
891 {
892 to_there[0] = (c >> 6) + '0';
893 to_there[1] = ((c >> 3) & 07) + '0';
894 to_there[2] = (c & 07) + '0';
895 to_there += 3;
896 }
897 }
898 }
899 if (copying)
900 {
901 *to_there = '\0';
902 return copy_buf;
903 }
904 return (char *) 0;
905 }
906
907
908 /* Un_quote_string takes a quoted c-string (like those produced by
909 quote_string or quote_copy_string and turns it back into the
910 un-quoted original. This is done in place.
911 */
912
913 /* There is no un-quote-copy-string. Write it yourself */
914
915 char *
916 un_quote_string (string)
917 char *string;
918 {
919 char *ret;
920 char *from_here;
921 char *to_there;
922 int tmp;
923
924 ret = string;
925 to_there = string;
926 from_here = string;
927 while (*from_here)
928 {
929 if (*from_here != '\\')
930 {
931 if (from_here != to_there)
932 *to_there++ = *from_here++;
933 else
934 from_here++, to_there++;
935 continue;
936 }
937 switch (*++from_here)
938 {
939 case '\\':
940 *to_there++ = *from_here++;
941 break;
942 case 'n':
943 *to_there++ = '\n';
944 from_here++;
945 break;
946 case 't':
947 *to_there++ = '\t';
948 from_here++;
949 break;
950 case 'f':
951 *to_there++ = '\f';
952 from_here++;
953 break;
954 case 'b':
955 *to_there++ = '\b';
956 from_here++;
957 break;
958 case 'r':
959 *to_there++ = '\r';
960 from_here++;
961 break;
962 case '?':
963 *to_there++ = 0177;
964 from_here++;
965 break;
966 case '0':
967 case '1':
968 case '2':
969 case '3':
970 case '4':
971 case '5':
972 case '6':
973 case '7':
974 tmp = *from_here - '0';
975 from_here++;
976 if (*from_here < '0' || *from_here > '7')
977 {
978 *to_there++ = tmp;
979 break;
980 }
981 tmp = tmp * 8 + *from_here - '0';
982 from_here++;
983 if (*from_here < '0' || *from_here > '7')
984 {
985 *to_there++ = tmp;
986 break;
987 }
988 tmp = tmp * 8 + *from_here - '0';
989 from_here++;
990 *to_there = tmp;
991 break;
992 default:
993 ret = 0;
994 *to_there++ = '\\';
995 *to_there++ = *from_here++;
996 break;
997 }
998 }
999 if (*to_there)
1000 *to_there++ = '\0';
1001 return ret;
1002 }
1003
1004 #ifndef __MSDOS__
1005 void
1006 ck_pipe (pipes)
1007 int *pipes;
1008 {
1009 if (pipe (pipes) < 0)
1010 {
1011 msg_perror ("can't open a pipe");
1012 exit (EX_SYSTEM);
1013 }
1014 }
1015 #endif /* !__MSDOS__ */
1016
1017 #ifndef HAVE_STRSTR
1018 /*
1019 * strstr - find first occurrence of wanted in s
1020 */
1021
1022 char * /* found string, or NULL if none */
1023 strstr (s, wanted)
1024 char *s;
1025 char *wanted;
1026 {
1027 register char *scan;
1028 register size_t len;
1029 register char firstc;
1030
1031 if (*wanted == '\0')
1032 return (char *) 0;
1033 /*
1034 * The odd placement of the two tests is so "" is findable.
1035 * Also, we inline the first char for speed.
1036 * The ++ on scan has been moved down for optimization.
1037 */
1038 firstc = *wanted;
1039 len = strlen (wanted);
1040 for (scan = s; *scan != firstc || strncmp (scan, wanted, len) != 0;)
1041 if (*scan++ == '\0')
1042 return (char *) 0;
1043 return scan;
1044 }
1045
1046 #endif /* !HAVE_STRSTR */
1047
1048 #ifndef HAVE_FTRUNCATE
1049
1050 #ifdef F_CHSIZE
1051 int
1052 ftruncate (fd, length)
1053 int fd;
1054 off_t length;
1055 {
1056 return fcntl (fd, F_CHSIZE, length);
1057 }
1058
1059 #else /* !F_CHSIZE */
1060 #ifdef F_FREESP
1061 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
1062
1063 int
1064 ftruncate (fd, length)
1065 int fd; /* file descriptor */
1066 off_t length; /* length to set file to */
1067 {
1068 struct flock fl;
1069
1070 fl.l_whence = 0;
1071 fl.l_len = 0;
1072 fl.l_start = length;
1073 fl.l_type = F_WRLCK; /* write lock on file space */
1074
1075 /*
1076 * This relies on the UNDOCUMENTED F_FREESP argument to
1077 * fcntl(2), which truncates the file so that it ends at the
1078 * position indicated by fl.l_start.
1079 *
1080 * Will minor miracles never cease?
1081 */
1082
1083 if (fcntl (fd, F_FREESP, &fl) < 0)
1084 return -1;
1085
1086 return 0;
1087 }
1088
1089 #else /* !F_FREESP */
1090
1091 int
1092 ftruncate (fd, length)
1093 int fd;
1094 off_t length;
1095 {
1096 errno = EIO;
1097 return -1;
1098 }
1099
1100 #endif /* !F_FREESP */
1101 #endif /* !F_CHSIZE */
1102 #endif /* !HAVE_FTRUNCATE */
1103
1104
1105 extern FILE *msg_file;
1106
1107 #if defined (HAVE_VPRINTF) && __STDC__
1108 #include <stdarg.h>
1109
1110 void
1111 msg (char *str,...)
1112 {
1113 va_list args;
1114
1115 va_start (args, str);
1116 fflush (msg_file);
1117 fprintf (stderr, "%s: ", tar);
1118 if (f_sayblock)
1119 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1120 vfprintf (stderr, str, args);
1121 va_end (args);
1122 putc ('\n', stderr);
1123 fflush (stderr);
1124 }
1125
1126 void
1127 msg_perror (char *str,...)
1128 {
1129 va_list args;
1130 int save_e;
1131
1132 save_e = errno;
1133 fflush (msg_file);
1134 fprintf (stderr, "%s: ", tar);
1135 if (f_sayblock)
1136 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1137 va_start (args, str);
1138 vfprintf (stderr, str, args);
1139 va_end (args);
1140 errno = save_e;
1141 perror (" ");
1142 fflush (stderr);
1143 }
1144
1145 #endif /* HAVE_VPRINTF and __STDC__ */
1146
1147 #if defined(HAVE_VPRINTF) && !__STDC__
1148 #include <varargs.h>
1149 void
1150 msg (str, va_alist)
1151 char *str;
1152 va_dcl
1153 {
1154 va_list args;
1155
1156 fflush (msg_file);
1157 fprintf (stderr, "%s: ", tar);
1158 if (f_sayblock)
1159 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1160 va_start (args);
1161 vfprintf (stderr, str, args);
1162 va_end (args);
1163 putc ('\n', stderr);
1164 fflush (stderr);
1165 }
1166
1167 void
1168 msg_perror (str, va_alist)
1169 char *str;
1170 va_dcl
1171 {
1172 va_list args;
1173 int save_e;
1174
1175 save_e = errno;
1176 fflush (msg_file);
1177 fprintf (stderr, "%s: ", tar);
1178 if (f_sayblock)
1179 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1180 va_start (args);
1181 vfprintf (stderr, str, args);
1182 va_end (args);
1183 errno = save_e;
1184 perror (" ");
1185 fflush (stderr);
1186 }
1187
1188 #endif /* HAVE_VPRINTF and not __STDC__ */
1189
1190 #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
1191 void
1192 msg (str, args)
1193 char *str;
1194 int args;
1195 {
1196 fflush (msg_file);
1197 fprintf (stderr, "%s: ", tar);
1198 if (f_sayblock)
1199 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1200 _doprnt (str, &args, stderr);
1201 putc ('\n', stderr);
1202 fflush (stderr);
1203 }
1204
1205 void
1206 msg_perror (str, args)
1207 char *str;
1208 int args;
1209 {
1210 int save_e;
1211
1212 save_e = errno;
1213 fflush (msg_file);
1214 fprintf (stderr, "%s: ", tar);
1215 if (f_sayblock)
1216 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1217 _doprnt (str, &args, stderr);
1218 errno = save_e;
1219 perror (" ");
1220 fflush (stderr);
1221 }
1222
1223 #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
1224
1225 #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
1226 void
1227 msg (str, a1, a2, a3, a4, a5, a6)
1228 char *str;
1229 {
1230 fflush (msg_file);
1231 fprintf (stderr, "%s: ", tar);
1232 if (f_sayblock)
1233 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1234 fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
1235 putc ('\n', stderr);
1236 fflush (stderr);
1237 }
1238
1239 void
1240 msg_perror (str, a1, a2, a3, a4, a5, a6)
1241 char *str;
1242 {
1243 int save_e;
1244
1245 save_e = errno;
1246 fflush (msg_file);
1247 fprintf (stderr, "%s: ", tar);
1248 if (f_sayblock)
1249 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1250 fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
1251 fprintf (stderr, ": ");
1252 errno = save_e;
1253 perror (" ");
1254 }
1255
1256 #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
This page took 0.093765 seconds and 4 git commands to generate.