To expand on Ben's answer, it works conceptually exactly the same way in PL/pgSQL. The only difference is that the syntax is a bit different - when the trigger calls your PL/pgSQL function it has access to both the new and old row being affected by the DML statement. Just like in Oracle.
Check portal_tables_audit_update in portals.sql and the trigger definition that calls it for an example of how we're maintaining audit tables.
The major difference is that the trigger definition must call a separately defined function, as there's no notion of an inline PL/pgSQL block. In Oracle you can define the relevant code right in the trigger. Slightly clumsy, I guess, but it means you can write the trigger in assembly or C if you don't like PL/pgSQL :)