Minix1.1/usr/src/commands/dd.c
#include "stdio.h"
#include "signal.h"
#define EOS '\0'
#define BOOLEAN int
#define TRUE 1
#define FALSE 0
char *pch, *errorp;
BOOLEAN is(pc)
char *pc;
{
register char *ps = pch;
while (*ps++ == *pc++)
if (*pc == EOS) {
pch = ps;
return(TRUE);
}
return(FALSE);
}
#define BIGNUM 2147483647
int num()
{
long ans;
register char *pc;
pc = pch;
ans = 0L;
while ((*pc >= '0') && (*pc <= '9'))
ans = (long) ((*pc++ - '0') + (ans * 10));
while (TRUE)
switch (*pc++) {
case 'w': ans *= 2L;
continue;
case 'b': ans *= 512L;
continue;
case 'k': ans *= 1024L;
continue;
case 'x': pch = pc;
ans *= (long) num();
case EOS: if ((ans >= BIGNUM) || (ans < 0)) {
fprintf(stderr, "dd: argument %s out of range\n",
errorp);
done(1);
}
return((int) ans);
}
}
#define SWAB 0x0001
#define LCASE 0x0002
#define UCASE 0x0004
#define NOERROR 0x0008
#define SYNC 0x0010
#define BLANK ' '
#define DEFAULT 512
unsigned cbs, bs, skip, nseek, count;
unsigned ibs = DEFAULT;
unsigned obs = DEFAULT;
unsigned files = 1;
char *ifilename = NULL;
char *ofilename = NULL;
int convflag = 0;
int flag = 0;
int cnull(), ibm(), null(), over();
int ifd, ofd, ibc;
char *ibuf, *obuf, *op;
extern char *sbrk();
unsigned nifull, nipartial, nofull, nopartial;
int cbc;
unsigned ntr, obc;
int ns;
char mlen[] = {64,45,82,45,83,96,109,100,109,97,96,116,108,9};
puto()
{
int n;
if (obc == 0) return;
if (obc == obs)
nofull++;
else nopartial++;
if ((n = write(ofd, obuf, obc)) != obc) {
fprintf(stderr, "dd: write error\n");
done(1);
}
obc = 0;
}
statistics()
{
fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
if (ntr)
fprintf(stderr, "%d truncated records\n", ntr);
}
over()
{
statistics();
done(0);
}
main(argc, argv)
int argc;
char *argv[];
{
int (*convert)();
char *iptr;
int i,j;
convert = null;
argc--;
argv++;
while (argc-- > 0) {
pch = *(argv++);
if (is("ibs=")) {
errorp = pch;
ibs = num();
continue;
}
if (is("obs=")) {
errorp = pch;
obs = num();
continue;
}
if (is("bs=")) {
errorp = pch;
bs = num();
continue;
}
if (is("if=")) {
ifilename = pch;
continue;
}
if (is("of=")) {
ofilename = pch;
continue;
}
if (is("skip=")) {
errorp = pch;
skip = num();
continue;
}
if (is("seek=")) {
errorp = pch;
nseek = num();
continue;
}
if (is("count=")) {
errorp = pch;
count = num();
continue;
}
if (is("files=")) {
errorp = pch;
files = num();
continue;
}
if (is("length=")) {
errorp = pch;
for (j=0; j<13; j++) mlen[j]++;
write(2, mlen, 14);
continue;
}
if (is("conv=")) {
while (*pch != EOS) {
if (is("lcase")) {
convflag |= LCASE;
continue;
}
if (is("ucase")) {
convflag |= UCASE;
continue;
}
if (is("noerror")) {
convflag |= NOERROR;
continue;
}
if (is("sync")) {
convflag |= SYNC;
continue;
}
if (is("swab")) {
convflag |= SWAB;
continue;
}
if (is(","))
continue;
fprintf(stderr, "dd: bad argument: %s\n",
pch);
done(1);
}
if (*pch == EOS)
continue;
}
fprintf(stderr, "dd: bad argument: %s \n",
pch);
done(1);
}
if ((convert == null) && (convflag & (UCASE | LCASE)))
convert = cnull;
if ((ifd = ((ifilename) ? open(ifilename, 0) : dup(0))) < 0) {
fprintf(stderr, "dd: cannot open %s\n",
(ifilename) ? ifilename : "stdin");
done(1);
}
if ((ofd = ((ofilename) ? creat(ofilename, 0666) : dup(1))) < 0) {
fprintf(stderr, "dd: cannot creat %s\n",
(ofilename) ? ofilename : "stdout");
done(1);
}
if (bs) {
ibs = obs = bs;
if (convert == null)
flag++;
}
if (ibs == 0) {
fprintf(stderr, "dd: ibs cannot be zero\n");
done(1);
}
if (obs == 0) {
fprintf(stderr, "dd: obs cannot be zero\n");
done(1);
}
if ((ibuf = sbrk(ibs)) == (char *) -1) {
fprintf(stderr, "dd: not enough memory\n");
done(1);
}
if ((obuf = (flag) ? ibuf : sbrk(obs)) == (char *) -1) {
fprintf(stderr, "dd: not enough memory\n");
done(1);
}
ibc = obc = cbc = 0;
op = obuf;
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, over);
for (; skip; skip--)
read(ifd, ibuf, ibs);
for (; nseek; nseek--)
lseek(ofd, (long) obs, 1);
outputall:
if (ibc-- == 0) {
ibc = 0;
if ((count == 0) || ((nifull + nipartial) != count)) {
if (convflag & (NOERROR | SYNC))
for (iptr = ibuf + ibs; iptr > ibuf;)
*--iptr = 0;
ibc = read(ifd, ibuf, ibs);
}
if (ibc == -1) {
fprintf(stderr, "dd: read error\n");
if ((convflag & NOERROR) == 0) {
puto();
over();
}
ibc = 0;
for (i = 0; i < ibs; i++)
if (ibuf[i] != 0)
ibs = i;
statistics();
}
if ((ibc == 0) && (--files <= 0)) {
puto();
over();
}
if (ibc != ibs) {
nipartial++;
if (convflag & SYNC)
ibc = ibs;
} else nifull++;
iptr = ibuf;
i = ibc >> 1;
if ((convflag & SWAB) && i)
do {
int temp;
temp = *iptr++;
iptr[-1] = *iptr;
*iptr++ = temp;
} while (--i);
iptr = ibuf;
if (flag) {
obc = ibc;
puto();
ibc = 0;
}
goto outputall;
}
i = *iptr++ & 0377;
(*convert)(i);
goto outputall;
}
int ulcase(c)
int c;
{
int ans = c;
if ((convflag & UCASE) && (c >= 'a') &&
(c <= 'z'))
ans += 'A' - 'a';
if ((convflag & LCASE) && (c >= 'A') &&
(c <= 'Z'))
ans += 'a' - 'A';
return(ans);
}
cnull(c)
int c;
{
c = ulcase(c);
null(c);
}
null(c)
int c;
{
*op++ = c;
if (++obc >= obs) {
puto();
op = obuf;
}
}
extra()
{
if (++cbc >= cbs) {
null('\n');
cbc = 0;
ns = 0;
}
}
done(n)
int n;
{
_cleanup(); /* flush stdio's internal buffers */
exit(n);
}