rtregn@immd3.informatik.uni-erlangen.de (Robert Regn) (10/21/88)
Changing the official tar to handle stdin/out has needed more than one year - so I don't want wait for a tar *preserving the link structure* and have improved tar.c myself - based on cpdir. Tar also saves now time and owner. It is tested on a SYS V machine in all modes, on Minix only in c and t mode. Cdiff follows. A cb(1) program was posted in comp.sys.ibm.pc - I have modified it for Minix. The source is included. If someone has the cut(1) program recently posted in comp.sources.unix or another one, please send it to me. At last, some people would like a clear and shure shutdown approach for Minix - I too. So I wrote a program shut, which executes a shell script /etc/shutdown. Calling shut can made by a shut login: shut::2:2::/:/etc/shut Shut is required because login (1) needs an executable program, not a shell script. The shutdown script should be customized for your system. It does: umounting floppies copying login, true and echo to bin - this prevents a root shell if Ctrl F9 is typed after shutdown umounting /usr and root partition (hd3 and hd2) gives messages about success Problem: Because we have no ps(1), shutdown cannot kill processes itself. For making the copies shut must have uid 2 or 0. Using shut is also good for last (1), which can recognize the shutdown time in wtmp. ----------------------------------------------cut ------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: tar.c.cdif cb.c shutdown shut.c # Wrapped by rtregn@faui32 on Thu Oct 20 15:16:33 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'tar.c.cdif' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tar.c.cdif'\" else echo shar: Extracting \"'tar.c.cdif'\" \(4473 characters\) sed "s/^X//" >'tar.c.cdif' <<'END_OF_FILE' X*** 1.3/c.fertig/commands/tar.c Wed Oct 5 12:40:21 1988 X--- tar.c Thu Oct 20 12:55:16 1988 X*************** X*** 39,44 **** X--- 39,53 ---- X X HEADER header; X X+ #define MAXLINKS 512 X+ X+ struct { X+ unsigned short ino; X+ unsigned short dev; X+ char *path; X+ } links[MAXLINKS]; X+ int nlinks = 0; X+ X #define INT_TYPE (sizeof(header.member.m_uid)) X #define LONG_TYPE (sizeof(header.member.m_size)) X X*************** X*** 185,190 **** X--- 194,200 ---- X register char *file; X { X register int fd; X+ struct stat st; X X if (header.member.m_linked == '1') { X if (link(header.member.m_link, file) < 0) X*************** X*** 205,210 **** X--- 215,224 ---- X (void) close(fd); X X chmod(file, (int)convert(header.member.m_mode, INT_TYPE)); X+ st.st_mtime = (int)convert(header.member.m_time, LONG_TYPE); X+ st.st_atime = st.st_mtime; X+ utime(file, &st.st_atime); X+ chown(file, (int)convert(header.member.m_uid, INT_TYPE),(int)convert(header.member.m_gid, INT_TYPE)); X flush(); X } X X*************** X*** 329,334 **** X--- 343,349 ---- X struct stat st; X struct direct dir; X register int fd; X+ char *islink(), *link=NIL_PTR; X X if (stat(file, &st) < 0) { X string_print(NIL_PTR, "Cannot find %s\n", file); X*************** X*** 339,349 **** X return; X } X X! make_header(path_name(file), &st); X mwrite(tar_fd, &header, sizeof(header)); X! if (st.st_mode & S_IFREG) X! copy(path_name(file), fd, tar_fd, st.st_size); X! else if (st.st_mode & S_IFDIR) { X if (chdir(file) < 0) X string_print(NIL_PTR, "Cannot chdir to %s\n", file); X else { X--- 354,371 ---- X return; X } X X! X! /* check for link */ X! if ((st.st_mode & S_IFMT)!=S_IFDIR && st.st_nlink>1) X! link = islink (path_name(file), &st, header.member.m_link); X! X! make_header(path_name(file), &st ,link); X mwrite(tar_fd, &header, sizeof(header)); X! if ((st.st_mode & S_IFMT) == S_IFREG) X! {if (link == 0) X! copy(path_name(file), fd, tar_fd, st.st_size); X! } X! else if ((st.st_mode & S_IFMT) == S_IFDIR) { X if (chdir(file) < 0) X string_print(NIL_PTR, "Cannot chdir to %s\n", file); X else { X*************** X*** 363,370 **** X (void) close(fd); X } X X! make_header(file, st) X! char *file; X register struct stat *st; X { X register char *ptr = header.member.m_name; X--- 385,395 ---- X (void) close(fd); X } X X! /* a new arg link is necessary because link must be written beetween X! clear_header() and checksum() - calling islink in make_header isn't clean*/ X! X! make_header(file, st,link) X! char *file, *link; X register struct stat *st; X gi re[(ster char *ptr = header.member.m_name; X*************** X*** 384,392 **** X string_print(header.member.m_gid, "%I ", st->st_gid); X string_print(header.member.m_size, "%L ", st->st_size); X string_print(header.member.m_time, "%L ", st->st_mtime); X! header.member.m_linked = ' '; X string_print(header.member.m_checksum, "%I", checksum()); X } X X clear_header() X { X--- 409,465 ---- X string_print(header.member.m_gid, "%I ", st->st_gid); X string_print(header.member.m_size, "%L ", st->st_size); X string_print(header.member.m_time, "%L ", st->st_mtime); X! if (link != NIL_PTR) X! { X! header.member.m_linked = '1'; X! strncpy (header.member.m_link, link, NAME_SIZE); X! } X! else X! header.member.m_linked = ' '; X string_print(header.member.m_checksum, "%I", checksum()); X } X+ X+ char *islink(file, st) X+ struct stat *st; X+ char *file; X+ { X+ /* Handle files that are links. X+ * Returns 0 if file must be copied. X+ * Returns 1 if file has been successfully linked. X+ */ X+ int i; X+ int linkent; X+ char *malloc(); X+ X+ linkent = -1; X+ for (i=0; i<nlinks; i++) X+ { X+ if (links[i].dev==st->st_dev X+ && links[i].ino==st->st_ino) X+ linkent=i; X+ } X+ if (linkent>=0) /* It's already in the link table */ X+ { /* we must have copied it earlier. X+ * Don't copy it twice. X+ */ X+ X+ return(links[linkent].path); /* Don't try to copy it */ X+ X+ } else { /* Make an entry in the link table */ X+ if (nlinks >= MAXLINKS) X+ error("Too many links at %s\n",file); X+ links[nlinks].dev = st->st_dev; X+ links[nlinks].ino = st->st_ino; X+ links[nlinks].path = malloc(strlen(file)+1); X+ if (links[nlinks].path == 0) X+ error("No more memory at %s\n",file); X+ strcpy(links[nlinks].path,file); X+ nlinks++; X+ /* Go ahead and copy it the first time */ X+ return(NIL_PTR); X+ } X+ } X+ X X clear_header() X { END_OF_FILE if test 4473 -ne `wc -c <'tar.c.cdif'`; then echo shar: \"'tar.c.cdif'\" unpacked with wrong size! fi # end of 'tar.c.cdif' fi if test -f 'cb.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cb.c'\" else echo shar: Extracting \"'cb.c'\" \(6929 characters\) sed "s/^X//" >'cb.c' <<'END_OF_FILE' X/* X Compiled on Manx C86 by Allen Morris 3/22/86 X X Modified for DeSmet C by S. Lekach 3/20/86 X X Modified for Lattice C Ver 1.01 X by: John W. Kindschi Jr. (10-30-83) X X Modified for Minix X by: Robert Regn rtregn@faui32.uucp (12. 10. 88) X X Swiped from CPIG'S UNIX system and modified to X run under BDS C by William C. Colley, III X X X To use the program type the following command line: X X cb [file] X X If no input file is specified, then the console is read X*/ X#include <stdio.h> X#define print printf X XFILE *f1; X Xint slevel[10]; Xint clevel; Xint spflg[20][10]; Xint sind[20][10]; Xint siflev[10]; Xint sifflg[10]; Xint iflev; Xint ifflg; Xint level; Xint eflg; Xint paren; Xint aflg; Xint ct; Xint stabs[20][10]; Xint qflg; Xint j; Xint sflg; Xint bflg; Xint peek; Xint tabs; X Xstatic int ind[10] = { X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Xstatic int pflg[10] = { X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; X Xchar lchar; Xchar pchar; Xchar *wif[2]; Xchar *welse[2]; Xchar *wfor[2]; Xchar *wds[3]; Xchar cc; Xchar string[200]; Xint lastchar; Xint c; X X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X X /* Initialize everything here */ X if (argc > 2){ X printf("Usage: %s [file]\n", *argv); X exit(1); X } X if ( argc == 1) /*stdin*/ X f1 = stdin; X else if ((f1 = fopen(*++argv,"r")) == NULL){ X printf("File not found: %s\n", *argv); X exit(1); X } X clevel = iflev = level = eflg = paren = 0; X aflg = qflg = j = bflg = tabs = 0; X ifflg = peek = -1; X sflg = 1; X wif[0] = "if"; X welse[0] = "else"; X wfor[0] = "for"; X wds[0] = "case"; X wds[1] = "default"; X wif[1] = welse[1] = wfor[1] = wds[2] = 0; X X /* End of Initialization */ X X cb(); X fclose(f1); X} X Xcb() X{ X while ((c = getchr()) != EOF){ X switch(c){ X default: X string[j++] = c; X if (c != ',') lchar = c; X break; X case ' ': X case '\t': X if (lookup(welse) == 1){ X gotelse(); X if(sflg == 0 || j > 0)string[j++] = c; X putsx(); X sflg = 0; X break; X } X if(sflg == 0 || j > 0) string[j++] = c; X break; X case '\n': X if (eflg = lookup(welse) == 1) gotelse(); X putsx(); X print("\n"); X sflg = 1; X if (eflg == 1){ X pflg[level]++; X tabs++; X } else X if(pchar == lchar) X aflg = 1; X break; X case '{': X if (lookup(welse) == 1) gotelse(); X siflev[clevel] = iflev; X sifflg[clevel] = ifflg; X iflev = ifflg = 0; X clevel++; X if (sflg == 1 && pflg[level] != 0){ X pflg[level]--; X tabs--; X } X string[j++] = c; X putsx(); X getnl(); X putsx(); X print("\n"); X tabs++; X sflg = 1; X if (pflg[level] > 0){ X ind[level] = 1; X level++; X slevel[level] = clevel; X } X break; X case '}': X clevel--; X if ((iflev = siflev[clevel]-1) < 0) iflev = 0; X ifflg = sifflg[clevel]; X putsx(); X tabs--; X ptabs(); X if ((peek = getchr()) == ';'){ X print("%c;",c); X peek = -1; X } else print("%c",c); X getnl(); X putsx(); X print("\n"); X sflg = 1; X if (clevel < slevel[level]) if (level > 0) level--; X if (ind[level] != 0){ X tabs -= pflg[level]; X pflg[level] = 0; X ind[level] = 0; X } X break; X case '"': X case '\'': X string[j++] = c; X while((cc = getchr()) != c){ X string[j++] = cc; X if(cc == '\\'){ X string[j++] = getchr(); X } X if(cc == '\n'){ X putsx(); X sflg = 1; X } X } X string[j++] = cc; X if(getnl() == 1){ X lchar = cc; X peek = '\n'; X } X break; X case ';': X string[j++] = c; X putsx(); X if(pflg[level] > 0 && ind[level] == 0){ X tabs -= pflg[level]; X pflg[level] = 0; X } X getnl(); X putsx(); X print("\n"); X sflg = 1; X if(iflev > 0) X if(ifflg == 1){ X iflev--; X ifflg = 0; X } X else iflev = 0; X break; X case '\\': X string[j++] = c; X string[j++] = getchr(); X break; X case '?': X qflg = 1; X string[j++] = c; X break; X case ':': X string[j++] = c; X if(qflg == 1){ X qflg = 0; X break; X } X if(lookup(wds) == 0){ X sflg = 0; X putsx(); X } else { X tabs--; X putsx(); X tabs++; X } X if((peek = getchr()) == ';'){ X print(";"); X peek = -1; X } X getnl(); X putsx(); X print("\n"); X sflg = 1; X break; X case '/': X string[j++] = c; X if((peek = getchr()) != '*') break; X string[j++] = peek; X peek = -1; X comment(); X break; X case ')': X paren--; X string[j++] = c; X putsx(); X if(getnl() == 1){ X peek = '\n'; X if(paren != 0) aflg = 1; X else if(tabs > 0){ X pflg[level]++; X tabs++; X ind[level] = 0; X } X } X break; X case '#': X string[j++] = c; X while((cc = getchr()) != '\n') string[j++] = cc; X string[j++] = cc; X sflg = 0; X putsx(); X sflg = 1; X break; X case '(': X string[j++] = c; X paren++; X if(lookup(wfor) == 1){ X while((c = getsx()) != ';'); X ct = 0; Xcont: X while((c = getsx()) != ')'){ X if(c == '(') ct++; X } X if(ct != 0){ X ct--; X goto cont; X } X paren--; X putsx(); X if(getnl() == 1){ X peek = '\n'; X pflg[level]++; X tabs++; X ind[level] = 0; X } X break; X } X if(lookup(wif) == 1){ X putsx(); X stabs[clevel][iflev] = tabs; X spflg[clevel][iflev] = pflg[level]; X sind[clevel][iflev] = ind[level]; X iflev++; X ifflg = 1; X } X } X } X} X X Xptabs() X{ X int i; X for (i=0; i < tabs; i++) print("\t"); X} X Xgetchr() X{ X if(peek<0 && lastchar != ' ' && lastchar != '\t')pchar = lastchar; X lastchar = (peek < 0) ? getc(f1) : peek; X peek = -1; X return(lastchar == '\r' ? getchr() : lastchar); X} X Xputsx() X{ X if (j > 0) X { X if (sflg != 0) X { X ptabs(); X sflg = 0; X if (aflg == 1) X { X aflg = 0; X if (tabs > 0) print (" "); X } X } X string[j] = '\0'; X print("%s",string); X j = 0; X } else { X if (sflg != 0) { X sflg = 0; X aflg = 0; X } X } X} X Xlookup(tab) Xchar *tab[]; X{ X char r; X int i,kk,k,l; X if(j < 1) return(0); X kk = 0; X while (string[kk] == ' ') kk++; X for (i = 0; tab[i] != 0; i++) X { X l = 0; X for(k=kk;(r = tab[i][l++]) == string[k] && r != '\0';k++); X if(r == '\0' && (string[k] < 'a' || string[k] > 'z'))return(1); X } X return(0); X} X Xgetsx() X{ X char ch; Xbeg: X if((ch = string[j++] = getchr()) == '\\') X { X string[j++] = getchr(); X goto beg; X } X if(ch == '\'' || ch == '"') X { X while((cc = string[j++] = getchr()) != ch) if(cc == '\\') string[j++] = getchr(); X goto beg; X } X if(ch == '\n'){ X putsx(); X aflg = 1; X goto beg; X } else return(ch); X} X Xgotelse() X{ X tabs = stabs[clevel][iflev]; X pflg[level] = spflg[clevel][iflev]; X ind[level] = sind[clevel][iflev]; X ifflg = 1; X} X Xgetnl() X{ X while ((peek = getchr()) == '\t' || peek == ' '){ X string[j++] = peek; X peek = -1; X } X if((peek = getchr()) == '/'){ X peek = -1; X if ((peek = getchr()) == '*'){ X string[j++] = '/'; X string[j++] = '*'; X peek = -1; X comment(); X } else string[j++] = '/'; X } X if((peek = getchr()) == '\n'){ X peek = -1; X return(1); X } X return(0); X} X Xcomment() X{ Xrep: X while ((c = string[j++] = getchr()) != '*') X if (c == '\n'){ X putsx(); X sflg = 1; X } Xgotstar: X if ((c = string[j++] = getchr()) != '/'){ X if (c == '*') goto gotstar; X goto rep; X } X} END_OF_FILE if test 6929 -ne `wc -c <'cb.c'`; then echo shar: \"'cb.c'\" unpacked with wrong size! fi # end of 'cb.c' fi if test -f 'shutdown' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'shutdown'\" else echo shar: Extracting \"'shutdown'\" \(363 characters\) sed "s/^X//" >'shutdown' <<'END_OF_FILE' Xsync Xsync X/etc/umount /dev/fd0 2>/dev/null X/etc/umount /dev/fd1 2>/dev/null X/etc/umount /dev/hd2 2>/dev/null Xcp /usr/bin/echo /tmp Xcp /usr/bin/true /tmp Xcp /usr/bin/login /bin Xif /etc/umount /dev/hd3 X then /tmp/echo ' ' NORMAL SYSTEM SHUTDOWN X while /tmp/true X do : X done X else /tmp/echo cannot umount hard disk -- please kill processes X /tmp/echo type F9 Xfi END_OF_FILE if test 363 -ne `wc -c <'shutdown'`; then echo shar: \"'shutdown'\" unpacked with wrong size! fi chmod +x 'shutdown' # end of 'shutdown' fi if test -f 'shut.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'shut.c'\" else echo shar: Extracting \"'shut.c'\" \(105 characters\) sed "s/^X//" >'shut.c' <<'END_OF_FILE' Xmain() X{ X close(0); X open("/etc/shutdown", 0); X execl("/bin/sh", "sh", 0); X printf("shutdown failed"); X} END_OF_FILE if test 105 -ne `wc -c <'shut.c'`; then echo shar: \"'shut.c'\" unpacked with wrong size! fi # end of 'shut.c' fi echo shar: End of shell archive. exit 0 Robert Regn rtregn.faui32.uucp