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