South Africa need 352 runs to win the first Test against Sri Lanka after the hosts were bowled out for 190 in their second innings in Galle.
Veteran Dale Steyn claimed his 421st wicket in Test cricket on the third day to equal the South African record held by Shaun Pollock when he dismissed last man Lakshan Sandakan.
South Africa faced three overs before lunch and reached 0-5.
Sri Lanka were bowled out 20 minutes before lunch.
With a first-innings lead of 161 runs, they were feeling comfortable on a wicket that was favourable to spin.
The hosts resumed on 4-111 on Saturday and slumped to 7-134, with Kagiso Rabada playing a part in all three dismissals.
Overnight batsman Roshen Silva was dismissed for 13.
Going in for the fifth over of his spell in the morning, Rabada dismissed Niroshan Dickwella and Dilruwan Perera in the space of three deliveries.
Dickwella was caught behind by Quinton de Kock, while Perera was trapped lbw after he offered no stroke to a delivery that cut back in.
With Perera's dismissal, Rabada completed 150 wickets in Test cricket.