commit 44ae0f1
shrub
·
2026-05-27 12:37:21 +0000 UTC
parent 30ef0e4
add a simple shar
5 files changed,
+280,
-2
M
Makefile
+1,
-1
1@@ -1,7 +1,7 @@
2 .POSIX:
3
4 #RECURSIVE MAKE CONSIDERED USEFUL?
5-SUBDIRS = apply col ctags finger jot look pr rs script
6+SUBDIRS = apply col ctags finger jot look pr rs script shar
7 all:
8 @set -e; \
9 for dir in $(SUBDIRS); do \
+3,
-1
1@@ -3,6 +3,8 @@ netmisc
2
3 misc programs from netbsd with some compatibilty shim and portability bits.
4
5+the shar implementation is not from netbsd, but a slightly improved version in C by me
6+
7 you need cc, make, yacc, etc to build, and a reasonably posix-compliant system.
8
9-all code under it's original license
10+all netbsd code under it's original license
+26,
-0
1@@ -0,0 +1,26 @@
2+.POSIX:
3+
4+PROG = shar
5+SRCS = shar.c
6+MAN = shar.1
7+
8+CC = cc
9+CFLAGS = -O2
10+DESTDIR =
11+BINDIR = /usr/local/bin
12+MANDIR = /usr/local/share/man
13+
14+all: $(PROG)
15+
16+$(PROG): $(SRCS)
17+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $(SRCS) $(LDLIBS)
18+
19+install: $(PROG)
20+ mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1
21+ cp $(PROG) $(DESTDIR)$(BINDIR)/$(PROG)
22+ chmod 755 $(DESTDIR)$(BINDIR)/$(PROG)
23+ cp $(MAN) $(DESTDIR)$(MANDIR)/man1/$(MAN)
24+ chmod 644 $(DESTDIR)$(MANDIR)/man1/$(MAN)
25+
26+clean:
27+ rm -f $(PROG) *.o
+93,
-0
1@@ -0,0 +1,93 @@
2+.\" $NetBSD: shar.1,v 1.14 2023/01/25 19:52:14 rillig Exp $
3+.\" [[[[ SLIGHTLY MODIFIED BY SHRUB :) ]]]]
4+.\" Copyright (c) 1990, 1993
5+.\" The Regents of the University of California. All rights reserved.
6+.\"
7+.\" Redistribution and use in source and binary forms, with or without
8+.\" modification, are permitted provided that the following conditions
9+.\" are met:
10+.\" 1. Redistributions of source code must retain the above copyright
11+.\" notice, this list of conditions and the following disclaimer.
12+.\" 2. Redistributions in binary form must reproduce the above copyright
13+.\" notice, this list of conditions and the following disclaimer in the
14+.\" documentation and/or other materials provided with the distribution.
15+.\" 3. Neither the name of the University nor the names of its contributors
16+.\" may be used to endorse or promote products derived from this software
17+.\" without specific prior written permission.
18+.\"
19+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29+.\" SUCH DAMAGE.
30+.\"
31+.\" @(#)shar.1 8.1 (Berkeley) 6/6/93
32+.\"
33+.Dd May 27, 2026
34+.Dt SHAR 1
35+.Os
36+.Sh NAME
37+.Nm shar
38+.Nd create a shell archive of files
39+.Sh SYNOPSIS
40+.Nm
41+.Ar
42+.Sh DESCRIPTION
43+.Nm
44+writes an
45+.Xr sh 1
46+shell script to the standard output which will recreate the file
47+hierarchy specified by the command line operands.
48+Parent directories for file operands are created as needed.
49+File and directory permissions are restored.
50+.Pp
51+.Nm
52+is normally used for distributing files by
53+.Xr ftp 1
54+or
55+.Xr mail 1 .
56+.Sh EXAMPLES
57+To create a shell archive of the program
58+.Xr ls 1
59+and mail it to Rick:
60+.Bd -literal -offset indent
61+cd ls
62+shar `find . -print` \&| mail -s "ls source" rick
63+.Ed
64+.Pp
65+To recreate the program directory:
66+.Bd -literal -offset indent
67+mkdir ls
68+cd ls
69+\&...
70+<delete header lines and examine mailed archive>
71+\&...
72+sh archive
73+.Ed
74+.Sh SEE ALSO
75+.Xr compress 1 ,
76+.Xr mail 1 ,
77+.Xr tar 1 ,
78+.Xr uuencode 1
79+.Sh HISTORY
80+The
81+.Nm
82+command appeared in
83+.Bx 4.4 .
84+.Sh BUGS
85+.Nm
86+makes no provisions for special types of files.
87+It is not intended for binary files containing NUL bytes.
88+.Sh SECURITY CONSIDERATIONS
89+It is easy to insert trojan horses into
90+.Nm
91+files.
92+It is strongly recommended that all shell archive files be examined
93+before running them through
94+.Xr sh 1 .
+157,
-0
1@@ -0,0 +1,157 @@
2+/*small shar in C inspired by netbsd shar script but with some
3+ * improvements, public domain :] */
4+
5+#include <sys/stat.h>
6+
7+#include <errno.h>
8+#include <stdio.h>
9+#include <stdlib.h>
10+#include <string.h>
11+
12+
13+/* single quote path name */
14+static void
15+q(char *s)
16+{
17+ putchar('\'');
18+ for (; *s; s++)
19+ if (*s == '\'')
20+ fputs("'\\''", stdout);
21+ else
22+ putchar(*s);
23+ putchar('\'');
24+}
25+
26+static void
27+qt(char *s, char *t)
28+{
29+ q(s);
30+ fputs(t, stdout);
31+}
32+
33+static void
34+mkpar(char *s)
35+{
36+ char *p, *e;
37+ size_t n;
38+
39+ if ((e = strrchr(s, '/')) == NULL || e == s)
40+ return;
41+ n = e - s;
42+ if ((p = malloc(n + 1)) == NULL) {
43+ fprintf(stderr, "shar: %s\n", strerror(errno));
44+ exit(1);
45+ }
46+ memcpy(p, s, n);
47+ p[n] = 0;
48+ fputs("mkdir -p ", stdout);
49+ q(p);
50+ fputs(" > /dev/null 2>&1\n", stdout);
51+ free(p);
52+}
53+
54+static int
55+readfile(char *s)
56+{
57+ FILE *f;
58+ struct stat st;
59+ int c, bol = 1;
60+
61+ if ((f = fopen(s, "r")) == NULL) {
62+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
63+ return 1;
64+ }
65+ if (fstat(fileno(f), &st) == -1) {
66+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
67+ fclose(f);
68+ return 1;
69+ }
70+ mkpar(s);
71+ fputs("echo x - ", stdout);
72+ q(s);
73+ fputs("\nsed 's/^X//' >", stdout);
74+ q(s);
75+ fputs(" << 'SHAR_EOF'\n", stdout);
76+ while ((c = getc(f)) != EOF) {
77+ if (bol)
78+ putchar('X');
79+ putchar(c);
80+ bol = c == '\n';
81+ }
82+ if (ferror(f)) {
83+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
84+ fclose(f);
85+ return 1;
86+ }
87+ fclose(f);
88+ /* netbsd shar glues the marker to non newline files but we fix and trim */
89+ if (!bol)
90+ putchar('\n');
91+ fputs("SHAR_EOF\n", stdout);
92+ if (!bol) {
93+ fputs("dd if=", stdout);
94+ q(s);
95+ fputs(" of=", stdout);
96+ qt(s, ".$$");
97+ printf(" bs=1 count=%lld > /dev/null 2>&1 && mv ",
98+ (long long)st.st_size);
99+ qt(s, ".$$");
100+ putchar(' ');
101+ q(s);
102+ putchar('\n');
103+ }
104+ printf("chmod %03o ", (unsigned)st.st_mode & 0777);
105+ q(s);
106+ putchar('\n');
107+ return 0;
108+}
109+
110+static void
111+makedir(char *s, mode_t m)
112+{
113+ fputs("echo c - ", stdout);
114+ q(s);
115+ fputs("\nmkdir -p ", stdout);
116+ q(s);
117+ fputs(" > /dev/null 2>&1\n", stdout);
118+ printf("chmod %03o ", (unsigned)m & 0777);
119+ q(s);
120+ putchar('\n');
121+}
122+
123+static void
124+head(int n, char **v)
125+{
126+ int i;
127+
128+ fputs("# This is a shell archive. Save it in a file, remove anything before\n"
129+ "# this line, and then unpack it by entering \"sh file\". Note, it may\n"
130+ "# create directories; files and directories will be owned by you and\n"
131+ "# have their original permissions.\n"
132+ "#\n"
133+ "# This archive contains:\n"
134+ "#\n", stdout);
135+ for (i = 1; i < n; i++)
136+ printf("#\t%s\n", v[i]);
137+ printf("#\n");
138+}
139+
140+int
141+main(int n, char **v)
142+{
143+ struct stat st;
144+ int i;
145+
146+ if (n == 1) {
147+ fprintf(stderr, "usage: shar [file ...]\n");
148+ return 1;
149+ }
150+ head(n, v);
151+ for (i = 1; i < n; i++)
152+ if (stat(v[i], &st) == 0 && S_ISDIR(st.st_mode))
153+ makedir(v[i], st.st_mode);
154+ else if (readfile(v[i]))
155+ return 1;
156+ printf("exit\n\n");
157+ return 0;
158+}