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