/****************************************************************************
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#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;i<MAXFILES;i++)
{
if(filep[i].fp)
fprintf(stderr,"Fd:%d, fp:%X, Name:%s, Mode:%s\n",
i,filep[i].fp,filep[i].name,filep[i].mode);
}
}
/* -------------------------------------------------------------- */
/* initialize function */
void InitFunc(PVAL pret, PVAL parg)
{
int i;
for(i=0;i<MAXFILES;i++)
memset(&filep,0,sizeof(Fs));
}
/* -------------------------------------------------------------- */
/* Function counts the number of lines in a text file.
in: char string (PASCAL) filename.
out: int number of lines in file
*/
void NumLines(PVAL pret, PVAL parg)
{
int flen, linecount = 0;
char filename[255],c;
int fd;
if (parg[0].flag == STRING)
{
pret->flag = 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<MAXFILES;i++)
if(!filep[i].fp)
{
filep[i].fp=fp;
filep[i].name=strdup(name);
filep[i].mode=strdup(mode);
return i;
}
return -1;
}
int del_fp(int i)
{
if( (i>=0) && (i<MAXFILES))
{
filep[i].fp=NULL;
if(filep[i].name)
free(filep[i].name);
filep[i].name=NULL;
if(filep[i].mode)
free(filep[i].mode);
filep[i].mode=NULL;
return 1;
}
return 0;
}
FILE * find_fp(int fd)
{
if( (fd>=0) && (fd<MAXFILES))
return filep[fd].fp;
return NULL;
}
/* -------------------------------------------------------------- */
syntax highlighted by Code2HTML, v. 0.9.1