commit c677451
shrub
·
2026-06-24 00:12:35 +0000 UTC
parent 03a391f
add shar
4 files changed,
+302,
-0
+42,
-0
1@@ -0,0 +1,42 @@
2+# i know this is a ninja file, but you're allowed to edit it.
3+# you can also pass things on the command line if you like, eg
4+#
5+# CC=clang ninja
6+
7+cc = $${CC:-cc}
8+cflags = $${CFLAGS:--O2 -std=c99}
9+ldflags = $${LDFLAGS:-}
10+libs = $${LIBS:-}
11+prefix = $${PREFIX:-/usr/local}
12+destdir = $${DESTDIR:-}
13+bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
14+mandir = $${MANDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/man/man1}
15+
16+rule cc
17+ command = $cc $cflags -MMD -MF $out.d -c -o $out $in
18+ deps = gcc
19+ depfile = $out.d
20+ description = cc $out
21+
22+rule link
23+ command = $cc $ldflags -o $out $in $libs
24+ description = link $out
25+
26+rule install
27+ command = mkdir -p $bindir && cp shar $bindir/
28+ description = install shar
29+
30+rule install-man
31+ command = mkdir -p $mandir && cp shar.1 $mandir/
32+ description = man shar.1
33+
34+build shar.o: cc shar.c
35+
36+build shar: link shar.o
37+build all: phony shar
38+build man: install-man shar.1
39+build install: phony install-bin install-man
40+build install-bin: install shar
41+build install-man: install-man shar.1
42+
43+default all
+9,
-0
1@@ -0,0 +1,9 @@
2+shar
3+----
4+a small public domain shar implementation.
5+
6+build:
7+ ninja
8+ ninja install
9+
10+
+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 .
+158,
-0
1@@ -0,0 +1,158 @@
2+/*small shar in C inspired by netbsd shar script but with some
3+ * improvements, public domain :] */
4+
5+#include <sys/stat.h>
6+#include <sys/types.h>
7+
8+#include <errno.h>
9+#include <stdio.h>
10+#include <stdlib.h>
11+#include <string.h>
12+
13+
14+/* single quote path name */
15+static void
16+q(char *s)
17+{
18+ putchar('\'');
19+ for (; *s; s++)
20+ if (*s == '\'')
21+ fputs("'\\''", stdout);
22+ else
23+ putchar(*s);
24+ putchar('\'');
25+}
26+
27+static void
28+qt(char *s, char *t)
29+{
30+ q(s);
31+ fputs(t, stdout);
32+}
33+
34+static void
35+mkpar(char *s)
36+{
37+ char *p, *e;
38+ size_t n;
39+
40+ if ((e = strrchr(s, '/')) == NULL || e == s)
41+ return;
42+ n = e - s;
43+ if ((p = malloc(n + 1)) == NULL) {
44+ fprintf(stderr, "shar: %s\n", strerror(errno));
45+ exit(1);
46+ }
47+ memcpy(p, s, n);
48+ p[n] = 0;
49+ fputs("mkdir -p ", stdout);
50+ q(p);
51+ fputs(" > /dev/null 2>&1\n", stdout);
52+ free(p);
53+}
54+
55+static int
56+readfile(char *s)
57+{
58+ FILE *f;
59+ struct stat st;
60+ int c, bol = 1;
61+
62+ if ((f = fopen(s, "r")) == NULL) {
63+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
64+ return 1;
65+ }
66+ if (stat(s, &st) == -1) {
67+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
68+ fclose(f);
69+ return 1;
70+ }
71+ mkpar(s);
72+ fputs("echo x - ", stdout);
73+ q(s);
74+ fputs("\nsed 's/^X//' >", stdout);
75+ q(s);
76+ fputs(" << 'SHAR_EOF'\n", stdout);
77+ while ((c = getc(f)) != EOF) {
78+ if (bol)
79+ putchar('X');
80+ putchar(c);
81+ bol = c == '\n';
82+ }
83+ if (ferror(f)) {
84+ fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
85+ fclose(f);
86+ return 1;
87+ }
88+ fclose(f);
89+ /* netbsd shar glues the marker to non newline files but we fix and trim */
90+ if (!bol)
91+ putchar('\n');
92+ fputs("SHAR_EOF\n", stdout);
93+ if (!bol) {
94+ fputs("dd if=", stdout);
95+ q(s);
96+ fputs(" of=", stdout);
97+ qt(s, ".$$");
98+ printf(" bs=1 count=%lld > /dev/null 2>&1 && mv ",
99+ (long long)st.st_size);
100+ qt(s, ".$$");
101+ putchar(' ');
102+ q(s);
103+ putchar('\n');
104+ }
105+ printf("chmod %03o ", (unsigned)st.st_mode & 0777);
106+ q(s);
107+ putchar('\n');
108+ return 0;
109+}
110+
111+static void
112+makedir(char *s, mode_t m)
113+{
114+ fputs("echo c - ", stdout);
115+ q(s);
116+ fputs("\nmkdir -p ", stdout);
117+ q(s);
118+ fputs(" > /dev/null 2>&1\n", stdout);
119+ printf("chmod %03o ", (unsigned)m & 0777);
120+ q(s);
121+ putchar('\n');
122+}
123+
124+static void
125+head(int n, char **v)
126+{
127+ int i;
128+
129+ fputs("# This is a shell archive. Save it in a file, remove anything before\n"
130+ "# this line, and then unpack it by entering \"sh file\". Note, it may\n"
131+ "# create directories; files and directories will be owned by you and\n"
132+ "# have their original permissions.\n"
133+ "#\n"
134+ "# This archive contains:\n"
135+ "#\n", stdout);
136+ for (i = 1; i < n; i++)
137+ printf("#\t%s\n", v[i]);
138+ printf("#\n");
139+}
140+
141+int
142+main(int n, char **v)
143+{
144+ struct stat st;
145+ int i;
146+
147+ if (n == 1) {
148+ fprintf(stderr, "usage: shar [file ...]\n");
149+ return 1;
150+ }
151+ head(n, v);
152+ for (i = 1; i < n; i++)
153+ if (stat(v[i], &st) == 0 && S_ISDIR(st.st_mode))
154+ makedir(v[i], st.st_mode);
155+ else if (readfile(v[i]))
156+ return 1;
157+ printf("exit\n\n");
158+ return 0;
159+}