]> Dogcows Code - chaz/tar/blob - src/port.c
*** empty log message ***
[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
49 #else /* not __MSDOS__ */
50
51 char TTY_NAME[] = "/dev/tty";
52
53 #endif /* not __MSDOS__ */
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 void
1005 ck_pipe (pipes)
1006 int *pipes;
1007 {
1008 if (pipe (pipes) < 0)
1009 {
1010 msg_perror ("can't open a pipe");
1011 exit (EX_SYSTEM);
1012 }
1013 }
1014
1015
1016 #ifndef HAVE_STRSTR
1017 /*
1018 * strstr - find first occurrence of wanted in s
1019 */
1020
1021 char * /* found string, or NULL if none */
1022 strstr (s, wanted)
1023 char *s;
1024 char *wanted;
1025 {
1026 register char *scan;
1027 register size_t len;
1028 register char firstc;
1029
1030 if (*wanted == '\0')
1031 return (char *) 0;
1032 /*
1033 * The odd placement of the two tests is so "" is findable.
1034 * Also, we inline the first char for speed.
1035 * The ++ on scan has been moved down for optimization.
1036 */
1037 firstc = *wanted;
1038 len = strlen (wanted);
1039 for (scan = s; *scan != firstc || strncmp (scan, wanted, len) != 0;)
1040 if (*scan++ == '\0')
1041 return (char *) 0;
1042 return scan;
1043 }
1044
1045 #endif /* !HAVE_STRSTR */
1046
1047 #ifndef HAVE_FTRUNCATE
1048
1049 #ifdef F_CHSIZE
1050 int
1051 ftruncate (fd, length)
1052 int fd;
1053 off_t length;
1054 {
1055 return fcntl (fd, F_CHSIZE, length);
1056 }
1057
1058 #else /* !F_CHSIZE */
1059 #ifdef F_FREESP
1060 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
1061
1062 int
1063 ftruncate (fd, length)
1064 int fd; /* file descriptor */
1065 off_t length; /* length to set file to */
1066 {
1067 struct flock fl;
1068
1069 fl.l_whence = 0;
1070 fl.l_len = 0;
1071 fl.l_start = length;
1072 fl.l_type = F_WRLCK; /* write lock on file space */
1073
1074 /*
1075 * This relies on the UNDOCUMENTED F_FREESP argument to
1076 * fcntl(2), which truncates the file so that it ends at the
1077 * position indicated by fl.l_start.
1078 *
1079 * Will minor miracles never cease?
1080 */
1081
1082 if (fcntl (fd, F_FREESP, &fl) < 0)
1083 return -1;
1084
1085 return 0;
1086 }
1087
1088 #else /* !F_FREESP */
1089
1090 int
1091 ftruncate (fd, length)
1092 int fd;
1093 off_t length;
1094 {
1095 errno = EIO;
1096 return -1;
1097 }
1098
1099 #endif /* !F_FREESP */
1100 #endif /* !F_CHSIZE */
1101 #endif /* !HAVE_FTRUNCATE */
1102
1103
1104 extern FILE *msg_file;
1105
1106 #if defined (HAVE_VPRINTF) && __STDC__
1107 #include <stdarg.h>
1108
1109 void
1110 msg (char *str,...)
1111 {
1112 va_list args;
1113
1114 va_start (args, str);
1115 fflush (msg_file);
1116 fprintf (stderr, "%s: ", tar);
1117 if (f_sayblock)
1118 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1119 vfprintf (stderr, str, args);
1120 va_end (args);
1121 putc ('\n', stderr);
1122 fflush (stderr);
1123 }
1124
1125 void
1126 msg_perror (char *str,...)
1127 {
1128 va_list args;
1129 int save_e;
1130
1131 save_e = errno;
1132 fflush (msg_file);
1133 fprintf (stderr, "%s: ", tar);
1134 if (f_sayblock)
1135 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1136 va_start (args, str);
1137 vfprintf (stderr, str, args);
1138 va_end (args);
1139 errno = save_e;
1140 perror (" ");
1141 fflush (stderr);
1142 }
1143
1144 #endif /* HAVE_VPRINTF and __STDC__ */
1145
1146 #if defined(HAVE_VPRINTF) && !__STDC__
1147 #include <varargs.h>
1148 void
1149 msg (str, va_alist)
1150 char *str;
1151 va_dcl
1152 {
1153 va_list args;
1154
1155 fflush (msg_file);
1156 fprintf (stderr, "%s: ", tar);
1157 if (f_sayblock)
1158 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1159 va_start (args);
1160 vfprintf (stderr, str, args);
1161 va_end (args);
1162 putc ('\n', stderr);
1163 fflush (stderr);
1164 }
1165
1166 void
1167 msg_perror (str, va_alist)
1168 char *str;
1169 va_dcl
1170 {
1171 va_list args;
1172 int save_e;
1173
1174 save_e = errno;
1175 fflush (msg_file);
1176 fprintf (stderr, "%s: ", tar);
1177 if (f_sayblock)
1178 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1179 va_start (args);
1180 vfprintf (stderr, str, args);
1181 va_end (args);
1182 errno = save_e;
1183 perror (" ");
1184 fflush (stderr);
1185 }
1186
1187 #endif /* HAVE_VPRINTF and not __STDC__ */
1188
1189 #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
1190 void
1191 msg (str, args)
1192 char *str;
1193 int args;
1194 {
1195 fflush (msg_file);
1196 fprintf (stderr, "%s: ", tar);
1197 if (f_sayblock)
1198 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1199 _doprnt (str, &args, stderr);
1200 putc ('\n', stderr);
1201 fflush (stderr);
1202 }
1203
1204 void
1205 msg_perror (str, args)
1206 char *str;
1207 {
1208 int save_e;
1209
1210 save_e = errno;
1211 fflush (msg_file);
1212 fprintf (stderr, "%s: ", tar);
1213 if (f_sayblock)
1214 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1215 _doprnt (str, &args, stderr);
1216 errno = save_e;
1217 perror (" ");
1218 fflush (stderr);
1219 }
1220
1221 #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
1222
1223 #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
1224 void
1225 msg (str, a1, a2, a3, a4, a5, a6)
1226 char *str;
1227 {
1228 fflush (msg_file);
1229 fprintf (stderr, "%s: ", tar);
1230 if (f_sayblock)
1231 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1232 fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
1233 putc ('\n', stderr);
1234 fflush (stderr);
1235 }
1236
1237 void
1238 msg_perror (str, a1, a2, a3, a4, a5, a6)
1239 char *str;
1240 {
1241 int save_e;
1242
1243 save_e = errno;
1244 fflush (msg_file);
1245 fprintf (stderr, "%s: ", tar);
1246 if (f_sayblock)
1247 fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
1248 fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
1249 fprintf (stderr, ": ");
1250 errno = save_e;
1251 perror (" ");
1252 }
1253
1254 #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
This page took 0.091425 seconds and 5 git commands to generate.