To check if disk can be read without errors run
dd if=/dev/sda of=/dev/null
If read errors in source disks should be ignored
dd if=/dev/sda of=/media/backupdisk/image.img conv=noerror,sync
Compressing on the fly
dd if=/dev/sda | gzip > disk.img.gz (fast) dd if=/dev/sda | bzip2 > disk.img.bz2 (slow) dd if=/dev/sda | pigz > disk.img.gz (faster)
Uncompressing on the fly
gunzip -c /mnt/sda1/hda.img.gz | dd of=/dev/sda conv=sync,noerror
To get a better compression ratio, first fill the unused sectors of the disk with zeros like this
nice cat /dev/zero > zero.fill sync sleep 1 sync rm -f zero.fill
It is a good idea to backup the disk partition info as well:
fdisk -l /dev/hda > /media/backupdisk/sda_fdisk.info
I encountered the following strange behaviour on my computer: Some programs didn’t respond for a long time whilst the hard disk activity LED was lit all the time but I couldn’t hear any seeking noise from the disk. I took a look at the kernel log and discovered the following:
Apr 16 12:06:45 deepblue kernel: [29731.290118] sd 0:0:0:0: [sda] Unhandled sense code Apr 16 12:06:45 deepblue kernel: [29731.290123] sd 0:0:0:0: [sda] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE Apr 16 12:06:45 deepblue kernel: [29731.290130] sd 0:0:0:0: [sda] Sense Key : Medium Error [current] [descriptor] Apr 16 12:06:45 deepblue kernel: [29731.290140] Descriptor sense data with sense descriptors (in hex): Apr 16 12:06:45 deepblue kernel: [29731.290145] 72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00 Apr 16 12:06:45 deepblue kernel: [29731.290168] 06 8d 51 1e Apr 16 12:06:45 deepblue kernel: [29731.290177] sd 0:0:0:0: [sda] Add. Sense: Unrecovered read error - auto reallocate failed Apr 16 12:06:45 deepblue kernel: [29731.290210] ata1: EH complete
This looked to me like a hard disk failure so I inspected the disk with the smartmontools
sudo smartctl -a /dev/sda
This revealed the following:
Error 2428 occurred at disk power-on lifetime: 1109 hours (46 days + 5 hours) When the command that caused the error occurred, the device was in an unknown state. After command completion occurred, registers were: ER ST SC SN CL CH DH -- -- -- -- -- -- -- 40 51 08 17 51 8d e6 Error: UNC 8 sectors at LBA = 0x068d5117 = 109924631 Commands leading to the command that caused the error were: CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name -- -- -- -- -- -- -- -- ---------------- -------------------- c8 00 08 17 51 8d e6 00 02:07:21.312 READ DMA ec 00 00 00 00 00 a0 00 02:07:18.125 IDENTIFY DEVICE ef 03 46 00 00 00 a0 00 02:07:18.125 SET FEATURES [Set transfer mode] ec 00 00 00 00 00 a0 00 02:07:18.125 IDENTIFY DEVICE
So it seems that I have 8 defective sectors sitting at 0x068d5117 (109924631). Of course I was curious, which file would sit at this position and how I probably could mark this sector as defective. I found this very informative site: [http://smartmontools.sourceforge.net/badblockhowto.html].
I went ahead by checking on which partition this sector sits:
uli@deepblue:~$ sudo fdisk -lu /dev/sda Disk /dev/sda: 160.0 GB, 160041885696 bytes 255 heads, 63 sectors/track, 19457 cylinders, total 312581808 sectors Units = sectors of 1 * 512 = 512 bytes Disk identifier: 0x0009bd2c Device Boot Start End Blocks Id System /dev/sda1 * 63 299805029 149902483+ 83 Linux /dev/sda2 299805030 312576704 6385837+ 5 Extended /dev/sda5 299805093 312576704 6385806 82 Linux swap / Solaris
Seems that the defective sector is located in partition /dev/sda1. We need now the block size of this partition:
uli@deepblue:~$ sudo tune2fs -l /dev/sda1 | grep Block Block count: 37475620 Block size: 4096 Blocks per group: 32768
The following formula finds the corresponding file system block number:
b = (int)((L-S)*512/B) where: b = File System block number B = File system block size in bytes L = LBA of bad sector S = Starting sector of partition as shown by fdisk -lu and (int) denotes the integer part.
Resulting in
b = (int)((109924631-63)*512/4096) = 13740571
With this information we are now able to determine the corresponding file:
uli@deepblue:~$ sudo debugfs debugfs 1.41.9 (22-Aug-2009) debugfs: open /dev/sda1 debugfs: testb 13740571 Block 13740571 marked in use debugfs: icheck 13740571 Block Inode number 13740571 159700 debugfs: ncheck 159700 Inode Pathname 159700 /home/uli/.mozilla/firefox/n87cja9y.default/places.sqlite
We can now check if this file really uses the defective sector by trying to access it
uli@deepblue:~$ cp /home/uli/.mozilla/firefox/n87cja9y.default/places.sqlite delme.bin cp: reading `/home/uli/.mozilla/firefox/n87cja9y.default/places.sqlite': Input/output error
Ouch. Ok. Found. We can now fix it with the following commands
uli@deepblue:~$ sudo dd if=/dev/zero of=/dev/sda1 bs=4096 count=1 seek=13740571 1+0 records in 1+0 records out 4096 bytes (4.1 kB) copied, 7.4032e-05 s, 55.3 MB/s uli@deepblue:~$ sudo sync uli@deepblue:~$ rm /home/uli/.mozilla/firefox/n87cja9y.default/places.sqlite
The file is now lost though - in this case I was lucky though since it was just a dynamically generated data base of firefox. But since ff accessed it very often I was exposed to this defective sector in a heavy way.
You should run a fsck afterwards.
NOTE: THIS IS PURELY INFORMATIVE. EVERYTHING YOU DO YOU DO AT YOUR OWN RISK.
This is available as script from [http://www.pro-linux.de/NB3/artikel/2/140/2,fehlerhafte-festplattensektoren-neu-zuweisen.html] in German.
Comment out the following lines in /etc/pulse/default.pa
load-module module-udev-detect load-module module-detect
and add the following lines below
load-module module-alsa-sink sink_name=M2496_out device=hw:M2496 format=s32le channels=10 channel_map=left,right,aux0,aux1,aux2,aux3,aux4,aux5,aux6,aux7 load-module module-alsa-source source_name=M2496_in device=hw:M2496 format=s32le channels=10 channel_map=left,right,aux0,aux1,aux2,aux3,aux4,aux5,aux6,aux7 set-default-sink M2496_out set-default-source M2496_in
Get source distribution, compile and install:
wget http://phuk.ath.cx:3080/thinkfan/thinkfan-latest.tar.gz tar xzf thinkfan-latest.tar.gz cd thinkfan make sudo cp thinkfan /usr/bin/thinkfan sudo cp thinkfan.conf.thinkpad /etc/thinkfan.conf cd ..
Thinkpad acpi driver must be loaded with fan control enabled. For that we set module loading parameters as required for ubuntu:
sudo echo "options thinkpad_acpi fan_control=1" > /etc/modprobe.d/thinkpad_acpi.conf modprobe -r thinkpad_acpi && modprobe thinkpad_acpi
The thinkfan daemon should be launched at startup, so we need a startup script:
#!/bin/bash
### BEGIN INIT INFO
# Provides: thinkfan
# Required-Start: $syslog
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description:
### END INIT INFO
case "$1" in
start)
echo -n "Starting thinkpad fan control..."
/usr/bin/thinkfan -q -p 1.0
echo "done."
;;
stop)
echo -n "Stopping thinkpad fan control..."
kill `cat /var/run/thinkfan.pid`
echo "done."
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
Save this to a file called thinkfan.sh and:
chmod uga+x thinkfan.sh sudo cp thinkfan.sh /etc/init.d/ sudo sudo update-rc.d thinkfan.sh defaults
for VirtualBox’ USB forwarding the vendor ID and device name must be known.
hwinfo | grep usb
dos2unix `find ./ -name "*.sh"
whereas dos2unix can be any command accepting multiple arguments.
Extract everything between
//START
and
//END
from source.c and print it into target.c
cat source.c | sed -n '/\/\/START/,/\/\/END/ s/.*/&/p' > target.c
Sometimes I really hate ff, because it eats up my memory like mad. One solution which forces ff to free up memory on minimizing it can be set in ff’s preferences. Add boolean
config.trim_on_minimize
and set it to true.
More recent gdb releases on windows stop on every library event. After the first halt enter
set stop-on-solib-events 0
in the gdb command line. This should disable this behavior. Unfortunately this command takes effect not before the first halt. Adding this command to the .gdbinit has no effect.
msiexec.exe /i installer-of-your-program.msi
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite \
-sOutputFile=all.pdf file1.pdf file2.pdf
| I found out that this is only required when the drive is mounted in text mode. When mounted in binary mode no changes are required |
Get the lrzsz package from http://www.ohse.de/uwe/software/lrzsz.html and apply the following patch to src/lsz.c:
$ diff ../src/lsz.c.bak ../src/lsz.c 847c847 < fd=open(tmp,O_WRONLY|O_CREAT|O_EXCL,0700); --- > fd=open(tmp,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0700); 1044c1044 < } else if ((input_f=fopen(oname, "r"))==NULL) { --- > } else if ((input_f=fopen(oname, "rb"))==NULL) {
This fixes the problem that binary sequences in the file like 0x0D 0x0A get corrupted to 0x0A due to windoze/micro$ofts fucked up “textmode”. I should bill them for the time I had problems w/ that.
Note that I have tested lsz only. The correctness of lrz is unknown (and I even read on some lists that there were some problems - perhaps related to this?).
Here some useful commands to use lsz in conjunction w/ redboot:
# set baudrate stty -F /dev/com1 115200 printf "load -r -m ymodem -b 0x30000\n" > /dev/ttyS0 lsz --zmodem ../bin/myOperatingSystem.bin <> /dev/ttyS0 >&0
Copy partition table from one HD to another
sfdisk -d /dev/sda | sfdisk /dev/sdb
List all partitions of all drives
fdisk -l
Runlevels:
When I really dislike something:
#pragma once #include "stdafx.h" #include <vector> #include <string> using namespace std;
This is compiler anti-portability paired with unused headers (the guy was to lazy to check if fsking “stdafx.h” is required at all) and name space spoiling.
$ nohup abcd & $ exitBut the screen application is better.
#! /usr/bin/perl -w # this script encodes your CD library to whatever format using # "a better CD encoder" (abcde) with as few user intervention # as possible (CD changing by hand is required though). use strict; package main; $| = 1; print <<HEADER ; $0 version 1.0 (uli franke <cls\@nebadje.org>) inspired by autorip.pl from jonathan usage guide: 1. configure /etc/abcde.conf 2. run $0 3. drop audio CD into the CD-ROM tray. 4. do something else until autorip ejects your CD. 5. repeat steps 3-4 until CD supply is exhausted. HEADER while (1) { print "Waiting for next disk...\n"; { while (1) { my $error = `cdparanoia -qQ 2>&1`; last if (($? >> 8) == 0); sleep(2); } } # verbosed, non interactive, eject CD when done system ("abcde -N -V -x"); } exit(0);
Get the latest rtl-wifi release from http://rtl-wifi.sourceforge.net/wiki/Installing. I used http://www.hauke-m.de/fileadmin/rtl-wifi/rtl-wifi-20070729.tar.bz2 (rev. 57). Untar it then build it
cd rtl-wifi make
Remove the default ieee80211 modules (you can backup them somewhere outside the /lib/modules directory):
find /lib/modules/`uname -r` -name ieee80211 rm -r /lib/modules/`uname -r`/kernel/net/ieee80211
test your freshly built modules with
insmod ieee80211/ieee80211_crypt-rtl.ko insmod ieee80211/ieee80211_crypt_wep-rtl.ko insmod ieee80211/ieee80211_crypt_tkip-rtl.ko insmod ieee80211/ieee80211_crypt_ccmp-rtl.ko insmod ieee80211/ieee80211-rtl.ko insmod rtl818x-newstack/r8180.ko
Perhaps you setup your network before doing this by adding your wireless configuration similar to the following to your /etc/network/interfaces file
# Wireless
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wireless-mode managed
wireless-essid XXXXXXXXXXXXXXX
wireless-key XXXXXXXXXXXXXXXXXXXXXXXX
wireless-keymode restricted
If you can connect to your network the modules have to be installed such that they get loaded at boot time. The make install mentioned in the rtl-wifi wiki did not work, therefore you have to install them manually (from within your rtl-wifi dir):
cp iee80211/*.ko /lib/modules/$(uname -r)/kernel/net/ieee80211/ cp rtl818x-newstack/r8180.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/
Then rebuild the modules dependency database (found in /lib/modules/$(uname -r)/modules.dep) with
depmod
And finally add your modules as follows to your /etc/modules file (the modules listed there get loaded at boot time):
ieee80211_crypt-rtl ieee80211_crypt_wep-rtl ieee80211_crypt_tkip-rtl ieee80211_crypt_ccmp-rtl ieee80211-rtl r8180
That’s it. Any questions? Email me: cls{A_T}nebadje{D_O_T}org
To get a swiss keyboard running w/ the default Cygwin installation Roller found out that you have to install a symbolic link
ln -s de de_CH
in
/etc/X11/xkb/symbols/pc
The umlauts and accents won’t work but at least all important keys are mapped correctly.
tar xzf expat-2.0.0.tar.gz tar xjf whatever.tar.bz2
% first this
\usepackage{listings}
% then this (listings settings, can be redefined for each code inclusion ...)
\lstset{% general command to set parameter(s)
basicstyle=\small\ttfamily, % print whole listing small and typewriter
keywordstyle=\color{blue}\bfseries, % bold blue keywords
identifierstyle=, % nothing happens
commentstyle=\color{red}, % white comments
stringstyle=\ttfamily\emph, % typewriter type for strings
showstringspaces=false, %
frame=tRBl, %
language=[ANSI]C, %
tabsize=4,
numbers=left,
numberstyle=\tiny,
stepnumber=2,
numbersep=5pt}
% finally this here...
\lstinputlisting[]{../../firmware/globals.h}
I love John Carpenter’s Dark Star
\documentclass[a4paper,twoside,10pt]{letter}
\usepackage[ansinew]{inputenc} % äü...
\pagestyle{plain}
\usepackage{a4}
% uncomment if envelope address labels should be printed
% \makelabels
\address{
Va Fanculo\\
Via Stronza 2\\
666 Zurigo\\
Switzerland}
\telephone{0041 44 XXX XX XX}
\name{Uli Franke}
\signature{Uli}
\begin{document}
\begin{letter}{
Rolf Anderegg\\
Hell's Avenue 667\\
8055 Zürich\\
Switzerland}
\opening{Liebster Roller,}
Hei, so geil. Ab jetzt schreibe ich meine Briefe nur noch in \LaTeX2e \ldots
\closing{Alles Gute, Dein}
\end{letter}
\end{document}
$ startx$ tgif&rm Tgif.tmpl cp Tgif.tmpl-cygwin Tgif.tmpl xmkmf make tgif.exe make install
The dynamic libraries on MacOS X have to reside in /usr/local/lib. The linker includes the paths to the dylibs in the executable what makes it difficult to have dylibs on different locations. If an application has to be “self-contained” and must be installable without copying to any system directories (by leaving the libraries in the bundle) but it relies on dynamic libraries (.dylib) it can be chosen between two methods:
DYLD_LIBRARY_PATH (adding the path of the dylib location). This can be useful for debugging but not for distribution.
Method 2. is described up to a certain degree here. This information has to be extended by mentioning that when linking the binaries (libraries and executables) the -headerpad_max_install_names should be turned on. Otherwise complications may arise due to the fact that there is no room for a change of the pathnames of the dynamic libraries to the new locations. Furthermore when using a library consisting of several dynamic libraries (e.g. wxWidgets) all library-internal cross references have to be removed (replaced) too. In the case of wxWidgets the library has been linked internally to the major.minor.micro named versions of the dynamic libraries (e.g. libwx_mac_qa-2.6.0.dylib).
To accomplish this task I’ve written a bash script which is listed here:
WXLIBPOSTFIX=*wx*2.6.0.dylib APP=WorldApp WXLIBDIR=../../../wxwidgets/build-dynamic/lib BINDIR=./build/Release/$APP.app/Contents/MacOS LIBDEFDIR=/usr/local/lib echo "Copying dynamic libraries to " $BINDIR " ..." cp $WXLIBDIR/*.dylib $BINDIR echo "Changing directory to " $BINDIR " ..." export TMP=$PWD cd $BINDIR # patch all wx dynlibs and Saracon executable for file in `ls $WXLIBPOSTFIX` do # patch all library internal cross references echo "Patching " $file "..." for fileother in `ls $WXLIBPOSTFIX ` do # library echo " Patching " $fileother " with " $file "..." install_name_tool -change $LIBDEFDIR/$file @executable_path/$file $fileother done # patch current library itself install_name_tool -id @executable_path/$file $file # patch executable install_name_tool -change $LIBDEFDIR/$file @executable_path/$file $APP done cd $TMP
This script can be added for instance to the build phases of XCode (after linking) or called from within of a makefile. Make sure that it’s a bash shell, others might cause errors.
The following variables are required and must be set by the user:
WXLIBPOSTFIX: The wx dylib pattern which matches the desired version and wx-internal cross references. APP: The executable name.WXLIBDIR: Directory of the wxWidgets dylibs (can also be a system directory when installed)BINDIR: Directory of the executable AND dylibs (it’s a limitation of this script but it can be adapted easily)LIBDEFDIR: Default dylib directory when linking (ususally it’s /usr/local/lib). It can be found out when inspecting the crash report...
Fotos der Pantani Memorial Velotour 2006 können hier heruntergeladen werden: pantani-2006-uli.zip (6MB)



Some Script-Fu scripts to efficiently handle repetitive image processing jobs.
If a class which allocates memory dynamically provides a copy constructor and overloads the assignment operator, then another class which uses this class as a member will do deep copies of those objects automatically.
A good team player
Detection of audio signals can become handy for remote amplifiers which switch on autonomously on audio input activity and turn of after a certain delay.
The circuit presented here is an excerpt of an upcoming project here at nebadje and it has been designed and simulated last weekend (18.02.2006) by jns and cls. The simulation makes use of a very nice feature of LT-Spice (see next section): The ability of using wav-files as voltage source.
The circuit is a precision full-wave rectifier combined with an integrator (at the second operational amplifier U2). It rectifies the audio input signal and integrates the result with a timeconstant formed by R4 and C1. U2 is single supply but that s not mandatory, it’s simply useful when this part of the circuit is operated on a digital board.
The green graph (top) shows the input, the blue (bottom) the output. Click the pictures for larger view. The project file for LT-Spice is available here.
How to monitor negative voltages with a microcontroller which is powered by a positive voltage (e.g. 5V) using only the 5V supply and as few components as possible? Make use of the virtual ground of an single supplied opamp in inverting amplifier operation. The common node of R1 and R2 will be at 0V and the current through R2 will be copied into R1, because of the very high input impedance of the opamp.
|
The upper graph is the output the lower the input. Rail-to-rail opamps are more suitable than the opamp used in this example (LT1001). The LM324 (LM124 = single) for example swings down to ground even when powered from a single positive supply. Citing its datasheet:
In the linear mode the input common-mode voltage range includes ground and the output voltage can also swing to ground, even though operated from only a single power supply voltage
The SPICE analysis shown here was done with LT-Spice.
[cls] 2006/02/11 00:04
We had many confused users who did not know how to get to the registration page. This button (rendered beneath the “login” button of our current DokuWiki template) should solve this issue.
<?php /** Generates buttons with $caption calling the link * specified in $link. * $ author: cls$ */ function html_link_button($caption,$link){ $ret = ''; $ret = '<a href="'.htmlspecialchars($link).'"><input type="button" class="button" value="'.htmlspecialchars($caption).'" /></a>'; print $ret; } /** Generates a button which opens the "Register" page within * DokuWiki, when ACL is enabled and the current user is not * logged in. * $ author: cls$ */ function html_register_button(){ global $conf; if($conf['useacl']){ if($_SERVER['REMOTE_USER']){ }else{ html_link_button('Register', '?id=start&do=register'); } } } ?>
Patch for the ./lib/exe/fetch.php module of the DokuWiki. Logs all (currently scanning for .mp3 files) downloads passing through fetch.php and writes the details to a log file located in ./data/medialog.log.
To patch your current DokuWiki distribution, perform the following steps:
Add the following line to the “fetch” code (to the end, before the functions):
addMediaLogEntry($FILE);
Add the following line to the ./conf/dokuwiki.php main configuration file:
$conf['medialog'] = 'medialog.log'; //must be placed in data dir
And create the empty text file ./data/medialog.log.
Finally append the following function to the end of the fetch.php file.
/** * Add's an entry to the media log * HACK! currently logs only mp3 * Stolen and adapted from the generic * addLogEntry function. * @author Uli Franke <xxx@nebadje.org> */ function addMediaLogEntry($mediafile){ global $conf; //log only mp3 if(!(substr($mediafile,-3,3) == 'mp3')){ return; } $file = DOKU_INC.$conf['savedir'].'/'.$conf['medialog']; if(!@is_writable($file)){ msg($file.' is not writable!',-1); return; } //$date = time(); //somehow human readable $timestamp = time(); $date = date("Y.m.d - H:i",$timestamp); $remote = $_SERVER['REMOTE_ADDR']; $user = $_SERVER['REMOTE_USER']; $size = filesize($mediafile); $logline = join("\t",array($date,$remote,$user,$size,$mediafile))."\n"; io_saveFile($file,$logline,true); }
The entries in the generated logfile look like:
| Time | IP | User | Size [Bytes] | File |
|---|---|---|---|---|
1139663347 | 80.254.166.165 | chaib | 9109944 | /.../tracks/klangforschung/waermeregefilde.mp3 |
2006.02.11 - 14:09 | 80.254.166.165 | chaib | 9109944 | /.../tracks/klangforschung/waermeregefilde.mp3 |
If you like to log all downloads (attention: this includes every stupid picture every user gets displayed), modify the following lines of the above function according to your needs.
//log only mp3 if(!(substr($mediafile,-3,3) == 'mp3')){ return; }
Logging functionality without analysis doesn’t make sense somehow. Therefor here some code which generates a nice table listing all users sorted by their download behaviour.
The function has to be located in a function.php (or similar) file located in the template directory and the function itself has to be added to the main.php just below the wiki generator (or somewhere else if you like)1). The download logging patch is running of course. To get the statistics displayed
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); require_once (DOKU_INC.'inc/auth.php'); /** Print out statistics. global arguments: * * name: 'stat' * value: 'dwn': download statistics * */ function html_print_statistics(){ global $conf; $STATS = $_REQUEST['stat']; //print $STATS; if ( auth_quickaclcheck('') < AUTH_ADMIN ) return; if ( $STATS == 'dwn' ){ $filename = DOKU_INC.$conf['savedir'].'/'.$conf['medialog']; $handle = @fopen($filename, "r"); if ($handle) { $entries = array(); while (!feof($handle)) { // get a line from log file $buffer = fgets($handle, 4096); // parse line into words $words = array(); $numwords = 0; $lastwordpos = 0; for( $i = 0; $i < strlen($buffer) ; $i++) { // space or tab found if ( $buffer{$i} == "\t" || $buffer{$i} == " " ){ $words[$numwords] = substr($buffer, $lastwordpos, $i - $lastwordpos); trim( $words[$numwords] ); $numwords++; $lastwordpos = $i; } } // one entry per user gets accumulated $entries[$words[2]] = $entries[$words[2]] + $words[3]; } // sort (highest at top (idx=0)) arsort ($entries); $users = array_keys($entries); $amount = array_values($entries); $i = 0; print ' <br><br> <a name="download_statistics"></a><h1>Download Statistics</h1> <br> <table class="inline"> <tr> <th class="rightalign">User:</th> <th class="rightalign">Data [Bytes]</th> </tr>'; foreach( $users as $a ){ print '<tr>'; print '<td class="rightalign">'.$users[$i].'</td>'; print '<td class="rightalign">'.$amount[$i].'</td>'; print '</tr>'; $i++; } print '</table><br><br>'; } fclose($handle); } }
@require_once(dirname(FILE).’/functions.php’); to the head of the file