BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 1 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 1 /******************************************************************** 2 * lindner 3 * 3.12 4 * 1995/02/17 18:29:36 5 * /home/arcwelder/GopherSrc/CVS/gopher+/object/BLblock.c,v 6 * Exp 7 * 8 * Paul Lindner, University of Minnesota CIS. 9 * 10 * Copyright 1991, 1992, 1993 by the Regents of the University of Minnesota 11 * see the file "Copyright" in the distribution for conditions of use. 12 ********************************************************************* 13 * MODULE: BLblock.c 14 * Implementation of Block handling routines. 15 ********************************************************************* 16 * Revision History: 17 * BLblock.c,v 18 * Revision 3.12 1995/02/17 18:29:36 lindner 19 * Abstract display support 20 * 21 * Revision 3.11 1994/08/08 20:26:35 lindner 22 * fix bug for Abstract= lines. 23 * 24 * Revision 3.10 1994/06/29 05:45:24 lindner 25 * Mods for tickets 26 * 27 * Revision 3.9 1994/02/20 21:49:09 lindner 28 * deal with malformed views lines better 29 * 30 * Revision 3.8 1993/11/02 06:13:36 lindner 31 * Fix for HTML mods 32 * 33 * Revision 3.7 1993/07/29 19:59:23 lindner 34 * Removed extraneous variables 35 * 36 * Revision 3.6 1993/07/27 05:30:17 lindner 37 * Mondo Debug overhaul from Mitra 38 * 39 * Revision 3.5 1993/06/15 06:10:34 lindner 40 * Moved string.h include 41 * 42 * Revision 3.4 1993/04/27 20:54:32 lindner 43 * really fixed BLtoNet() 44 * 45 * Revision 3.3 1993/04/23 20:14:48 lindner 46 * Fix for BltoNet(), using wrong datatype 47 * 48 * Revision 3.2 1993/03/26 19:49:34 lindner 49 * More comments, memory leak fix, etc 50 * 51 * Revision 3.1.1.1 1993/02/11 18:03:06 lindner 52 * Gopher+1.2beta release 53 * 54 * Revision 2.1 1993/02/09 22:45:54 lindner 55 * Fixes for retrieving from the net. New BLAsearch BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 2 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 56 * 57 * Revision 1.1 1993/01/31 00:22:51 lindner 58 * Initial revision 59 * 60 * 61 *********************************************************************/ 62 63 #include "String.h" 945 #include "BLblock.h" 3055 #include "Malloc.h" 3713 #include 3962 3963 /* 3964 * Make a new Block Object 3965 */ 3966 3967 Blockobj * 3968 BLnew() 3969 { 3970 1 Blockobj *temp; 3971 1 3972 1 temp = (Blockobj *) malloc(sizeof(Blockobj)); 3973 1 3974 1 temp->btype = BLOCK_UNKNOWN; 3975 1 temp->Blockname = STRnew(); 3976 1 temp->datatype = BDATA_NONE; 3977 1 3978 1 return(temp); 3979 1 } 3980 3981 3982 /* 3983 * Initialize the block structure 3984 */ 3985 3986 void 3987 BLinit(bl) 3988 Blockobj *bl; 3989 { 3990 1 STRinit(bl->Blockname); 3991 1 switch (BLgetDatatype(bl)) { 3992 2 case BDATA_FILE: 3993 2 STRinit(bl->data.filename); 3994 2 break; 3995 2 case BDATA_GREF: 3996 2 GSinit(bl->data.gs); 3997 2 break; 3998 2 case BDATA_TEXT: 3999 2 STAinit(bl->data.text); 4000 2 break; 4001 2 } 4002 1 } 4003 4004 /* 4005 * Calls the right destory fcn depending on the object in the union. 4006 * 4007 * wouldn't c++ be nice right here? :-) BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 3 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4008 */ 4009 4010 static void 4011 BLdatadestroy(bl) 4012 Blockobj *bl; 4013 { 4014 1 switch (BLgetDatatype(bl)) { 4015 2 case BDATA_FILE: 4016 2 STRdestroy(bl->data.filename); 4017 2 break; 4018 2 case BDATA_TEXT: 4019 2 STAdestroy(bl->data.text); 4020 2 break; 4021 2 case BDATA_GREF: 4022 2 GSdestroy(bl->data.gs); 4023 2 break; 4024 2 } 4025 1 } 4026 4027 /* 4028 * Free memory of BlockObj 4029 */ 4030 4031 void 4032 BLdestroy(bl) 4033 Blockobj *bl; 4034 { 4035 1 STRdestroy(bl->Blockname); 4036 1 BLdatadestroy(bl); 4037 1 free(bl); 4038 1 } 4039 4040 4041 void 4042 BLcpy(dest, orig) 4043 Blockobj *dest,*orig; 4044 { 4045 1 BLsetName(dest,BLgetName(orig)); 4046 1 dest->btype = orig->btype; 4047 1 4048 1 switch (BLgetDatatype(orig)) { 4049 2 case BDATA_FILE: 4050 2 BLsetFile(dest, STRget(orig->data.filename)); 4051 2 break; 4052 2 case BDATA_GREF: 4053 2 BLsetGref(dest, orig->data.gs); 4054 2 break; 4055 2 case BDATA_TEXT: 4056 2 BLsetText(dest, orig->data.text); 4057 2 break; 4058 2 } 4059 1 } 4060 4061 4062 /* 4063 * BLgetNumLines() returns the number of lines for the Text record 4064 * It returns -1 if this isn't the type of record. BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 4 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4065 */ 4066 4067 int 4068 BLgetNumLines(bl) 4069 Blockobj *bl; 4070 { 4071 1 switch (BLgetDatatype(bl)) { 4072 2 case BDATA_TEXT: 4073 2 return(STAgetTop(bl->data.text)); 4074 2 default: 4075 2 return(-1); 4076 2 } 4077 1 ; 4078 1 } 4079 4080 4081 /* 4082 * BLgetLine() returns a character pointer to the line for the Text data type 4083 */ 4084 4085 char* 4086 BLgetLine(bl, lineno) 4087 Blockobj *bl; 4088 int lineno; 4089 { 4090 1 switch (BLgetDatatype(bl)) { 4091 2 case BDATA_TEXT: 4092 2 return(STRget(STAgetEntry(bl->data.text, lineno))); 4093 2 } 4094 1 return(NULL); 4095 1 } 4096 4097 4098 /* 4099 * BLsetFile() sets up a block to contain a file reference. 4100 * Really handy for the server. 4101 */ 4102 4103 void 4104 BLsetFile(bl, filename) 4105 Blockobj *bl; 4106 char *filename; 4107 { 4108 1 /** Reset data field and put in new values **/ 4109 1 4110 1 BLdatadestroy(bl); 4111 1 4112 1 bl->datatype = BDATA_FILE; 4113 1 bl->data.filename = STRnew(); 4114 1 4115 1 STRset(bl->data.filename, filename); 4116 1 } 4117 4118 4119 /* 4120 * BLsetText sets everything up for storing text, if the optional parameter 4121 * sta is set, it copies it in. BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 5 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4122 */ 4123 4124 void 4125 BLsetText(bl, sta) 4126 Blockobj *bl; 4127 StrArray *sta; 4128 { 4129 1 /** Reset data field and put in new values **/ 4130 1 if (BLgetDatatype(bl) != BDATA_TEXT) { 4131 2 BLdatadestroy(bl); 4132 2 4133 2 bl->datatype = BDATA_TEXT; 4134 2 bl->data.text = STAnew(10); 4135 2 } 4136 1 if (sta != NULL) { 4137 2 STAcpy(bl->data.text, sta); 4138 2 } 4139 1 } 4140 4141 4142 /* 4143 * Keep data in memory, text is a line to be added to the text 4144 */ 4145 4146 void 4147 BLaddText(bl, text) 4148 Blockobj *bl; 4149 char *text; 4150 { 4151 1 String *tempstr; 4152 1 4153 1 BLsetText(bl, NULL); 4154 1 4155 1 tempstr = STRnew(); 4156 1 4157 1 STRset(tempstr, text); 4158 1 STApush(bl->data.text, tempstr); 4159 1 4160 1 STRdestroy(tempstr); 4161 1 } 4162 4163 /* 4164 * Make the block a gopher-reference 4165 */ 4166 4167 void 4168 BLsetGref(bl, gs) 4169 Blockobj *bl; 4170 GopherObj *gs; 4171 { 4172 1 /** Reset data field and put in new values **/ 4173 1 BLdatadestroy(bl); 4174 1 4175 1 bl->datatype = BDATA_GREF; 4176 1 4177 1 bl->data.gs = GSnew(); 4178 1 BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 6 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4179 1 GScpy(bl->data.gs, gs); 4180 1 4181 1 GSdestroy(gs); 4182 1 } 4183 4184 4185 /* 4186 * BLtoNet() transmits the block as per gopher+ protocol 4187 * if the data field is a file, it opens it and sends it out 4188 */ 4189 4190 void 4191 BLtoNet(bl, fd, showheader) 4192 Blockobj *bl; 4193 int fd; 4194 boolean showheader; 4195 { 4196 1 FILE *infile; 4197 1 int i; 4198 1 char outputline[512]; 4199 1 4200 1 /** Switch on data type **/ 4201 1 4202 1 if (showheader) { 4203 2 sprintf(outputline, "+%s:", BLgetName(bl)); 4204 2 writestring(fd, outputline); 4205 2 } 4206 1 4207 1 switch (BLgetDatatype(bl)) { 4208 2 4209 2 case BDATA_GREF: 4210 2 writestring(fd, " "); 4211 2 GStoNet(bl->data.gs,fd, GSFORM_G0, NULL); 4212 2 break; 4213 2 4214 2 case BDATA_TEXT: 4215 2 writestring(fd, "\r\n"); 4216 2 for (i=0; idata.text); i++) { 4217 3 writestring(fd, " "); 4218 3 writestring(fd, STRget(STAgetEntry(bl->data.text, i))); 4219 3 writestring(fd, "\r\n"); 4220 3 } 4221 2 break; 4222 2 4223 2 case BDATA_FILE: 4224 2 writestring(fd, "\r\n"); 4225 2 4226 2 if ((infile = fopen(STRget(bl->data.filename), "r"))==NULL) 4227 2 break; 4228 2 4229 2 while (fgets(outputline, sizeof(outputline), infile)!=NULL) { 4230 3 ZapCRLF(outputline); 4231 3 writestring(fd, " "); 4232 3 writestring(fd, outputline); 4233 3 writestring(fd, "\r\n"); 4234 3 } 4235 2 fclose(infile); BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 7 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4236 2 break; 4237 2 } 4238 1 } 4239 4240 4241 /* 4242 * BLfromNet() assumes that the initial '+' in the data stream has been read, 4243 * along with the blockname, up to the ':', but not anything after.. 4244 * 4245 * It then executes most of the state diagram, it returns when it has 4246 * encountered EOF, or encounters the next '+', or '.' 4247 * 4248 * Returns the following: 4249 * 0 for EOF encountered, block retrieved successfully 4250 * 1 for successful retrieve, and another block coming 4251 * neg value for error conditions from read routines and botched block vals 4252 */ 4253 4254 int 4255 BLfromNet(bl, fd, blockname) 4256 Blockobj *bl; 4257 int fd; 4258 char *blockname; 4259 { 4260 1 char inputline[512]; 4261 1 int err; 4262 1 4263 1 4264 1 /*** State: _GotBlockName_ ***/ 4265 1 4266 1 BLsetName(bl, blockname); 4267 1 4268 1 /** Find out if there's a gopher reference **/ 4269 1 err = readrecvbuf(fd, inputline, 1); 4270 1 4271 1 if (*inputline == ' ') { 4272 2 /** GREF coming up, State: _GotBnameSpace_ **/ 4273 2 GopherObj *gs; 4274 2 4275 2 gs = GSnew(); 4276 2 GSfromNet(gs, fd); 4277 2 BLsetGref(bl, gs); 4278 2 /** read up to the next \r\n+ **/ 4279 2 while (1) { 4280 3 if ((err= readrecvbuf(fd, inputline, 1)) <= 0) 4281 3 return(err); 4282 3 if (*inputline == '+') 4283 3 return(1); 4284 3 else { 4285 4 err = readline(fd, inputline, sizeof(inputline)); 4286 4 if (err <= 0) 4287 4 return(err); /*** Error ***/ 4288 4 } 4289 3 } 4290 2 } 4291 1 4292 1 /** Okay, let's just stick the text in verbatim **/ BLBLOCK 22-SEP-1995 18:31:24 VAX C V3.2-044 Page 8 V1.0 17-FEB-1995 12:29:36 [GOPHER.G2.VMS2_13.OBJECT]BLBLOCK.C;1 (1) 4293 1 4294 1 /** get rid of remaining newline **/ 4295 1 readline(fd, inputline, sizeof(inputline)); 4296 1 4297 1 /** State: _FirstChar_ **/ 4298 1 4299 1 while (1) { 4300 2 /** Check for plus **/ 4301 2 if ((err= readrecvbuf(fd, inputline, 1)) <=0) 4302 2 return(err); 4303 2 4304 2 if (*inputline == '+') 4305 2 return(1); 4306 2 /*** Return to state _NewBlock_ ***/ 4307 2 4308 2 if (*inputline == '.') { 4309 3 readline(fd, inputline, sizeof(inputline)); 4310 3 return(0); 4311 3 } 4312 2 4313 2 if (*inputline == ' ') { 4314 3 /** add a line otherwise State: _Addline_ **/ 4315 3 readline(fd, inputline, sizeof(inputline)); 4316 3 ZapCRLF(inputline); 4317 3 BLaddText(bl, inputline); 4318 3 } else { 4319 3 /** malformed block line received 4320 3 proceed as if it was OK, but don't add the line **/ 4321 3 readline(fd, inputline, sizeof(inputline)); 4322 3 } 4323 2 } 4324 1 } 4325 4326 4327 int 4328 BLAsearch(bla, bname) 4329 BlockArray *bla; 4330 char *bname; 4331 { 4332 1 int i; 4333 1 4334 1 if (bla == NULL) 4335 1 return(-1); 4336 1 4337 1 for (i=0; i