|
|
1.1 root 1: /* uucode.c */
2:
3: /* Unix-to-unix encoding/decoding routines */
4:
5: /* $Id: uucode.c,v 1.4 2004/04/08 05:21:32 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include <stdio.h>
39: #include <stdlib.h>
40: #include <string.h>
41: #include <ctype.h>
42: #include "uucode.h"
43:
44: int uudecode(char *target, size_t tlen, const char *source, size_t slen)
45: {
46: int i;
47: char ch;
48: size_t rd=0;
49: size_t wr=0;
50: size_t block;
51: size_t len;
52: unsigned char cell[4];
53:
54: if(slen==0)
55: slen=strlen(source);
56: while(rd<slen && wr<tlen) {
57: ch=source[rd++];
58: if(ch<' ')
59: continue;
60: len=(ch-' ')&0x3f;
61: if(len<=0 || rd>=slen)
62: break;
63: block=0;
64: while(block<len && wr<tlen && rd<slen) {
65: memset(cell,0,sizeof(cell));
66: /* Remove space bias */
67: for(i=0;i<sizeof(cell) && rd<slen;i++) {
68: cell[i]=source[rd++];
69: if(cell[i]>=' ') cell[i]-=' ';
70: }
71: /* Convert block of 4 6-bit chars into 3 8-bit chars */
72: target[wr]=(cell[0]&0x3f)<<2; /* lower 6 (s1) to upper 6 (d1) */
73: target[wr++]|=(cell[1]&0x30)>>4; /* upper 2 (s2) to lower 2 (d1) */
74: target[wr]=(cell[1]&0x0f)<<4; /* lower 4 (s2) to upper 4 (d2) */
75: target[wr++]|=(cell[2]&0x3c)>>2; /* upper 4 (s3) to lower 4 (d2) */
76: target[wr]=(cell[2]&0x03)<<6; /* lower 2 (s3) to upper 2 (d3) */
77: target[wr++]|=cell[3]&0x3f; /* lower 6 (s4) to lower 6 (d3) */
78: block+=3;
79: }
80: #if 0
81: if(block!=len) {
82: fprintf(stderr,"block (%d) != len (%d)\n",block,len);
83: return(-1);
84: }
85: #endif
86: while(rd<slen && source[rd]>' ')
87: rd++; /* find whitespace (line termination) */
88: while(rd<slen && source[rd]!=0 && source[rd]<=' ')
89: rd++; /* skip whitespace separating blocks/lines */
90: }
91:
92: return(wr);
93: }
94:
95: #define BIAS(b) if((b)==0) (b)='`'; else (b)+=' ';
96:
97: int uuencode(char *target, size_t tlen, const char *source, size_t slen)
98: {
99: size_t rd=0;
100: size_t wr=0;
101: size_t block;
102: size_t len;
103:
104: if(slen==0)
105: slen=strlen(source);
106:
107: if(tlen<3)
108: return(-1);
109: tlen-=3; /* reserve room for terminator */
110: while(rd<=slen && wr<tlen) {
111: len=45;
112: if(rd+len>slen)
113: len=slen-rd;
114: BIAS(len);
115: target[wr++]=len;
116:
117: block=0;
118: while(block<len && wr<tlen && rd<slen) {
119: target[wr]=source[rd]>>2; /* upper 6 (s1) to lower 6 (d1) */
120: BIAS(target[wr]); wr++;
121: target[wr]=(source[rd++]&0x03)<<4; /* lower 2 (s1) to upper 2 (d2) */
122: target[wr]|=source[rd]>>4; /* upper 4 (s2) to lower 4 (d2) */
123: BIAS(target[wr]); wr++;
124: target[wr]=(source[rd++]&0x0f)<<2; /* lower 4 (s2) to upper 4 (d3) */
125: target[wr]|=source[rd]>>6; /* upper 2 (s3) to lower 2 (d3) */
126: BIAS(target[wr]); wr++;
127: target[wr]=source[rd++]&0x3f; /* lower 6 (s3) to lower 6 (d4) */
128: BIAS(target[wr]); wr++;
129: block+=3;
130: }
131: if(wr<tlen) {
132: target[wr++]='\r';
133: target[wr++]='\n';
134: }
135: if(rd>=slen)
136: break;
137: }
138:
139: if(wr<tlen)
140: target[wr++]=0;
141: return(wr);
142: }
143:
144: #ifdef UUDECODE_TEST
145:
146: static char* truncstr(char* str, const char* set)
147: {
148: char* p;
149:
150: p=strpbrk(str,set);
151: if(p!=NULL)
152: *p=0;
153:
154: return(p);
155: }
156:
157: int main(int argc, char**argv)
158: {
159: char str[1024];
160: char buf[256];
161: char* p;
162: FILE* in;
163: FILE* out=NULL;
164: int len;
165: int line;
166:
167: if(argc<2) {
168: fprintf(stderr,"usage: uudecode infile\n");
169: return 1;
170: }
171:
172: if((in=fopen(argv[1],"rb"))==NULL) {
173: perror(argv[1]);
174: return 1;
175: }
176:
177: while(!feof(in)) {
178: memset(str,0,sizeof(str));
179: if(fgets(str,sizeof(str),in)==NULL)
180: break;
181: truncstr(str,"\r\n");
182: if(strncmp(str,"begin ",6)==0) {
183: p=str+7;
184: while(*p && isdigit(*p)) p++; /* skip mode */
185: while(*p && *p<=' ') p++;
186: if((out=fopen(p,"wb"))==NULL) {
187: perror(p);
188: return 1;
189: }
190: fprintf(stderr,"Creating %s\n",p);
191: line=1;
192: continue;
193: }
194: if(strcmp(str,"end")==0) {
195: if(out!=NULL) {
196: fclose(out);
197: out=NULL;
198: }
199: continue;
200: }
201: if(out==NULL)
202: continue;
203: len=uudecode(buf,sizeof(buf),str,0);
204: if(len<0) {
205: fprintf(stderr,"!Error decoding: %s\n",str);
206: break;
207: }
208: fwrite(buf,len,1,out);
209: line++;
210: }
211:
212: return 0;
213: }
214: #elif defined(UUENCODE_TEST)
215:
216: int main(int argc, char**argv)
217: {
218: char str[1024];
219: char buf[256];
220: FILE* in;
221: int len;
222:
223: if(argc<2) {
224: fprintf(stderr,"usage: uuencode infile\n");
225: return 1;
226: }
227:
228: if((in=fopen(argv[1],"rb"))==NULL) {
229: perror(argv[1]);
230: return 1;
231: }
232:
233: while(!feof(in)) {
234: len=fread(buf,1,45,in);
235: if(len<0)
236: break;
237: len=uuencode(str,sizeof(str),buf,len);
238: if(len<1)
239: break;
240: printf("%.*s",len,str);
241: }
242:
243: return 0;
244: }
245:
246: #endif
247:
248:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.