X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=f2b2d64aef563463fde6cd2a95160e150247a5f6;hb=0eceef9ba14ca872e57ecd2f4ca4f5893b78bac8;hp=f402374df6614566ae15963d2b64ad25c0ec3673;hpb=740b318ceadbc4bbe4141982ffe8f9f7191959ea;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index f402374..f2b2d64 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,5 +1,5 @@ /* Buffer management for tar. - Copyright (C) 1988 Free Software Foundation + Copyright (C) 1988, 1992 Free Software Foundation This file is part of GNU Tar. @@ -21,34 +21,38 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ * Buffer management for tar. * * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985. - * - * @(#) buffer.c 1.28 11/6/87 - gnu */ #include #include +#ifndef STDC_HEADERS +extern int errno; +#endif #include /* For non-Berkeley systems */ -#include #include +#include +time_t time(); -#ifndef MSDOS +#ifdef HAVE_SYS_MTIO_H #include -#if !defined(USG) || defined(HAVE_MTIO) #include #endif + +#ifdef BSD42 +#include +#else +#ifndef V7 +#include +#endif #endif -#ifdef MSDOS -# include +#ifdef __MSDOS__ #include -#else -# ifdef XENIX -# include -# endif -# include #endif -extern int errno; +#ifdef XENIX +#include +#endif #include "tar.h" #include "port.h" @@ -65,45 +69,24 @@ FILE *msg_file = stdout; #define PREAD 0 /* Read file descriptor from pipe() */ #define PWRITE 1 /* Write file descriptor from pipe() */ -#ifdef __STDC__ -extern void *malloc(); -extern void *valloc(); -#else -extern char *malloc(); -extern char *valloc(); -#endif -extern time_t time(); - -extern char *index(), *strcat(); -extern char *strcpy(); - -/* - * V7 doesn't have a #define for this. - */ -#ifndef O_RDONLY -#define O_RDONLY 0 -#endif -#ifndef O_RDWR -#define O_RDWR 2 -#endif -#ifndef O_CREAT -#define O_CREAT 0 -#endif -#ifndef O_BINARY -#define O_BINARY 0 -#endif - #define MAGIC_STAT 105 /* Magic status returned by child, if it can't exec. We hope compress/sh never return this status! */ +char *valloc(); + void writeerror(); void readerror(); void ck_pipe(); void ck_close(); +int backspace_output(); extern void finish_header(); +void flush_archive(); +int isfile(); +int new_volume(); +void verify_volume(); extern void to_oct(); #ifndef __MSDOS__ @@ -142,7 +125,10 @@ static int r_error_count; /* * Have we hit EOF yet? */ -static int eof; +static int hit_eof; + +/* Checkpointing counter */ +static int checkpoint; /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; @@ -151,6 +137,7 @@ int file_to_switch_to= -1; /* If remote update, close archive, and use static int volno = 1; /* JF which volume of a multi-volume tape we're on */ +static int global_volno = 1; /* Volume number to print in external messages. */ char *save_name = 0; /* Name of the file we are currently writing */ long save_totsize; /* total size of file we are writing. Only @@ -170,8 +157,8 @@ static long real_s_sizeleft; void reset_eof() { - if(eof) { - eof=0; + if(hit_eof) { + hit_eof=0; ar_record=ar_block; ar_last=ar_block+blocking; ar_reading=0; @@ -187,11 +174,11 @@ union record * findrec() { if (ar_record == ar_last) { - if (eof) + if (hit_eof) return (union record *)NULL; /* EOF */ flush_archive(); if (ar_record == ar_last) { - eof++; + hit_eof++; return (union record *)NULL; /* EOF */ } } @@ -258,11 +245,11 @@ dupto(from, to, msg) } } -#ifdef MSDOS +#ifdef __MSDOS__ void child_open() { - fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar); + fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar); exit(EX_ARGSBAD); } #else @@ -271,6 +258,7 @@ child_open() { int pipe[2]; int err = 0; + int nar; int kidpipe[2]; int kidchildpid; @@ -314,24 +302,24 @@ child_open() 2: the file is to be accessed by rmt (compress doesn't know how) 3: the file is not a plain file */ #ifdef NO_REMOTE - if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file)) + if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && isfile(ar_files[0])) #else - if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file)) + if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0])) #endif { /* We don't need a child tar. Open the archive */ if(ar_reading) { - archive=open(ar_file, O_RDONLY|O_BINARY, 0666); + archive=open(ar_files[0], O_RDONLY|O_BINARY, 0666); if(archive<0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } dupto(archive,STDIN,"archive to stdin"); /* close(archive); */ } else { - archive=creat(ar_file,0666); + archive=creat(ar_files[0],0666); if(archive<0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } dupto(archive,STDOUT,"archive to stdout"); @@ -374,20 +362,20 @@ child_open() ck_close(kidpipe[WRITE]); } - if (ar_file[0] == '-' && ar_file[1] == '\0') { + if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { if (ar_reading) archive = STDIN; else archive = STDOUT; } else /* This can't happen if (ar_reading==2) - archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); else */if(ar_reading) - archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); else - archive = rmtcreat(ar_file, 0666); + archive = rmtcreat(ar_files[0], 0666); if (archive < 0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } @@ -474,6 +462,7 @@ child_open() /* return non-zero if p is the name of a directory */ +int isfile(p) char *p; { @@ -481,7 +470,7 @@ char *p; if(stat(p,&stbuf)<0) return 1; - if((stbuf.st_mode&S_IFMT)==S_IFREG) + if(S_ISREG(stbuf.st_mode)) return 1; return 0; } @@ -493,6 +482,7 @@ char *p; * reading or writing. */ /* JF if the arg is 2, open for reading and writing. */ +void open_archive(reading) int reading; { @@ -503,7 +493,7 @@ open_archive(reading) exit(EX_ARGSBAD); } - if(ar_file==0) { + if(n_ar_files==0) { msg("No archive name given, what should I do?"); exit(EX_BADARCH); } @@ -525,16 +515,26 @@ open_archive(reading) ar_last = ar_block + blocking; ar_reading = reading; + if (f_multivol && f_verify) + { + msg ("cannot verify multi-volume archives"); + exit (EX_ARGSBAD); + } + if (f_compress) { if(reading==2 || f_verify) { msg("cannot update or verify compressed archives"); exit(EX_ARGSBAD); } + if (f_multivol) { + msg ("cannot use multi-volume compressed archives"); + exit (EX_ARGSBAD); + } child_open(); - if(!reading && ar_file[0]=='-' && ar_file[1]=='\0') + if(!reading && ar_files[0][0]=='-' && ar_files[0][1]=='\0') msg_file = stderr; /* child_open(rem_host, rem_file); */ - } else if (ar_file[0] == '-' && ar_file[1] == '\0') { + } else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { f_reblock++; /* Could be a pipe, be safe */ if(f_verify) { msg("can't verify stdin/stdout archive"); @@ -551,29 +551,29 @@ open_archive(reading) msg_file = stderr; } } else if (reading==2 || f_verify) { - archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); } else if(reading) { - archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); } else { - archive = rmtcreat(ar_file, 0666); + archive = rmtcreat(ar_files[0], 0666); + } + if (archive < 0) { + msg_perror("can't open %s",ar_files[0]); + exit(EX_BADARCH); } #ifndef __MSDOS__ if(!_isrmt(archive)) { struct stat tmp_stat; fstat(archive,&tmp_stat); - if((tmp_stat.st_mode&S_IFMT)==S_IFREG) { + if(S_ISREG(tmp_stat.st_mode)) { ar_dev=tmp_stat.st_dev; ar_ino=tmp_stat.st_ino; } } #endif - if (archive < 0) { - msg_perror("can't open %s",ar_file); - exit(EX_BADARCH); - } -#ifdef MSDOS +#ifdef __MSDOS__ setmode(archive, O_BINARY); #endif @@ -597,10 +597,10 @@ open_archive(reading) msg("Archive not labelled to match %s",f_volhdr); exit(EX_BADVOL); } - if (re_match (label_pattern, head->header.name, - strlen (head->header.name), 0, 0) < 0) { + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), 0, 0) < 0) { msg ("Volume mismatch! %s!=%s", f_volhdr, - head->header.name); + head->header.arch_name); exit (EX_BADVOL); } #if 0 @@ -615,9 +615,9 @@ open_archive(reading) } else if(f_volhdr) { bzero((void *)ar_block,RECORDSIZE); if(f_multivol) - sprintf(ar_block->header.name,"%s Volume 1",f_volhdr); + sprintf(ar_block->header.arch_name,"%s Volume 1",f_volhdr); else - strcpy(ar_block->header.name,f_volhdr); + strcpy(ar_block->header.arch_name,f_volhdr); ar_block->header.linkflag = LF_VOLHDR; to_oct(time(0), 1+12, ar_block->header.mtime); finish_header(ar_block); @@ -636,6 +636,7 @@ open_archive(reading) * adding (baserec+ar_record), doing a 9-bit shift of baserec, then * subtracting ar_block from that, shifting it back, losing the top 9 bits. */ +void saverec(pointer) union record **pointer; { @@ -657,12 +658,15 @@ saverec(pointer) } */ +void fl_write() { int err; int copy_back; static long bytes_written = 0; + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Write checkpoint %d\n", checkpoint); if(tape_length && bytes_written >= tape_length * 1024) { errno = ENOSPC; err = 0; @@ -683,7 +687,7 @@ fl_write() real_s_sizeleft = 0; return; } -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -699,9 +703,11 @@ fl_write() /* We're multivol Panic if we didn't get the right kind of response */ /* ENXIO is for the UNIX PC */ - if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)) + if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO) writeerror(err); + /* If error indicates a short write, we just move to the next tape. */ + if(new_volume(0)<0) return; bytes_written=0; @@ -715,7 +721,7 @@ fl_write() copy_back = 0; if(f_volhdr) { bzero((void *)ar_block,RECORDSIZE); - sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno); + sprintf(ar_block->header.arch_name,"%s Volume %d",f_volhdr,volno); to_oct(time(0), 1+12, ar_block->header.mtime); ar_block->header.linkflag = LF_VOLHDR; finish_header(ar_block); @@ -726,7 +732,7 @@ fl_write() if(f_volhdr) ar_block++; bzero((void *)ar_block,RECORDSIZE); - strcpy(ar_block->header.name,real_s_name); + strcpy(ar_block->header.arch_name,real_s_name); ar_block->header.linkflag = LF_MULTIVOL; to_oct((long)real_s_sizeleft,1+12, ar_block->header.size); @@ -760,7 +766,7 @@ fl_write() else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back) real_s_name[0] = '\0'; else { -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -784,10 +790,10 @@ writeerror(err) int err; { if (err < 0) { - msg_perror("can't write to %s",ar_file); + msg_perror("can't write to %s",ar_files[cur_ar_file]); exit(EX_BADARCH); } else { - msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file); + msg("only wrote %u of %u bytes to %s",err,blocksize,ar_files[cur_ar_file]); exit(EX_BADARCH); } } @@ -804,7 +810,7 @@ readerror() read_error_flag++; /* Tell callers */ - msg_perror("read error on %s",ar_file); + msg_perror("read error on %s",ar_files[cur_ar_file]); if (baserec == 0) { /* First block of tape. Probably stupidity error */ @@ -827,12 +833,16 @@ readerror() /* * Perform a read to flush the buffer. */ +void fl_read() { int err; /* Result from system call */ int left; /* Bytes left */ char *more; /* Pointer to next byte to read */ + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Read checkpoint %d\n", checkpoint); + /* * Clear the count of errors. This only applies to a single * call to fl_read. We leave read_error_flag alone; it is @@ -859,7 +869,7 @@ fl_read() if(f_multivol) { if(save_name) { if(save_name!=real_s_name) { -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -884,7 +894,7 @@ error_loop: if (err == blocksize) return; - if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) { + if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) { union record *head; try_volume: @@ -909,12 +919,13 @@ error_loop: ptr=(char *)malloc(strlen(f_volhdr)+20); sprintf(ptr,"%s Volume %d",f_volhdr,volno); #endif - if (re_match (label_pattern, head->header.name, - strlen (head->header.name), + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), 0, 0) < 0) { msg("Volume mismatch! %s!=%s",f_volhdr, - head->header.name); + head->header.arch_name); --volno; + --global_volno; goto try_volume; } @@ -922,6 +933,7 @@ error_loop: if(strcmp(ptr,head->header.name)) { msg("Volume mismatch! %s!=%s",ptr,head->header.name); --volno; + --global_volno; free(ptr); goto try_volume; } @@ -929,7 +941,7 @@ error_loop: #endif } if(f_verbose) - fprintf(msg_file,"Reading %s\n",head->header.name); + fprintf(msg_file,"Reading %s\n",head->header.arch_name); head++; } else if(f_volhdr) { msg("Warning: No volume header!"); @@ -938,22 +950,25 @@ error_loop: if(real_s_name[0]) { long from_oct(); - if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { + if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.arch_name,real_s_name)) { msg("%s is not continued on this volume!",real_s_name); --volno; + --global_volno; goto try_volume; } if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { msg("%s is the wrong size (%ld!=%ld+%ld)", - head->header.name,save_totsize, + head->header.arch_name,save_totsize, from_oct(1+12,head->header.size), from_oct(1+12,head->header.offset)); --volno; + --global_volno; goto try_volume; } if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { msg("This volume is out of sequence"); --volno; + --global_volno; goto try_volume; } head++; @@ -993,7 +1008,7 @@ error2loop: goto error2loop; /* Try again */ } if (err == 0) { - msg("archive %s EOF not on block boundary",ar_file); + msg("archive %s EOF not on block boundary",ar_files[cur_ar_file]); exit(EX_BADARCH); } left -= err; @@ -1001,7 +1016,7 @@ error2loop: goto again; } } else { - msg("only read %d bytes from archive %s",err,ar_file); + msg("only read %d bytes from archive %s",err,ar_files[cur_ar_file]); exit(EX_BADARCH); } } @@ -1010,6 +1025,7 @@ error2loop: /* * Flush the current buffer to/from the archive. */ +void flush_archive() { int c; @@ -1025,7 +1041,7 @@ flush_archive() if(file_to_switch_to>=0) { if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); archive=file_to_switch_to; } else @@ -1041,6 +1057,7 @@ flush_archive() /* Backspace the archive descriptor by one blocks worth. If its a tape, MTIOCTOP will work. If its something else, we try to seek on it. If we can't seek, we lose! */ +int backspace_output() { long cur; @@ -1078,6 +1095,7 @@ backspace_output() /* * Close the archive file. */ +void close_archive() { int child; @@ -1087,12 +1105,11 @@ close_archive() if (time_to_start_writing || !ar_reading) flush_archive(); if(cmd_mode==CMD_DELETE) { - long pos; + off_t pos; pos = rmtlseek(archive,0L,1); -#ifndef MSDOS - /* FIXME does ftruncate really take an INT?! */ - (void) ftruncate(archive,(int)pos); +#ifndef __MSDOS__ + (void) ftruncate(archive,pos); #else (void)rmtwrite(archive,"",0); #endif @@ -1101,9 +1118,9 @@ close_archive() verify_volume(); if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); -#ifndef MSDOS +#ifndef __MSDOS__ if (childpid) { /* * Loop waiting for the right child to die, or for @@ -1113,32 +1130,32 @@ close_archive() ; if (child != -1) { - switch (TERM_SIGNAL(status)) { + switch (WTERMSIG(status)) { case 0: /* Child voluntarily terminated -- but why? */ - if (TERM_VALUE(status) == MAGIC_STAT) { + if (WEXITSTATUS(status) == MAGIC_STAT) { exit(EX_SYSTEM);/* Child had trouble */ } - if (TERM_VALUE(status) == (SIGPIPE + 128)) { + if (WEXITSTATUS(status) == (SIGPIPE + 128)) { /* * /bin/sh returns this if its child * dies with SIGPIPE. 'Sok. */ break; - } else if (TERM_VALUE(status)) + } else if (WEXITSTATUS(status)) msg("child returned status %d", - TERM_VALUE(status)); + WEXITSTATUS(status)); case SIGPIPE: break; /* This is OK. */ default: msg("child died with signal %d%s", - TERM_SIGNAL(status), - TERM_COREDUMP(status)? " (core dumped)": ""); + WTERMSIG(status), + WIFCOREDUMPED(status)? " (core dumped)": ""); } } } -#endif /* MSDOS */ +#endif /* __MSDOS__ */ } @@ -1197,8 +1214,42 @@ anno(stream, prefix, savedp) } #endif +/* Called to initialize the global volume number. */ +int +init_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "r"); + if (!vf && errno != ENOENT) + msg_perror ("%s", f_volno_file); + + if (vf) + { + fscanf (vf, "%d", &global_volno); + fclose (vf); + } +} + +/* Called to write out the closing global volume number. */ +int +closeout_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "w"); + if (!vf) + msg_perror ("%s", f_volno_file); + else + { + fprintf (vf, "%d\n", global_volno); + fclose (vf); + } +} + /* We've hit the end of the old volume. Close it and open the next one */ /* Values for type: 0: writing 1: reading 2: updating */ +int new_volume(type) int type; { @@ -1209,6 +1260,7 @@ int type; extern int now_verifying; extern char TTY_NAME[]; char *getenv(); + static int looped = 0; if(!read_file && !f_run_script_at_end) read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin; @@ -1218,101 +1270,112 @@ int type; if(f_verify) verify_volume(); if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); + global_volno++; volno++; + cur_ar_file++; + if (cur_ar_file == n_ar_files) + { + cur_ar_file = 0; + looped = 1; + } + tryagain: - if (f_run_script_at_end) - system(info_script); - else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno); - fflush(msg_file); - if(fgets(inbuf,sizeof(inbuf),read_file)==0) { - fprintf(msg_file,"EOF? What does that mean?"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); - } - if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') - break; - - switch(inbuf[0]) { - case '?': - { - fprintf(msg_file,"\ + if (looped) + { + /* We have to prompt from now on. */ + if (f_run_script_at_end) + system(info_script); + else for(;;) { + fprintf(msg_file,"\007Prepare volume #%d for %s and hit return: ",global_volno, ar_files[cur_ar_file]); + fflush(msg_file); + if(fgets(inbuf,sizeof(inbuf),read_file)==0) { + fprintf(msg_file,"EOF? What does that mean?"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + } + if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') + break; + + switch(inbuf[0]) { + case '?': + { + fprintf(msg_file,"\ n [name] Give a new filename for the next (and subsequent) volume(s)\n\ q Abort tar\n\ ! Spawn a subshell\n\ ? Print this list\n"); - } - break; - - case 'q': /* Quit */ - fprintf(msg_file,"No new volume; exiting.\n"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); - - case 'n': /* Get new file name */ - { - char *q,*r; - static char *old_name; - - for(q= &inbuf[1];*q==' ' || *q=='\t';q++) - ; - for(r=q;*r;r++) - if(*r=='\n') - *r='\0'; - if(old_name) - free(old_name); - old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); - if(p==0) { - msg("Can't allocate memory for name"); - exit(EX_SYSTEM); - } - (void) strcpy(p,q); - ar_file=p; - } - break; - - case '!': -#ifdef MSDOS - spawnl(P_WAIT,getenv("COMSPEC"),"-",0); -#else - /* JF this needs work! */ - switch(fork()) { - case -1: - msg_perror("can't fork!"); - break; - case 0: - p=getenv("SHELL"); - if(p==0) p="/bin/sh"; - execlp(p,"-sh","-i",0); - msg_perror("can't exec a shell %s",p); - _exit(55); - default: - wait(0); - break; - } -#endif - break; - } + } + break; + + case 'q': /* Quit */ + fprintf(msg_file,"No new volume; exiting.\n"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + + case 'n': /* Get new file name */ + { + char *q,*r; + static char *old_name; + + for(q= &inbuf[1];*q==' ' || *q=='\t';q++) + ; + for(r=q;*r;r++) + if(*r=='\n') + *r='\0'; + old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); + if(p==0) { + msg("Can't allocate memory for name"); + exit(EX_SYSTEM); + } + (void) strcpy(p,q); + ar_files[cur_ar_file]=p; + } + break; + + case '!': + #ifdef __MSDOS__ + spawnl(P_WAIT,getenv("COMSPEC"),"-",0); + #else + /* JF this needs work! */ + switch(fork()) { + case -1: + msg_perror("can't fork!"); + break; + case 0: + p=getenv("SHELL"); + if(p==0) p="/bin/sh"; + execlp(p,"-sh","-i",0); + msg_perror("can't exec a shell %s",p); + _exit(55); + default: + wait(0); + break; + } + #endif + break; + } + } } + if(type==2 || f_verify) - archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666); + archive=rmtopen(ar_files[cur_ar_file],O_RDWR|O_CREAT,0666); else if(type==1) - archive=rmtopen(ar_file,O_RDONLY,0666); + archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666); else if(type==0) - archive=rmtcreat(ar_file,0666); + archive=rmtcreat(ar_files[cur_ar_file],0666); else archive= -1; if(archive<0) { - msg_perror("can't open %s",ar_file); + msg_perror("can't open %s",ar_files[cur_ar_file]); goto tryagain; } -#ifdef MSDOS +#ifdef __MSDOS__ setmode(archive,O_BINARY); #endif return 0;