1 diff --git a/.gitignore b/.gitignore
2 index 0caee61..92aa5c5 100644
11 +/src/fireinfo/__init__.py
38 diff --git a/COPYING b/COPYING
40 index 0000000..94a9ed0
44 + GNU GENERAL PUBLIC LICENSE
45 + Version 3, 29 June 2007
47 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
48 + Everyone is permitted to copy and distribute verbatim copies
49 + of this license document, but changing it is not allowed.
53 + The GNU General Public License is a free, copyleft license for
54 +software and other kinds of works.
56 + The licenses for most software and other practical works are designed
57 +to take away your freedom to share and change the works. By contrast,
58 +the GNU General Public License is intended to guarantee your freedom to
59 +share and change all versions of a program--to make sure it remains free
60 +software for all its users. We, the Free Software Foundation, use the
61 +GNU General Public License for most of our software; it applies also to
62 +any other work released this way by its authors. You can apply it to
65 + When we speak of free software, we are referring to freedom, not
66 +price. Our General Public Licenses are designed to make sure that you
67 +have the freedom to distribute copies of free software (and charge for
68 +them if you wish), that you receive source code or can get it if you
69 +want it, that you can change the software or use pieces of it in new
70 +free programs, and that you know you can do these things.
72 + To protect your rights, we need to prevent others from denying you
73 +these rights or asking you to surrender the rights. Therefore, you have
74 +certain responsibilities if you distribute copies of the software, or if
75 +you modify it: responsibilities to respect the freedom of others.
77 + For example, if you distribute copies of such a program, whether
78 +gratis or for a fee, you must pass on to the recipients the same
79 +freedoms that you received. You must make sure that they, too, receive
80 +or can get the source code. And you must show them these terms so they
83 + Developers that use the GNU GPL protect your rights with two steps:
84 +(1) assert copyright on the software, and (2) offer you this License
85 +giving you legal permission to copy, distribute and/or modify it.
87 + For the developers' and authors' protection, the GPL clearly explains
88 +that there is no warranty for this free software. For both users' and
89 +authors' sake, the GPL requires that modified versions be marked as
90 +changed, so that their problems will not be attributed erroneously to
91 +authors of previous versions.
93 + Some devices are designed to deny users access to install or run
94 +modified versions of the software inside them, although the manufacturer
95 +can do so. This is fundamentally incompatible with the aim of
96 +protecting users' freedom to change the software. The systematic
97 +pattern of such abuse occurs in the area of products for individuals to
98 +use, which is precisely where it is most unacceptable. Therefore, we
99 +have designed this version of the GPL to prohibit the practice for those
100 +products. If such problems arise substantially in other domains, we
101 +stand ready to extend this provision to those domains in future versions
102 +of the GPL, as needed to protect the freedom of users.
104 + Finally, every program is threatened constantly by software patents.
105 +States should not allow patents to restrict development and use of
106 +software on general-purpose computers, but in those that do, we wish to
107 +avoid the special danger that patents applied to a free program could
108 +make it effectively proprietary. To prevent this, the GPL assures that
109 +patents cannot be used to render the program non-free.
111 + The precise terms and conditions for copying, distribution and
112 +modification follow.
114 + TERMS AND CONDITIONS
118 + "This License" refers to version 3 of the GNU General Public License.
120 + "Copyright" also means copyright-like laws that apply to other kinds of
121 +works, such as semiconductor masks.
123 + "The Program" refers to any copyrightable work licensed under this
124 +License. Each licensee is addressed as "you". "Licensees" and
125 +"recipients" may be individuals or organizations.
127 + To "modify" a work means to copy from or adapt all or part of the work
128 +in a fashion requiring copyright permission, other than the making of an
129 +exact copy. The resulting work is called a "modified version" of the
130 +earlier work or a work "based on" the earlier work.
132 + A "covered work" means either the unmodified Program or a work based
135 + To "propagate" a work means to do anything with it that, without
136 +permission, would make you directly or secondarily liable for
137 +infringement under applicable copyright law, except executing it on a
138 +computer or modifying a private copy. Propagation includes copying,
139 +distribution (with or without modification), making available to the
140 +public, and in some countries other activities as well.
142 + To "convey" a work means any kind of propagation that enables other
143 +parties to make or receive copies. Mere interaction with a user through
144 +a computer network, with no transfer of a copy, is not conveying.
146 + An interactive user interface displays "Appropriate Legal Notices"
147 +to the extent that it includes a convenient and prominently visible
148 +feature that (1) displays an appropriate copyright notice, and (2)
149 +tells the user that there is no warranty for the work (except to the
150 +extent that warranties are provided), that licensees may convey the
151 +work under this License, and how to view a copy of this License. If
152 +the interface presents a list of user commands or options, such as a
153 +menu, a prominent item in the list meets this criterion.
157 + The "source code" for a work means the preferred form of the work
158 +for making modifications to it. "Object code" means any non-source
161 + A "Standard Interface" means an interface that either is an official
162 +standard defined by a recognized standards body, or, in the case of
163 +interfaces specified for a particular programming language, one that
164 +is widely used among developers working in that language.
166 + The "System Libraries" of an executable work include anything, other
167 +than the work as a whole, that (a) is included in the normal form of
168 +packaging a Major Component, but which is not part of that Major
169 +Component, and (b) serves only to enable use of the work with that
170 +Major Component, or to implement a Standard Interface for which an
171 +implementation is available to the public in source code form. A
172 +"Major Component", in this context, means a major essential component
173 +(kernel, window system, and so on) of the specific operating system
174 +(if any) on which the executable work runs, or a compiler used to
175 +produce the work, or an object code interpreter used to run it.
177 + The "Corresponding Source" for a work in object code form means all
178 +the source code needed to generate, install, and (for an executable
179 +work) run the object code and to modify the work, including scripts to
180 +control those activities. However, it does not include the work's
181 +System Libraries, or general-purpose tools or generally available free
182 +programs which are used unmodified in performing those activities but
183 +which are not part of the work. For example, Corresponding Source
184 +includes interface definition files associated with source files for
185 +the work, and the source code for shared libraries and dynamically
186 +linked subprograms that the work is specifically designed to require,
187 +such as by intimate data communication or control flow between those
188 +subprograms and other parts of the work.
190 + The Corresponding Source need not include anything that users
191 +can regenerate automatically from other parts of the Corresponding
194 + The Corresponding Source for a work in source code form is that
197 + 2. Basic Permissions.
199 + All rights granted under this License are granted for the term of
200 +copyright on the Program, and are irrevocable provided the stated
201 +conditions are met. This License explicitly affirms your unlimited
202 +permission to run the unmodified Program. The output from running a
203 +covered work is covered by this License only if the output, given its
204 +content, constitutes a covered work. This License acknowledges your
205 +rights of fair use or other equivalent, as provided by copyright law.
207 + You may make, run and propagate covered works that you do not
208 +convey, without conditions so long as your license otherwise remains
209 +in force. You may convey covered works to others for the sole purpose
210 +of having them make modifications exclusively for you, or provide you
211 +with facilities for running those works, provided that you comply with
212 +the terms of this License in conveying all material for which you do
213 +not control copyright. Those thus making or running the covered works
214 +for you must do so exclusively on your behalf, under your direction
215 +and control, on terms that prohibit them from making any copies of
216 +your copyrighted material outside their relationship with you.
218 + Conveying under any other circumstances is permitted solely under
219 +the conditions stated below. Sublicensing is not allowed; section 10
220 +makes it unnecessary.
222 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
224 + No covered work shall be deemed part of an effective technological
225 +measure under any applicable law fulfilling obligations under article
226 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
227 +similar laws prohibiting or restricting circumvention of such
230 + When you convey a covered work, you waive any legal power to forbid
231 +circumvention of technological measures to the extent such circumvention
232 +is effected by exercising rights under this License with respect to
233 +the covered work, and you disclaim any intention to limit operation or
234 +modification of the work as a means of enforcing, against the work's
235 +users, your or third parties' legal rights to forbid circumvention of
236 +technological measures.
238 + 4. Conveying Verbatim Copies.
240 + You may convey verbatim copies of the Program's source code as you
241 +receive it, in any medium, provided that you conspicuously and
242 +appropriately publish on each copy an appropriate copyright notice;
243 +keep intact all notices stating that this License and any
244 +non-permissive terms added in accord with section 7 apply to the code;
245 +keep intact all notices of the absence of any warranty; and give all
246 +recipients a copy of this License along with the Program.
248 + You may charge any price or no price for each copy that you convey,
249 +and you may offer support or warranty protection for a fee.
251 + 5. Conveying Modified Source Versions.
253 + You may convey a work based on the Program, or the modifications to
254 +produce it from the Program, in the form of source code under the
255 +terms of section 4, provided that you also meet all of these conditions:
257 + a) The work must carry prominent notices stating that you modified
258 + it, and giving a relevant date.
260 + b) The work must carry prominent notices stating that it is
261 + released under this License and any conditions added under section
262 + 7. This requirement modifies the requirement in section 4 to
263 + "keep intact all notices".
265 + c) You must license the entire work, as a whole, under this
266 + License to anyone who comes into possession of a copy. This
267 + License will therefore apply, along with any applicable section 7
268 + additional terms, to the whole of the work, and all its parts,
269 + regardless of how they are packaged. This License gives no
270 + permission to license the work in any other way, but it does not
271 + invalidate such permission if you have separately received it.
273 + d) If the work has interactive user interfaces, each must display
274 + Appropriate Legal Notices; however, if the Program has interactive
275 + interfaces that do not display Appropriate Legal Notices, your
276 + work need not make them do so.
278 + A compilation of a covered work with other separate and independent
279 +works, which are not by their nature extensions of the covered work,
280 +and which are not combined with it such as to form a larger program,
281 +in or on a volume of a storage or distribution medium, is called an
282 +"aggregate" if the compilation and its resulting copyright are not
283 +used to limit the access or legal rights of the compilation's users
284 +beyond what the individual works permit. Inclusion of a covered work
285 +in an aggregate does not cause this License to apply to the other
286 +parts of the aggregate.
288 + 6. Conveying Non-Source Forms.
290 + You may convey a covered work in object code form under the terms
291 +of sections 4 and 5, provided that you also convey the
292 +machine-readable Corresponding Source under the terms of this License,
293 +in one of these ways:
295 + a) Convey the object code in, or embodied in, a physical product
296 + (including a physical distribution medium), accompanied by the
297 + Corresponding Source fixed on a durable physical medium
298 + customarily used for software interchange.
300 + b) Convey the object code in, or embodied in, a physical product
301 + (including a physical distribution medium), accompanied by a
302 + written offer, valid for at least three years and valid for as
303 + long as you offer spare parts or customer support for that product
304 + model, to give anyone who possesses the object code either (1) a
305 + copy of the Corresponding Source for all the software in the
306 + product that is covered by this License, on a durable physical
307 + medium customarily used for software interchange, for a price no
308 + more than your reasonable cost of physically performing this
309 + conveying of source, or (2) access to copy the
310 + Corresponding Source from a network server at no charge.
312 + c) Convey individual copies of the object code with a copy of the
313 + written offer to provide the Corresponding Source. This
314 + alternative is allowed only occasionally and noncommercially, and
315 + only if you received the object code with such an offer, in accord
316 + with subsection 6b.
318 + d) Convey the object code by offering access from a designated
319 + place (gratis or for a charge), and offer equivalent access to the
320 + Corresponding Source in the same way through the same place at no
321 + further charge. You need not require recipients to copy the
322 + Corresponding Source along with the object code. If the place to
323 + copy the object code is a network server, the Corresponding Source
324 + may be on a different server (operated by you or a third party)
325 + that supports equivalent copying facilities, provided you maintain
326 + clear directions next to the object code saying where to find the
327 + Corresponding Source. Regardless of what server hosts the
328 + Corresponding Source, you remain obligated to ensure that it is
329 + available for as long as needed to satisfy these requirements.
331 + e) Convey the object code using peer-to-peer transmission, provided
332 + you inform other peers where the object code and Corresponding
333 + Source of the work are being offered to the general public at no
334 + charge under subsection 6d.
336 + A separable portion of the object code, whose source code is excluded
337 +from the Corresponding Source as a System Library, need not be
338 +included in conveying the object code work.
340 + A "User Product" is either (1) a "consumer product", which means any
341 +tangible personal property which is normally used for personal, family,
342 +or household purposes, or (2) anything designed or sold for incorporation
343 +into a dwelling. In determining whether a product is a consumer product,
344 +doubtful cases shall be resolved in favor of coverage. For a particular
345 +product received by a particular user, "normally used" refers to a
346 +typical or common use of that class of product, regardless of the status
347 +of the particular user or of the way in which the particular user
348 +actually uses, or expects or is expected to use, the product. A product
349 +is a consumer product regardless of whether the product has substantial
350 +commercial, industrial or non-consumer uses, unless such uses represent
351 +the only significant mode of use of the product.
353 + "Installation Information" for a User Product means any methods,
354 +procedures, authorization keys, or other information required to install
355 +and execute modified versions of a covered work in that User Product from
356 +a modified version of its Corresponding Source. The information must
357 +suffice to ensure that the continued functioning of the modified object
358 +code is in no case prevented or interfered with solely because
359 +modification has been made.
361 + If you convey an object code work under this section in, or with, or
362 +specifically for use in, a User Product, and the conveying occurs as
363 +part of a transaction in which the right of possession and use of the
364 +User Product is transferred to the recipient in perpetuity or for a
365 +fixed term (regardless of how the transaction is characterized), the
366 +Corresponding Source conveyed under this section must be accompanied
367 +by the Installation Information. But this requirement does not apply
368 +if neither you nor any third party retains the ability to install
369 +modified object code on the User Product (for example, the work has
370 +been installed in ROM).
372 + The requirement to provide Installation Information does not include a
373 +requirement to continue to provide support service, warranty, or updates
374 +for a work that has been modified or installed by the recipient, or for
375 +the User Product in which it has been modified or installed. Access to a
376 +network may be denied when the modification itself materially and
377 +adversely affects the operation of the network or violates the rules and
378 +protocols for communication across the network.
380 + Corresponding Source conveyed, and Installation Information provided,
381 +in accord with this section must be in a format that is publicly
382 +documented (and with an implementation available to the public in
383 +source code form), and must require no special password or key for
384 +unpacking, reading or copying.
386 + 7. Additional Terms.
388 + "Additional permissions" are terms that supplement the terms of this
389 +License by making exceptions from one or more of its conditions.
390 +Additional permissions that are applicable to the entire Program shall
391 +be treated as though they were included in this License, to the extent
392 +that they are valid under applicable law. If additional permissions
393 +apply only to part of the Program, that part may be used separately
394 +under those permissions, but the entire Program remains governed by
395 +this License without regard to the additional permissions.
397 + When you convey a copy of a covered work, you may at your option
398 +remove any additional permissions from that copy, or from any part of
399 +it. (Additional permissions may be written to require their own
400 +removal in certain cases when you modify the work.) You may place
401 +additional permissions on material, added by you to a covered work,
402 +for which you have or can give appropriate copyright permission.
404 + Notwithstanding any other provision of this License, for material you
405 +add to a covered work, you may (if authorized by the copyright holders of
406 +that material) supplement the terms of this License with terms:
408 + a) Disclaiming warranty or limiting liability differently from the
409 + terms of sections 15 and 16 of this License; or
411 + b) Requiring preservation of specified reasonable legal notices or
412 + author attributions in that material or in the Appropriate Legal
413 + Notices displayed by works containing it; or
415 + c) Prohibiting misrepresentation of the origin of that material, or
416 + requiring that modified versions of such material be marked in
417 + reasonable ways as different from the original version; or
419 + d) Limiting the use for publicity purposes of names of licensors or
420 + authors of the material; or
422 + e) Declining to grant rights under trademark law for use of some
423 + trade names, trademarks, or service marks; or
425 + f) Requiring indemnification of licensors and authors of that
426 + material by anyone who conveys the material (or modified versions of
427 + it) with contractual assumptions of liability to the recipient, for
428 + any liability that these contractual assumptions directly impose on
429 + those licensors and authors.
431 + All other non-permissive additional terms are considered "further
432 +restrictions" within the meaning of section 10. If the Program as you
433 +received it, or any part of it, contains a notice stating that it is
434 +governed by this License along with a term that is a further
435 +restriction, you may remove that term. If a license document contains
436 +a further restriction but permits relicensing or conveying under this
437 +License, you may add to a covered work material governed by the terms
438 +of that license document, provided that the further restriction does
439 +not survive such relicensing or conveying.
441 + If you add terms to a covered work in accord with this section, you
442 +must place, in the relevant source files, a statement of the
443 +additional terms that apply to those files, or a notice indicating
444 +where to find the applicable terms.
446 + Additional terms, permissive or non-permissive, may be stated in the
447 +form of a separately written license, or stated as exceptions;
448 +the above requirements apply either way.
452 + You may not propagate or modify a covered work except as expressly
453 +provided under this License. Any attempt otherwise to propagate or
454 +modify it is void, and will automatically terminate your rights under
455 +this License (including any patent licenses granted under the third
456 +paragraph of section 11).
458 + However, if you cease all violation of this License, then your
459 +license from a particular copyright holder is reinstated (a)
460 +provisionally, unless and until the copyright holder explicitly and
461 +finally terminates your license, and (b) permanently, if the copyright
462 +holder fails to notify you of the violation by some reasonable means
463 +prior to 60 days after the cessation.
465 + Moreover, your license from a particular copyright holder is
466 +reinstated permanently if the copyright holder notifies you of the
467 +violation by some reasonable means, this is the first time you have
468 +received notice of violation of this License (for any work) from that
469 +copyright holder, and you cure the violation prior to 30 days after
470 +your receipt of the notice.
472 + Termination of your rights under this section does not terminate the
473 +licenses of parties who have received copies or rights from you under
474 +this License. If your rights have been terminated and not permanently
475 +reinstated, you do not qualify to receive new licenses for the same
476 +material under section 10.
478 + 9. Acceptance Not Required for Having Copies.
480 + You are not required to accept this License in order to receive or
481 +run a copy of the Program. Ancillary propagation of a covered work
482 +occurring solely as a consequence of using peer-to-peer transmission
483 +to receive a copy likewise does not require acceptance. However,
484 +nothing other than this License grants you permission to propagate or
485 +modify any covered work. These actions infringe copyright if you do
486 +not accept this License. Therefore, by modifying or propagating a
487 +covered work, you indicate your acceptance of this License to do so.
489 + 10. Automatic Licensing of Downstream Recipients.
491 + Each time you convey a covered work, the recipient automatically
492 +receives a license from the original licensors, to run, modify and
493 +propagate that work, subject to this License. You are not responsible
494 +for enforcing compliance by third parties with this License.
496 + An "entity transaction" is a transaction transferring control of an
497 +organization, or substantially all assets of one, or subdividing an
498 +organization, or merging organizations. If propagation of a covered
499 +work results from an entity transaction, each party to that
500 +transaction who receives a copy of the work also receives whatever
501 +licenses to the work the party's predecessor in interest had or could
502 +give under the previous paragraph, plus a right to possession of the
503 +Corresponding Source of the work from the predecessor in interest, if
504 +the predecessor has it or can get it with reasonable efforts.
506 + You may not impose any further restrictions on the exercise of the
507 +rights granted or affirmed under this License. For example, you may
508 +not impose a license fee, royalty, or other charge for exercise of
509 +rights granted under this License, and you may not initiate litigation
510 +(including a cross-claim or counterclaim in a lawsuit) alleging that
511 +any patent claim is infringed by making, using, selling, offering for
512 +sale, or importing the Program or any portion of it.
516 + A "contributor" is a copyright holder who authorizes use under this
517 +License of the Program or a work on which the Program is based. The
518 +work thus licensed is called the contributor's "contributor version".
520 + A contributor's "essential patent claims" are all patent claims
521 +owned or controlled by the contributor, whether already acquired or
522 +hereafter acquired, that would be infringed by some manner, permitted
523 +by this License, of making, using, or selling its contributor version,
524 +but do not include claims that would be infringed only as a
525 +consequence of further modification of the contributor version. For
526 +purposes of this definition, "control" includes the right to grant
527 +patent sublicenses in a manner consistent with the requirements of
530 + Each contributor grants you a non-exclusive, worldwide, royalty-free
531 +patent license under the contributor's essential patent claims, to
532 +make, use, sell, offer for sale, import and otherwise run, modify and
533 +propagate the contents of its contributor version.
535 + In the following three paragraphs, a "patent license" is any express
536 +agreement or commitment, however denominated, not to enforce a patent
537 +(such as an express permission to practice a patent or covenant not to
538 +sue for patent infringement). To "grant" such a patent license to a
539 +party means to make such an agreement or commitment not to enforce a
540 +patent against the party.
542 + If you convey a covered work, knowingly relying on a patent license,
543 +and the Corresponding Source of the work is not available for anyone
544 +to copy, free of charge and under the terms of this License, through a
545 +publicly available network server or other readily accessible means,
546 +then you must either (1) cause the Corresponding Source to be so
547 +available, or (2) arrange to deprive yourself of the benefit of the
548 +patent license for this particular work, or (3) arrange, in a manner
549 +consistent with the requirements of this License, to extend the patent
550 +license to downstream recipients. "Knowingly relying" means you have
551 +actual knowledge that, but for the patent license, your conveying the
552 +covered work in a country, or your recipient's use of the covered work
553 +in a country, would infringe one or more identifiable patents in that
554 +country that you have reason to believe are valid.
556 + If, pursuant to or in connection with a single transaction or
557 +arrangement, you convey, or propagate by procuring conveyance of, a
558 +covered work, and grant a patent license to some of the parties
559 +receiving the covered work authorizing them to use, propagate, modify
560 +or convey a specific copy of the covered work, then the patent license
561 +you grant is automatically extended to all recipients of the covered
562 +work and works based on it.
564 + A patent license is "discriminatory" if it does not include within
565 +the scope of its coverage, prohibits the exercise of, or is
566 +conditioned on the non-exercise of one or more of the rights that are
567 +specifically granted under this License. You may not convey a covered
568 +work if you are a party to an arrangement with a third party that is
569 +in the business of distributing software, under which you make payment
570 +to the third party based on the extent of your activity of conveying
571 +the work, and under which the third party grants, to any of the
572 +parties who would receive the covered work from you, a discriminatory
573 +patent license (a) in connection with copies of the covered work
574 +conveyed by you (or copies made from those copies), or (b) primarily
575 +for and in connection with specific products or compilations that
576 +contain the covered work, unless you entered into that arrangement,
577 +or that patent license was granted, prior to 28 March 2007.
579 + Nothing in this License shall be construed as excluding or limiting
580 +any implied license or other defenses to infringement that may
581 +otherwise be available to you under applicable patent law.
583 + 12. No Surrender of Others' Freedom.
585 + If conditions are imposed on you (whether by court order, agreement or
586 +otherwise) that contradict the conditions of this License, they do not
587 +excuse you from the conditions of this License. If you cannot convey a
588 +covered work so as to satisfy simultaneously your obligations under this
589 +License and any other pertinent obligations, then as a consequence you may
590 +not convey it at all. For example, if you agree to terms that obligate you
591 +to collect a royalty for further conveying from those to whom you convey
592 +the Program, the only way you could satisfy both those terms and this
593 +License would be to refrain entirely from conveying the Program.
595 + 13. Use with the GNU Affero General Public License.
597 + Notwithstanding any other provision of this License, you have
598 +permission to link or combine any covered work with a work licensed
599 +under version 3 of the GNU Affero General Public License into a single
600 +combined work, and to convey the resulting work. The terms of this
601 +License will continue to apply to the part which is the covered work,
602 +but the special requirements of the GNU Affero General Public License,
603 +section 13, concerning interaction through a network will apply to the
604 +combination as such.
606 + 14. Revised Versions of this License.
608 + The Free Software Foundation may publish revised and/or new versions of
609 +the GNU General Public License from time to time. Such new versions will
610 +be similar in spirit to the present version, but may differ in detail to
611 +address new problems or concerns.
613 + Each version is given a distinguishing version number. If the
614 +Program specifies that a certain numbered version of the GNU General
615 +Public License "or any later version" applies to it, you have the
616 +option of following the terms and conditions either of that numbered
617 +version or of any later version published by the Free Software
618 +Foundation. If the Program does not specify a version number of the
619 +GNU General Public License, you may choose any version ever published
620 +by the Free Software Foundation.
622 + If the Program specifies that a proxy can decide which future
623 +versions of the GNU General Public License can be used, that proxy's
624 +public statement of acceptance of a version permanently authorizes you
625 +to choose that version for the Program.
627 + Later license versions may give you additional or different
628 +permissions. However, no additional obligations are imposed on any
629 +author or copyright holder as a result of your choosing to follow a
632 + 15. Disclaimer of Warranty.
634 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
635 +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
636 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
637 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
638 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
639 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
640 +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
641 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
643 + 16. Limitation of Liability.
645 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
646 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
647 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
648 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
649 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
650 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
651 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
652 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
655 + 17. Interpretation of Sections 15 and 16.
657 + If the disclaimer of warranty and limitation of liability provided
658 +above cannot be given local legal effect according to their terms,
659 +reviewing courts shall apply local law that most closely approximates
660 +an absolute waiver of all civil liability in connection with the
661 +Program, unless a warranty or assumption of liability accompanies a
662 +copy of the Program in return for a fee.
664 + END OF TERMS AND CONDITIONS
666 + How to Apply These Terms to Your New Programs
668 + If you develop a new program, and you want it to be of the greatest
669 +possible use to the public, the best way to achieve this is to make it
670 +free software which everyone can redistribute and change under these terms.
672 + To do so, attach the following notices to the program. It is safest
673 +to attach them to the start of each source file to most effectively
674 +state the exclusion of warranty; and each file should have at least
675 +the "copyright" line and a pointer to where the full notice is found.
677 + <one line to give the program's name and a brief idea of what it does.>
678 + Copyright (C) <year> <name of author>
680 + This program is free software: you can redistribute it and/or modify
681 + it under the terms of the GNU General Public License as published by
682 + the Free Software Foundation, either version 3 of the License, or
683 + (at your option) any later version.
685 + This program is distributed in the hope that it will be useful,
686 + but WITHOUT ANY WARRANTY; without even the implied warranty of
687 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
688 + GNU General Public License for more details.
690 + You should have received a copy of the GNU General Public License
691 + along with this program. If not, see <http://www.gnu.org/licenses/>.
693 +Also add information on how to contact you by electronic and paper mail.
695 + If the program does terminal interaction, make it output a short
696 +notice like this when it starts in an interactive mode:
698 + <program> Copyright (C) <year> <name of author>
699 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
700 + This is free software, and you are welcome to redistribute it
701 + under certain conditions; type `show c' for details.
703 +The hypothetical commands `show w' and `show c' should show the appropriate
704 +parts of the General Public License. Of course, your program's commands
705 +might be different; for a GUI interface, you would use an "about box".
707 + You should also get your employer (if you work as a programmer) or school,
708 +if any, to sign a "copyright disclaimer" for the program, if necessary.
709 +For more information on this, and how to apply and follow the GNU GPL, see
710 +<http://www.gnu.org/licenses/>.
712 + The GNU General Public License does not permit incorporating your program
713 +into proprietary programs. If your program is a subroutine library, you
714 +may consider it more useful to permit linking proprietary applications with
715 +the library. If this is what you want to do, use the GNU Lesser General
716 +Public License instead of this License. But first, please read
717 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
718 diff --git a/MANIFEST b/MANIFEST
719 deleted file mode 100644
720 index 24ca115..0000000
726 -fireinfo/__init__.py
729 -fireinfo/hypervisor.py
733 diff --git a/Makefile.am b/Makefile.am
735 index 0000000..260f14f
739 +###############################################################################
741 +# Pakfire - The IPFire package management system #
742 +# Copyright (C) 2013 Pakfire development team #
744 +# This program is free software: you can redistribute it and/or modify #
745 +# it under the terms of the GNU General Public License as published by #
746 +# the Free Software Foundation, either version 3 of the License, or #
747 +# (at your option) any later version. #
749 +# This program is distributed in the hope that it will be useful, #
750 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
751 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
752 +# GNU General Public License for more details. #
754 +# You should have received a copy of the GNU General Public License #
755 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
757 +###############################################################################
759 +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
760 +AM_MAKEFLAGS = --no-print-directory
761 +AUTOMAKE_OPTIONS = color-tests
763 +# remove target it the command fails
766 +# keep itermediate files
774 + -include $(top_builddir)/config.h \
775 + -I $(top_srcdir)/include \
778 +AM_CFLAGS = $(OUR_CFLAGS)
779 +AM_LDFLAGS = $(OUR_LDFLAGS)
781 +pkgpyexec_LTLIBRARIES =
783 +# ------------------------------------------------------------------------------
788 +# ------------------------------------------------------------------------------
790 +dist_bin_SCRIPTS = \
793 +# ------------------------------------------------------------------------------
796 + src/fireinfo/__init__.py \
797 + src/fireinfo/bios.py \
798 + src/fireinfo/cpu.py \
799 + src/fireinfo/device.py \
800 + src/fireinfo/hypervisor.py \
801 + src/fireinfo/network.py \
802 + src/fireinfo/system.py
804 +fireinfodir = $(pythondir)/fireinfo
806 +# ------------------------------------------------------------------------------
808 +pkgpyexec_LTLIBRARIES += \
811 +_fireinfo_la_SOURCES = \
812 + src/_fireinfo/fireinfo.c
814 +_fireinfo_la_CFLAGS = \
816 + $(PYTHON_DEVEL_CFLAGS)
818 +_fireinfo_la_LDFLAGS = \
824 +_fireinfo_la_LIBADD = \
825 + $(PYTHON_DEVEL_LIBS)
826 diff --git a/autogen.sh b/autogen.sh
828 index 0000000..c08fadf
834 +autoreconf --force --install --symlink
835 diff --git a/configure.ac b/configure.ac
837 index 0000000..4d5efef
841 +###############################################################################
843 +# Pakfire - The IPFire package management system #
844 +# Copyright (C) 2013 Pakfire development team #
846 +# This program is free software: you can redistribute it and/or modify #
847 +# it under the terms of the GNU General Public License as published by #
848 +# the Free Software Foundation, either version 3 of the License, or #
849 +# (at your option) any later version. #
851 +# This program is distributed in the hope that it will be useful, #
852 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
853 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
854 +# GNU General Public License for more details. #
856 +# You should have received a copy of the GNU General Public License #
857 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
859 +###############################################################################
867 + [http://git.ipfire.org/?p=oddments/fireinfo.git;a=summary])
869 +AC_CONFIG_MACRO_DIR([m4])
870 +AC_CONFIG_HEADERS([config.h])
871 +AC_CONFIG_AUX_DIR([build-aux])
873 +AC_USE_SYSTEM_EXTENSIONS
875 +AC_PREFIX_DEFAULT([/usr])
886 +AM_SILENT_RULES([yes])
888 +LT_INIT([disable-static])
892 +# This makes sure pkg.m4 is available.
893 +m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
899 +AC_PROG_GCC_TRADITIONAL
902 +CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
908 + "-Wformat=2 -Wformat-security -Wformat-nonliteral" \
909 + -Wno-unused-parameter \
910 + -Wno-unused-result \
911 + -fno-strict-aliasing \
912 + -ffunction-sections \
914 + -fstack-protector-all \
915 + --param=ssp-buffer-size=4])
916 +AC_SUBST([OUR_CFLAGS], $with_cflags)
918 +AS_CASE([$CFLAGS], [*-O[[12345g\ ]]*],
919 + [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
920 + -Wp,-D_FORTIFY_SOURCE=2])],
921 + [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])])
922 +AC_SUBST([OUR_CPPFLAGS], $with_cppflags)
924 +CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
926 + -Wl,--no-undefined \
927 + -Wl,--gc-sections \
930 +AC_SUBST([OUR_LDFLAGS], $with_ldflags)
933 +AM_PATH_PYTHON([2.7])
934 +PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}])
938 + src/fireinfo/__init__.py
943 + $PACKAGE_NAME $VERSION
945 + CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
946 + CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
947 + LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
948 + PYTHON_CFLAGS: ${PYTHON_DEVEL_CFLAGS}
949 + PYTHON_LIBS: ${PYTHON_DEVEL_LIBS}
951 diff --git a/fireinfo/__init__.py b/fireinfo/__init__.py
952 deleted file mode 100644
953 index 86fcc66..0000000
954 --- a/fireinfo/__init__.py
958 -###############################################################################
961 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
963 -# This program is free software: you can redistribute it and/or modify #
964 -# it under the terms of the GNU General Public License as published by #
965 -# the Free Software Foundation, either version 3 of the License, or #
966 -# (at your option) any later version. #
968 -# This program is distributed in the hope that it will be useful, #
969 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
970 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
971 -# GNU General Public License for more details. #
973 -# You should have received a copy of the GNU General Public License #
974 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
976 -###############################################################################
978 -__version__ = "2.1.7"
980 -from system import System
981 diff --git a/fireinfo/cpu.py b/fireinfo/cpu.py
982 deleted file mode 100644
983 index 32d885d..0000000
984 --- a/fireinfo/cpu.py
988 -###############################################################################
991 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
993 -# This program is free software: you can redistribute it and/or modify #
994 -# it under the terms of the GNU General Public License as published by #
995 -# the Free Software Foundation, either version 3 of the License, or #
996 -# (at your option) any later version. #
998 -# This program is distributed in the hope that it will be useful, #
999 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1000 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1001 -# GNU General Public License for more details. #
1003 -# You should have received a copy of the GNU General Public License #
1004 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1006 -###############################################################################
1012 -PROC_CPUINFO = "/proc/cpuinfo"
1016 - A class that represents the first CPU in a system.
1018 - We get all information form the first CPU (or core) and assume that
1019 - all other ones are equal.
1024 - def __init__(self):
1026 - Initialize this class by reading all data from /proc/cpuinfo.
1028 - self.__cpuinfo = self.read_cpuinfo()
1032 - return system.System()
1035 - def read_cpuinfo():
1037 - Read information from PROC_CPUINFO and store
1038 - it into a dictionary cpuinfo.
1042 - f = open(PROC_CPUINFO)
1044 - line = f.readline()
1050 - key, val = line.split(":", 1)
1051 - except ValueError:
1052 - # We got a line without key, pass that.
1055 - key = key.strip().replace(" ", "_")
1058 - cpuinfo[key] = val
1065 - def bogomips(self):
1067 - Return the bogomips of this CPU.
1070 - bogomips = self.__cpuinfo["bogomips"]
1072 - bogomips = self.__cpuinfo["BogoMIPS"]
1074 - return float(bogomips)
1079 - Return the model id of this CPU.
1082 - model = int(self.__cpuinfo["model"])
1089 - def model_string(self):
1091 - Return the model string of this CPU.
1094 - return self.__cpuinfo["model_name"]
1096 - return self.__cpuinfo["Processor"]
1101 - Return the vendor string of this CPU.
1104 - vendor = self.__cpuinfo["vendor_id"]
1106 - if self.system.arch.startswith("arm"):
1114 - def stepping(self):
1116 - Return the stepping id of this CPU.
1119 - stepping = int(self.__cpuinfo["stepping"])
1128 - Return all flags of this CPU.
1131 - flags = self.__cpuinfo["flags"]
1133 - flags = self.__cpuinfo["Features"]
1135 - return flags.split()
1140 - Return the speed (in MHz) of this CPU.
1143 - speed = float(self.__cpuinfo["cpu_MHz"])
1152 - Return the family id of this CPU.
1155 - family = int(self.__cpuinfo["cpu_family"])
1164 - Count number of CPUs (cores).
1166 - return os.sysconf("SC_NPROCESSORS_ONLN")
1169 -if __name__ == "__main__":
1172 - print "Vendor:", c.vendor
1173 - print "Model:", c.model
1174 - print "Stepping:", c.stepping
1175 - print "Flags:", c.flags
1176 - print "Bogomips:", c.bogomips
1177 - print "Speed:", c.speed
1178 - print "Family:", c.family
1179 - print "Count:", c.count
1180 - print "Model string:", c.model_string
1181 diff --git a/fireinfo/device.py b/fireinfo/device.py
1182 deleted file mode 100644
1183 index 01338b2..0000000
1184 --- a/fireinfo/device.py
1188 -###############################################################################
1191 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1193 -# This program is free software: you can redistribute it and/or modify #
1194 -# it under the terms of the GNU General Public License as published by #
1195 -# the Free Software Foundation, either version 3 of the License, or #
1196 -# (at your option) any later version. #
1198 -# This program is distributed in the hope that it will be useful, #
1199 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1200 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1201 -# GNU General Public License for more details. #
1203 -# You should have received a copy of the GNU General Public License #
1204 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1206 -###############################################################################
1210 -class Device(object):
1212 - This is an abstract class that represents all devices in the system.
1213 - Every single device has its own instance of this class.
1216 - def __init__(self, path):
1218 - Collect all information about the device by reading the
1219 - "uevent" file and parsing it.
1222 - # Save the path in /sys to the device.
1225 - # Datastructure to store information we read.
1228 - # Open the uevent file and parse all lines.
1229 - with open(os.path.join(path, "uevent")) as f:
1230 - for line in f.readlines():
1231 - key, val = line.split("=")
1232 - self._uevent[key] = val.rstrip().lower()
1237 - Get the driver/kernel module that device is driven by or return None.
1239 - return self._uevent.get("DRIVER", None)
1242 -class PCIDevice(Device):
1244 - A class that represents all PCI (and PCIe) devices in a system.
1252 - Return the PCI model id of this device.
1254 - return self._uevent['PCI_ID'].split(":")[1]
1259 - Return the PCI vendor id of this device.
1261 - return self._uevent['PCI_ID'].split(":")[0]
1264 - def deviceclass(self):
1266 - Return the PCI device class of this device.
1268 - return self._uevent['PCI_CLASS']
1271 - def sub_vendor(self):
1273 - Return the PCI vendor sub id of this device.
1275 - return self._uevent["PCI_SUBSYS_ID"].split(":")[0]
1278 - def sub_model(self):
1280 - Return the PCI model sub id of this device.
1282 - return self._uevent["PCI_SUBSYS_ID"].split(":")[1]
1285 -class USBDevice(Device):
1287 - A class that represents all USB devices in a system.
1294 - A function to pad ids that have no leading zeroes.
1303 - Return the USB vendor id of this device.
1305 - return self.pad(self._uevent['PRODUCT'].split("/")[0])
1310 - Return the USB model id of this device.
1312 - return self.pad(self._uevent['PRODUCT'].split("/")[1])
1315 - def deviceclass(self):
1317 - Return the USB device class of this device.
1319 - return self._uevent.get("INTERFACE", None)
1320 diff --git a/fireinfo/hypervisor.py b/fireinfo/hypervisor.py
1321 deleted file mode 100644
1322 index 9a3fb09..0000000
1323 --- a/fireinfo/hypervisor.py
1327 -###############################################################################
1330 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1332 -# This program is free software: you can redistribute it and/or modify #
1333 -# it under the terms of the GNU General Public License as published by #
1334 -# the Free Software Foundation, either version 3 of the License, or #
1335 -# (at your option) any later version. #
1337 -# This program is distributed in the hope that it will be useful, #
1338 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1339 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1340 -# GNU General Public License for more details. #
1342 -# You should have received a copy of the GNU General Public License #
1343 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1345 -###############################################################################
1350 -class Hypervisor(object):
1351 - def __init__(self):
1352 - self.__info = _fireinfo.get_hypervisor()
1357 - Return the current instance of the System class.
1359 - We need to do that as a property because otherwise
1360 - we get a recursion.
1362 - return system.System()
1367 - Returns the name of the hypervisor vendor.
1369 - if not self.virtual:
1372 - # Some of the hypervisors can be detected in a right way.
1373 - # We can return them at this place.
1374 - if self.__info["hypervisor"] in ("Xen", "VMWare", "KVM"):
1375 - return self.__info["hypervisor"]
1377 - # Citrix Xen says it is Microsoft Hv.
1378 - if self.__info["hypervisor"] == "Microsoft" and \
1379 - self.system.bios_vendor == "Xen":
1382 - if not self.__info["hypervisor"]:
1383 - # On VMWare systems, the bios vendor string contains "VMWare".
1384 - if self.__is_hypervisor_vmware():
1387 - # VirtualBox got "innotek GmbH" as bios vendor.
1388 - elif self.__is_hypervisor_virtualbox():
1389 - return "VirtualBox"
1392 - elif self.__is_hypervisor_qemu():
1395 - # Check for Microsoft.
1396 - elif self.__is_hypervisor_microsoft():
1397 - return "Microsoft"
1404 - Returns if the host is running in full virt mode or
1405 - if it is running in a paravirtualized environment.
1407 - if not self.virtual:
1410 - if self.__info["virtype"]:
1411 - return self.__info["virtype"]
1413 - if self.vendor in ("Qemu", "KVM", "VirtualBox", "VMWare"):
1419 - def virtual(self):
1421 - Returns true if the host is running in a virtual environment.
1424 - return _fireinfo.is_virtualized() or \
1425 - "hypervisor" in self.system.cpu.flags or \
1426 - self.__is_hypervisor_virtualbox() or \
1427 - self.__is_hypervisor_vmware() or \
1428 - self.__is_hypervisor_qemu() or \
1429 - self.__is_hypervisor_microsoft()
1431 - def __is_hypervisor_virtualbox(self):
1433 - Check for virtualbox hypervisor by comparing the bios vendor string
1434 - to "innotek GmbH".
1436 - return self.system.bios_vendor == "innotek GmbH"
1438 - def __is_hypervisor_vmware(self):
1440 - Check for the VMWare hypervisor by the VMWare Hypervisor port check.
1442 - http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
1444 - if self.system.vendor:
1445 - return self.system.vendor.startswith("VMware")
1447 - # XXX We should use _fireinfo.vmware_hypervisor_port_check() here, too.
1448 - # This currently segfaults (and I have no clue why) on VMware player.
1450 - def __is_hypervisor_qemu(self):
1452 - Check for old qemu emulator.
1454 - if self.system.bios_vendor:
1455 - return self.system.bios_vendor == "Bochs"
1459 - def __is_hypervisor_microsoft(self):
1461 - Check for Microsoft hypervisor.
1463 - if self.system.vendor:
1464 - return "Microsoft" in self.system.vendor
1469 -if __name__ == "__main__":
1472 - print "Vendor:", h.vendor
1473 - print "Type:", h.type
1474 - print "Virtual:", h.virtual
1475 diff --git a/fireinfo/network.py b/fireinfo/network.py
1476 deleted file mode 100644
1477 index 063e9ec..0000000
1478 --- a/fireinfo/network.py
1482 -###############################################################################
1485 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1487 -# This program is free software: you can redistribute it and/or modify #
1488 -# it under the terms of the GNU General Public License as published by #
1489 -# the Free Software Foundation, either version 3 of the License, or #
1490 -# (at your option) any later version. #
1492 -# This program is distributed in the hope that it will be useful, #
1493 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1494 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1495 -# GNU General Public License for more details. #
1497 -# You should have received a copy of the GNU General Public License #
1498 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1500 -###############################################################################
1504 -SYS_CLASS_NET = "/sys/class/net"
1506 -class Network(object):
1507 - def __init__(self):
1508 - self._devices = os.listdir(SYS_CLASS_NET)
1510 - def has_green(self):
1511 - return "green0" in self._devices
1513 - def has_red(self):
1514 - for i in ("red0", "ppp0"):
1515 - if i in self._devices:
1520 - def has_blue(self):
1521 - return "blue0" in self._devices
1523 - def has_orange(self):
1524 - return "orange0" in self._devices
1527 -if __name__ == "__main__":
1530 - print "has_green", n.has_green()
1531 - print "has_red", n.has_red()
1532 - print "has_blue", n.has_blue()
1533 - print "has_orange", n.has_orange()
1534 diff --git a/fireinfo/system.py b/fireinfo/system.py
1535 deleted file mode 100644
1536 index 6f02312..0000000
1537 --- a/fireinfo/system.py
1541 -###############################################################################
1544 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1546 -# This program is free software: you can redistribute it and/or modify #
1547 -# it under the terms of the GNU General Public License as published by #
1548 -# the Free Software Foundation, either version 3 of the License, or #
1549 -# (at your option) any later version. #
1551 -# This program is distributed in the hope that it will be useful, #
1552 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1553 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1554 -# GNU General Public License for more details. #
1556 -# You should have received a copy of the GNU General Public License #
1557 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1559 -###############################################################################
1573 -PROFILE_VERSION = 0
1575 -SYS_CLASS_DMI = "/sys/class/dmi/id"
1576 -SECRET_ID_FILE = "/etc/fireinfo-id"
1578 -INVALID_ID_STRINGS = (
1579 - "OEM", "O.E.M.", "o.e.m.",
1581 - "12345", "54321", "202020",
1582 - "Chassis", "chassis",
1585 - "01010101-0101-0101-0101-010101010101",
1586 - "00020003-0004-0005-0006-000700080009",
1587 - "03000200-0400-0500-0006-000700080009",
1588 - "0000000", "00000000",
1591 -class Singleton(type):
1592 - def __init__(cls, name, bases, dict):
1593 - super(Singleton, cls).__init__(name, bases, dict)
1594 - cls.instance = None
1596 - def __call__(cls, *args, **kw):
1597 - if cls.instance is None:
1598 - cls.instance = super(Singleton, cls).__call__(*args, **kw)
1600 - return cls.instance
1603 -def read_from_file(filename):
1605 - Read all data from filename.
1607 - if not os.path.exists(filename):
1611 - with open(filename) as f:
1612 - return f.read().strip()
1616 -class System(object):
1617 - __metaclass__ = Singleton
1619 - def __init__(self):
1620 - # find all devices
1623 - self.cpu = cpu.CPU()
1624 - self.hypervisor = hypervisor.Hypervisor()
1626 - # Read /proc/cpuinfo for vendor information.
1627 - self.__cpuinfo = self.cpu.read_cpuinfo()
1629 - def profile(self):
1632 - # System information
1633 - "model" : self.model,
1634 - "vendor" : self.vendor,
1636 - # Indicator if the system is running in a
1637 - # virtual environment.
1638 - "virtual" : self.virtual,
1641 - "language" : self.language,
1643 - # Release information
1644 - "release" : self.release,
1645 - "kernel_release" : self.kernel_release,
1647 - "memory" : self.memory,
1648 - "root_size" : self.root_size,
1652 - for device in self.devices:
1654 - "subsystem" : device.subsystem.lower(),
1655 - "vendor" : device.vendor.lower(),
1656 - "model" : device.model.lower(),
1657 - "deviceclass" : device.deviceclass,
1658 - "driver" : device.driver,
1661 - # PCI devices provide subsystem information, USB don't.
1662 - if d["subsystem"] == "pci":
1663 - d["sub_model"] = device.sub_model
1664 - d["sub_vendor"] = device.sub_vendor
1666 - p["devices"].append(d)
1669 - "arch" : self.arch,
1670 - "vendor" : self.cpu.vendor,
1671 - "model" : self.cpu.model,
1672 - "model_string" : self.cpu.model_string,
1673 - "stepping" : self.cpu.stepping,
1674 - "flags" : self.cpu.flags,
1675 - "bogomips" : self.cpu.bogomips,
1676 - "speed" : self.cpu.speed,
1677 - "family" : self.cpu.family,
1678 - "count" : self.cpu.count
1682 - "green" : self.network.has_green(),
1683 - "blue" : self.network.has_blue(),
1684 - "orange" : self.network.has_orange(),
1685 - "red" : self.network.has_red(),
1688 - # Only append hypervisor information if we are virtualized.
1690 - p["hypervisor"] = {
1691 - "type" : self.hypervisor.type,
1692 - "vendor" : self.hypervisor.vendor,
1697 - "profile_version" : PROFILE_VERSION,
1699 - # Identification and authorization codes
1700 - "public_id" : self.public_id,
1701 - "private_id" : self.private_id,
1703 - # Actual profile data
1710 - return os.uname()[4]
1713 - def public_id(self):
1715 - This returns a globally (hopefully) ID to identify the host
1716 - later (by request) in the database.
1718 - public_id = self.secret_id
1722 - return hashlib.sha1(public_id).hexdigest()
1725 - def private_id(self):
1727 - The private ID is built out of the _unique_id and used to
1728 - permit a host to do changes on the database.
1730 - No one could ever guess this without access to the host.
1733 - for i in reversed(self.secret_id):
1736 - if not private_id:
1739 - return hashlib.sha1(private_id).hexdigest()
1742 - def secret_id(self):
1744 - Read a "secret" ID from a file if available
1745 - or calculate it from the hardware.
1747 - if os.path.exists(SECRET_ID_FILE):
1748 - return read_from_file(SECRET_ID_FILE)
1750 - return hashlib.sha1(self._unique_id).hexdigest()
1753 - def _unique_id(self):
1755 - This is a helper ID which is generated out of some hardware information
1756 - that is considered to be constant over a PC's lifetime.
1758 - None of the data here is ever sent to the server.
1762 - # Virtual machines (for example) and some boards have a UUID
1763 - # which is globally unique.
1764 - for file in ("product_uuid", "product_serial", "chassis_serial"):
1765 - id = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1768 - # Sort out all bogous or invalid strings from the list.
1774 - for i in INVALID_ID_STRINGS:
1784 - # Use serial number from root disk (if available) and if
1785 - # no other ID was found, yet.
1787 - root_disk_serial = self.root_disk_serial
1788 - if root_disk_serial and not root_disk_serial.startswith("QM000"):
1789 - ids.append(root_disk_serial)
1791 - # As last resort, we use the UUID from pakfire.
1793 - id = read_from_file("/opt/pakfire/db/uuid")
1796 - return "#".join(ids)
1799 - def language(self):
1801 - Return the language code of IPFire or "unknown" if we cannot get it.
1803 - # Return "unknown" if settings file does not exist.
1804 - filename = "/var/ipfire/main/settings"
1805 - if not os.path.exists(filename):
1808 - with open(filename, "r") as f:
1809 - for line in f.readlines():
1810 - key, val = line.split("=", 1)
1811 - if key == "LANGUAGE":
1812 - return val.strip()
1815 - def release(self):
1817 - Return the system release string.
1819 - return read_from_file("/etc/system-release") or "unknown"
1822 - def bios_vendor(self):
1824 - Return the bios vendor name.
1826 - return read_from_file("/sys/class/dmi/id/bios_vendor")
1828 - def vendor_model_tuple(self):
1830 - s = self.__cpuinfo["Hardware"]
1832 - return (None, None)
1834 - if s.startswith("ARM-Versatile"):
1838 - v, m = s.split(" ", 1)
1839 - except ValueError:
1840 - if s.startswith("BCM"):
1852 - Return the vendor string of this system (if any).
1855 - for file in ("sys_vendor", "board_vendor", "chassis_vendor",):
1856 - ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1861 - v, m = self.vendor_model_tuple()
1869 - Return the model string of this system (if any).
1872 - for file in ("product_name", "board_model", "chassis_model",):
1873 - ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1878 - v, m = self.vendor_model_tuple()
1886 - Return the amount of memory in kilobytes.
1888 - with open("/proc/meminfo", "r") as f:
1889 - firstline = f.readline().strip()
1890 - return int(firstline.split()[1])
1893 - def kernel_release(self):
1895 - Return the kernel release string.
1897 - return os.uname()[2]
1900 - def root_disk(self):
1902 - Return the dev node of the root disk.
1904 - with open("/etc/mtab", "r") as f:
1905 - dev, mountpoint, rest = f.readline().split(" ", 2)
1906 - if mountpoint == "/":
1910 - # Handle raids and MMC cards like (mmcblk0p3).
1911 - if dev[-2] == "p":
1914 - # Otherwise cut off all digits at end of string
1915 - while dev[-1] in string.digits:
1921 - def root_size(self):
1923 - Return the size of the root disk in kilobytes.
1925 - path = "/sys/block/%s/size" % self.root_disk
1926 - if not os.path.exists(path):
1929 - with open(path, "r") as f:
1930 - return int(f.readline()) * 512 / 1024
1933 - def root_disk_serial(self):
1935 - Return the serial number of the root disk (if any).
1937 - serial = _fireinfo.get_harddisk_serial("/dev/%s" % self.root_disk)
1940 - # Strip all spaces
1941 - return serial.strip()
1945 - Scan for all devices (PCI/USB) in the system and append them
1951 - ("/sys/bus/pci/devices", device.PCIDevice),
1952 - ("/sys/bus/usb/devices", device.USBDevice)
1954 - for path, cls in toscan:
1955 - if not os.path.exists(path):
1958 - dirlist = os.listdir(path)
1959 - for dir in dirlist:
1960 - self.devices.append(cls(os.path.join(path, dir)))
1963 - def virtual(self):
1965 - Say if the host is running in a virtual environment.
1967 - return self.hypervisor.virtual
1970 - def network(self):
1972 - Reference to the network class.
1974 - return network.Network()
1977 -if __name__ == "__main__":
1982 - print s.bios_vendor
1987 - print "------------\n", s.devices, "\n------------\n"
1988 - print json.dumps(s.profile(), sort_keys=True, indent=4)
1989 diff --git a/m4/.gitignore b/m4/.gitignore
1990 new file mode 100644
1991 index 0000000..38066dd
2000 diff --git a/m4/attributes.m4 b/m4/attributes.m4
2001 new file mode 100644
2002 index 0000000..7e080da
2004 +++ b/m4/attributes.m4
2006 +dnl Macros to check the presence of generic (non-typed) symbols.
2007 +dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
2008 +dnl Copyright (c) 2006-2008 xine project
2009 +dnl Copyright (c) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
2011 +dnl This program is free software; you can redistribute it and/or modify
2012 +dnl it under the terms of the GNU General Public License as published by
2013 +dnl the Free Software Foundation; either version 2, or (at your option)
2014 +dnl any later version.
2016 +dnl This program is distributed in the hope that it will be useful,
2017 +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
2018 +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2019 +dnl GNU General Public License for more details.
2021 +dnl You should have received a copy of the GNU General Public License
2022 +dnl along with this program; if not, write to the Free Software
2023 +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2024 +dnl 02110-1301, USA.
2026 +dnl As a special exception, the copyright owners of the
2027 +dnl macro gives unlimited permission to copy, distribute and modify the
2028 +dnl configure scripts that are the output of Autoconf when processing the
2029 +dnl Macro. You need not follow the terms of the GNU General Public
2030 +dnl License when using or distributing such scripts, even though portions
2031 +dnl of the text of the Macro appear in them. The GNU General Public
2032 +dnl License (GPL) does govern all other use of the material that
2033 +dnl constitutes the Autoconf Macro.
2035 +dnl This special exception to the GPL applies to versions of the
2036 +dnl Autoconf Macro released by this project. When you make and
2037 +dnl distribute a modified version of the Autoconf Macro, you may extend
2038 +dnl this special exception to the GPL to apply to your modified version as
2041 +dnl Check if FLAG in ENV-VAR is supported by compiler and append it
2042 +dnl to WHERE-TO-APPEND variable
2043 +dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG])
2045 +AC_DEFUN([CC_CHECK_FLAG_APPEND], [
2046 + AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
2047 + AS_TR_SH([cc_cv_$2_$3]),
2048 + [eval "AS_TR_SH([cc_save_$2])='${$2}'"
2049 + eval "AS_TR_SH([$2])='-Werror $3'"
2050 + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
2051 + [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"],
2052 + [eval "AS_TR_SH([cc_cv_$2_$3])='no'"])
2053 + eval "AS_TR_SH([$2])='$cc_save_$2'"])
2055 + AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes],
2056 + [eval "$1='${$1} $3'"])
2059 +dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2])
2060 +AC_DEFUN([CC_CHECK_FLAGS_APPEND], [
2061 + for flag in $3; do
2062 + CC_CHECK_FLAG_APPEND($1, $2, $flag)
2066 +dnl Check if the flag is supported by linker (cacheable)
2067 +dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
2069 +AC_DEFUN([CC_CHECK_LDFLAGS], [
2070 + AC_CACHE_CHECK([if $CC supports $1 flag],
2071 + AS_TR_SH([cc_cv_ldflags_$1]),
2072 + [ac_save_LDFLAGS="$LDFLAGS"
2073 + LDFLAGS="$LDFLAGS $1"
2074 + AC_LINK_IFELSE([int main() { return 1; }],
2075 + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
2076 + [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
2077 + LDFLAGS="$ac_save_LDFLAGS"
2080 + AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
2084 +dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
2085 +dnl the current linker to avoid undefined references in a shared object.
2086 +AC_DEFUN([CC_NOUNDEFINED], [
2087 + dnl We check $host for which systems to enable this for.
2088 + AC_REQUIRE([AC_CANONICAL_HOST])
2091 + dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
2092 + dnl are requested, as different implementations are present; to avoid problems
2093 + dnl use -Wl,-z,defs only for those platform not behaving this way.
2094 + *-freebsd* | *-openbsd*) ;;
2096 + dnl First of all check for the --no-undefined variant of GNU ld. This allows
2097 + dnl for a much more readable commandline, so that people can understand what
2098 + dnl it does without going to look for what the heck -z defs does.
2099 + for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
2100 + CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
2106 + AC_SUBST([LDFLAGS_NOUNDEFINED])
2109 +dnl Check for a -Werror flag or equivalent. -Werror is the GCC
2110 +dnl and ICC flag that tells the compiler to treat all the warnings
2111 +dnl as fatal. We usually need this option to make sure that some
2112 +dnl constructs (like attributes) are not simply ignored.
2114 +dnl Other compilers don't support -Werror per se, but they support
2115 +dnl an equivalent flag:
2116 +dnl - Sun Studio compiler supports -errwarn=%all
2117 +AC_DEFUN([CC_CHECK_WERROR], [
2119 + [for $CC way to treat warnings as errors],
2121 + [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
2122 + [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
2126 +AC_DEFUN([CC_CHECK_ATTRIBUTE], [
2127 + AC_REQUIRE([CC_CHECK_WERROR])
2128 + AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
2129 + AS_TR_SH([cc_cv_attribute_$1]),
2130 + [ac_save_CFLAGS="$CFLAGS"
2131 + CFLAGS="$CFLAGS $cc_cv_werror"
2132 + AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
2133 + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
2134 + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
2135 + CFLAGS="$ac_save_CFLAGS"
2138 + AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
2140 + AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
2141 + [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
2147 +AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
2148 + CC_CHECK_ATTRIBUTE(
2150 + [void __attribute__((constructor)) ctor() { int a; }],
2154 +AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
2155 + CC_CHECK_ATTRIBUTE(
2156 + [format], [format(printf, n, n)],
2157 + [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
2161 +AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
2162 + CC_CHECK_ATTRIBUTE(
2163 + [format_arg], [format_arg(printf)],
2164 + [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
2168 +AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
2169 + CC_CHECK_ATTRIBUTE(
2170 + [visibility_$1], [visibility("$1")],
2171 + [void __attribute__((visibility("$1"))) $1_function() { }],
2175 +AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
2176 + CC_CHECK_ATTRIBUTE(
2177 + [nonnull], [nonnull()],
2178 + [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
2182 +AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
2183 + CC_CHECK_ATTRIBUTE(
2185 + [void some_function(void *foo, __attribute__((unused)) void *bar);],
2189 +AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
2190 + CC_CHECK_ATTRIBUTE(
2192 + [void some_function(void *foo, ...) __attribute__((sentinel));],
2196 +AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
2197 + CC_CHECK_ATTRIBUTE(
2199 + [void some_function(void *foo, ...) __attribute__((deprecated));],
2203 +AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
2204 + CC_CHECK_ATTRIBUTE(
2205 + [alias], [weak, alias],
2206 + [void other_function(void *foo) { }
2207 + void some_function(void *foo) __attribute__((weak, alias("other_function")));],
2211 +AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
2212 + CC_CHECK_ATTRIBUTE(
2214 + [void * __attribute__((malloc)) my_alloc(int n);],
2218 +AC_DEFUN([CC_ATTRIBUTE_PACKED], [
2219 + CC_CHECK_ATTRIBUTE(
2221 + [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
2225 +AC_DEFUN([CC_ATTRIBUTE_CONST], [
2226 + CC_CHECK_ATTRIBUTE(
2228 + [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
2232 +AC_DEFUN([CC_FLAG_VISIBILITY], [
2233 + AC_REQUIRE([CC_CHECK_WERROR])
2234 + AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
2235 + [cc_cv_flag_visibility],
2236 + [cc_flag_visibility_save_CFLAGS="$CFLAGS"
2237 + CFLAGS="$CFLAGS $cc_cv_werror"
2238 + CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
2239 + cc_cv_flag_visibility='yes',
2240 + cc_cv_flag_visibility='no')
2241 + CFLAGS="$cc_flag_visibility_save_CFLAGS"])
2243 + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
2244 + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
2245 + [Define this if the compiler supports the -fvisibility flag])
2250 +AC_DEFUN([CC_FUNC_EXPECT], [
2251 + AC_REQUIRE([CC_CHECK_WERROR])
2252 + AC_CACHE_CHECK([if compiler has __builtin_expect function],
2253 + [cc_cv_func_expect],
2254 + [ac_save_CFLAGS="$CFLAGS"
2255 + CFLAGS="$CFLAGS $cc_cv_werror"
2256 + AC_COMPILE_IFELSE([AC_LANG_SOURCE(
2257 + [int some_function() {
2259 + return (int)__builtin_expect(a, 3);
2261 + [cc_cv_func_expect=yes],
2262 + [cc_cv_func_expect=no])
2263 + CFLAGS="$ac_save_CFLAGS"
2266 + AS_IF([test "x$cc_cv_func_expect" = "xyes"],
2267 + [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
2268 + [Define this if the compiler supports __builtin_expect() function])
2273 +AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
2274 + AC_REQUIRE([CC_CHECK_WERROR])
2275 + AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
2276 + [cc_cv_attribute_aligned],
2277 + [ac_save_CFLAGS="$CFLAGS"
2278 + CFLAGS="$CFLAGS $cc_cv_werror"
2279 + for cc_attribute_align_try in 64 32 16 8 4 2; do
2280 + AC_COMPILE_IFELSE([AC_LANG_SOURCE([
2282 + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
2284 + }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
2286 + CFLAGS="$ac_save_CFLAGS"
2289 + if test "x$cc_cv_attribute_aligned" != "x"; then
2290 + AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
2291 + [Define the highest alignment supported])
2294 diff --git a/runpychecker.sh b/runpychecker.sh
2295 index 407b7d6..64366fd 100755
2296 --- a/runpychecker.sh
2297 +++ b/runpychecker.sh
2298 @@ -5,4 +5,4 @@ pychecker --only --limit 1000 \
2299 --no-callinit --no-local --no-shadow --no-shadowbuiltin \
2300 --no-import --no-miximport --no-pkgimport --no-reimport \
2301 --no-argsused --no-varargsused --no-override \
2304 diff --git a/sendprofile b/sendprofile
2305 deleted file mode 100644
2306 index da480ce..0000000
2311 -###############################################################################
2314 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
2316 -# This program is free software: you can redistribute it and/or modify #
2317 -# it under the terms of the GNU General Public License as published by #
2318 -# the Free Software Foundation, either version 3 of the License, or #
2319 -# (at your option) any later version. #
2321 -# This program is distributed in the hope that it will be useful, #
2322 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
2323 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
2324 -# GNU General Public License for more details. #
2326 -# You should have received a copy of the GNU General Public License #
2327 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
2329 -###############################################################################
2333 -import logging.handlers
2341 -ENABLED_FILE = "/var/ipfire/main/send_profile"
2342 -PROXY_SETTINGS = "/var/ipfire/proxy/advanced/settings"
2344 -log_level = logging.INFO
2345 -if "-d" in sys.argv:
2346 - log_level = logging.DEBUG
2349 -log = logging.getLogger()
2350 -log.setLevel(log_level)
2351 -log.addHandler(logging.handlers.SysLogHandler("/dev/log"))
2352 -log.addHandler(logging.StreamHandler(sys.stderr))
2353 -for handler in log.handlers:
2354 - handler.setLevel(log_level)
2356 -PROFILE_URL = "http://fireinfo.ipfire.org/send/%(public_id)s"
2358 -def get_upstream_proxy():
2359 - if not os.path.exists(PROXY_SETTINGS):
2360 - return {"host" : ""}
2362 - proxy_settings = {}
2363 - with open(PROXY_SETTINGS) as f:
2364 - for line in f.readlines():
2365 - k, v = line.split("=", 1)
2366 - proxy_settings[k] = v.strip()
2369 - "host" : proxy_settings.get("UPSTREAM_PROXY", ""),
2370 - "user" : proxy_settings.get("UPSTREAM_USER", ""),
2371 - "pass" : proxy_settings.get("UPSTREAM_PASSWORD", ""),
2374 -def send_profile(profile):
2375 - logging.debug("Sending profile:")
2376 - for line in json.dumps(profile, sort_keys=True, indent=4).splitlines():
2377 - logging.debug(line)
2379 - request = urllib2.Request(PROFILE_URL % profile,
2380 - data = urllib.urlencode({"profile" : json.dumps(profile)}),
2382 - request.add_header("User-Agent", "fireinfo/%s" % fireinfo.__version__)
2384 - # Set upstream proxy if we have one.
2385 - # XXX this cannot handle authentication
2386 - proxy = get_upstream_proxy()
2388 - request.set_proxy(proxy["host"], "http")
2391 - urllib2.urlopen(request, timeout=60)
2392 - except (urllib2.HTTPError, urllib2.URLError), e:
2393 - reason = "Unknown reason"
2395 - if isinstance(e, urllib2.HTTPError):
2397 - elif isinstance(e, urllib2.URLError):
2400 - logging.error("Profile was not sent propertly: %s" % reason)
2403 - logging.debug("Profile was sent successfully.")
2406 - # Collect system information
2407 - system = fireinfo.System()
2408 - profile = system.profile()
2410 - # If --dump is passed -> only dump the output.
2411 - if "--dump" in sys.argv:
2412 - # Remove the private id when dumping the profile because
2413 - # it contains no information and may confuse people.
2414 - del profile["private_id"]
2416 - print json.dumps(profile, sort_keys=True, indent=4)
2419 - if "--secret-id" in sys.argv:
2420 - print system.secret_id
2423 - if "--hardware-string" in sys.argv:
2424 - print system._unique_id
2427 - if "--public-id" in sys.argv:
2428 - print system.public_id
2431 - if not os.path.exists(ENABLED_FILE):
2432 - del profile["profile"]
2435 - send_profile(profile)
2436 - except urllib2.URLError:
2442 diff --git a/setup.py b/setup.py
2443 deleted file mode 100644
2444 index 8149f0a..0000000
2449 -###############################################################################
2452 -# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
2454 -# This program is free software: you can redistribute it and/or modify #
2455 -# it under the terms of the GNU General Public License as published by #
2456 -# the Free Software Foundation, either version 3 of the License, or #
2457 -# (at your option) any later version. #
2459 -# This program is distributed in the hope that it will be useful, #
2460 -# but WITHOUT ANY WARRANTY; without even the implied warranty of #
2461 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
2462 -# GNU General Public License for more details. #
2464 -# You should have received a copy of the GNU General Public License #
2465 -# along with this program. If not, see <http://www.gnu.org/licenses/>. #
2467 -###############################################################################
2469 -from distutils.core import setup, Extension
2472 - name = "fireinfo",
2473 - version = "2.1.7",
2474 - description = "Hardware information gathering library.",
2475 - license = "GPLv3",
2476 - author = "IPFire.org Team",
2477 - author_email = "info@ipfire.org",
2478 - url = "https://bugzilla.ipfire.org/describecomponents.cgi?product=Fireinfo",
2480 - Extension("_fireinfo", ["src/fireinfo.c"])
2482 - packages = ["fireinfo"],
2483 - scripts = ["sendprofile"],
2485 diff --git a/src/_fireinfo/fireinfo.c b/src/_fireinfo/fireinfo.c
2486 new file mode 100644
2487 index 0000000..08d714b
2489 +++ b/src/_fireinfo/fireinfo.c
2493 + * Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)
2495 + * This program is free software; you can redistribute it and/or modify
2496 + * it under the terms of the GNU General Public License as published by
2497 + * the Free Software Foundation; either version 3 of the License, or
2498 + * (at your option) any later version.
2500 + * This program is distributed in the hope that it will be useful,
2501 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2502 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2503 + * GNU General Public License for more details.
2505 + * You should have received a copy of the GNU General Public License
2506 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
2509 +#include <Python.h>
2513 +#include <linux/hdreg.h>
2514 +#include <stdbool.h>
2515 +#include <string.h>
2516 +#include <sys/ioctl.h>
2518 +/* hypervisor vendors */
2526 + HYPER_LAST /* for loop - must be last*/
2529 +const char *hypervisor_ids[] = {
2530 + [HYPER_NONE] = NULL,
2531 + [HYPER_XEN] = "XenVMMXenVMM",
2532 + [HYPER_KVM] = "KVMKVMKVM",
2533 + /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
2534 + [HYPER_MSHV] = "Microsoft Hv",
2535 + /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
2536 + [HYPER_VMWARE] = "VMwareVMware",
2537 + [HYPER_OTHER] = NULL
2540 +const char *hypervisor_vendors[] = {
2541 + [HYPER_NONE] = NULL,
2542 + [HYPER_XEN] = "Xen",
2543 + [HYPER_KVM] = "KVM",
2544 + [HYPER_MSHV] = "Microsoft",
2545 + [HYPER_VMWARE] = "VMWare",
2546 + [HYPER_OTHER] = "other"
2549 +#define NEWLINE "\n\r"
2551 +char *truncate_nl(char *s) {
2554 + s[strcspn(s, NEWLINE)] = 0;
2558 +int read_one_line_file(const char *filename, char **line) {
2563 + f = fopen(filename, "re");
2568 + if (!fgets(t, sizeof(t), f)) {
2570 + return errno ? -errno : -EIO;
2575 + char *c = strdup(t);
2585 + * This CPUID leaf returns the information about the hypervisor.
2586 + * EAX : maximum input value for CPUID supported by the hypervisor.
2587 + * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
2589 +#define HYPERVISOR_INFO_LEAF 0x40000000
2591 +int detect_hypervisor(int *hypervisor) {
2592 +#if defined(__x86_64__) || defined(__i386__)
2593 + /* Try high-level hypervisor sysfs file first: */
2594 + char *hvtype = NULL;
2595 + int r = read_one_line_file("/sys/hypervisor/type", &hvtype);
2597 + if (strcmp(hvtype, "xen") == 0) {
2598 + *hypervisor = HYPER_XEN;
2601 + } else if (r != -ENOENT)
2604 + /* http://lwn.net/Articles/301888/ */
2606 +#if defined(__amd64__)
2607 +#define REG_a "rax"
2608 +#define REG_b "rbx"
2609 +#elif defined(__i386__)
2610 +#define REG_a "eax"
2611 +#define REG_b "ebx"
2617 + uint32_t sig32[3];
2621 + __asm__ __volatile__ (
2622 + /* ebx/rbx is being used for PIC! */
2623 + " push %%"REG_b" \n\t"
2625 + " pop %%"REG_b" \n\t"
2627 + : "=a" (eax), "=c" (ecx)
2631 + bool has_hypervisor = !!(ecx & 0x80000000U);
2633 + if (has_hypervisor) {
2634 + /* There is a hypervisor, see what it is... */
2635 + eax = 0x40000000U;
2636 + __asm__ __volatile__ (
2637 + " push %%"REG_b" \n\t"
2639 + " mov %%ebx, %1 \n\t"
2640 + " pop %%"REG_b" \n\t"
2642 + : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
2645 + sig.text[12] = '\0';
2647 + *hypervisor = HYPER_OTHER;
2650 + for (id = HYPER_NONE + 1; id < HYPER_LAST; id++) {
2651 + if (strcmp(hypervisor_ids[id], sig.text) == 0) {
2665 +do_detect_hypervisor() {
2667 + Get hypervisor from the cpuid command.
2669 + int hypervisor = HYPER_NONE;
2671 + int r = detect_hypervisor(&hypervisor);
2673 + const char* hypervisor_vendor = hypervisor_vendors[hypervisor];
2674 + if (!hypervisor_vendor)
2677 + return PyString_FromString(hypervisor_vendor);
2684 +do_get_harddisk_serial(PyObject *o, PyObject *args) {
2686 + Python wrapper around read_harddisk_serial.
2688 + static struct hd_driveid hd;
2692 + if (!PyArg_ParseTuple(args, "s", &device))
2695 + if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0)
2698 + if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
2700 + strncpy(serial, (const char *)hd.serial_no, sizeof(serial));
2703 + return PyString_FromString(serial);
2709 +static PyMethodDef fireinfoModuleMethods[] = {
2710 + { "detect_hypervisor", (PyCFunction) do_detect_hypervisor, METH_NOARGS, NULL },
2711 + { "get_harddisk_serial", (PyCFunction) do_get_harddisk_serial, METH_VARARGS, NULL },
2712 + { NULL, NULL, 0, NULL }
2715 +void init_fireinfo(void) {
2718 + m = Py_InitModule("_fireinfo", fireinfoModuleMethods);
2722 diff --git a/src/fireinfo.c b/src/fireinfo.c
2723 deleted file mode 100644
2724 index 25b5333..0000000
2725 --- a/src/fireinfo.c
2730 - * Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)
2732 - * This program is free software; you can redistribute it and/or modify
2733 - * it under the terms of the GNU General Public License as published by
2734 - * the Free Software Foundation; either version 3 of the License, or
2735 - * (at your option) any later version.
2737 - * This program is distributed in the hope that it will be useful,
2738 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
2739 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2740 - * GNU General Public License for more details.
2742 - * You should have received a copy of the GNU General Public License
2743 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
2746 -#include <Python.h>
2749 -#include <linux/hdreg.h>
2750 -#include <stdbool.h>
2751 -#include <sys/ioctl.h>
2754 - Big parts of this were taken from
2755 - http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git;a=blob;f=sys-utils/lscpu.c
2759 -#define _PATH_PROC_XEN "/proc/xen"
2760 -#define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
2761 -#define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
2763 -/* Used for the vmware hypervisor port detection */
2764 -#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
2765 -#define VMWARE_HYPERVISOR_PORT 0x5658
2767 -#define VMWARE_PORT_CMD_GETVERSION 10
2769 -/* virtualization types */
2775 -const char *virt_types[] = {
2776 - [VIRT_NONE] = "none",
2777 - [VIRT_PARA] = "para",
2778 - [VIRT_FULL] = "full"
2781 -/* hypervisor vendors */
2789 -const char *hv_vendors[] = {
2790 - [HYPER_NONE] = NULL,
2791 - [HYPER_XEN] = "Xen",
2792 - [HYPER_KVM] = "KVM",
2793 - [HYPER_MSHV] = "Microsoft",
2794 - [HYPER_VMWARE] = "VMWare"
2797 -struct hypervisor_desc {
2798 - int hyper; /* hypervisor vendor ID */
2799 - int virtype; /* VIRT_PARA|FULL|NONE ? */
2802 -static size_t sysrootlen;
2803 -static char pathbuf[PATH_MAX];
2805 -static FILE *path_fopen(const char *mode, const char *path, ...)
2806 - __attribute__ ((__format__ (__printf__, 2, 3)));
2807 -static int path_exist(const char *path, ...)
2808 - __attribute__ ((__format__ (__printf__, 1, 2)));
2810 -static const char *
2811 -path_vcreate(const char *path, va_list ap)
2814 - vsnprintf(pathbuf + sysrootlen,
2815 - sizeof(pathbuf) - sysrootlen, path, ap);
2817 - vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
2822 -path_vfopen(const char *mode, const char *path, va_list ap)
2824 - const char *p = path_vcreate(path, ap);
2826 - return fopen(p, mode);
2830 -path_fopen(const char *mode, const char *path, ...)
2835 - va_start(ap, path);
2836 - fd = path_vfopen(mode, path, ap);
2843 -path_exist(const char *path, ...)
2848 - va_start(ap, path);
2849 - p = path_vcreate(path, ap);
2852 - return access(p, F_OK) == 0;
2856 -has_pci_device(int vendor, int device)
2859 - int num, fn, ven, dev;
2862 - f = path_fopen("r", _PATH_PROC_PCIDEVS);
2866 - /* for more details about bus/pci/devices format see
2867 - * drivers/pci/proc.c in linux kernel
2869 - while(fscanf(f, "%02x%02x\t%04x%04x\t%*[^\n]",
2870 - &num, &fn, &ven, &dev) == 4) {
2872 - if (ven == vendor && dev == device)
2882 -#if defined(__x86_64__) || defined(__i386__)
2885 - * This CPUID leaf returns the information about the hypervisor.
2886 - * EAX : maximum input value for CPUID supported by the hypervisor.
2887 - * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
2889 -#define HYPERVISOR_INFO_LEAF 0x40000000
2892 -cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
2893 - unsigned int *ecx, unsigned int *edx)
2896 -#if defined(__PIC__) && defined(__i386__)
2897 - /* x86 PIC cannot clobber ebx -- gcc bitches */
2900 - "movl %%ebx, %%esi;"
2910 - : "1" (op), "c"(0));
2914 -read_hypervisor_cpuid(struct hypervisor_desc *desc)
2916 - unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
2917 - char hyper_vendor_id[13];
2919 - memset(hyper_vendor_id, 0, sizeof(hyper_vendor_id));
2921 - cpuid(HYPERVISOR_INFO_LEAF, &eax, &ebx, &ecx, &edx);
2922 - memcpy(hyper_vendor_id + 0, &ebx, 4);
2923 - memcpy(hyper_vendor_id + 4, &ecx, 4);
2924 - memcpy(hyper_vendor_id + 8, &edx, 4);
2925 - hyper_vendor_id[12] = '\0';
2927 - if (!hyper_vendor_id[0])
2930 - if (!strncmp("XenVMMXenVMM", hyper_vendor_id, 12))
2931 - desc->hyper = HYPER_XEN;
2932 - else if (!strncmp("KVMKVMKVM", hyper_vendor_id, 9))
2933 - desc->hyper = HYPER_KVM;
2934 - else if (!strncmp("Microsoft Hv", hyper_vendor_id, 12))
2935 - desc->hyper = HYPER_MSHV;
2936 - else if (!strncmp("VMwareVMware", hyper_vendor_id, 12))
2937 - desc->hyper = HYPER_VMWARE;
2940 -#else /* ! __x86_64__ */
2942 -read_hypervisor_cpuid(struct hypervisor_desc *desc)
2948 -read_hypervisor(struct hypervisor_desc *desc)
2950 - read_hypervisor_cpuid(desc);
2954 - desc->virtype = VIRT_FULL;
2956 - else if (path_exist(_PATH_PROC_XEN)) {
2957 - /* Xen para-virt or dom0 */
2958 - FILE *fd = path_fopen("r", _PATH_PROC_XENCAP);
2964 - if (fscanf(fd, "%s", buf) == 1 &&
2965 - !strcmp(buf, "control_d"))
2969 - desc->virtype = dom0 ? VIRT_NONE : VIRT_PARA;
2970 - desc->hyper = HYPER_XEN;
2972 - } else if (has_pci_device(0x5853, 0x0001)) {
2973 - /* Xen full-virt on non-x86_64 */
2974 - desc->hyper = HYPER_XEN;
2975 - desc->virtype = VIRT_FULL;
2980 -read_harddisk_serial(char *device, char *serial) {
2981 - static struct hd_driveid hd;
2984 - if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
2988 - if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
2989 - strncpy(serial, (const char *)hd.serial_no, 20);
2993 -#if defined(__x86_64__) || defined(__i386__)
2996 - unsigned int eax, ebx, ecx, edx;
2998 - cpuid(0x1, &eax, &ebx, &ecx, &edx);
3001 - Bitwise detection of the 31st bit.
3002 - This indicates if a host runs in a virtual environment.
3004 - if (ecx & (1<<31))
3011 -hypervisor_port(unsigned int cmd, unsigned int *eax, unsigned int *ebx,
3012 - unsigned int *ecx, unsigned int *edx)
3015 -#if defined(__PIC__) && defined(__i386__)
3016 - /* x86 PIC really cannot clobber ebx */
3019 - "movl %%ebx, %%esi;"
3029 - : "0" (VMWARE_HYPERVISOR_MAGIC),
3031 - "2" (VMWARE_HYPERVISOR_PORT),
3040 - Always return false, because other architectures
3041 - do not support the virtualization bit.
3047 -hypervisor_port(unsigned int cmd, unsigned int *eax, unsigned int *ebx,
3048 - unsigned int *ecx, unsigned int *edx)
3054 -hypervisor_port_check(void) {
3055 - uint32_t eax, ebx, ecx, edx;
3057 - hypervisor_port(VMWARE_PORT_CMD_GETVERSION, &eax, &ebx, &ecx, &edx);
3059 - if (ebx == VMWARE_HYPERVISOR_MAGIC)
3060 - return 1; // Success - running under VMware
3066 -do_get_hypervisor() {
3068 - Get hypervisor from the cpuid command.
3070 - struct hypervisor_desc _desc, *desc = &_desc;
3071 - memset(desc, 0, sizeof(*desc));
3073 - read_hypervisor(desc);
3075 - PyObject *d = PyDict_New();
3079 - if (desc->hyper == HYPER_NONE) {
3082 - o = PyString_FromString((const char *)hv_vendors[desc->hyper]);
3084 - PyDict_SetItemString(d, "hypervisor", o);
3086 - /* Virtualization type */
3087 - if (desc->virtype == VIRT_NONE) {
3090 - o = PyString_FromString((const char *)virt_types[desc->virtype]);
3092 - PyDict_SetItemString(d, "virtype", o);
3098 -do_is_virtualized() {
3100 - Python wrapper around is_virtualized().
3103 - if (is_virtualized())
3110 -do_get_harddisk_serial(PyObject *o, PyObject *args) {
3112 - Python wrapper around read_harddisk_serial.
3116 - memset(serial, 0, sizeof(serial));
3119 - if (!PyArg_ParseTuple(args, "s", &device))
3122 - read_harddisk_serial(device, serial);
3125 - return PyString_FromString(serial);
3131 -do_hypervisor_port_check() {
3133 - Python wrapper around hypervisor_port_check().
3136 - if (hypervisor_port_check())
3142 -static PyMethodDef fireinfoModuleMethods[] = {
3143 - { "get_hypervisor", (PyCFunction) do_get_hypervisor, METH_NOARGS, NULL },
3144 - { "is_virtualized", (PyCFunction) do_is_virtualized, METH_NOARGS, NULL },
3145 - { "get_harddisk_serial", (PyCFunction) do_get_harddisk_serial, METH_VARARGS, NULL },
3146 - { "vmware_hypervisor_port_check", (PyCFunction) do_hypervisor_port_check, METH_NOARGS, NULL },
3147 - { NULL, NULL, 0, NULL }
3150 -void init_fireinfo(void) {
3153 - m = Py_InitModule("_fireinfo", fireinfoModuleMethods);
3155 diff --git a/src/fireinfo/__init__.py.in b/src/fireinfo/__init__.py.in
3156 new file mode 100644
3157 index 0000000..05c520e
3159 +++ b/src/fireinfo/__init__.py.in
3162 +###############################################################################
3165 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3167 +# This program is free software: you can redistribute it and/or modify #
3168 +# it under the terms of the GNU General Public License as published by #
3169 +# the Free Software Foundation, either version 3 of the License, or #
3170 +# (at your option) any later version. #
3172 +# This program is distributed in the hope that it will be useful, #
3173 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3174 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3175 +# GNU General Public License for more details. #
3177 +# You should have received a copy of the GNU General Public License #
3178 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3180 +###############################################################################
3182 +__version__ = "@PACKAGE_VERSION@"
3184 +from system import System
3185 diff --git a/src/fireinfo/bios.py b/src/fireinfo/bios.py
3186 new file mode 100644
3187 index 0000000..56e3af0
3189 +++ b/src/fireinfo/bios.py
3192 +###############################################################################
3195 +# Copyright (C) 2013 IPFire Team (www.ipfire.org) #
3197 +# This program is free software: you can redistribute it and/or modify #
3198 +# it under the terms of the GNU General Public License as published by #
3199 +# the Free Software Foundation, either version 3 of the License, or #
3200 +# (at your option) any later version. #
3202 +# This program is distributed in the hope that it will be useful, #
3203 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3204 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3205 +# GNU General Public License for more details. #
3207 +# You should have received a copy of the GNU General Public License #
3208 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3210 +###############################################################################
3215 + "/sys/class/dmi/id/sys_vendor",
3216 + "/sys/class/dmi/id/board_vendor",
3217 + "/sys/class/dmi/id/bios_vendor",
3220 +class BIOS(object):
3221 + def __init__(self, system):
3222 + self.system = system
3224 + def check_vendor(self, vendor, startswith=True):
3225 + for file in DMI_VENDORS:
3226 + if not os.path.exists(file):
3229 + with open(file, "r") as f:
3232 + # Strip the vendor string.
3235 + if startswith and v.startswith(vendor):
3241 diff --git a/src/fireinfo/cpu.py b/src/fireinfo/cpu.py
3242 new file mode 100644
3243 index 0000000..32d885d
3245 +++ b/src/fireinfo/cpu.py
3248 +###############################################################################
3251 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3253 +# This program is free software: you can redistribute it and/or modify #
3254 +# it under the terms of the GNU General Public License as published by #
3255 +# the Free Software Foundation, either version 3 of the License, or #
3256 +# (at your option) any later version. #
3258 +# This program is distributed in the hope that it will be useful, #
3259 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3260 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3261 +# GNU General Public License for more details. #
3263 +# You should have received a copy of the GNU General Public License #
3264 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3266 +###############################################################################
3272 +PROC_CPUINFO = "/proc/cpuinfo"
3276 + A class that represents the first CPU in a system.
3278 + We get all information form the first CPU (or core) and assume that
3279 + all other ones are equal.
3284 + def __init__(self):
3286 + Initialize this class by reading all data from /proc/cpuinfo.
3288 + self.__cpuinfo = self.read_cpuinfo()
3292 + return system.System()
3295 + def read_cpuinfo():
3297 + Read information from PROC_CPUINFO and store
3298 + it into a dictionary cpuinfo.
3302 + f = open(PROC_CPUINFO)
3304 + line = f.readline()
3310 + key, val = line.split(":", 1)
3311 + except ValueError:
3312 + # We got a line without key, pass that.
3315 + key = key.strip().replace(" ", "_")
3318 + cpuinfo[key] = val
3325 + def bogomips(self):
3327 + Return the bogomips of this CPU.
3330 + bogomips = self.__cpuinfo["bogomips"]
3332 + bogomips = self.__cpuinfo["BogoMIPS"]
3334 + return float(bogomips)
3339 + Return the model id of this CPU.
3342 + model = int(self.__cpuinfo["model"])
3349 + def model_string(self):
3351 + Return the model string of this CPU.
3354 + return self.__cpuinfo["model_name"]
3356 + return self.__cpuinfo["Processor"]
3361 + Return the vendor string of this CPU.
3364 + vendor = self.__cpuinfo["vendor_id"]
3366 + if self.system.arch.startswith("arm"):
3374 + def stepping(self):
3376 + Return the stepping id of this CPU.
3379 + stepping = int(self.__cpuinfo["stepping"])
3388 + Return all flags of this CPU.
3391 + flags = self.__cpuinfo["flags"]
3393 + flags = self.__cpuinfo["Features"]
3395 + return flags.split()
3400 + Return the speed (in MHz) of this CPU.
3403 + speed = float(self.__cpuinfo["cpu_MHz"])
3412 + Return the family id of this CPU.
3415 + family = int(self.__cpuinfo["cpu_family"])
3424 + Count number of CPUs (cores).
3426 + return os.sysconf("SC_NPROCESSORS_ONLN")
3429 +if __name__ == "__main__":
3432 + print "Vendor:", c.vendor
3433 + print "Model:", c.model
3434 + print "Stepping:", c.stepping
3435 + print "Flags:", c.flags
3436 + print "Bogomips:", c.bogomips
3437 + print "Speed:", c.speed
3438 + print "Family:", c.family
3439 + print "Count:", c.count
3440 + print "Model string:", c.model_string
3441 diff --git a/src/fireinfo/device.py b/src/fireinfo/device.py
3442 new file mode 100644
3443 index 0000000..01338b2
3445 +++ b/src/fireinfo/device.py
3448 +###############################################################################
3451 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3453 +# This program is free software: you can redistribute it and/or modify #
3454 +# it under the terms of the GNU General Public License as published by #
3455 +# the Free Software Foundation, either version 3 of the License, or #
3456 +# (at your option) any later version. #
3458 +# This program is distributed in the hope that it will be useful, #
3459 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3460 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3461 +# GNU General Public License for more details. #
3463 +# You should have received a copy of the GNU General Public License #
3464 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3466 +###############################################################################
3470 +class Device(object):
3472 + This is an abstract class that represents all devices in the system.
3473 + Every single device has its own instance of this class.
3476 + def __init__(self, path):
3478 + Collect all information about the device by reading the
3479 + "uevent" file and parsing it.
3482 + # Save the path in /sys to the device.
3485 + # Datastructure to store information we read.
3488 + # Open the uevent file and parse all lines.
3489 + with open(os.path.join(path, "uevent")) as f:
3490 + for line in f.readlines():
3491 + key, val = line.split("=")
3492 + self._uevent[key] = val.rstrip().lower()
3497 + Get the driver/kernel module that device is driven by or return None.
3499 + return self._uevent.get("DRIVER", None)
3502 +class PCIDevice(Device):
3504 + A class that represents all PCI (and PCIe) devices in a system.
3512 + Return the PCI model id of this device.
3514 + return self._uevent['PCI_ID'].split(":")[1]
3519 + Return the PCI vendor id of this device.
3521 + return self._uevent['PCI_ID'].split(":")[0]
3524 + def deviceclass(self):
3526 + Return the PCI device class of this device.
3528 + return self._uevent['PCI_CLASS']
3531 + def sub_vendor(self):
3533 + Return the PCI vendor sub id of this device.
3535 + return self._uevent["PCI_SUBSYS_ID"].split(":")[0]
3538 + def sub_model(self):
3540 + Return the PCI model sub id of this device.
3542 + return self._uevent["PCI_SUBSYS_ID"].split(":")[1]
3545 +class USBDevice(Device):
3547 + A class that represents all USB devices in a system.
3554 + A function to pad ids that have no leading zeroes.
3563 + Return the USB vendor id of this device.
3565 + return self.pad(self._uevent['PRODUCT'].split("/")[0])
3570 + Return the USB model id of this device.
3572 + return self.pad(self._uevent['PRODUCT'].split("/")[1])
3575 + def deviceclass(self):
3577 + Return the USB device class of this device.
3579 + return self._uevent.get("INTERFACE", None)
3580 diff --git a/src/fireinfo/hypervisor.py b/src/fireinfo/hypervisor.py
3581 new file mode 100644
3582 index 0000000..0c07cfa
3584 +++ b/src/fireinfo/hypervisor.py
3587 +###############################################################################
3590 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3592 +# This program is free software: you can redistribute it and/or modify #
3593 +# it under the terms of the GNU General Public License as published by #
3594 +# the Free Software Foundation, either version 3 of the License, or #
3595 +# (at your option) any later version. #
3597 +# This program is distributed in the hope that it will be useful, #
3598 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3599 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3600 +# GNU General Public License for more details. #
3602 +# You should have received a copy of the GNU General Public License #
3603 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3605 +###############################################################################
3610 +class Hypervisor(object):
3611 + def __init__(self):
3612 + self.__hypervisor = _fireinfo.detect_hypervisor()
3617 + Return the current instance of the System class.
3619 + We need to do that as a property because otherwise
3620 + we get a recursion.
3622 + return system.System()
3627 + Returns the name of the hypervisor vendor.
3629 + # Citrix Xen says it is Microsoft Hv.
3630 + if self.__hypervisor == "Microsoft" and self.system.bios_vendor == "Xen":
3633 + # Some of the hypervisors can be detected in a right way.
3634 + # We can return them at this place.
3635 + if self.__hypervisor:
3636 + return self.__hypervisor
3638 + # Check DMI and BIOS information...
3639 + if self.__bios_is_bochs():
3641 + elif self.__bios_is_microsoft():
3642 + return "Microsoft"
3643 + elif self.__bios_is_qemu():
3645 + elif self.__bios_is_virtualbox():
3646 + return "VirtualBox"
3647 + elif self.__bios_is_vmware():
3649 + elif self.__bios_is_xen():
3653 + def virtual(self):
3655 + Returns true if the host is running in a virtual environment.
3663 + def __bios_is_bochs(self):
3665 + Check for Bochs emulator.
3667 + return self.system.bios.check_vendor("Bochs")
3669 + def __bios_is_microsoft(self):
3671 + Check for Microsoft hypervisor.
3673 + return self.system.bios.check_vendor("Microsoft Corporation")
3675 + def __bios_is_qemu(self):
3677 + Check for qemu emulator.
3679 + return self.system.bios.check_vendor("QEMU")
3681 + def __bios_is_virtualbox(self):
3683 + Check for virtualbox hypervisor by comparing the bios vendor string
3684 + to "innotek GmbH".
3686 + return self.system.bios.check_vendor("innotek GmbH")
3688 + def __bios_is_vmware(self):
3689 + if self.system.bios.check_vendor("VMware-"):
3691 + elif self.system.bios.check_vendor("VMW"):
3696 + def __bios_is_xen(self):
3697 + return self.system.bios.check_vendor("Xen")
3700 +if __name__ == "__main__":
3703 + print "Vendor:", h.vendor
3704 + print "Virtual:", h.virtual
3705 diff --git a/src/fireinfo/network.py b/src/fireinfo/network.py
3706 new file mode 100644
3707 index 0000000..063e9ec
3709 +++ b/src/fireinfo/network.py
3712 +###############################################################################
3715 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3717 +# This program is free software: you can redistribute it and/or modify #
3718 +# it under the terms of the GNU General Public License as published by #
3719 +# the Free Software Foundation, either version 3 of the License, or #
3720 +# (at your option) any later version. #
3722 +# This program is distributed in the hope that it will be useful, #
3723 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3724 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3725 +# GNU General Public License for more details. #
3727 +# You should have received a copy of the GNU General Public License #
3728 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3730 +###############################################################################
3734 +SYS_CLASS_NET = "/sys/class/net"
3736 +class Network(object):
3737 + def __init__(self):
3738 + self._devices = os.listdir(SYS_CLASS_NET)
3740 + def has_green(self):
3741 + return "green0" in self._devices
3743 + def has_red(self):
3744 + for i in ("red0", "ppp0"):
3745 + if i in self._devices:
3750 + def has_blue(self):
3751 + return "blue0" in self._devices
3753 + def has_orange(self):
3754 + return "orange0" in self._devices
3757 +if __name__ == "__main__":
3760 + print "has_green", n.has_green()
3761 + print "has_red", n.has_red()
3762 + print "has_blue", n.has_blue()
3763 + print "has_orange", n.has_orange()
3764 diff --git a/src/fireinfo/system.py b/src/fireinfo/system.py
3765 new file mode 100644
3766 index 0000000..0a60bcc
3768 +++ b/src/fireinfo/system.py
3771 +###############################################################################
3774 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3776 +# This program is free software: you can redistribute it and/or modify #
3777 +# it under the terms of the GNU General Public License as published by #
3778 +# the Free Software Foundation, either version 3 of the License, or #
3779 +# (at your option) any later version. #
3781 +# This program is distributed in the hope that it will be useful, #
3782 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3783 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3784 +# GNU General Public License for more details. #
3786 +# You should have received a copy of the GNU General Public License #
3787 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3789 +###############################################################################
3804 +PROFILE_VERSION = 0
3806 +SYS_CLASS_DMI = "/sys/class/dmi/id"
3807 +SECRET_ID_FILE = "/etc/fireinfo-id"
3809 +INVALID_ID_STRINGS = (
3810 + "OEM", "O.E.M.", "o.e.m.",
3812 + "12345", "54321", "202020",
3813 + "Chassis", "chassis",
3816 + "01010101-0101-0101-0101-010101010101",
3817 + "00020003-0004-0005-0006-000700080009",
3818 + "03000200-0400-0500-0006-000700080009",
3819 + "0000000", "00000000",
3822 +class Singleton(type):
3823 + def __init__(cls, name, bases, dict):
3824 + super(Singleton, cls).__init__(name, bases, dict)
3825 + cls.instance = None
3827 + def __call__(cls, *args, **kw):
3828 + if cls.instance is None:
3829 + cls.instance = super(Singleton, cls).__call__(*args, **kw)
3831 + return cls.instance
3834 +def read_from_file(filename):
3836 + Read all data from filename.
3838 + if not os.path.exists(filename):
3842 + with open(filename) as f:
3843 + return f.read().strip()
3847 +class System(object):
3848 + __metaclass__ = Singleton
3850 + def __init__(self):
3851 + self.bios = bios.BIOS(self)
3853 + # find all devices
3856 + self.cpu = cpu.CPU()
3857 + self.hypervisor = hypervisor.Hypervisor()
3859 + # Read /proc/cpuinfo for vendor information.
3860 + self.__cpuinfo = self.cpu.read_cpuinfo()
3862 + def profile(self):
3865 + # System information
3866 + "model" : self.model,
3867 + "vendor" : self.vendor,
3869 + # Indicator if the system is running in a
3870 + # virtual environment.
3871 + "virtual" : self.virtual,
3874 + "language" : self.language,
3876 + # Release information
3877 + "release" : self.release,
3878 + "kernel_release" : self.kernel_release,
3880 + "memory" : self.memory,
3881 + "root_size" : self.root_size,
3885 + for device in self.devices:
3887 + "subsystem" : device.subsystem.lower(),
3888 + "vendor" : device.vendor.lower(),
3889 + "model" : device.model.lower(),
3890 + "deviceclass" : device.deviceclass,
3891 + "driver" : device.driver,
3894 + # PCI devices provide subsystem information, USB don't.
3895 + if d["subsystem"] == "pci":
3896 + d["sub_model"] = device.sub_model
3897 + d["sub_vendor"] = device.sub_vendor
3899 + p["devices"].append(d)
3902 + "arch" : self.arch,
3903 + "vendor" : self.cpu.vendor,
3904 + "model" : self.cpu.model,
3905 + "model_string" : self.cpu.model_string,
3906 + "stepping" : self.cpu.stepping,
3907 + "flags" : self.cpu.flags,
3908 + "bogomips" : self.cpu.bogomips,
3909 + "speed" : self.cpu.speed,
3910 + "family" : self.cpu.family,
3911 + "count" : self.cpu.count
3915 + "green" : self.network.has_green(),
3916 + "blue" : self.network.has_blue(),
3917 + "orange" : self.network.has_orange(),
3918 + "red" : self.network.has_red(),
3921 + # Only append hypervisor information if we are virtualized.
3923 + p["hypervisor"] = {
3924 + "vendor" : self.hypervisor.vendor,
3929 + "profile_version" : PROFILE_VERSION,
3931 + # Identification and authorization codes
3932 + "public_id" : self.public_id,
3933 + "private_id" : self.private_id,
3935 + # Actual profile data
3942 + return os.uname()[4]
3945 + def public_id(self):
3947 + This returns a globally (hopefully) ID to identify the host
3948 + later (by request) in the database.
3950 + public_id = self.secret_id
3954 + return hashlib.sha1(public_id).hexdigest()
3957 + def private_id(self):
3959 + The private ID is built out of the _unique_id and used to
3960 + permit a host to do changes on the database.
3962 + No one could ever guess this without access to the host.
3965 + for i in reversed(self.secret_id):
3968 + if not private_id:
3971 + return hashlib.sha1(private_id).hexdigest()
3974 + def secret_id(self):
3976 + Read a "secret" ID from a file if available
3977 + or calculate it from the hardware.
3979 + if os.path.exists(SECRET_ID_FILE):
3980 + return read_from_file(SECRET_ID_FILE)
3982 + return hashlib.sha1(self._unique_id).hexdigest()
3985 + def _unique_id(self):
3987 + This is a helper ID which is generated out of some hardware information
3988 + that is considered to be constant over a PC's lifetime.
3990 + None of the data here is ever sent to the server.
3994 + # Virtual machines (for example) and some boards have a UUID
3995 + # which is globally unique.
3996 + for file in ("product_uuid", "product_serial", "chassis_serial"):
3997 + id = read_from_file(os.path.join(SYS_CLASS_DMI, file))
4000 + # Sort out all bogous or invalid strings from the list.
4006 + for i in INVALID_ID_STRINGS:
4016 + # Use serial number from root disk (if available) and if
4017 + # no other ID was found, yet.
4019 + root_disk_serial = self.root_disk_serial
4020 + if root_disk_serial and not root_disk_serial.startswith("QM000"):
4021 + ids.append(root_disk_serial)
4023 + # As last resort, we use the UUID from pakfire.
4025 + id = read_from_file("/opt/pakfire/db/uuid")
4028 + return "#".join(ids)
4031 + def language(self):
4033 + Return the language code of IPFire or "unknown" if we cannot get it.
4035 + # Return "unknown" if settings file does not exist.
4036 + filename = "/var/ipfire/main/settings"
4037 + if not os.path.exists(filename):
4040 + with open(filename, "r") as f:
4041 + for line in f.readlines():
4042 + key, val = line.split("=", 1)
4043 + if key == "LANGUAGE":
4044 + return val.strip()
4047 + def release(self):
4049 + Return the system release string.
4051 + return read_from_file("/etc/system-release") or "unknown"
4054 + def bios_vendor(self):
4056 + Return the bios vendor name.
4058 + return read_from_file("/sys/class/dmi/id/bios_vendor")
4060 + def vendor_model_tuple(self):
4062 + s = self.__cpuinfo["Hardware"]
4064 + return (None, None)
4066 + if s.startswith("ARM-Versatile"):
4070 + v, m = s.split(" ", 1)
4071 + except ValueError:
4072 + if s.startswith("BCM"):
4084 + Return the vendor string of this system (if any).
4087 + for file in ("sys_vendor", "board_vendor", "chassis_vendor",):
4088 + ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
4093 + v, m = self.vendor_model_tuple()
4101 + Return the model string of this system (if any).
4104 + for file in ("product_name", "board_model", "chassis_model",):
4105 + ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
4110 + v, m = self.vendor_model_tuple()
4118 + Return the amount of memory in kilobytes.
4120 + with open("/proc/meminfo", "r") as f:
4121 + firstline = f.readline().strip()
4122 + return int(firstline.split()[1])
4125 + def kernel_release(self):
4127 + Return the kernel release string.
4129 + return os.uname()[2]
4132 + def root_disk(self):
4134 + Return the dev node of the root disk.
4136 + with open("/etc/mtab", "r") as f:
4137 + dev, mountpoint, fs, rest = f.readline().split(" ", 3)
4138 + if mountpoint == "/" and not fs == "rootfs":
4142 + # Handle raids and MMC cards like (mmcblk0p3).
4143 + if dev[-2] == "p":
4146 + # Otherwise cut off all digits at end of string
4147 + while dev[-1] in string.digits:
4153 + def root_size(self):
4155 + Return the size of the root disk in kilobytes.
4157 + path = "/sys/block/%s/size" % self.root_disk
4158 + if not os.path.exists(path):
4161 + with open(path, "r") as f:
4162 + return int(f.readline()) * 512 / 1024
4165 + def root_disk_serial(self):
4167 + Return the serial number of the root disk (if any).
4169 + serial = _fireinfo.get_harddisk_serial("/dev/%s" % self.root_disk)
4172 + # Strip all spaces
4173 + return serial.strip()
4177 + Scan for all devices (PCI/USB) in the system and append them
4183 + ("/sys/bus/pci/devices", device.PCIDevice),
4184 + ("/sys/bus/usb/devices", device.USBDevice)
4186 + for path, cls in toscan:
4187 + if not os.path.exists(path):
4190 + dirlist = os.listdir(path)
4191 + for dir in dirlist:
4192 + self.devices.append(cls(os.path.join(path, dir)))
4195 + def virtual(self):
4197 + Say if the host is running in a virtual environment.
4199 + return self.hypervisor.virtual
4202 + def network(self):
4204 + Reference to the network class.
4206 + return network.Network()
4209 +if __name__ == "__main__":
4214 + print s.bios_vendor
4219 + print "------------\n", s.devices, "\n------------\n"
4220 + print json.dumps(s.profile(), sort_keys=True, indent=4)
4221 diff --git a/src/sendprofile b/src/sendprofile
4222 new file mode 100644
4223 index 0000000..da480ce
4225 +++ b/src/sendprofile
4228 +###############################################################################
4231 +# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
4233 +# This program is free software: you can redistribute it and/or modify #
4234 +# it under the terms of the GNU General Public License as published by #
4235 +# the Free Software Foundation, either version 3 of the License, or #
4236 +# (at your option) any later version. #
4238 +# This program is distributed in the hope that it will be useful, #
4239 +# but WITHOUT ANY WARRANTY; without even the implied warranty of #
4240 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
4241 +# GNU General Public License for more details. #
4243 +# You should have received a copy of the GNU General Public License #
4244 +# along with this program. If not, see <http://www.gnu.org/licenses/>. #
4246 +###############################################################################
4250 +import logging.handlers
4258 +ENABLED_FILE = "/var/ipfire/main/send_profile"
4259 +PROXY_SETTINGS = "/var/ipfire/proxy/advanced/settings"
4261 +log_level = logging.INFO
4262 +if "-d" in sys.argv:
4263 + log_level = logging.DEBUG
4266 +log = logging.getLogger()
4267 +log.setLevel(log_level)
4268 +log.addHandler(logging.handlers.SysLogHandler("/dev/log"))
4269 +log.addHandler(logging.StreamHandler(sys.stderr))
4270 +for handler in log.handlers:
4271 + handler.setLevel(log_level)
4273 +PROFILE_URL = "http://fireinfo.ipfire.org/send/%(public_id)s"
4275 +def get_upstream_proxy():
4276 + if not os.path.exists(PROXY_SETTINGS):
4277 + return {"host" : ""}
4279 + proxy_settings = {}
4280 + with open(PROXY_SETTINGS) as f:
4281 + for line in f.readlines():
4282 + k, v = line.split("=", 1)
4283 + proxy_settings[k] = v.strip()
4286 + "host" : proxy_settings.get("UPSTREAM_PROXY", ""),
4287 + "user" : proxy_settings.get("UPSTREAM_USER", ""),
4288 + "pass" : proxy_settings.get("UPSTREAM_PASSWORD", ""),
4291 +def send_profile(profile):
4292 + logging.debug("Sending profile:")
4293 + for line in json.dumps(profile, sort_keys=True, indent=4).splitlines():
4294 + logging.debug(line)
4296 + request = urllib2.Request(PROFILE_URL % profile,
4297 + data = urllib.urlencode({"profile" : json.dumps(profile)}),
4299 + request.add_header("User-Agent", "fireinfo/%s" % fireinfo.__version__)
4301 + # Set upstream proxy if we have one.
4302 + # XXX this cannot handle authentication
4303 + proxy = get_upstream_proxy()
4305 + request.set_proxy(proxy["host"], "http")
4308 + urllib2.urlopen(request, timeout=60)
4309 + except (urllib2.HTTPError, urllib2.URLError), e:
4310 + reason = "Unknown reason"
4312 + if isinstance(e, urllib2.HTTPError):
4314 + elif isinstance(e, urllib2.URLError):
4317 + logging.error("Profile was not sent propertly: %s" % reason)
4320 + logging.debug("Profile was sent successfully.")
4323 + # Collect system information
4324 + system = fireinfo.System()
4325 + profile = system.profile()
4327 + # If --dump is passed -> only dump the output.
4328 + if "--dump" in sys.argv:
4329 + # Remove the private id when dumping the profile because
4330 + # it contains no information and may confuse people.
4331 + del profile["private_id"]
4333 + print json.dumps(profile, sort_keys=True, indent=4)
4336 + if "--secret-id" in sys.argv:
4337 + print system.secret_id
4340 + if "--hardware-string" in sys.argv:
4341 + print system._unique_id
4344 + if "--public-id" in sys.argv:
4345 + print system.public_id
4348 + if not os.path.exists(ENABLED_FILE):
4349 + del profile["profile"]
4352 + send_profile(profile)
4353 + except urllib2.URLError: