00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "molfile_plugin.h"
00019
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <string.h>
00023
00024 #if defined(_AIX)
00025 #include <strings.h>
00026 #endif
00027
00028 #define LINESIZE 256
00029 #define MAXBONDS 16
00030
00031 typedef struct {
00032 FILE *file;
00033 molfile_atom_t *atomlist;
00034 molfile_metadata_t *meta;
00035 int natoms, nbonds, optflags, coords_read;
00036 int *from, *to;
00037 float *bondorder;
00038 } xbgfdata;
00039
00040
00041
00042
00043 static void *open_xbgf_read(const char *path, const char *filetype,
00044 int *natoms) {
00045 FILE *fd;
00046 xbgfdata *bgf;
00047 char line[LINESIZE];
00048 int nbonds, optflags;
00049 int numat=0;
00050 nbonds=0;
00051 int nbline;
00052
00053
00054 bgf = (xbgfdata *) malloc(sizeof(xbgfdata));
00055 memset(bgf, 0, sizeof(xbgfdata));
00056
00057 bgf->meta = (molfile_metadata_t *) malloc(sizeof(molfile_metadata_t));
00058 memset(bgf->meta, 0, sizeof(molfile_metadata_t));
00059
00060 bgf->meta->remarklen = 0;
00061 bgf->meta->remarks = NULL;
00062
00063 if ((fd = fopen(path, "r")) == NULL)
00064 return NULL;
00065
00066 do {
00067 fgets(line, LINESIZE, fd);
00068 if ( ferror(fd) || feof(fd) ) {
00069 printf("xbgfplugin) Improperly terminated bgf file\n");
00070 return NULL;
00071 }
00072
00073 if ((strncmp(line, "ATOM", 4) == 0) || (strncmp(line, "HETATM", 6)==0))
00074 numat++;
00075
00076 if (strncmp(line,"CONECT",6)==0) {
00077 nbline=(strlen(line)-1)/6;
00078 nbline -= 2;
00079 nbonds += nbline;
00080 }
00081
00082
00083 if (strncmp(line, "REMARK", 4)==0 || strncmp(line, "LEWIS", 4)==0 ||
00084 strncmp(line, "VDW", 3)==0) {
00085 int len=strlen(line);
00086 int newlen = len + bgf->meta->remarklen;
00087 char *newstr=(char*) realloc(bgf->meta->remarks, newlen + 1);
00088 if (newstr != NULL) {
00089 bgf->meta->remarks = newstr;
00090 bgf->meta->remarks[bgf->meta->remarklen] = '\0';
00091 memcpy(bgf->meta->remarks + bgf->meta->remarklen, line, len);
00092 bgf->meta->remarks[newlen] = '\0';
00093 bgf->meta->remarklen = newlen;
00094 }
00095 }
00096
00097 optflags = MOLFILE_INSERTION | MOLFILE_CHARGE | MOLFILE_BFACTOR | MOLFILE_OCCUPANCY | MOLFILE_ATOMICNUMBER;
00098 } while ( strncmp(line, "END", 3) );
00099
00100 *natoms = numat;
00101 rewind(fd);
00102
00103 bgf->file = fd;
00104 bgf->natoms = *natoms;
00105 bgf->nbonds = nbonds;
00106
00107 bgf->optflags = optflags;
00108 bgf->coords_read = 0;
00109 bgf->from = NULL;
00110 bgf->to = NULL;
00111 bgf->bondorder = NULL;
00112
00113 return bgf;
00114 }
00115
00116
00117 static void adjust_xbgf_field_string(char *field) {
00118 int i, len;
00119
00120 len = strlen(field);
00121 while (len > 0 && field[len-1] == ' ') {
00122 field[len-1] = '\0';
00123 len--;
00124 }
00125
00126 while (len > 0 && field[0] == ' ') {
00127 for (i=0; i < len; i++)
00128 field[i] = field[i+1];
00129 len--;
00130 }
00131 }
00132
00133 static void get_xbgf_coordinates(const char *record,
00134 float *x, float *y, float *z) {
00135 char numstr[50];
00136 memset(numstr, 0, sizeof(numstr));
00137 if (x != NULL) {
00138 strncpy(numstr, record + 32, 10);
00139 *x = (float) atof(numstr);
00140 }
00141
00142 if (y != NULL) {
00143 strncpy(numstr+10, record + 42, 10);
00144 *y = (float) atof(numstr+10);
00145 }
00146
00147 if (z != NULL) {
00148 strncpy(numstr+20, record + 52, 10);
00149 *z = (float) atof(numstr+20);
00150 }
00151 }
00152
00153
00154 static void get_xbgf_fields(const char *record, char *name, char *resname,
00155 char *chain, char* segname, float *occupancy,
00156 float *bfactor, int *elementindex,
00157 int *resid, char *type, float *charge,
00158 float *x, float *y, float *z, char* insert) {
00159 char tempresid[6];
00160 char tempcharge[8];
00161 char tempbeta[7];
00162 char tempocc[7];
00163 char tempelem[4];
00164 strcpy(insert, " ");
00165
00166
00167 strncpy(name, record + 14, 5);
00168 name[5] = '\0';
00169 adjust_xbgf_field_string(name);
00170
00171
00172 strncpy(resname, record + 20, 4);
00173 resname[4] = '\0';
00174 adjust_xbgf_field_string(resname);
00175
00176
00177 strncpy(segname, record + 101, 4);
00178 segname[4]='\0';
00179 adjust_xbgf_field_string(segname);
00180
00181
00182 chain[0] = record[25];
00183 chain[1] = '\0';
00184
00185
00186 strncpy(tempresid, record + 27, 5);
00187 tempresid[5] = '\0';
00188 adjust_xbgf_field_string(tempresid);
00189 *resid=atoi(tempresid);
00190
00191
00192 strncpy(type, record+63, 5);
00193 type[5]='\0';
00194 adjust_xbgf_field_string(type);
00195
00196
00197 strncpy(tempcharge, record + 74, 7);
00198 tempcharge[7] = '\0';
00199 adjust_xbgf_field_string(tempcharge);
00200 *charge=atof(tempcharge);
00201
00202
00203 strncpy(tempbeta, record + 83, 6);
00204 tempbeta[6] = '\0';
00205 adjust_xbgf_field_string(tempbeta);
00206 *bfactor=atof(tempbeta);
00207
00208 strncpy(tempocc, record + 90, 6);
00209 tempocc[6] = '\0';
00210 adjust_xbgf_field_string(tempocc);
00211 *occupancy=atof(tempocc);
00212
00213 strncpy(tempelem, record + 97, 3);
00214 tempelem[3] = '\0';
00215 adjust_xbgf_field_string(tempelem);
00216 *elementindex=atoi(tempelem);
00217
00218
00219 get_xbgf_coordinates(record, x, y, z);
00220 }
00221
00222
00223
00224 static int read_xbgf_structure(void *v, int *optflags, molfile_atom_t *atoms) {
00225 xbgfdata *bgf = (xbgfdata *)v;
00226 char line[LINESIZE];
00227 molfile_atom_t *atom;
00228 int natoms=0;
00229
00230
00231 *optflags = bgf->optflags;
00232
00233
00234 rewind(bgf->file);
00235 do {
00236 fgets(line, LINESIZE, bgf->file);
00237 if ( ferror(bgf->file) || feof(bgf->file) ) {
00238 printf("xbgfplugin) FORMAT ATOM record found in file.\n");
00239 return MOLFILE_ERROR;
00240 }
00241 } while ( strncmp(line, "FORMAT ATOM", 11) );
00242
00243
00244 do {
00245 fgets(line, LINESIZE, bgf->file);
00246 if ( ferror(bgf->file) || feof(bgf->file) ) {
00247 printf("xbgfplugin) Error occurred reading atom record.\n");
00248 return MOLFILE_ERROR;
00249 }
00250
00251 if (strncmp(line, "ATOM", 4) && strncmp(line, "HETATM", 6)) continue;
00252 atom=atoms+natoms;
00253 natoms++;
00254 get_xbgf_fields(line, atom->name, atom->resname, atom->chain, atom->segid,
00255 &atom->occupancy, &atom->bfactor, &atom->atomicnumber,
00256 &atom->resid, atom->type, &atom->charge,
00257 NULL, NULL, NULL, atom->insertion);
00258 } while (strncmp(line, "END", 3));
00259
00260 bgf->natoms = natoms;
00261
00262 return MOLFILE_SUCCESS;
00263 }
00264
00265
00266
00267 static int read_xbgf_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00268 xbgfdata *bgf = (xbgfdata *)v;
00269 char line[LINESIZE];
00270 int i;
00271 float x, y, z;
00272
00273
00274
00275
00276 if (bgf->coords_read) {
00277 return MOLFILE_EOF;
00278 }
00279
00280
00281 rewind(bgf->file);
00282 do {
00283 fgets(line, LINESIZE, bgf->file);
00284 if ( ferror(bgf->file) || feof(bgf->file) ) {
00285 printf("xbgfplugin) No FORMAT ATOM record found in file.\n");
00286 return MOLFILE_ERROR;
00287 }
00288 } while ( strncmp(line, "FORMAT ATOM", 11) );
00289
00290
00291 for (i = 0; i < bgf->natoms; i++) {
00292 fgets(line, LINESIZE, bgf->file);
00293 if ( ferror(bgf->file) || feof(bgf->file) ) {
00294 printf("xbgfplugin) Error occurred reading atom coordinates.\n");
00295 return MOLFILE_ERROR;
00296 }
00297
00298
00299 if (strncmp(line,"ATOM",4)!=0 && strncmp(line,"HETATM",6)!=0) continue;
00300
00301 get_xbgf_coordinates(line, &x, &y, &z);
00302
00303 if (ts) {
00304 ts->coords[3*i ] = x;
00305 ts->coords[3*i+1] = y;
00306 ts->coords[3*i+2] = z;
00307 }
00308 }
00309
00310 bgf->coords_read = 1;
00311 return MOLFILE_SUCCESS;
00312 }
00313
00314
00315 static void *open_xbgf_write(const char *filename, const char *filetype,
00316 int natoms) {
00317 FILE *fd;
00318 xbgfdata *data;
00319
00320 if ((fd = fopen(filename, "w")) == NULL) {
00321 printf("xbgfplugin) Error, unable to open xbgf file %s for writing\n",
00322 filename);
00323 return NULL;
00324 }
00325
00326 data = (xbgfdata *) malloc(sizeof(xbgfdata));
00327 memset(data, 0, sizeof(xbgfdata));
00328 data->natoms = natoms;
00329 data->file = fd;
00330 data->nbonds = 0;
00331 return data;
00332 }
00333
00334
00335 static int write_xbgf_structure(void *mydata, int optflags,
00336 const molfile_atom_t *atoms) {
00337 fflush(stdout);
00338 xbgfdata *data = (xbgfdata *)mydata;
00339 data->atomlist = (molfile_atom_t *)malloc(data->natoms*sizeof(molfile_atom_t));
00340 memcpy(data->atomlist, atoms, data->natoms*sizeof(molfile_atom_t));
00341 return MOLFILE_SUCCESS;
00342 }
00343
00344
00345 static int read_xbgf_bonds_aux(void *v, int *nbonds, int **fromptr, int **toptr, float **bondorderptr) {
00346 xbgfdata *bgf = (xbgfdata *)v;
00347 char line[LINESIZE];
00348 char nextline[LINESIZE];
00349 if (bgf->nbonds == 0) {
00350 *nbonds = 0;
00351 *fromptr = NULL;
00352 *toptr = NULL;
00353 *bondorderptr = NULL;
00354 return MOLFILE_SUCCESS;
00355 }
00356
00357
00358 rewind(bgf->file);
00359 do {
00360 fgets(line, LINESIZE, bgf->file);
00361 if ( ferror(bgf->file) || feof(bgf->file) ) {
00362 printf("xbgfplugin) No bond record found in file.\n");
00363 return MOLFILE_ERROR;
00364 }
00365 } while ( strncmp(line, "FORMAT CONECT", 13) != 0 );
00366
00367
00368 int j;
00369 int k;
00370 bool conline=false;
00371 char currbond[7]="xxxxxx";
00372 char currcon[7]="xxxxxx";
00373 char* bondptr;
00374 char* conptr;
00375 int bonds[MAXBONDS];
00376 float orders[MAXBONDS];
00377 int numbonds;
00378 int numords;
00379 float bo;
00380 int i=0;
00381 int numfields=0;
00382 fgets(line, LINESIZE, bgf->file);
00383 while (1) {
00384
00385
00386 conline=false;
00387 if (strncmp(line,"END",3)==0)
00388 break;
00389
00390 fgets(nextline, LINESIZE, bgf->file);
00391 if ( ferror(bgf->file) || feof(bgf->file) ) {
00392 printf("xbgfplugin) Error occurred reading bond record.\n");
00393 return MOLFILE_ERROR;
00394 }
00395
00396 if (strncmp(nextline,"ORDER",5)==0)
00397 conline=true;
00398
00399 if (strncmp(line,"CONECT",6)==0) {
00400 numfields=(strlen(line)-1)/6;
00401 bondptr=&line[0];
00402 numfields--;
00403 bondptr += 6;
00404 numbonds=0;
00405 numords=0;
00406 strncpy(currbond,bondptr,6);
00407 j=atoi(currbond);
00408 numfields--;
00409 bondptr += 6;
00410
00411 while ((numfields > 0) && (numbonds <= MAXBONDS)) {
00412 strncpy(currbond,bondptr,6);
00413 numfields--;
00414 bondptr += 6;
00415 bonds[numbonds]=atoi(currbond);
00416 numbonds++;
00417 }
00418
00419 if (conline) {
00420 numfields=(strlen(line)-1)/6;
00421 conptr=&nextline[0];
00422 numfields -= 2;
00423 conptr += 12;
00424 numords=0;
00425 while ((numfields > 0) && (numords < numbonds)) {
00426 strncpy(currcon,conptr,6);
00427 numfields--;
00428 conptr+=6;
00429 bo=atof(currcon);
00430 orders[numords]=bo;
00431 numords++;
00432 }
00433 }
00434
00435 for (int l=0;l<numbonds;l++) {
00436 k=bonds[l];
00437 if (j<k) {
00438 bgf->from[i]=j;
00439 bgf->to[i]=k;
00440 if (conline) {
00441 bgf->bondorder[i]=orders[l];
00442 } else {
00443 bgf->bondorder[i]=1.0;
00444 }
00445 i++;
00446 }
00447 }
00448
00449 if (conline) {
00450 fgets(line, LINESIZE, bgf->file);
00451 } else {
00452 strncpy(line,nextline,LINESIZE);
00453 }
00454 } else {
00455 strncpy(line,nextline,LINESIZE);
00456 }
00457 }
00458
00459 *nbonds = i;
00460 *fromptr = bgf->from;
00461 *toptr = bgf->to;
00462 *bondorderptr = bgf->bondorder;
00463
00464 return MOLFILE_SUCCESS;
00465 }
00466
00467
00468 static int read_xbgf_bonds(void *v, int *nbonds, int **fromptr, int **toptr,
00469 float **bondorderptr, int **bondtype,
00470 int *nbondtypes, char ***bondtypename) {
00471 xbgfdata *bgf = (xbgfdata *)v;
00472
00473
00474 *nbonds=bgf->nbonds;
00475 if (bgf->nbonds > 0) {
00476 bgf->from = (int *) malloc(*nbonds*sizeof(int));
00477 bgf->to = (int *) malloc(*nbonds*sizeof(int));
00478 bgf->bondorder = (float *) malloc(*nbonds*sizeof(float));
00479
00480 if ((read_xbgf_bonds_aux(bgf, nbonds, &(bgf->from), &(bgf->to), &(bgf->bondorder))) != MOLFILE_SUCCESS) {
00481 fclose(bgf->file);
00482 bgf->file = NULL;
00483 return MOLFILE_ERROR;
00484 }
00485 *fromptr = bgf->from;
00486 *toptr = bgf->to;
00487 *bondorderptr = bgf->bondorder;
00488 *bondtype = NULL;
00489 *nbondtypes = 0;
00490 *bondtypename = NULL;
00491 } else {
00492 printf("xbgfplugin) WARNING: no bonds defined in xbgf file.\n");
00493 *fromptr = NULL;
00494 *toptr = NULL;
00495 *bondorderptr = NULL;
00496 *bondtype = NULL;
00497 *nbondtypes = 0;
00498 *bondtypename = NULL;
00499 }
00500 return MOLFILE_SUCCESS;
00501 }
00502
00503
00504 static int write_xbgf_timestep(void *mydata, const molfile_timestep_t *ts) {
00505 fflush(stdout);
00506 xbgfdata *data = (xbgfdata *)mydata;
00507 const molfile_atom_t *atom;
00508 const float *pos;
00509 int i;
00510
00511
00512 fprintf(data->file, "BIOGRF 332\n");
00513 fprintf(data->file, "REMARK NATOM %4i\n", data->natoms);
00514 fprintf(data->file, "FORCEFIELD DREIDING\n");
00515 fprintf(data->file, "FORMAT ATOM (a6,1x,i6,1x,a5,1x,a4,1x,a1,1x,i5,3f10.5,1x,a5,i3,i2,1x,f8.5,1x,f6.3,1x,f6.3,1x,i3,1x,a4)\n");
00516
00517
00518 atom = data->atomlist;
00519 pos = ts->coords;
00520 int numbonds=0;
00521 int lp=0;
00522 for (i = 0; i < data->natoms; i++) {
00523 fprintf(data->file, "%-6s %6i %5s %4s %1s %5i%10.5f%10.5f%10.5f %-5s%3i%2i %8.5f %6.3f %6.3f %3i %4s\n", "ATOM", i+1, atom->name, atom->resname, atom->chain, atom->resid, pos[0], pos[1], pos[2], atom->type, numbonds, lp, atom->charge, atom->bfactor, atom->occupancy, atom->atomicnumber, atom->segid);
00524 ++atom;
00525 pos += 3;
00526 }
00527
00528
00529 fprintf(data->file,"FORMAT CONECT (a6,14i6) \nFORMAT ORDER (a6,i6,13f6.3)\n");
00530
00531
00532 int* bonds=(int *)malloc((data->natoms+1) * sizeof(int) * MAXBONDS);
00533 float* orders=(float *)malloc((data->natoms+1)*sizeof(float) * MAXBONDS);
00534 int* numcons=(int *)malloc((data->natoms+1)*sizeof(int));
00535 for (i=0;i<data->natoms+1;i++) {
00536 numcons[i]=0;
00537 }
00538
00539 int j,k;
00540 float o;
00541 for (i=0;i<data->nbonds;i++) {
00542 j=data->from[i];
00543 k=data->to[i];
00544
00545 if (data->bondorder != NULL)
00546 o=data->bondorder[i];
00547 else
00548 o=1.0f;
00549
00550 numcons[j]++;
00551 numcons[k]++;
00552 if (numcons[j]>MAXBONDS) {
00553 printf("xbgfplugin) Warning: Bond overflow. Not all bonds were written\n");
00554 numcons[j]--;
00555 numcons[k]--;
00556 continue;
00557 }
00558
00559 if (numcons[k]>MAXBONDS) {
00560 printf("xbgfplugin) Warning: Bond overflow. Not all bonds were written\n");
00561 numcons[k]--;
00562 numcons[j]--;
00563 continue;
00564 }
00565 bonds[6*j+numcons[j]-1]=k;
00566 bonds[6*k+numcons[k]-1]=j;
00567 orders[6*j+numcons[j]-1]=o;
00568 orders[6*k+numcons[k]-1]=o;
00569 }
00570
00571 for (i=1;i<=data->natoms;i++) {
00572 fprintf(data->file,"CONECT%6i",i);
00573 for (j=0;j<numcons[i];j++) {
00574 fprintf(data->file,"%6i",bonds[6*i+j]);
00575 }
00576 fprintf(data->file,"\nORDER %6i",i);
00577 for (j=0;j<numcons[i];j++) {
00578 fprintf(data->file,"%6.3f",orders[6*i+j]);
00579 }
00580 fprintf(data->file,"\n");
00581 }
00582
00583 if (bonds != NULL) {
00584 free(bonds);
00585 bonds = NULL;
00586 }
00587 if (orders != NULL) {
00588 free(orders);
00589 orders = NULL;
00590 }
00591 if (numcons != NULL) {
00592 free(numcons);
00593 numcons = NULL;
00594 }
00595
00596 fprintf(data->file,"END\n");
00597 return MOLFILE_SUCCESS;
00598 }
00599
00600 static int write_xbgf_bonds(void *v, int nbonds, int *fromptr, int *toptr,
00601 float *bondorderptr, int *bondtype,
00602 int nbondtypes, char **bondtypename) {
00603 xbgfdata *data = (xbgfdata *)v;
00604 data->from = (int*) malloc (nbonds * sizeof(int));
00605 data->to = (int*) malloc (nbonds * sizeof(int));
00606 data->nbonds = nbonds;
00607 fflush(stdout);
00608
00609
00610
00611 for (int i=0;i<nbonds;i++) {
00612 data->from[i]=fromptr[i];
00613 data->to[i]=toptr[i];
00614 }
00615
00616 if (bondorderptr != NULL) {
00617 data->bondorder = (float*) malloc (nbonds * sizeof(float));
00618 for (int i=0;i<nbonds;i++) {
00619 data->bondorder[i]=bondorderptr[i];
00620 }
00621 }
00622
00623
00624 return MOLFILE_SUCCESS;
00625 }
00626
00627 static void close_xbgf_write(void *mydata) {
00628 xbgfdata *data = (xbgfdata *)mydata;
00629 if (data) {
00630 fclose(data->file);
00631
00632 if (data->atomlist != NULL) free(data->atomlist);
00633 data->atomlist = NULL;
00634 if (data->from != NULL) free(data->from);
00635 data->from = NULL;
00636 if (data->to != NULL) free(data->to);
00637 data->to = NULL;
00638 if (data->bondorder != NULL) free(data->bondorder);
00639 data->bondorder = NULL;
00640 free(data);
00641 }
00642 }
00643
00644
00645
00646 static void close_xbgf_read(void *v) {
00647 xbgfdata *bgf = (xbgfdata *)v;
00648 if (bgf) {
00649 if (bgf->file) fclose(bgf->file);
00650 if (bgf->from != NULL) free(bgf->from);
00651 if (bgf->to != NULL) free(bgf->to);
00652 if (bgf->bondorder != NULL) free(bgf->bondorder);
00653
00654 if (bgf->meta->remarks != NULL)
00655 free(bgf->meta->remarks);
00656 if (bgf->meta != NULL)
00657 free(bgf->meta);
00658 free(bgf);
00659 }
00660 bgf=NULL;
00661 }
00662
00663
00664 static int read_xbgf_molecule_metadata(void *v, molfile_metadata_t **metadata) {
00665 xbgfdata *bgf = (xbgfdata *)v;
00666 *metadata = bgf->meta;
00667 return MOLFILE_SUCCESS;
00668 }
00669
00670
00671 static molfile_plugin_t plugin;
00672
00673 VMDPLUGIN_API int VMDPLUGIN_init() {
00674 memset(&plugin, 0, sizeof(molfile_plugin_t));
00675 plugin.abiversion = vmdplugin_ABIVERSION;
00676 plugin.type = MOLFILE_PLUGIN_TYPE;
00677 plugin.name = "xbgf";
00678 plugin.prettyname = "Internal Paratool Format";
00679 plugin.author = "Peter Freddolino ";
00680 plugin.majorv = 0;
00681 plugin.minorv = 13;
00682 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00683 plugin.filename_extension = "xbgf";
00684 plugin.open_file_read = open_xbgf_read;
00685 plugin.read_structure = read_xbgf_structure;
00686 plugin.read_bonds = read_xbgf_bonds;
00687 plugin.read_next_timestep = read_xbgf_timestep;
00688 plugin.close_file_read = close_xbgf_read;
00689 plugin.open_file_write = open_xbgf_write;
00690 plugin.write_structure = write_xbgf_structure;
00691 plugin.write_timestep = write_xbgf_timestep;
00692 plugin.close_file_write = close_xbgf_write;
00693 plugin.read_molecule_metadata = read_xbgf_molecule_metadata;
00694 plugin.write_bonds = write_xbgf_bonds;
00695 return VMDPLUGIN_SUCCESS;
00696 }
00697
00698 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00699 (*cb)(v, (vmdplugin_t *)&plugin);
00700 return VMDPLUGIN_SUCCESS;
00701 }
00702
00703 VMDPLUGIN_API int VMDPLUGIN_fini() {
00704 return VMDPLUGIN_SUCCESS;
00705 }
00706