chiark / gitweb /
Merge branch 'ijackson' into stable-3.x
[ypp-sc-tools.db-test.git] / yarrg / common.c
1 /*
2  * Utility functions
3  */
4 /*
5  *  This is part of ypp-sc-tools, a set of third-party tools for assisting
6  *  players of Yohoho Puzzle Pirates.
7  * 
8  *  Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
9  * 
10  *  This program is free software: you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation, either version 3 of the License, or
13  *  (at your option) any later version.
14  * 
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  * 
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  * 
23  *  Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
24  *  are used without permission.  This program is not endorsed or
25  *  sponsored by Three Rings.
26  */
27
28 #include "common.h"
29
30 void *mmalloc(size_t sz) {
31   void *r;
32   if (!sz) return 0;
33   sysassert( r= malloc(sz) );
34   return r;
35 }
36 void *mrealloc(void *p, size_t sz) {
37   assert(sz);
38   void *r;
39   sysassert( r= realloc(p,sz) );
40   return r;
41 }
42
43
44 FILE *dbfile;
45 static const char *basepath; /* as passed in by caller */
46 static pid_t dbzcat;
47
48 int dbfile_gzopen(const char *basepath_spec) {
49   assert(!dbfile);
50
51   basepath= basepath_spec;
52
53   char *zpath= masprintf("%s.gz", basepath);
54   int e= gzopen(zpath, O_RDONLY, &dbfile, &dbzcat, 0);
55   free(zpath);
56   if (e) { errno=e; sysassert(errno==ENOENT); return 0; }
57   
58   return 1;
59 }  
60
61 int dbfile_open(const char *tpath) {
62   assert(!dbfile);
63
64   basepath= tpath;
65
66   dbzcat= -1;
67   dbfile= fopen(tpath,"r");
68   if (!dbfile) { sysassert(errno==ENOENT); return 0; }
69   return 1;
70 }  
71
72 void dbfile_close(void) {
73   gzclose(&dbfile, &dbzcat, basepath);
74 }
75
76 #define dbassertgl(x) ((x) ? (void)0 : dbfile_assertfail(file,line,#x))
77
78 void dbfile_getsline(char *lbuf, size_t lbufsz, const char *file, int line) {
79   errno=0;
80   char *s= fgets(lbuf,lbufsz,dbfile);
81   sysassert(!ferror(dbfile));
82   dbassertgl(!feof(dbfile));
83   assert(s);
84   int l= strlen(lbuf);
85   dbassertgl(l>0);  dbassertgl(lbuf[--l]=='\n');
86   lbuf[l]= 0;
87 }
88
89 int dbfile_vscanf(const char *fmt, va_list al) {
90   int r= vfscanf(dbfile,fmt,al);
91   sysassert(!ferror(dbfile));
92   return r;
93 }
94
95 int dbfile_scanf(const char *fmt, ...) {
96   va_list al;
97   va_start(al,fmt);
98   int r= dbfile_vscanf(fmt,al);
99   va_end(al);
100   return r;
101 }
102
103 void dbfile_assertfail(const char *file, int line, const char *m) {
104   if (dbzcat)
105     fatal("Error in dictionary file %s.gz:\n"
106           " Requirement not met at %s:%d:\n"
107           " %s",
108           basepath, file,line, m);
109   else if (dbfile)
110     fatal("Error in dictionary file %s at byte %ld:\n"
111           " Requirement not met at %s:%d:\n"
112           " %s",
113           basepath,(long)ftell(dbfile), file,line, m);
114   else
115     fatal("Semantic error in dictionaries:\n"
116           " Requirement not met at %s:%d:\n"
117           " %s",
118           file,line, m);
119 }
120
121 int gzopen(const char *zpath, int oflags, FILE **f_r, pid_t *pid_r,
122            const char *gziplevel /* 0 for read; may be 0, or "-1" etc. */) {
123
124   int zfd= open(zpath, oflags, 0666);
125   if (zfd<0) return errno;
126
127   int pipefds[2];
128   sysassert(! pipe(pipefds) );
129
130   int oi,io; const char *cmd; const char *stdiomode;
131   switch ((oflags & O_ACCMODE)) {
132   case O_RDONLY: oi=0; io=1; cmd="gunzip"; stdiomode="r"; break;
133   case O_WRONLY: oi=1; io=0; cmd="gzip";   stdiomode="w"; break;
134   default: abort();
135   }
136
137   sysassert( (*pid_r=fork()) != -1 );
138   if (!*pid_r) {
139     sysassert( dup2(zfd,oi)==oi );
140     sysassert( dup2(pipefds[io],io)==io );
141     sysassert(! close(zfd) );
142     sysassert(! close(pipefds[0]) );
143     sysassert(! close(pipefds[1]) );
144     execlp(cmd,cmd,gziplevel,(char*)0);
145     sysassert(!"execlp gzip/gunzip");
146   }
147   sysassert(! close(zfd) );
148   sysassert(! close(pipefds[io]) );
149   sysassert( *f_r= fdopen(pipefds[oi], stdiomode) );
150
151   return 0;
152 }
153
154 void gzclose(FILE **f, pid_t *p, const char *what) {
155   if (!*f) return;
156   
157   sysassert(!ferror(*f));
158   sysassert(!fclose(*f));
159
160   if (*p != -1) {
161     char *process= masprintf("%s (de)compressor",what);
162     waitpid_check_exitstatus(*p,process,1);
163     free(process);
164     *p= -1;
165   }
166
167   *f= 0;
168 }