Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / ctm / ctm / ctm_input.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD: src/usr.sbin/ctm/ctm/ctm_input.c,v 1.8 1999/08/28 01:15:59 peter Exp $
10  *
11  */
12
13 #include "ctm.h"
14
15 /*---------------------------------------------------------------------------*/
16 void
17 Fatal_(int ln, char *fn, char *kind)
18 {
19     if(Verbose > 2)
20         fprintf(stderr,"Fatal error. (%s:%d)\n",fn,ln);
21     fprintf(stderr,"%s Fatal error: %s\n",FileName, kind);
22 }
23 #define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
24 #define Assert() Fatal_(__LINE__,__FILE__,"Assert failed.")
25
26 /*---------------------------------------------------------------------------*/
27 /* get next field, check that the terminating whitespace is what we expect */
28 u_char *
29 Ffield(FILE *fd, MD5_CTX *ctx,u_char term)
30 {
31     static u_char buf[BUFSIZ];
32     int i,l;
33
34     for(l=0;;) {
35         if((i=getc(fd)) == EOF) {
36             Fatal("Truncated patch.");
37             return 0;
38         }
39         buf[l++] = i;
40         if(isspace(i))
41             break;
42         if(l >= sizeof buf) {
43             Fatal("Corrupt patch.");
44             printf("Token is too long.\n");
45             return 0;
46         }
47     }
48     buf[l] = '\0';
49     MD5Update(ctx,buf,l);
50     if(buf[l-1] != term) {
51         Fatal("Corrupt patch.");
52         fprintf(stderr,"Expected \"%s\" but didn't find it {%02x}.\n",
53             term == '\n' ? "\\n" : " ",buf[l-1]);
54         if(Verbose > 4)
55             fprintf(stderr,"{%s}\n",buf);
56         return 0;
57     }
58     buf[--l] = '\0';
59     if(Verbose > 4)
60         fprintf(stderr,"<%s>\n",buf);
61     return buf;
62 }
63
64 int
65 Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term)
66 {
67     u_char *p,*q;
68     int u_chars=0;
69
70     p = Ffield(fd,ctx,term);
71     if(!p) return -1;
72     for(q=p;*q;q++) {
73         if(!isdigit(*q)) {
74             Fatal("Bytecount contains non-digit.");
75             return -1;
76         }
77         u_chars *= 10;
78         u_chars += (*q - '0');
79     }
80     if(u_chars > MAXSIZE) {
81         Fatal("Bytecount too large.");
82         return -1;
83     }
84     return u_chars;
85 }
86
87 u_char *
88 Fdata(FILE *fd, int u_chars, MD5_CTX *ctx)
89 {
90     u_char *p = Malloc(u_chars+1);
91
92     if(u_chars+1 != fread(p,1,u_chars+1,fd)) {
93         Fatal("Truncated patch.");
94         return 0;
95     }
96     MD5Update(ctx,p,u_chars+1);
97     if(p[u_chars] != '\n') {
98         if(Verbose > 3)
99             printf("FileData wasn't followed by a newline.\n");
100         Fatal("Corrupt patch.");
101         return 0;
102     }
103     p[u_chars] = '\0';
104     return p;
105 }
106
107 /*---------------------------------------------------------------------------*/
108 /* get the filename in the next field, prepend BaseDir and give back the result
109    strings. The sustitute filename is return (the one with the suffix SUBSUFF) 
110    if it exists and the qualifier contains CTM_Q_Name_Subst
111    NOTA: Buffer is already initialize with BaseDir, CatPtr is the insertion
112    point on this buffer + the length test in Ffield() is enough for Fname() */
113
114 u_char *
115 Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose)
116 {
117     u_char * p;
118     struct stat st;
119
120     if ((p = Ffield(fd,ctx,term)) == NULL) return(NULL);
121
122     strcpy(CatPtr, p);
123
124     if (!(qual & CTM_Q_Name_Subst)) return(Buffer);
125
126     p = Buffer + strlen(Buffer);
127
128     strcat(Buffer, SUBSUFF);
129
130     if ( -1 == stat(Buffer, &st) ) {
131         *p = '\0';
132     } else {
133         if(verbose > 2)
134             fprintf(stderr,"Using %s as substitute file\n", Buffer);
135     }
136
137     return (Buffer);
138 }