1# Flawfinder.  Released under the General Public License (GPL).
2# (C) 2001-2014 David A. Wheeler.
3
4# To change version number, edit this here, the beginning of the
5# "flawfinder" script, flawfinder.spec, setup.py, and index.html.
6# Then "make test-is-correct" to get the updated version number.
7# To distribute, "make distribute && su && make rpm".
8# Then use make my_install to install to website image.
9# Eventually switch to using DistUtils to autogenerate.
10
11NAME=flawfinder
12VERSION=1.31
13RPM_VERSION=1
14VERSIONEDNAME=$(NAME)-$(VERSION)
15ARCH=noarch
16
17SAMPLE_DIR=/usr/src/linux-2.2.16
18
19# Flawfinder has traditionally used INSTALL_DIR, INSTALL_DIR_BIN, and
20# INSTALL_DIR_MAN.  Here we add support for GNU variables like prefix, etc.;
21# users who override the older flawfinder-specific variable names will
22# not notice any changes.  We define exec_prefix oddly so we can
23# quietly merge these 2 systems:
24
25prefix=/usr/local
26INSTALL_DIR=$(prefix)
27exec_prefix=$(INSTALL_DIR)
28bindir=$(exec_prefix)/bin
29INSTALL_DIR_BIN=$(bindir)
30
31datarootdir=$(INSTALL_DIR)/share
32mandir=$(datarootdir)/man
33man1dir=$(mandir)/man1
34INSTALL_DIR_MAN=$(man1dir)
35
36FLEX=flex
37
38# For Cygwin on Windows, set PYTHONEXT=.py
39# (EXE=.exe would be needed on some systems, but not for flawfinder)
40EXE=
41PYTHONEXT=
42# EXE=.exe
43# PYTHONEXT=.py
44
45# The rpm build command.  "rpmbuild" for rpm version 4.1+
46# (e.g., in Red Hat Linux 8), "rpm" for older versions.
47
48RPMBUILD=rpmbuild
49
50DESTDIR=
51
52all: flawfinder.pdf flawfinder.1.gz
53	chmod -R a+rX *
54
55# We use the "-p" option of mkdir; some very old Unixes
56# might not support this option, but it's a really common option
57# and required by SUSv3 (and probably earlier, I haven't checked).
58MKDIR_P=mkdir -p
59
60INSTALL_PROGRAM=cp -p
61INSTALL_DATA=cp -p
62
63# This installer doesn't install the compiled Python bytecode.
64# It doesn't take long to compile the short Python code, so
65# it doesn't save much time, and having the source code available
66# makes it easier to see what it does.  It also avoids the
67# (admittedly rare) problem of bad date/timestamps causing the
68# compiled code to override later uncompiled Python code.
69install:
70	-$(MKDIR_P) $(DESTDIR)$(INSTALL_DIR_BIN)
71	$(INSTALL_PROGRAM) flawfinder$(PYTHONEXT) $(DESTDIR)$(INSTALL_DIR_BIN)/flawfinder$(PYTHONEXT)
72	-$(MKDIR_P) $(DESTDIR)$(INSTALL_DIR_MAN)
73	$(INSTALL_DATA) flawfinder.1 $(DESTDIR)$(INSTALL_DIR_MAN)/flawfinder.1
74
75uninstall:
76	rm -f $(DESTDIR)$(INSTALL_DIR_BIN)/flawfinder$(PYTHONEXT)
77	rm -f $(DESTDIR)$(INSTALL_DIR_MAN)/flawfinder.1
78
79flawfinder.1.gz: flawfinder.1
80	gzip -c9 < flawfinder.1 > flawfinder.1.gz
81
82flawfinder.ps: flawfinder.1
83	man -t ./flawfinder.1 > flawfinder.ps
84
85flawfinder.pdf: flawfinder.ps
86	ps2pdf flawfinder.ps flawfinder.pdf
87
88# Not built by default, since man2html is not widely available
89# and the PDF is prettier.
90flawfinder.html: flawfinder.1
91	man2html flawfinder.1 | tail -n +3 > flawfinder.html
92
93clean:
94	rm -f *.pyc
95	rm -f flawfinder-$(VERSION).tar.gz
96	rm -f cwe.c cwe
97	rm -f *.tar *.exe ./cwe
98
99distribute: clean flawfinder.pdf flawfinder.ps
100	chmod -R a+rX *
101	mkdir ,tempdir
102	cp -p [a-zA-Z]* ,tempdir
103	rm -f ,tempdir/*.tar.gz
104	rm -f ,tempdir/*.rpm
105	# We don't need both "flawfinder" and "flawfinder.py":
106	rm -f ,tempdir/flawfinder.py
107	mv ,tempdir flawfinder-$(VERSION)
108	# Nobody else needs "update" either.
109	rm -f ,tempdir/update
110	# Don't need compressed version of document.
111	rm -f ,tempdir/flawfinder.1.gz
112	# Don't include (out of date) index.html
113	rm -f ,tempdir/index.html
114	tar cvfz flawfinder-$(VERSION).tar.gz flawfinder-$(VERSION)
115	chown --reference=. flawfinder-$(VERSION).tar.gz
116	rm -fr flawfinder-$(VERSION)
117
118dist: distribute
119
120time:
121	echo "Timing the program. First, time taken:"
122	time ./flawfinder $(SAMPLE_DIR)/*/*.[ch] > /dev/null
123	echo "Lines examined:"
124	wc -l $(SAMPLE_DIR)/*/*.[ch] | tail -2
125
126test: flawfinder test.c test2.c
127	# Omit time report so that results are always the same textually.
128	./flawfinder --omittime test.c test2.c > test-results.txt
129	echo >> test-results.txt
130	echo "Testing for no ending newline:" >> test-results.txt
131	./flawfinder --omittime no-ending-newline.c | \
132	  grep 'Lines analyzed' >> test-results.txt
133	./flawfinder --omittime --html --context test.c test2.c > test-results.html
134	@echo "Differences from expected results:"
135	@diff -u correct-results.txt test-results.txt
136	@diff -u correct-results.html test-results.html
137
138check: test
139
140# Run "make test-is-correct" if the results are as expected.
141test-is-correct: test-results.txt
142	mv test-results.txt correct-results.txt
143	mv test-results.html correct-results.html
144
145profile:
146	/usr/lib/python1.5/profile.py ./flawfinder > profile-results $(SAMPLE_DIR)/*/*.[ch] > profile-results
147
148
149rpm: distribute
150	chmod -R a+rX *
151	cp $(VERSIONEDNAME).tar.gz /usr/src/redhat/SOURCES
152	cp flawfinder.spec /usr/src/redhat/SPECS
153	cd /usr/src/redhat/SPECS
154	$(RPMBUILD) -ba flawfinder.spec
155	chmod a+r /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm
156	chmod a+r /usr/src/redhat/SRPMS/$(VERSIONEDNAME)-$(RPM_VERSION)*.src.rpm
157	# cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm .
158	# cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm  $(VERSIONEDNAME)-$(RPM_VERSION).noarch.rpm
159	cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm  .
160	cp -p /usr/src/redhat/SRPMS/$(VERSIONEDNAME)-$(RPM_VERSION)*.src.rpm .
161	chown --reference=README *.rpm
162	# Install, for testing.  Ignore the "not installed" message here,
163	# unless you already installed it; we're just removing any old copies:
164	-rpm -e flawfinder
165	rpm -ivh /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm
166	echo "Use rpm -e $(NAME) to remove the package"
167	chown --reference=. *.rpm
168
169# This is a developer convenience target, not intended for general use.
170my-install: flawfinder.pdf flawfinder.ps test
171	cp -p $(VERSIONEDNAME).tar.gz \
172	      flawfinder flawfinder.1 makefile \
173	      flawfinder.pdf flawfinder.ps ChangeLog \
174	      test.c test2.c test-results.txt test-results.html \
175	           /home/dwheeler/dwheeler.com/flawfinder/
176
177# This is intended to be a local capability to list CWEs
178cwe.c: cwe.l
179	$(FLEX) -o cwe.c cwe.l
180
181cwe: cwe.c
182	$(CC) -o cwe cwe.c -lfl
183
184show-cwes: cwe
185	./cwe < flawfinder | sort -u -V
186
187
188.PHONY: install clean test check profile test-is-correct rpm uninstall distribute my-install show-cwes
189
190
191# When I switch to using "DistUtils", I may need to move the MANIFEST.in
192# file into a subdirectory (named flawfinder-versionnumber).
193# I can then create all the distribution files by just typing:
194#  python setup.py bdist_rpm
195
196