summaryrefslogtreecommitdiffstats
path: root/usr.bin/uudecode/uudecode.c
diff options
context:
space:
mode:
authorfanf <fanf@FreeBSD.org>2002-09-10 20:48:44 +0000
committerfanf <fanf@FreeBSD.org>2002-09-10 20:48:44 +0000
commit0df46c2bed44a6ff10a334ceefe7c5d6b2beac62 (patch)
treee8bdaa89439a4a77006adea57822d67773ce477d /usr.bin/uudecode/uudecode.c
parent02ac4ff9b2b05ba4cdc456960b6353e350f29720 (diff)
downloadFreeBSD-src-0df46c2bed44a6ff10a334ceefe7c5d6b2beac62.zip
FreeBSD-src-0df46c2bed44a6ff10a334ceefe7c5d6b2beac62.tar.gz
Fix tilde-expansion of the filename obtained from the "begin" line in -s
mode, and be more accurate about identifying begin lines so that spurious ones don't have to be manually edited out, and be more forgiving about errors so that -c mode is more useful.
Diffstat (limited to 'usr.bin/uudecode/uudecode.c')
-rw-r--r--usr.bin/uudecode/uudecode.c179
1 files changed, 84 insertions, 95 deletions
diff --git a/usr.bin/uudecode/uudecode.c b/usr.bin/uudecode/uudecode.c
index 28bf7ce..9175c91 100644
--- a/usr.bin/uudecode/uudecode.c
+++ b/usr.bin/uudecode/uudecode.c
@@ -72,7 +72,7 @@ int cflag, iflag, oflag, pflag, sflag;
static void usage(void);
int decode(void);
-int decode2(int);
+int decode2(void);
void base64_decode(const char *);
int
@@ -134,123 +134,112 @@ main(int argc, char *argv[])
int
decode(void)
{
- int flag;
+ int r, v;
- /* decode only one file per input stream */
- if (!cflag)
- return (decode2(0));
-
- /* multiple uudecode'd files */
- for (flag = 0; ; flag++)
- if (decode2(flag))
- return (1);
- else if (feof(stdin))
+ v = decode2();
+ if (v == EOF) {
+ warnx("%s: missing or bad \"begin\" line", filename);
+ return (1);
+ }
+ for (r = v; cflag; r |= v) {
+ v = decode2();
+ if (v == EOF)
break;
-
- return (0);
+ }
+ return (r);
}
int
-decode2(int flag)
+decode2(void)
{
- struct passwd *pw;
+ int base64;
int n;
- char ch, *p;
- int base64, n1;
+ char ch, *p, *q;
+ void *mode;
+ struct passwd *pw;
+ struct stat st;
char buf[MAXPATHLEN+1];
char buffn[MAXPATHLEN+1]; /* file name buffer */
- char *mode, *s;
- void *mode_handle;
- struct stat st;
base64 = 0;
/* search for header line */
- do {
- if (!fgets(buf, sizeof(buf), stdin)) {
- if (flag) /* no error */
- return (0);
-
- warnx("%s: no \"begin\" line", filename);
- return (1);
- }
- } while (strncmp(buf, "begin", 5) != 0);
-
- if (strncmp(buf, "begin-base64", 12) == 0)
- base64 = 1;
-
- /* Parse the header: begin{,-base64} mode outfile. */
- s = strtok(buf, " ");
- if (s == NULL)
- errx(1, "no mode or filename in input file");
- s = strtok(NULL, " ");
- if (s == NULL)
- errx(1, "no mode in input file");
- else {
- mode = strdup(s);
- if (mode == NULL)
- err(1, "strdup()");
+ for (;;) {
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ return (EOF);
+ p = buf;
+ if (strncmp(p, "begin-base64 ", 13) == 0) {
+ base64 = 1;
+ p += 13;
+ } else if (strncmp(p, "begin ", 6) == 0)
+ p += 6;
+ else
+ continue;
+ /* p points to mode */
+ q = strchr(p, ' ');
+ if (q == NULL)
+ continue;
+ *q++ = '\0';
+ /* q points to filename */
+ n = strlen(q);
+ while (n > 0 && (q[n-1] == '\n' || q[n-1] == '\r'))
+ q[--n] = '\0';
+ /* found valid header? */
+ if (n > 0)
+ break;
}
- if (!oflag) {
- outfile = strtok(NULL, "\r\n");
- if (outfile == NULL)
- errx(1, "no filename in input file");
+
+ mode = setmode(p);
+ if (mode == NULL) {
+ warnx("%s: unable to parse file mode", filename);
+ return (1);
}
- if (strlcpy(buf, outfile, sizeof(buf)) >= sizeof(buf))
- errx(1, "%s: filename too long", outfile);
- if (!sflag && !pflag) {
- strlcpy(buffn, buf, sizeof(buffn));
- if (strrchr(buffn, '/') != NULL)
- strncpy(buf, strrchr(buffn, '/') + 1, sizeof(buf));
- if (buf[0] == '\0') {
- warnx("%s: illegal filename", buffn);
- return (1);
+ if (oflag) {
+ /* use command-line filename */
+ n = strlcpy(buffn, outfile, sizeof(buffn));
+ } else if (sflag) {
+ /* don't strip, so try ~user/file expansion */
+ p = NULL;
+ pw = NULL;
+ if (*q == '~')
+ p = strchr(q, '/');
+ if (p != NULL) {
+ *p = '\0';
+ pw = getpwnam(q + 1);
+ *p = '/';
}
-
- /* handle ~user/file format */
- if (buf[0] == '~') {
- if (!(p = index(buf, '/'))) {
- warnx("%s: illegal ~user", filename);
- return (1);
- }
- *p++ = '\0';
- if (!(pw = getpwnam(buf + 1))) {
- warnx("%s: no user %s", filename, buf);
- return (1);
- }
- n = strlen(pw->pw_dir);
- n1 = strlen(p);
- if (n + n1 + 2 > MAXPATHLEN) {
- warnx("%s: path too long", filename);
- return (1);
- }
- bcopy(p, buf + n + 1, n1 + 1);
- bcopy(pw->pw_dir, buf, n);
- buf[n] = '/';
+ if (pw != NULL) {
+ strlcpy(buffn, pw->pw_dir, sizeof(buffn));
+ n = strlcat(buffn, p, sizeof(buffn));
+ } else {
+ n = strlcpy(buffn, q, sizeof(buffn));
}
+ } else {
+ /* strip down to leaf name */
+ p = strrchr(q, '/');
+ if (p != NULL)
+ n = strlcpy(buffn, p+1, sizeof(buffn));
+ else
+ n = strlcpy(buffn, q, sizeof(buffn));
+ }
+ if (n >= sizeof(buffn) || *buffn == '\0') {
+ warnx("%s: bad output filename", filename);
+ return (1);
}
- /* create output file, set mode */
- if (pflag)
- ; /* print to stdout */
-
- else {
- mode_handle = setmode(mode);
- if (mode_handle == NULL)
- err(1, "setmode()");
- if (iflag && !access(buf, F_OK)) {
- warnx("not overwritten: %s", buf);
+ if (!pflag) {
+ if (iflag && !access(buffn, F_OK)) {
+ warnx("not overwritten: %s", buffn);
return (0);
- } else if (freopen(buf, "w", stdout) == NULL ||
- stat(buf, &st) < 0 || (S_ISREG(st.st_mode) &&
- fchmod(fileno(stdout), getmode(mode_handle, 0) & 0666))) {
- warn("%s: %s", buf, filename);
+ }
+ if (freopen(buffn, "w", stdout) == NULL ||
+ stat(buffn, &st) < 0 || (S_ISREG(st.st_mode) &&
+ fchmod(fileno(stdout), getmode(mode, 0) & 0666) < 0)) {
+ warn("%s: %s", filename, buffn);
return (1);
}
- free(mode_handle);
- free(mode);
}
- strcpy(buffn, buf); /* store file name from header line */
+ free(mode);
/* for each input line */
for (;;) {
OpenPOWER on IntegriCloud