Sri Lanka showed resistance on day four of the first Test but South Africa need just five wickets to take a series lead in Port Elizabeth after Kagiso Rabada and Keshav Maharaj claimed two wickets apiece.
The Proteas declared on 406-6 early on the penultimate day after Quinton de Kock was removed for 69, leaving captain Faf du Plessis unbeaten on 67 and the tourists needing a highly improbable 488 to win.
Kusal Mendis (58) made an impressive half-century before paceman Rabada (2-72) struck for a second time, having already removed Kaushal Silva (48) after tea, as Sri Lanka closed on 240-5, needing another 248 to claim an unlikely victory in the first of three Tests.
Angelo Mathews was 58 not out at stumps, but it will take a Herculean effort from his side to deny South Africa on the final day after Maharaj (2-84) also struck twice.
Earlier, du Plessis and de Kock brought up their half-centuries as South Africa chased quick runs after the pair resumed on 351-5.
The skipper and de Kock had put on 129 by the time the wicketkeeper-batsman was trapped leg before by veteran spinner Rangana Herath (1-84), prompting the declaration.
Dimuth Karunaratne (43) and Silva set about frustrating South Africa with a battling opening stand of 87, the latter riding his luck when de Kock failed to hang on to a difficult chance off Rabada.
The pair saw Sri Lanka through to 27 without loss at lunch, with the sun beating down on a flat pitch. Silva showed his quality with some elegant drives, but had another slice of fortune when Dean Elgar was unable to cling on to another tricky catch at midwicket.
An elusive breakthrough came when JP Duminy ran out Karunaratne, who fell seven short of his half-century, and the tourists were 118-2 at tea after spinner Maharaj snared Kusal Perera caught behind.
The rapid Rabada had Silva leg before just after the interval, but Mendis and Mathews looked comfortable as they showed great discipline, combined with some textbook strokes on a surface which still offered little for the bowlers.
Mendis was rewarded for a mature innings with a third Test half-century, but was trudging back to the pavilion after attempting to guide Rabada for his 10th boundary and edging through to de Kock.
The unflappable Mathews looked untroubled, but Dinesh Chandimal (8) failed to cash in after Stephen Cook dropped a simple chance, as Rabada held on to give the persistent Maharaj a second scalp.
Dhananjaya de Silva (9no) succeeded with a review after Kyle Abbott was given an lbw decision, Mathews then passing 50 after the Proteas took the second new ball, but Sri Lanka will undoubtedly need something special to avoid defeat on day five.