/**************************************************************************** Program Name: FileIO.c Author : Phil Shotton. Description : This program is an example on how to develop external functions in WingZ. It allows text input-output and arbitrary file positioning with read and write. Your attention is also directed at the file 'FILEIO.README' for documention on these functions. Version : @(#)FileIO.c 2.1.2.1 95/05/11 12:38:21 copyright 1994, Investment Intelligence Systems Corporation ****************************************************************************/ #include #include #include #include #include #define numfuncs 12 #define MAXFILES 128 #include "WZTools.h" #ifndef min # define min(a,b) ((a)<(b)?(a):(b)) #endif /* prototypes */ typedef struct { FILE * fp; char * name; char * mode; } Fs; Fs filep[MAXFILES]; void InitFunc(); void NumLines(PVAL,PVAL), OpenFile(PVAL,PVAL), CloseFile(PVAL,PVAL); void ReadFile(PVAL,PVAL), WriteFile(PVAL,PVAL); void GetBytes(PVAL,PVAL), PutBytes(PVAL,PVAL), FilePos(PVAL,PVAL); void Shell(PVAL,PVAL), POpen(PVAL,PVAL), PClose(PVAL,PVAL); void Showf(PVAL,PVAL); FILE * find_fp(int); int add_fp(FILE *,char *,char *), del_fp(int); /* set up structure */ void (*initfunc) () = InitFunc; ROUT rout = { numfuncs, NULL, { {NumLines, "\010NumLines", 1}, {OpenFile, "\010OpenFile", 2}, {CloseFile, "\011CloseFile", 1}, {ReadFile, "\010ReadFile", 1}, {WriteFile, "\011WriteFile", 2}, {GetBytes, "\010GetBytes", 3}, {PutBytes, "\010PutBytes", 3}, {FilePos, "\007FilePos", 1}, {Shell,"\005Shell", 1}, {POpen,"\005POpen", 2}, {PClose,"\006PClose", 1}, {Showf,"\005Showf", 0} } }; void Showf(PVAL pr,PVAL ps) { int i; for(i=0;iflag = NUMERIC; /* remember first byte is length of string */ flen = parg[0].val.string[0]; strncpy(filename, &parg[0].val.string[1], flen); filename[flen] = '\0'; /* open the file */ if ((fd = open(filename, O_RDONLY)) != -1) { while ( read(fd,&c,1)) if (c == '\n') linecount++; close(fd); /* set up the return values */ pret->val.numeric = linecount; /* printf("wk_NumLines: found %d lines.\n",linecount); */ } else { /* could not open file */ perror("open"); pret->val.numeric = 0; } } else { /* variable in was not a string */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function opens a file and passes back a file descriptor to wingz so futher processing can be applied. in: char string (PASCAL) filename. in: char string (PASCAL) access mode. "r" "w" see UNIX man page fopen() out: int file handle. */ void OpenFile(PVAL pret, PVAL parg) { char filename[255]; int flen, fd; FILE * fp; char mode[5]; pret->flag = NUMERIC; if ((parg[0].flag == STRING) && (parg[1].flag == STRING)) { flen = parg[0].val.string[0]; strncpy(filename, &parg[0].val.string[1], flen); filename[flen] = '\0'; flen=(int)parg[1].val.string[0]; flen=min(4,flen); strncpy(mode,parg[1].val.string+1,flen); mode[flen]=0; /* open the file */ if (NULL != (fp = fopen(filename,mode))) { if(0 > (fd=add_fp(fp,filename,mode))) fclose(fp); pret->val.numeric = fd; } else { perror("file open failed\n"); pret->val.numeric = -1; } } else { /* variable in was not a string */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function will close an existing file which was opened with OpenFile(). in: int filehandle fd from an OpenFile */ void CloseFile(PVAL pret, PVAL parg) { int fd; FILE * fp; if (parg[0].flag == NUMERIC) { pret->flag = NUMERIC; fd = parg[0].val.numeric; if(NULL!=(fp=find_fp(fd))) { fclose(fp); del_fp(fd); pret->val.numeric = 1; } else { /* problem in closing file */ perror("fclose"); pret->val.numeric = 0; } } else { /* variable in was not numeric */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function reads up to 255 characters or until a '\n' from a file, opened with OpenFile. in: int file handle. out: char string (PASCAL) line of file. */ void ReadFile(PVAL pret, PVAL parg) { int fd,len,c; char buff[255]; FILE * fp; if (parg[0].flag == NUMERIC) { fd = parg[0].val.numeric; len=0; if(NULL!=(fp=find_fp(fd))) { if (fgets(buff+1, 254, fp)) { /* okay lets return a PASCAL string */ buff[254]=0; len=strlen(buff+1); if('\n'==buff[len]) buff[len--]='\0'; } } buff[0] = (char)len; pret->flag = STRING; pret->val.string = buff; } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Functions writes up to 255 characters at current position to a file opened with OpenFile() and appends a \n in: int file handle. in: char string (PASCAL) line to inserted. */ void WriteFile(PVAL pret, PVAL parg) { int n, fd; FILE * fp; if ((parg[0].flag == NUMERIC) && (parg[1].flag == STRING)) { pret->flag = NUMERIC; fd = parg[0].val.numeric; /* pascal string, first byte is the length */ n = parg[1].val.string[0]; if(NULL!=(fp=find_fp(fd))) { if(0>fprintf(fp,"%.*s\n",n,parg[1].val.string+1)) { perror("fprintf"); pret->val.numeric = 0; } else pret->val.numeric = 1; } } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function reads count bytes (up to 255 characters) from a file opened with OpenFile. in: int file handle, int position, int count. out: char string (PASCAL) count bytes from file. */ void GetBytes(PVAL pret, PVAL parg) { int fd,len,pos; char buffer[255]; FILE * fp; if ( (parg[0].flag == NUMERIC) && (parg[1].flag == NUMERIC) && (parg[2].flag == NUMERIC) ) { fd = parg[0].val.numeric; pos = parg[1].val.numeric; len = parg[2].val.numeric; if( (NULL!=(fp=find_fp(fd))) && (fseek(fp,pos,SEEK_SET) != -1) ) { if (len=fread(buffer + 1,1, min(254,len),fp)) { buffer[0] = (char)len; pret->flag = STRING; pret->val.string = buffer; return; } else { perror("fread"); pret->flag = ERR; pret->val.err = 6; } } else { perror("fseek"); pret->flag = ERR; pret->val.err = 6; } } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Functions writes count bytes (up to 254 characters) at specified position to a file opened with OpenFile(). in: int file handle, int pos, char string (PASCAL) line to inserted. */ void PutBytes(PVAL pret, PVAL parg) { int pos, fd; FILE * fp; if ((parg[0].flag == NUMERIC) && (parg[1].flag == NUMERIC) && (parg[2].flag == STRING)) { pret->flag = NUMERIC; fd = parg[0].val.numeric; pos = parg[1].val.numeric; if( (NULL!=(fp=find_fp(fd))) && (fseek(fp,pos,SEEK_SET)!= -1) ) { if(pos=fwrite(parg[2].val.string+1,1,parg[2].val.string[0],fp)!= 0) pret->val.numeric = pos; else { perror("fwrite"); pret->val.numeric = 0; } return; } perror("fseek"); pret->flag = ERR; pret->val.err = 6; } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Functions returns current file position of a file opened with OpenFile(). in: int file handle out: current position (byte offset from 0) */ void FilePos(PVAL pret, PVAL parg) { int pos, fd; FILE * fp; if (parg[0].flag == NUMERIC) { pret->flag = NUMERIC; fd = parg[0].val.numeric; /* seek 0 bytes from current pos, returns pos */ if( (NULL!=(fp=find_fp(fd))) && ((pos=ftell(fp))!= -1) ) pret->val.numeric = pos; else { perror("fseek"); pret->flag = ERR; pret->val.err = 6; } } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function pumps input into a system call pret : return structure parg : argument structure */ void Shell(PVAL pret, PVAL parg) { char buffer[255]; int n; int ret; char c; if (parg[0].flag == STRING) { /* pascal string, first byte is the length */ n = parg[0].val.string[0]; /* copy from the argument+1 to the buffer store */ strncpy(buffer, &parg[0].val.string[1],n); buffer[n] = '\0'; /* lets put the string thru. system() in the background */ c=buffer[n-1]; if(c=='&') { if(fork() == 0) { ret=system(buffer); exit(ret); } else ret=0; } else ret=system(buffer); pret->flag = NUMERIC; pret->val.err=ret; } else { pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function to implement a pipe to/from a process, like UNIX's popen() in: char string (PASCAL) command to bex executed. in: char string (PASCAL) access mode. "r" or "w" see UNIX man popen(). out: int file handle. */ void POpen(PVAL pret, PVAL parg) { int n, fd; char command[255]; char type[2]; FILE *fp; /* make sure that second argument is only 1 character long */ if ( (parg[0].flag == STRING) && (parg[1].flag == STRING) && (parg[1].val.string[0]==1) ) { pret->flag = NUMERIC; /* pascal string, first byte is the length */ n = parg[0].val.string[0]; /* copy from the 1st argument+1 to the buffer store */ strncpy(command, &parg[0].val.string[1], n); command[n] = '\0'; /* get the type from the 2nd argument */ type[0] = parg[1].val.string[1]; type[1] = '\0'; /* printf("POpen received (%s %)\n",command,type); */ if ( (fp = popen(command, type)) != NULL) { if ( (fd=add_fp(fp,command,type)) != -1) { /* set variables to return File Handle */ pret->val.numeric = fd; } else { /* no more free slots return error */ pret->val.numeric = -1; } } else { perror("popen"); pret->val.numeric = -1; } } else { /* variable in was not a number */ pret->flag = ERR; pret->val.err = 12; } } /* -------------------------------------------------------------- */ /* Function to close an existing file handle returned from wk_POpen(). in: int file handle. */ void PClose(PVAL pret, PVAL parg) { int fd; FILE *fp; if (parg[0].flag == NUMERIC) { pret->flag = NUMERIC; fd = parg[0].val.numeric; /* remove the file handle from the lookup, and get the FILE pointer */ if (NULL!= (fp=find_fp(fd))) { if (! pclose(fp)) { /* pfile closed ok */ pret->val.numeric = 1; } else { /* problem in closing pipe */ pret->val.numeric = 0; } del_fp(fd); } else { /* problem in deleting file */ pret->val.numeric = 0; } } else { /* variable in was not a string */ pret->flag = ERR; pret->val.err = 12; } } int add_fp(FILE * fp,char * name,char * mode) { int i; for(i=0;i=0) && (i=0) && (fd