Fausto Marzoli: (not only) things I write down to remember, sometimes in italian
domenica 9 febbraio 2014
Del perche' la lampada a basso consumo sucks
Ho nostalgia della cara, vecchia illuminazione artificiale a incandescenza; le lampadine a basso consumo mi fanno schifo!
1) Costano 10 volte tanto le lampadine ad incancescenza: OTTO euro, dico otto euro minimo. Non se ne trovano a meno. Si, magari in un discount trovi lo scaffale con quelle a due euro, ma sono rottami che a malapena si accendono. Una lampadina standard quanto costava? Un euro? due? Zerocinquanta?
2) Durano UGUALE a quelle standard. Questa e' la mia percezione, non un dato oggettivo: mi sembra che si rompano con la stessa frequenza delle vecchie lampadine. Magari durano un po' di piu', ma poco. E non me ne accorgo.
3) Fanno una luce atroce. Alcune (quelle da DUE euro di cui sopra) secondo me fanno BUIO: attirano la luce ambiente come piccoli, malevoli buchi neri. Producono una luce vibrante, ci mettono un quarto d'ora ad accendersi e mezz'ora ad arrivare alla luce emessa massima; ho tre lampadine a basso consumo in bagno e rischio di tagliarmi quando mi faccio la barba se non mi alzo mezz'ora prima per accenderle!
4) COME CA**O PENSANO DI SMALTIRE QUELLE ROTTE? Una lampadina classica era un pezzo di vetro pieno di vuoto (o gas inerte) con un po' di latta: reciclabile al 100%, costo zero. Una lampadina a basso consumo e' fatta di: plastica, metallo, vetro, gas (non si sa bene quale e quanto dannoso sia), circuito stampato, stagno, rame, componenti elettronici vari. E forse ho dimenticato qualche pezzo.
NON E' RECICLABILE. Infatti non si sa mai dove buttarla.
5) Mi rompono le balle con la coscienza ecologica, e poi sul viale fuori casa c'e' accesa per tutta la notte un'alogena da centomilioni di kilowatt ogni cinque metri. Bah.
Spero solo nell'avvento dei LED, che pero' porteranno con se' il problema del flickering nella regolazione della luminosita' (problema gia' presente nei monitor LCD retroilluminati a LED).
venerdì 31 gennaio 2014
Install skype 4.2 on a linux system without GLIBCXX_3.4.15
Install Skype 4.2 on OpenSuSE 11.4
(a system without GLIBCXX_3.4.15)OpenSuSE 11.4 lacks GLIBCXX_3.4.15 (has GLIBCXX_3.4.14 only), while Skype 4.2 needs it.
You can verify which GLIBCXX you have installed with:
strings /usr/lib/libstdc++.so.6 | grep GLIBCIt is possible to install it anyway:
- Download Skype 4.2 for OpenSuSE 12.1 from [http://www.skype.com/it/download-skype/skype-for-linux/]
- Install skype ignoring the failed dependency warning
- Downlad libstdc++6-4.7.3_20130411-96.1.i586.rpm from [http://download.opensuse.org/repositories/devel:/gcc/openSUSE_12.2/i586/]
- Copy libstdc++6-4.7.3_20130411-96.1.i586.rpm in your ~/bin directory or somewhere else in your home
- cd ~/bin (or wherever you copied the rpm)
- Extract locally the rpm file with the command:
rpm2cpio libstdc++6-4.7.3_20130411-96.1.i586.rpm | cpio -idmv - Run skype from a terminal with the command:
LD_LIBRARY_PATH=/home/yourname/bin/usr/lib/:/usr/lib/:/usr/local/lib/ skype
domenica 29 dicembre 2013
Define TRUE and FALSE in C
What is FALSE and TRUE in C?
The C standard does not explicitly define TRUE and FALSE, you have to do it somewhere in your headers. Which is the best practice to define them?
It's not such a dumb question, because you may fall in this case:
To be honest, the problem is that writing
As shown above, it's not a so good approach, although works in most cases.
The reasons for that are good: enum will add some static-assign-checking of the Boolean declared variables. Not so much checking indeed, enum is not a great checker in C: can't check dinamically assigned varibles, and enum variables are typically int.
This is another good approach: the FALSE condition in C/C++ is ALWAYS == 0; on the contrary, TRUE condition is not always 0, but usually is a "NOT 0" condition. On the other side, the
Beside that, someone suggest:
Rather than this, I like more:
Here it is:
In order to avoid the
Using the solution (2), you may want to use also the following small functions/MACRO to set and clear bits:
(or you can pass a pointer to
They are quite the same. The result is exactly the same. I think that it's slightly better
Theoretically, you can't know how the compiler expand
Given the de facto rules that zero is interpreted as FALSE and any non-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUE or FALSE. Examples:
The right way to do this is either
Isn't that worth it?
The C standard does not explicitly define TRUE and FALSE, you have to do it somewhere in your headers. Which is the best practice to define them?
It's not such a dumb question, because you may fall in this case:
#define MASKBIT_0 0x01
#define MASKBIT_1 0x02
#define MASKBIT_2 0x04
...
unsigned int bits;
...
if (bits & MASKBIT_2) {
...
}
The example above works correctly, but if you are somewhere absent and you accidentally write: #define FALSE 0
#define TRUE 1
if ((bits & MASKBIT_2) == TRUE) {
...
}
The "if" test will fail, also if MASKBIT_2 is set. This is because ((bits & MASKBIT_2) == 4), that is not 1 (your defined TRUE).To be honest, the problem is that writing
if ((bits & MASKBIT_2) == TRUE) is not correct (you should use the if (bits & MASKBIT_2) semantics), but it's obvious what it means and I'd prefer there was a way to define TRUE and FALSE so that this kind of test would be supported.Approach 1
#define FALSE 0 #define TRUE 1
As shown above, it's not a so good approach, although works in most cases.
Approach 2
Some experienced programmer ("The Linux Programming Interface", not exactly a johnny-come-lately...) suggest the following: typedef enum { FALSE, TRUE } Boolean;
The reasons for that are good: enum will add some static-assign-checking of the Boolean declared variables. Not so much checking indeed, enum is not a great checker in C: can't check dinamically assigned varibles, and enum variables are typically int.
Approach 3
Other experienced programmer (i.e. gnome glib) suggest that:#define FALSE 0 #define TRUE (!(FALSE))
This is another good approach: the FALSE condition in C/C++ is ALWAYS == 0; on the contrary, TRUE condition is not always 0, but usually is a "NOT 0" condition. On the other side, the
if ((bits & MASKBIT_2) == TRUE) test will fail anyway: (!(FALSE)) is expanded as a constant (usually 1). There is no static-assign-checking.Beside that, someone suggest:
#define TRUE (1==1) #define FALSE (!TRUE)
Rather than this, I like more:
#define FALSE (1==0) #define TRUE (!(FALSE))In this way, you automatically assign the FALSE value also if (for a strange, rare case) your compiler DOES NOT use 0 as a FALSE value, and you assign a TRUE as the negation. This is "logically" good, but does not solve che
if ((bits & MASKBIT_2) == TRUE) problem.The MIX
So what I could do to mix-up the best practices?Here it is:
typedef enum { FALSE = (1==0), TRUE = (1==1) } boolean;
In order to avoid the
if ((bits & MASKBIT_2) == TRUE) problem, I suggest the following solutions:- 1) Use the following function or a similar macro:
boolean test (int val) { return (val > 0); }usage:if (test(bits & MASKBIT_2))- 2) Do not use bitmask
#definessuch as MASKBIT_2, instead use the following function or a similar macro: boolean test (unsigned int bitpool, int bitnr) { return ((bitpool & (1 << bitnr)) != 0); }usage:if (test(bits, 2))
test() function. You can always define verbose bit names such as:#define MYBIT 2
Using the solution (2), you may want to use also the following small functions/MACRO to set and clear bits:
unsigned int set (unsigned int bitpool, int bitnr)
{
return (bitpool | (1 << bitnr));
}
unsigned int clr (unsigned int bitpool, int bitnr)
{
return (bitpool & ~(1 << bitnr));
}
(or you can pass a pointer to
bitpool, if you prefer).(!(FALSE)) or (1==1)?
It's better to use this?:#define TRUE (!(FALSE))or this?:
#define TRUE (1==1)
They are quite the same. The result is exactly the same. I think that it's slightly better
#define TRUE (1==1) only because reading (!(FALSE)) may let you think that the result is anything else than FALSE, which is not correct.Theoretically, you can't know how the compiler expand
(!(FALSE)). Remember that FALSE is an int value you defined before: hypotetically, the compiler could expand (!(FALSE)) with a different value than (1==1); for example, it could expand #define FALSE (1==0) with 0, and (!(FALSE)) with -1 or 0xFFFFFFFF, and on the contrary expand (1==1) with 1. I don't think that any compiler do that, anyway.Best Practices
I found the following "Best Practices" on a forum discussion:Given the de facto rules that zero is interpreted as FALSE and any non-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUE or FALSE. Examples:
if (thisValue == FALSE) // Don't do this! if (thatValue == TRUE) // Or this! if (otherValue != TRUE) // Whatever you do, don't do this!Why? Because many programmers use the shortcut of treating ints as bools. They aren't the same, but compilers generally allow it. So, for example, it's perfectly legal to write
if (strcmp(yourString, myString) == TRUE) // Wrong!!!That looks legitimate, and the compiler will happily accept it, but it probably doesn't do what you'd want. That's because the return value of strcmp() is
0 if yourString == myString <0 if yourString < myString >0 if yourString > myStringSo the line above returns TRUE only when yourString > myString.
The right way to do this is either
// Valid, but still treats int as bool. if (strcmp(yourString, myString))or
// Better: lingustically clear, compiler will optimize. if (strcmp(yourString, myString) != 0)Similarly:
if (someBoolValue == FALSE) // Redundant. if (!someBoolValue) // Better. return (x > 0) ? TRUE : FALSE; // You're fired. return (x > 0); // Simpler, clearer, correct. if (ptr == NULL) // Perfect: compares pointers. if (!ptr) // Sleazy, but short and valid. if (ptr == FALSE) // Whatisthisidonteven.You'll often find some of these "bad examples" in production code, and many experienced programmers swear by them: they work, some are shorter than their (pedantically?) correct alternatives, and the idioms are almost universally recognized. But consider: the "right" versions are no less efficient, they're guaranteed to be portable, they'll pass even the strictest linters, and even new programmers will understand them.
Isn't that worth it?
Conclusions
I'm not sure that my considerations are defintely good. I may ignore something that is important for this topic. Discussion is open.mercoledì 10 luglio 2013
Chrome: problema audio ("saltellante") nelle riproduzioni video
Soluzione:
- Scrivere chrome://plugins nella barra degli indirizzi; premere invio
- A destra, cliccate su "+ Dettagli"
- Nella categoria di plugins Flash ci saranno 2 o 3 plugins; bisogna disabilitare quello in cui nel percorso c'è scritto "Pepperflash"
- Chiudere Chrome e riaprirlo
- Se ci sono ancora dei problemi, cliccare sulla chiave inglese -> strumenti -> cancella dati di navigazione -> selezionare solo la cache e dare l' OK
giovedì 4 luglio 2013
Disabling reverse DNS lookups in ssh
Disabling reverse DNS lookups in ssh
Reverse DNS lookup is the procedure used by sshd and other login daemons (i.e. telnet, ftp, etc.) for checking the truth of IP addresses of the incoming connection.Often in embedded systems networks there is no Internet connection, and no DNS server: in this case, ssh login may require a lot of time (30 sec. or more) or can even be impossible (if sshd has been compiled with the PARANOID option).
Reverse DNS lookup can be disabled on the sshd server side:
First of all, you can make "UseDNS no" in /etc/ssh/sshd_config file, default answer is yes and if this line not shown in your config file, just add it to as below:
UseDNS no
This directive tells sshd process to check resolved host name for the connected client's ip address maps back to the very same ip address or not.
However, it does not prevent the sshd server from performing any DNS lookups at all. That's not the purpose of that directive.
In order to remove dns lookups completely, you have to use -u0 options when starting sshd server. You can easily add this options to /etc/default/ssh or /etc/sysconfig/sshd or elsewhere suitable for your distribution.
-u0 option's means that it will not put hostnames into the utmp structure (i.e. what you see when you type "who" at the shell prompt), which means that sshd will not perform DNS lookups for that purpose. However there are still cases where a lookup has to be performed when a user has
"from=<hostname>"
like entries in his authorized_keys file, or when authentication methods or configuration directives are used that involve hostnames.
With this method you can disable ssh reverse DNS lookup for most situations; it's not a system-wide disable, anyway.
For a system-wide solution, you should consider installing a local DNS cache server like dnsmasq and configure it to false the DNS check results in local networks (bogus-priv option), like described here:
http://forums.gentoo.org/viewtopic-t-455597-start-0.html
http://wiki.debian.org/HowTo/dnsmasq
martedì 18 giugno 2013
The printf recursive substitution trap (bug)
Working with embedded linux boards make me use systems that are often not so much up-to-dated.
Kernel is often dated, compiler is often dated, libraries are often dated.
On a system I'm using, the cross compiler is gcc 3.3.2 and the glibc version is 2.2.5.
On this system I've found a bug in the glibc printf family functions, quite difficult to track.
The bug seems to be caused by a recursive substitution in the printf arguments: in printf("%s", text), if the text string includes itself the string "%s" again, the program on my embedded system crashes (with a no more specified "Killed" message).
No help with core dump, strace and dbg: I had to track down step by step to find that the crash happens on a snprintf call, ONLY if the substitution argument string contains a "%s".
So, what I think happens (but I'm not 100% sure) is that the substitution is made recursively also on the second "%s" found, and the program is killed by the kernel OOM Killer (Out-Of-Memory Killer) because the resulting string can't be allocated.
Nice.
Experimenting workarounds, I've found that the bug affects also the strcat functions (maybe it's based on sprintf). I had to use memcpy.
This bug is not present on another embedded system I'm using with a more recent glibc.
Kernel is often dated, compiler is often dated, libraries are often dated.
On a system I'm using, the cross compiler is gcc 3.3.2 and the glibc version is 2.2.5.
On this system I've found a bug in the glibc printf family functions, quite difficult to track.
The bug seems to be caused by a recursive substitution in the printf arguments: in printf("%s", text), if the text string includes itself the string "%s" again, the program on my embedded system crashes (with a no more specified "Killed" message).
No help with core dump, strace and dbg: I had to track down step by step to find that the crash happens on a snprintf call, ONLY if the substitution argument string contains a "%s".
So, what I think happens (but I'm not 100% sure) is that the substitution is made recursively also on the second "%s" found, and the program is killed by the kernel OOM Killer (Out-Of-Memory Killer) because the resulting string can't be allocated.
Nice.
Experimenting workarounds, I've found that the bug affects also the strcat functions (maybe it's based on sprintf). I had to use memcpy.
This bug is not present on another embedded system I'm using with a more recent glibc.
lunedì 17 giugno 2013
Nexus7: WiFi Hotspot app (che funziona!)
L'abilitazione delle opzioni per Tethering/WiFi Hotspot sul Nexus7 e' stato un problema fin dalla sua uscita.
Ora finalmente e' disponibile una app che rende il WiFi Hotspot attivo e funzionante: WiFi Tether Router di Fabio Grasso.
Lo sviluppatore e' italiano, attivo e disponibile a rispondere alle email degli utenti rapidamente e con efficienza.
Il router WiFi creato e' di tipo "infrastruttura" e quindi supporta la connessione di piu' dispositivi client.
L'applicazione richiede i permessi di root, e a tal proposito rimando al mio articolo relativo: Nexus 7: rooting da un PC Linux
Con questa applicazione si completano le capacita' di tethering del Nexus7:
- Via Bluetooth, utilizzando PdaNet
- Via USB, utilizzando AziLink (o PdaNet stesso, sotto Windows)
- Via WiFi, utilizzando WiFi Tether Router
Iscriviti a:
Post (Atom)