They say it's better late than never, so here's a quick (& somewhat dirty) suggestion for the "conditional" sending of the PIN to the modem.
'chat' is very limited in control flow, by reading the man page the best solution i could figure was to ALWAYS send the PIN and use the "subexpect-subsend" option. This is how it goes:
AT+CPIN=1234 TIMEOUT 5 ERROR-AT-OK
### end chatscript
With my modem, a Huawei 1556 (internally a E620 according to lsusb) if the sim is not locked, then the command to send the pin, "AT+CPIN=1234" will unlock it and return "OK", meanwhile if it was already unlocked by some previous use, the "AT+CPIN=1234" would return "ERROR".
Thus the logic is as follows: the script always sends the command, expecting "ERROR" (assuming the modem was previously unlocked).
If the modem was unlocked, it will respond with "ERROR" and everything will be fine, the -AT-OK part will be ignored and execution will continue with the AT+CGDCONT...
If the modem was locked, then it will respond with "OK" (which is wrong from chat's point of view, since it expected "ERROR", but this will unlock the modem anyway!). Since chat got a bad response it will tend to terminate with an error, but having the optional "-AT-OK" keeps it from dying and allows it to continue. A "send AT expect OK" should be harmless anyway
The TIMEOUT 5 is in order to accelerate the time before the optional part (AT-OK) is executed, otherwise the default is 45 seconds which is kind of too much. Since whenever the sim is really unlocked by the command, execution is stopped by 5 seconds, it has the (accidental) added benefit of giving the device enough time to hook onto the 3G network.
(this solution reminds me of badly written programs who abuse function side effects to carry out their logic in an unclear way...but hey)
When i have some time i will check the "expect" program which apparently allows "complex" (in terms of logic) scripts.