|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 18400 (0x47e0) Types: TextFile Notes: UNIX file Names: »dd.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/dd.c«
/* * DD - file conversion and copying */ #include <stdio.h> #include <ctype.h> #include <signal.h> #ifndef TYPES_H #include <sys/types.h> #include <mdata.h> #endif /* Conversions */ #define DD_ASC 01 /* EBCDIC->ASCII */ #define DD_EBC 02 /* ASCII->EBCDIC */ #define DD_IBM 04 /* ASCII-> special print EBCDIC */ #define DD_LCA 010 /* alphabetics to lower case */ #define DD_UCA 020 /* alphabetics to upper case */ #define DD_SWAB 040 /* Swap byte pairs */ #define DD_NERR 0100 /* Ignore errors */ #define DD_SYNC 0200 /* Pad input records to `ibs' */ #define DD_COPY (DD_ASC|DD_EBC|DD_IBM) /* Requires copy */ #define BSIZE BUFSIZ #define streq(a,b) strcmp(a,b)==0 /* * Conversion table from EBCDIC to ASCII. * This is from Nov. 1968, CACM (p 788). * It includes conversions of some controls in * EBCDIC up to characters that are >0200 which * is somewhat non-standard. */ char etoatab[256] = { 0000 /*NUL*/, 0001 /*SOH*/, 0002 /*STX*/, 0003 /*ETX*/, 0234 /*K28*/, 0011 /*HT */, 0206 /*K6 */, 0177 /*DEL*/, 0227 /*K23*/, 0215 /*K13*/, 0216 /*K14*/, 0013 /*VT */, 0014 /*FF */, 0015 /*CR */, 0016 /*SO */, 0017 /*SI */, 0020 /*DLE*/, 0021/*DC1*/, 0022 /*DC2*/, 0023 /*DC3*/, 0235 /*K29*/, 0205 /*K5 */, 0010 /*BS */, 0207 /*K7 */, 0030 /*CAN*/, 0031 /*EM */, 0222 /*K18*/, 0217 /*K15*/, 0034 /*FS */, 0035 /*GS */, 0036 /*RS */, 0037 /*US */, 0200 /*K0 */, 0201 /*K1 */, 0202 /*K2 */, 0203 /*K3 */, 0204 /*K4 */, 0012 /*LF */, 0027 /*ETB*/, 0033 /*ESC*/, 0210 /*K8 */, 0211 /*K9 */, 0212 /*K10*/, 0213 /*K11*/, 0214 /*K12*/, 0005 /*ENQ*/, 0006 /*ACK*/, 0007 /*BEL*/, 0220 /*K16*/, 0221 /*K17*/, 0026 /*SYN*/, 0223 /*K19*/, 0224 /*K20*/, 0225 /*K21*/, 0226 /*K22*/, 0004 /*EOT*/, 0230 /*K24*/, 0231 /*K25*/, 0232 /*K26*/, 0233 /*K27*/, 0024 /*DC4*/, 0025 /*NAK*/, 0236 /*K30*/, 0032 /*SUB*/, 0040 /* */, 0240 /*N0 */, 0241 /*N1 */, 0242 /*N2 */, 0243 /*N3 */, 0244 /*N4 */, 0245 /*N5 */, 0246 /*N6 */, 0247 /*N7 */, 0250 /*N8 */, 0133 /* [ */, 0056 /* . */, 0074 /* < */, 0050 /* ( */, 0053 /* + */, 0041 /* ! */, 0046 /* & */, 0251 /*N9 */, 0252 /*N10*/, 0253 /*N11*/, 0254 /*N12*/, 0255 /*N13*/, 0256 /*N14*/, 0257 /*N15*/, 0260 /*N16*/, 0261 /*N17*/, 0135 /* ] */, 0044 /* $ */, 0052 /* * */, 0051 /* ) */, 0073 /* ; */, 0136 /* ^ */, 0055 /* - */, 0057 /* / */, 0262 /*N18*/, 0263 /*N19*/, 0264 /*N20*/, 0265 /*N21*/, 0266 /*N22*/, 0267 /*N23*/, 0270 /*N24*/, 0271 /*N25*/, 0174 /* | */, 0054 /* , */, 0045 /* % */, 0137 /* _ */, 0076 /* > */, 0077 /* ? */, 0272 /*N26*/, 0273 /*N27*/, 0274 /*N28*/, 0275 /*N29*/, 0276 /*N30*/, 0277 /*N31*/, 0300 /*N32*/, 0301 /*N33*/, 0302 /*N34*/, 0140 /* ` */, 0072 /* : */, 0043 /* # */, 0100 /* @ */, 0047 /* ' */, 0075 /* = */, 0042 /* " */, 0303 /*N35*/, 0141 /* a */, 0142 /* b */, 0143 /* c */, 0144 /* d */, 0145 /* e */, 0146 /* f */, 0147 /* g */, 0150 /* h */, 0151 /* i */, 0304 /*N36*/, 0305 /*N37*/, 0306 /*N38*/, 0307 /*N39*/, 0310 /*N40*/, 0311 /*N41*/, 0312 /*N42*/, 0152 /* j */, 0153 /* k */, 0154 /* l */, 0155 /* m */, 0156 /* n */, 0157 /* o */, 0160 /* p */, 0161 /* q */, 0162 /* r */, 0313 /*N43*/, 0314 /*N44*/, 0315 /*N45*/, 0316 /*N46*/, 0317 /*N47*/, 0320 /*N48*/, 0321 /*N49*/, 0176 /* ~ */, 0163 /* s */, 0164 /* t */, 0165 /* u */, 0166 /* v */, 0167 /* w */, 0170 /* x */, 0171 /* y */, 0172 /* z */, 0322 /*N50*/, 0323 /*N51*/, 0324 /*N52*/, 0325 /*N53*/, 0326 /*N54*/, 0327 /*N55*/, 0330 /*N56*/, 0331 /*N57*/, 0332 /*N58*/, 0333 /*N59*/, 0334 /*N60*/, 0335 /*N61*/, 0336 /*N62*/, 0337 /*N63*/, 0340 /*G0 */, 0341 /*G1 */, 0342 /*G2 */, 0343 /*G3 */, 0344 /*G4 */, 0345 /*G5 */, 0346 /*G6 */, 0347 /*G7 */, 0173 /* { */, 0101 /* A */, 0102 /* B */, 0103 /* C */, 0104 /* D */, 0105 /* E */, 0106 /* F */, 0107 /* G */, 0110 /* H */, 0111 /* I */, 0350 /*G8 */, 0351 /*G9 */, 0352 /*G10*/, 0353 /*G11*/, 0354 /*G12*/, 0355 /*G13*/, 0175 /* } */, 0112 /* J */, 0113 /* K */, 0114 /* L */, 0115 /* M */, 0116 /* N */, 0117 /* O */, 0120 /* P */, 0121 /* Q */, 0122 /* R */, 0356 /*G14*/, 0357 /*G15*/, 0360 /*G16*/, 0361 /*G17*/, 0362 /*G18*/, 0363 /*G19*/, 0134 /* \ */, 0237 /*K31*/, 0123 /* S */, 0124 /* T */, 0125 /* U */, 0126 /* V */, 0127 /* W */, 0130 /* X */, 0131 /* Y */, 0132 /* Z */, 0364 /*G20*/, 0365 /*G21*/, 0366 /*G22*/, 0367 /*G23*/, 0370 /*G24*/, 0371 /*G25*/, 0060 /* 0 */, 0061 /* 1 */, 0062 /* 2 */, 0063 /* 3 */, 0064 /* 4 */, 0065 /* 5 */, 0066 /* 6 */, 0067 /* 7 */, 0070 /* 8 */, 0071 /* 9 */, 0372 /*G26*/, 0373 /*G27*/, 0374 /*G28*/, 0375 /*G29*/, 0376 /*G30*/, 0377 /*EO */, }; /* * Conversion table from ASCII to standard * EBCDIC (CACM). */ char atoetab[128] = { 0x00 /*NUL*/, 0x01 /*SOH*/, 0x02 /*STX*/, 0x03 /*ETX*/, 0x37 /*EOT*/, 0x2D /*ENQ*/, 0x2E /*ACK*/, 0x2F /*BEL*/, 0x16 /*BS */, 0x05 /*HT */, 0x25 /*LF */, 0x0B /*VT */, 0x0C /*FF */, 0x0D /*CR */, 0x0E /*SO */, 0x0F /*SI */, 0x10 /*DLE*/, 0x11 /*DC1*/, 0x12 /*DC2*/, 0x13 /*DC3*/, 0x3C /*DC4*/, 0x3D /*NAK*/, 0x32 /*SYN*/, 0x26 /*ETB*/, 0x18 /*CAN*/, 0x19 /*EM */, 0x3F /*SUB*/, 0x27 /*ESC*/, 0x1C /*FS */, 0x1D /*GS */, 0x1E /*RS */, 0x1F /*US */, 0x40 /* */, 0x4F /* ! */, 0x7F /* " */, 0x7B /* # */, 0x5B /* $ */, 0x6C /* % */, 0x50 /* & */, 0x7D /* ' */, 0x4D /* ( */, 0x5D /* ) */, 0x5C /* * */, 0x4E /* + */, 0x6B /* , */, 0x60 /* - */, 0x4B /* . */, 0x61 /* / */, 0xF0 /* 0 */, 0xF1 /* 1 */, 0xF2 /* 2 */, 0xF3 /* 3 */, 0xF4 /* 4 */, 0xF5 /* 5 */, 0xF6 /* 6 */, 0xF7 /* 7 */, 0xF8 /* 8 */, 0xF9 /* 9 */, 0x7A /* : */, 0x5E /* ; */, 0x4C /* < */, 0x7E /* = */, 0x6E /* > */, 0x6F /* ? */, 0x7C /* @ */, 0xC1 /* A */, 0xC2 /* B */, 0xC3 /* C */, 0xC4 /* D */, 0xC5 /* E */, 0xC6 /* F */, 0xC7 /* G */, 0xC8 /* H */, 0xC9 /* I */, 0xD1 /* J */, 0xD2 /* K */, 0xD3 /* L */, 0xD4 /* M */, 0xD5 /* N */, 0xD6 /* O */, 0xD7 /* P */, 0xD8 /* Q */, 0xD9 /* R */, 0xE2 /* S */, 0xE3 /* T */, 0xE4 /* U */, 0xE5 /* V */, 0xE6 /* W */, 0xE7 /* X */, 0xE8 /* Y */, 0xE9 /* Z */, 0x4A /* [ */, 0xE0 /* \ */, 0x5A /* ] */, 0x5F /* ^ */, 0x6D /* _ */, 0x79 /* ` */, 0x81 /* a */, 0x82 /* b */, 0x83 /* c */, 0x84 /* d */, 0x85 /* e */, 0x86 /* f */, 0x87 /* g */, 0x88 /* h */, 0x89 /* i */, 0x91 /* j */, 0x92 /* k */, 0x93 /* l */, 0x94 /* m */, 0x95 /* n */, 0x96 /* o */, 0x97 /* p */, 0x98 /* q */, 0x99 /* r */, 0xA2 /* s */, 0xA3 /* t */, 0xA4 /* u */, 0xA5 /* v */, 0xA6 /* w */, 0xA7 /* x */, 0xA8 /* y */, 0xA9 /* z */, 0xC0 /* { */, 0x6A /* | */, 0xD0 /* } */, 0xA1 /* ~ */, 0x07 /*DEL*/, }; /* * Conversion table from ASCII to ibm print * codes (a version of EBCDIC that may be more * useful). */ char atoietab[128] = { 0x00 /*NUL*/, 0x01 /*SOH*/, 0x02 /*STX*/, 0x03 /*ETX*/, 0x37 /*EOT*/, 0x2D /*ENQ*/, 0x2E /*ACK*/, 0x2F /*BEL*/, 0x16 /*BS */, 0x05 /*HT */, 0x25 /*LF */, 0x0B /*VT */, 0x0C /*FF */, 0x0D /*CR */, 0x0E /*SO */, 0x0F /*SI */, 0x10 /*DLE*/, 0x11 /*DC1*/, 0x12 /*DC2*/, 0x13 /*DC3*/, 0x3C /*DC4*/, 0x3D /*NAK*/, 0x32 /*SYN*/, 0x26 /*ETB*/, 0x18 /*CAN*/, 0x19 /*EM */, 0x3F /*SUB*/, 0x27 /*ESC*/, 0x1C /*FS */, 0x1D /*GS */, 0x1E /*RS */, 0x1F /*US */, 0x40 /* */, 0x5A /* !**/, 0x7F /* " */, 0x7B /* # */, 0x5B /* $ */, 0x6C /* % */, 0x50 /* & */, 0x7D /* ' */, 0x4D /* ( */, 0x5D /* ) */, 0x5C /* * */, 0x4E /* + */, 0x6B /* , */, 0x60 /* - */, 0x4B /* . */, 0x61 /* / */, 0xF0 /* 0 */, 0xF1 /* 1 */, 0xF2 /* 2 */, 0xF3 /* 3 */, 0xF4 /* 4 */, 0xF5 /* 5 */, 0xF6 /* 6 */, 0xF7 /* 7 */, 0xF8 /* 8 */, 0xF9 /* 9 */, 0x7A /* : */, 0x5E /* ; */, 0x4C /* < */, 0x7E /* = */, 0x6E /* > */, 0x6F /* ? */, 0x7C /* @ */, 0xC1 /* A */, 0xC2 /* B */, 0xC3 /* C */, 0xC4 /* D */, 0xC5 /* E */, 0xC6 /* F */, 0xC7 /* G */, 0xC8 /* H */, 0xC9 /* I */, 0xD1 /* J */, 0xD2 /* K */, 0xD3 /* L */, 0xD4 /* M */, 0xD5 /* N */, 0xD6 /* O */, 0xD7 /* P */, 0xD8 /* Q */, 0xD9 /* R */, 0xE2 /* S */, 0xE3 /* T */, 0xE4 /* U */, 0xE5 /* V */, 0xE6 /* W */, 0xE7 /* X */, 0xE8 /* Y */, 0xE9 /* Z */, 0xAD /* [**/, 0xE0 /* \ */, 0xBD /* ]**/, 0x4A /* ^**/, 0x6D /* _ */, 0x7D /* `**/, 0x81 /* a */, 0x82 /* b */, 0x83 /* c */, 0x84 /* d */, 0x85 /* e */, 0x86 /* f */, 0x87 /* g */, 0x88 /* h */, 0x89 /* i */, 0x91 /* j */, 0x92 /* k */, 0x93 /* l */, 0x94 /* m */, 0x95 /* n */, 0x96 /* o */, 0x97 /* p */, 0x98 /* q */, 0x99 /* r */, 0xA2 /* s */, 0xA3 /* t */, 0xA4 /* u */, 0xA5 /* v */, 0xA6 /* w */, 0xA7 /* x */, 0xA8 /* y */, 0xA9 /* z */, 0x8B /* {**/, 0x4F /* |**/, 0x9B /* }**/, 0x5F /* ~**/, 0x07 /*DEL*/, }; /* * Variables from options. */ char *ifname; char *ofname; FILE *ifp = stdin; FILE *ofp = stdout; int ibs; int obs; int cbs; char *ibp; /* Input buffer ptr. */ char *obp; /* Output buffer ptr. */ char *cbp; /* Intermediate conversion buffer (ebcdic) */ long skip; unsigned long files; size_t seek; unsigned long count = MAXULONG; /* Limit on records */ int conv; /* Flags above */ long nfri; /* Full records in */ long npri; /* Partial records in */ long nfro; /* Full records out */ long npro; /* Partial records out */ char nospace[] = "Out of memory for buffers"; int stats(); long number(); FILE *openfile(); extern int errno; main(argc, argv) char *argv[]; { register char *op; register char *ov; register int i; register int difbuf = 0; extern char *index(); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, stats); for (i=1; i<argc; i++) { if ((ov = index(op=argv[i], '=')) == NULL) dderr("Missing `=' in option `%s'", op); *ov++ = '\0'; if (*ov == '\0') dderr("Missing value in option `%s'", op); if (streq(op, "if")) ifp = openfile(ov, &ifname, 0); else if (streq(op, "of")) ofp = openfile(ov, &ofname, 1); else if (streq(op, "ibs")) { ibs = number(ov); difbuf++; } else if (streq(op, "obs")) { obs = number(ov); difbuf++; } else if (streq(op, "bs")) obs = ibs = number(ov); else if (streq(op, "cbs")) { cbs = number(ov); difbuf++; } else if (streq(op, "skip")) skip = number(ov); else if (streq(op, "files")) files = number(ov); else if (streq(op, "seek")) seek = number(ov); else if (streq(op, "count")) count = number(ov); else if (streq(op, "conv")) conversions(ov); else dderr("`%s' is a bad option", op); } if (ifname == NULL) ifname = "(stdin)"; if (ofname == NULL) ofname = "(stdout)"; if (conv & (DD_EBC|DD_IBM|DD_ASC)) { difbuf++; if ((conv&(DD_ASC|DD_EBC))==(DD_ASC|DD_EBC) || (conv&(DD_ASC|DD_IBM))==(DD_ASC|DD_IBM) || (conv&(DD_UCA|DD_LCA))==(DD_UCA|DD_LCA)) dderr("Conflicting case or character set conversions"); } if (ibs == 0) ibs = BSIZE; if (obs == 0) obs = BSIZE; if ((ibp = malloc(ibs)) == NULL) dderr(nospace); if (difbuf) { if ((obp = malloc(obs)) == NULL) dderr(nospace); } else obp = ibp; if (conv & (DD_EBC|DD_IBM|DD_ASC)) { if (cbs == 0) cbs = ibs; if ((cbp = malloc(cbs+1)) == NULL) dderr(nospace); } seek *= obs; stats(dd()); } /* * Do the actual data copying and * conversion operations. * Count down all the files. */ dd() { register int nf; register int rstat = 0; register int ddstat; register int n; if (seek != 0) lseek(fileno(ofp), seek, 0); while (skip != 0) { skip--; if ((n = read(fileno(ifp), ibp, ibs))==0 || n==-1) break; } if ((nf = files) == 0) nf = 1; do { ddstat = cbp==NULL ? dd1() : dd2(); rstat |= ddstat; if (ddstat) return (rstat); } while (--nf); return (rstat); } /* * Easy version of dd. * No ebcdic, ascii, or ibm conversions. */ dd1() { register int n; while (count-- != 0) { if ((n = ddread(fileno(ifp), ibp, ibs)) == 0) break; if (n == -1) { if (conv && DD_NERR) continue; else return (1); } ddconv(ibp, n); if (ddput(ibp, n)) return (1); } return (ddput(NULL, 0)); } /* * More complicated version of dd that uses * the conversion intermediate buffering * for ebcdic/ibm or ascii conversions. */ dd2() { static char *ecbp; register char *bp; register char *wcbp; register int nb; register int n; register int s = 0; ecbp = cbp+cbs; wcbp = cbp; while (count-- != 0) { if ((nb = ddread(fileno(ifp), ibp, ibs)) == 0) break; if (nb == -1) { if ((conv & DD_NERR) == 0) return (1); else { s = 1; continue; } } bp = ibp; if (conv & (DD_IBM|DD_EBC)) { do { if ((n = *wcbp++ = *bp++)=='\n' || wcbp>=ecbp) { if (n == '\n') wcbp--; n = ddconv(cbp, wcbp-cbp); if (ddput(cbp, n)) if ((conv & DD_NERR) == 0) return (1); else s = 1; wcbp = cbp; } } while(--nb); } else { do { *wcbp++ = *bp++; if (wcbp >= ecbp) { n = ddconv(cbp, cbs); if (ddput(cbp, n)) if ((conv & DD_NERR) == 0) return (1); else s = 1; wcbp = cbp; } } while (--nb); } } if ((n = wcbp-cbp) != 0) { n = ddconv(cbp, n); if (ddput(cbp, n)) if ((conv & DD_NERR) == 0) return (1); else s = 1; } s |= ddput(NULL, 0); return (s); } /* * Do output conversions (e.g. swab) * and write the record. Account * for partial records. * Return non-zero if non-repeatable error. */ ddwrite(bp, nb) register char *bp; register unsigned nb; { register unsigned wnb; if (nb == 0) return (0); if (conv & DD_SWAB) swab(bp, bp, nb); if ((wnb = write(fileno(ofp), bp, nb)) == nb) { if (nb == obs) nfro++; else npro++; } else perror("dd"); if (wnb!=nb && (conv&DD_NERR)==0) return (1); return (0); } /* * Put `n' bytes into the output buffer. * This is maintained internally, and * flushed when full. Also, if called * with 0 bytes (at end) flush as well. */ ddput(bp, nb) register char *bp; register unsigned nb; { static char *eobp; static char *cobp; register char *wobp; register int s = 0; if (eobp == NULL) { /* * Initialisation. */ if (ibp == obp) return (ddwrite(bp, nb)); eobp = obp + obs; cobp = obp; } wobp = cobp; if (nb == 0) { /* * Flush at end. */ if ((nb = wobp-obp) == 0) return (0); if (ddwrite(obp, nb) != nb) if ((conv & DD_NERR) == 0) return (1); return (0); } do { *wobp++ = *bp++; if (wobp >= eobp) { if (ddwrite(obp, obs)) if ((conv & DD_NERR) == 0) return (1); else s = 1; wobp = obp; } } while (--nb); cobp = wobp; return (s); } /* * Read in data. increment proper counts, * do conv=sync and noerrors checking. */ ddread(fd, bp, nb) int fd; register char *bp; register int nb; { register int n; if ((n = read(fd, bp, nb)) == -1) perror("dd"); else if (n != 0) { if (n == nb) nfri++; else npri++; if (conv&DD_SYNC && n<nb) { bp += n; n = nb-n; while (n--) *bp++ = 0; n = nb; } } return (n); } /* * Do other conversions. * Return new `nb' (useful only for ascii/ebcdic * conversions). */ ddconv(bp, nb) char *bp; unsigned nb; { register char *cp; register unsigned n; register int c; if (conv & DD_ASC) { etoa(bp, bp, n=nb); for (cp=bp+n; cp>bp; ) if (*--cp != ' ') { cp++; break; } *cp++ = '\n'; nb = cp-bp; } if (conv & DD_UCA) { for (cp=bp, n=nb; n-- != 0; cp++) if (isascii(c=*cp) && islower(c)) *cp = toupper(c); } if (conv & DD_LCA) { for (cp=bp, n=nb; n-- != 0; cp++) if (isascii(c=*cp) && isupper(c)) *cp = tolower(c); } if (conv & (DD_EBC|DD_IBM)) { if (nb < cbs) { n = cbs-nb; cp = bp+nb; while (n--) *cp++ = ' '; } nb = n = cbs; if (conv & DD_IBM) atoie(bp, bp, n); else atoe(bp, bp, n); } return (nb); } /* * Open a file on the input line. * `f' is 0 for read, 1 for write. */ FILE * openfile(fn, fnp, f) register char *fn; register char **fnp; int f; { register FILE *fp; register int errsave; if (*fnp != NULL) dderr("more than one `%s' specified", f ? "of=" : "if="); *fnp = fn; if ((fp = fopen(fn, f?"w":"r")) == NULL) { errsave = errno; fprintf(stderr, "dd: "); errno = errsave; perror(fn); exit(1); } return (fp); } /* * Read a number, scaled by the * multipliers `k', `b', or `w'. */ long number(num) char *num; { register char *s = num; long rn, n; register int base; rn = 1; again: n = 0; base = 10; if (*s == '0') { base = 8; s++; } while (isdigit(*s)) n = n*base + *s++ - '0'; for (; *s!='\0'; s++) if (*s=='b') n *= BSIZE; else if (*s == 'w') n *= sizeof(int); else if (*s == 'k') n *= 1024; else if (*s == 'x') { s++; rn *= n; goto again; } else dderr("bad number `%s'", num); if (rn != 1) return (n*rn); return (n); } /* * Read in the conversions from * the string given. */ conversions(s) register char *s; { register char *np = s; for (;;) { for (;; np++) { if (*np == ',') *np++ = '\0'; else if (*np == '\0') np = NULL; else continue; break; } if (streq(s, "ascii")) conv |= DD_ASC; else if (streq(s, "ebcdic")) conv |= DD_EBC; else if (streq(s, "ibm")) conv |= DD_IBM; else if (streq(s, "lcase")) conv |= DD_LCA; else if (streq(s, "ucase")) conv |= DD_UCA; else if (streq(s, "swab")) conv |= DD_SWAB; else if (streq(s, "noerror")) conv |= DD_NERR; else if (streq(s, "sync")) conv |= DD_SYNC; else dderr("`%s' is an illegal conversion", s); if (np == NULL) break; s = np; } } /* * Convert ascii to ebcdic. * This is the CACM standard one. */ atoe(ip, op, n) register unsigned char *ip; register unsigned char *op; register unsigned n; { if (n) do { if (isascii(*ip)) *op++ = atoetab[*ip++]; else { *op++ = 0; ip++; } } while (--n); } /* * Convert ascii to `ibm' ebcdic. * This is the more reasonable one * for printers. */ atoie(ip, op, n) register unsigned char *ip; register unsigned char *op; register unsigned n; { if (n) do { if (isascii(*ip)) *op++ = atoietab[*ip++]; else { *op++ = 0; ip++; } } while (--n); } /* * Convert EBCDIC to ASCII. * As it turns out, the mappings * are both the same. */ etoa(ip, op, n) register unsigned char *ip; register unsigned char *op; register unsigned n; { if (n) do { *op++ = etoatab[*ip++]; } while (--n); } /* * Print statistics and exit. */ stats(s) { fprintf(stderr, "%D+%D records in\n", nfri, npri); fprintf(stderr, "%D+%D records out\n", nfro, npro); exit(s); } usage() { fprintf(stderr, "Usage: dd [option=value] ...\n"); exit(1); } /* VARARGS */ dderr(x) { fprintf(stderr, "dd: %r\n", &x); exit(1); }