572 lines
16 KiB
C
572 lines
16 KiB
C
/*
|
|
* This function will set up a session to the TSM server and return the
|
|
* session handler
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <termio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "dsmrc.h"
|
|
#include "dsmapitd.h"
|
|
#include "dsmapifp.h"
|
|
|
|
#include "../tsmpipe.h"
|
|
|
|
dsBool_t compressEnabled=bFalse; // Is compression enabled
|
|
|
|
/* Print out TSM Error Code */
|
|
char *tsm_printerr(dsUint32_t dsmHandle, dsInt16_t rc) {
|
|
char rcStr[DSM_MAX_RC_MSG_LENGTH];
|
|
char *s;
|
|
|
|
s = malloc(sizeof(rcStr));
|
|
|
|
if (rc == DSM_RC_WILL_ABORT) {
|
|
dsUint16_t reason;
|
|
|
|
rc = dsmEndTxn(dsmHandle, DSM_VOTE_COMMIT, &reason);
|
|
|
|
if (rc == DSM_RC_CHECK_REASON_CODE)
|
|
rc = reason;
|
|
}
|
|
|
|
dsmRCMsg(dsmHandle,rc,rcStr);
|
|
|
|
strtok(rcStr, "\n");
|
|
|
|
sprintf(s,"[rc=%s]",rcStr);
|
|
|
|
return s;
|
|
}
|
|
|
|
/* Check the TSM API Version */
|
|
int tsm_checkapi(void) {
|
|
dsmApiVersionEx apiLibVer;
|
|
dsUint32_t apiVersion;
|
|
dsUint32_t applVersion = (10000 * DSM_API_VERSION) + (1000 * DSM_API_RELEASE) + (100 * DSM_API_LEVEL) + DSM_API_SUBLEVEL;
|
|
|
|
memset(&apiLibVer,0x00,sizeof(dsmApiVersionEx));
|
|
apiLibVer.stVersion = apiVersionExVer;
|
|
dsmQueryApiVersionEx(&apiLibVer);
|
|
|
|
apiVersion = (10000 * apiLibVer.version) + (1000 * apiLibVer.release) + (100 * apiLibVer.level) + apiLibVer.subLevel;
|
|
|
|
if (apiVersion < applVersion) {
|
|
printf("The Tivoli Storage Manager API library Version (%d.%d.%d.%d) is at a lower version than the application version (%d.%d.%d.%d)\n",
|
|
apiLibVer.version,
|
|
apiLibVer.release,
|
|
apiLibVer.level,
|
|
apiLibVer.subLevel,
|
|
DSM_API_VERSION,
|
|
DSM_API_RELEASE,
|
|
DSM_API_LEVEL,
|
|
DSM_API_SUBLEVEL);
|
|
|
|
printf("Please upgrade the API accordingly.\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Initialise a session to the TSM server */
|
|
dsUint32_t tsm_initsess(char *options, char *password) {
|
|
dsInt16_t rc=0;
|
|
dsUint32_t dsmHandle=0;
|
|
dsmApiVersionEx applApi;
|
|
dsmInitExIn_t initIn;
|
|
dsmInitExOut_t initOut;
|
|
optStruct dsmOpt;
|
|
ApiSessInfo dsmSessInfo;
|
|
|
|
if (! tsm_checkapi()) {
|
|
exit(2);
|
|
}
|
|
|
|
memset(&applApi,0x00,sizeof(dsmApiVersionEx));
|
|
applApi.stVersion = apiVersionExVer;
|
|
applApi.version = DSM_API_VERSION;
|
|
applApi.release = DSM_API_RELEASE;
|
|
applApi.level = DSM_API_LEVEL;
|
|
applApi.subLevel = DSM_API_SUBLEVEL;
|
|
|
|
memset(&initIn,0x00,sizeof(dsmInitExIn_t));
|
|
initIn.stVersion = dsmInitExInVersion;
|
|
initIn.apiVersionExP = &applApi;
|
|
initIn.clientNodeNameP = NULL;
|
|
initIn.clientOwnerNameP = NULL;
|
|
initIn.clientPasswordP = password;
|
|
initIn.applicationTypeP = NULL;
|
|
initIn.configfile = NULL;
|
|
initIn.options = options;
|
|
initIn.userNameP = NULL;
|
|
initIn.userPasswordP = NULL;
|
|
//initIn.dirDelimiter = dirDelimiter;
|
|
//initIn.useUnicode = useUnicode;
|
|
//initIn.bEncryptKeyEnabled = encrypt;
|
|
//initIn.encryptionPasswordP = encryptKey;
|
|
|
|
memset(&initOut,0x00,sizeof(dsmInitExOut_t));
|
|
initOut.stVersion = dsmInitExOutVersion;
|
|
|
|
rc = dsmInitEx(&dsmHandle, &initIn, &initOut);
|
|
|
|
/* If the TSM password has expired, change it. */
|
|
if (rc == DSM_RC_REJECT_VERIFIER_EXPIRED) {
|
|
rc = dsmChangePW(dsmHandle,NULL,NULL);
|
|
|
|
if (rc != DSM_RC_OK) {
|
|
printf("%s: dsmChangePW() failed %s\n",__func__,tsm_printerr(dsmHandle,rc));
|
|
dsmTerminate(dsmHandle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
} else if (rc != DSM_RC_OK) {
|
|
printf("%s: dsmInitEx() failed %s\n",__func__,tsm_printerr(dsmHandle, rc));
|
|
dsmTerminate(dsmHandle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Make sure if we have compression enabled, that we also have COMPRESSAlways YES
|
|
memset(&dsmOpt,0x00,sizeof(dsmOpt));
|
|
rc = dsmQuerySessOptions(dsmHandle, &dsmOpt);
|
|
|
|
memset(&dsmSessInfo,0x00,sizeof(ApiSessInfo));
|
|
dsmSessInfo.stVersion = ApiSessInfoVersion; /* Init struct version */
|
|
rc = dsmQuerySessInfo(dsmHandle, &dsmSessInfo);
|
|
|
|
rc = 1;
|
|
switch (dsmSessInfo.compression) {
|
|
case COMPRESS_YES : compressEnabled = bTrue; break;
|
|
case COMPRESS_NO : compressEnabled = bFalse; break;
|
|
case COMPRESS_CD : compressEnabled = dsmOpt.compression; break;
|
|
default: rc=0;
|
|
}
|
|
|
|
if (!rc || (compressEnabled && ! dsmOpt.compressalways)) {
|
|
debugLog(0,__func__,!rc ? "ERROR: Error Querying Session Capabilities" : "ERROR: COMPRESSion is ENABLED, but not COMPRESSAlways Yes",1);
|
|
}
|
|
|
|
return dsmHandle;
|
|
}
|
|
|
|
/* List objects that are in TSM */
|
|
int tsm_sessioninfo(dsUint32_t dsmHandle) {
|
|
extern int verbose;
|
|
dsInt16_t rc=0;
|
|
optStruct dsmOpt;
|
|
ApiSessInfo dsmSessInfo;
|
|
dsmApiVersionEx apiLibVer;
|
|
char t[50];
|
|
|
|
memset(&apiLibVer,0x00,sizeof(dsmApiVersionEx));
|
|
apiLibVer.stVersion = apiVersionExVer;
|
|
dsmQueryApiVersionEx(&apiLibVer);
|
|
|
|
printf("Application Version:\n");
|
|
printf(" TSMPIPE Version: %s\n",
|
|
_TSMPIPE_VERSION);
|
|
printf(" TSMPIPE API Version: %d.%d.%d.%d\n",
|
|
DSM_API_VERSION,
|
|
DSM_API_RELEASE,
|
|
DSM_API_LEVEL,
|
|
DSM_API_SUBLEVEL);
|
|
|
|
printf(" TSM Library: %d.%d.%d.%d\n",
|
|
apiLibVer.version,
|
|
apiLibVer.release,
|
|
apiLibVer.level,
|
|
apiLibVer.subLevel);
|
|
printf("\n");
|
|
|
|
memset(&dsmOpt,0x00,sizeof(dsmOpt));
|
|
rc = dsmQuerySessOptions(dsmHandle, &dsmOpt);
|
|
|
|
if (rc)
|
|
printf("%s: ERROR dsmQuerySessOptions() unable to query Session Options. RC = %d\n",__func__,rc);
|
|
else {
|
|
printf("dsmQuerySessOptions:\n");
|
|
printf(" DSMI_DIR: %s\n",dsmOpt.dsmiDir);
|
|
printf(" DSMI_CONFIG: %s\n",dsmOpt.dsmiConfig);
|
|
printf(" SErvername: %s\n",dsmOpt.serverName);
|
|
|
|
switch (dsmOpt.commMethod) {
|
|
case DSM_COMM_TCP : strcpy(t,"TCP/IP"); break;
|
|
case DSM_COMM_NAMEDPIPE : strcpy(t,"NAMED PIPE"); break;
|
|
case DSM_COMM_SHM : strcpy(t,"SHARED MEMORY"); break;
|
|
case DSM_COMM_TCPIP6 : strcpy(t,"TCP/IP v6"); break;
|
|
default: strcpy(t,"UNKNOWN");
|
|
}
|
|
|
|
printf(" COMMmethod: %s\n",t);
|
|
if (verbose)
|
|
fprintf(stderr,"%s: commMethod: [%d]\n",__func__,dsmOpt.commMethod);
|
|
|
|
printf(" TCPServerAddress: %s\n",dsmOpt.serverAddress);
|
|
if (verbose)
|
|
fprintf(stderr,"%s: serverAddress: [%s]\n",__func__,dsmOpt.serverAddress);
|
|
printf(" NODEName: %s\n",dsmOpt.nodeName);
|
|
printf(" COMPRESSIon: %s\n",dsmOpt.compression ? "YES" : "NO");
|
|
printf(" COMPRESSAlways: %s\n",dsmOpt.compressalways ? "YES" : "NO");
|
|
printf(" PASSWORDAccess: %s\n",dsmOpt.passwordAccess ? "GENERATE" : "PROMPT");
|
|
}
|
|
|
|
memset(&dsmSessInfo,0x00,sizeof(ApiSessInfo));
|
|
dsmSessInfo.stVersion = ApiSessInfoVersion; /* Init struct version */
|
|
rc = dsmQuerySessInfo(dsmHandle, &dsmSessInfo);
|
|
|
|
if (rc)
|
|
printf("%s: ERROR dsmQuerySessInfo() unable to query Session Info. RC = %d\n",__func__,rc);
|
|
else {
|
|
printf("\n");
|
|
printf("dsmQuerySessInfo:\n");
|
|
printf(" Server Information:\n");
|
|
printf(" Name: %s\n",dsmSessInfo.adsmServerName);
|
|
printf(" Host: %s\n",dsmSessInfo.serverHost);
|
|
printf(" Port: %u\n",dsmSessInfo.serverPort);
|
|
printf(" Date: %s\n",dsmDateToStr(dsmSessInfo.serverDate));
|
|
printf(" Type: %s\n",dsmSessInfo.serverType);
|
|
printf(" Version: %i.%i.%i.%i\n",
|
|
dsmSessInfo.serverVer,
|
|
dsmSessInfo.serverRel,
|
|
dsmSessInfo.serverLev,
|
|
dsmSessInfo.serverSubLev);
|
|
printf(" Archive Retention Protection : %s\n",dsmSessInfo.archiveRetentionProtection ? "YES" : "NO");
|
|
printf("\n");
|
|
printf(" Client Information:\n");
|
|
printf(" Node: %s\n",dsmSessInfo.id);
|
|
printf(" Node Type: %s\n",dsmSessInfo.nodeType);
|
|
printf(" Filespace delimiter: %c\n",dsmSessInfo.fsdelim);
|
|
printf(" HL & LL delimiter: %c\n",dsmSessInfo.hldelim);
|
|
|
|
switch (dsmSessInfo.compression) {
|
|
case COMPRESS_YES : strcpy(t,"ON"); break;
|
|
case COMPRESS_NO : strcpy(t,"OFF"); break;
|
|
case COMPRESS_CD : strcpy(t,"CLIENT"); break;
|
|
default: strcpy(t,"UNKNOWN");
|
|
}
|
|
printf(" Client compression: %s\n",t);
|
|
|
|
switch (dsmSessInfo.archDel) {
|
|
case ARCHDEL_YES : strcpy(t,"YES"); break;
|
|
case ARCHDEL_NO : strcpy(t,"NO"); break;
|
|
default: strcpy(t,"UNKNOWN");
|
|
}
|
|
printf(" ARCHIVE Delete: %s\n",t);
|
|
|
|
switch (dsmSessInfo.backDel) {
|
|
case BACKDEL_YES : strcpy(t,"YES"); break;
|
|
case ARCHDEL_NO : strcpy(t,"NO"); break;
|
|
default: strcpy(t,"UNKNOWN");
|
|
}
|
|
printf(" BACKUP delete: %s\n",t);
|
|
|
|
printf(" MAX objects per transactions: %u\n", dsmSessInfo.maxObjPerTxn);
|
|
printf(" LAN FREE Enabled: %s\n",dsmSessInfo.lanFreeEnabled ? "YES" : "NO");
|
|
printf(" Deduplication: %s\n",dsmSessInfo.dedupType == dedupClientOrServer ? "Client Or Server" : "Server Only");
|
|
printf("\n");
|
|
printf(" General session info:\n");
|
|
printf(" Owner: %s\n",dsmSessInfo.owner);
|
|
printf(" API Config file: %s\n",dsmSessInfo.confFile);
|
|
printf("\n");
|
|
printf(" Policy Information:\n");
|
|
printf(" Domain name: %s\n",dsmSessInfo.domainName);
|
|
printf(" Policyset name: %s\n",dsmSessInfo.policySetName);
|
|
printf(" Policy activation date: %s\n",dsmDateToStr(dsmSessInfo.polActDate));
|
|
printf(" Default management class: %s\n",dsmSessInfo.dfltMCName);
|
|
printf(" BACKUP retention grace: %u days\n",dsmSessInfo.gpBackRetn);
|
|
printf(" ARCHIVE retention grace: %u days\n",dsmSessInfo.gpArchRetn);
|
|
printf("\n");
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Query TSM for a list of objects.
|
|
*
|
|
* We use a callback to process the list, the callback should return:
|
|
* -1 upon error condition, application should exit.
|
|
* 0 if tsm_queryfile() should skip processing the remaining matches.
|
|
* 1 otherwise.
|
|
*/
|
|
dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly) {
|
|
extern int verbose;
|
|
dsInt16_t rc=0;
|
|
dsmQueryBuff *qDataP;
|
|
|
|
DataBlk qResp;
|
|
memset(&qResp,0x00,sizeof(DataBlk));
|
|
qResp.stVersion = DataBlkVersion;
|
|
|
|
switch (qType) {
|
|
case qtArchive:
|
|
qDataP = &qaData;
|
|
|
|
qryRespArchiveData qaResp;
|
|
|
|
qResp.bufferLen = sizeof(qaResp);
|
|
qResp.bufferPtr = (char *) &qaResp;
|
|
|
|
qaResp.stVersion = qryRespArchiveDataVersion;
|
|
|
|
if (verbose)
|
|
fprintf(stderr,"%s: Query filespace %s\n",__func__,dsmObjnameToStr(*qaData.objName));
|
|
|
|
break;
|
|
|
|
case qtBackup:
|
|
qDataP = &qbData;
|
|
|
|
qryRespBackupData qbResp;
|
|
|
|
qResp.bufferLen = sizeof(qbResp);
|
|
qResp.bufferPtr = (char *) &qbResp;
|
|
|
|
qbResp.stVersion = qryRespBackupDataVersion;
|
|
|
|
if (verbose)
|
|
fprintf(stderr,"%s: Query filespace %s\n",__func__,dsmObjnameToStr(*qbData.objName));
|
|
if (verbose > 1) {
|
|
fprintf(stderr,"%s: PIT Date: %s\n",__func__,dsmDateToStr(qbData.pitDate));
|
|
fprintf(stderr,"%s: OBJSTATE : %s\n",__func__,qbData.objState==DSM_ACTIVE ? "DSM_ACTIVE" : "DSM_ANY_MATCH");
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr,"%s: UNKNOWN Type %d\n",__func__,qType);
|
|
exit(1);
|
|
}
|
|
|
|
rc = dsmBeginQuery(dsmHandle, qType, qDataP);
|
|
if (rc != DSM_RC_OK) {
|
|
printf("%s: dsmBeginQuery() failed %s\n",__func__,tsm_printerr(dsmHandle,rc));
|
|
return rc;
|
|
}
|
|
|
|
/* Loop and apply our callback to the result */
|
|
while ((rc = dsmGetNextQObj(dsmHandle, &qResp)) == DSM_RC_MORE_DATA) {
|
|
int cbret;
|
|
|
|
if(verbose > 1) {
|
|
dsmObjName *rObjName;
|
|
|
|
if (qType == qtArchive) {
|
|
qryRespArchiveData *qr = (void *) qResp.bufferPtr;
|
|
rObjName = &(qr->objName);
|
|
|
|
} else if (qType == qtBackup) {
|
|
qryRespBackupData *qr = (void *) qResp.bufferPtr;
|
|
rObjName = &(qr->objName);
|
|
|
|
} else {
|
|
fprintf(stderr,"%s: UNKNOWN Type %d\n",__func__,qType);
|
|
|
|
return DSM_RC_UNKNOWN_ERROR;
|
|
}
|
|
|
|
fprintf(stderr,"%s: Match file %s\n",__func__,dsmObjnameToStr(*rObjName));
|
|
}
|
|
|
|
if (usercb == NULL)
|
|
continue;
|
|
|
|
cbret = usercb(qType,&qResp,userdata,friendly);
|
|
if (cbret < 0) {
|
|
return DSM_RC_UNKNOWN_ERROR;
|
|
|
|
} else if(cbret == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rc != DSM_RC_FINISHED && rc != DSM_RC_MORE_DATA) {
|
|
printf("%s: dsmGetNextQObj() failed %s\n",__func__,tsm_printerr(dsmHandle,rc));
|
|
return rc;
|
|
}
|
|
|
|
rc = dsmEndQuery(dsmHandle);
|
|
if (rc != DSM_RC_OK) {
|
|
printf("%s: dsmEndQuery() failed %s\n",__func__,tsm_printerr(dsmHandle,rc));
|
|
return rc;
|
|
}
|
|
|
|
return DSM_RC_OK;
|
|
}
|
|
|
|
/* Signal handler */
|
|
int intrupt = 0;
|
|
void Catch(int signo) {
|
|
if(signo) {}; /* so compiler won't complain about unused arguments */
|
|
|
|
intrupt = 1;
|
|
}
|
|
|
|
/* Uses sigaction to establish signal handler */
|
|
int install_sig_handler(int signum, void (*sig_handler)(int)) {
|
|
struct sigaction action;
|
|
int rc;
|
|
|
|
action.sa_handler = sig_handler; /* signal handler function */
|
|
sigemptyset( &action.sa_mask ); /* mask of signals to block */
|
|
|
|
action.sa_flags = SA_NOCLDSTOP;
|
|
|
|
rc = sigaction(
|
|
signum, /* I */ /* signal identifier */
|
|
&action, /* *I */ /* new action for signal */
|
|
NULL ); /* *O */ /* previous action - not needed */
|
|
|
|
return (rc);
|
|
}
|
|
|
|
int ReadPass(char *text, char *buffer, int length) {
|
|
struct termio ttyState, ttyStateSave;
|
|
register char *p;
|
|
register int c;
|
|
int rc;
|
|
FILE *ttyFH;
|
|
|
|
struct sigaction action;
|
|
|
|
/* Let's flush any prompt to the terminal that may be pending. */
|
|
fflush(stdout);
|
|
|
|
/* Open the console input device */
|
|
if((ttyFH = fopen("/dev/tty", "r")) == NULL)
|
|
return(-1);
|
|
else
|
|
setbuf(ttyFH, (char *)NULL);
|
|
|
|
/* Reset the interrupt flag */
|
|
intrupt = 0;
|
|
|
|
/* Trap the "BREAK" interrupt */
|
|
(void) sigaction( SIGINT, NULL, &action ); /* save current hdlr */
|
|
(void) install_sig_handler( SIGINT, Catch ); /* install new hdlr */
|
|
|
|
/* Get current state */
|
|
rc = ioctl(fileno(ttyFH), TCGETA, &ttyStateSave);
|
|
if (rc == -1)
|
|
return(-1);
|
|
|
|
/* Copy the saved tty state into a work field */
|
|
ttyState = ttyStateSave;
|
|
|
|
/* Turn off ECHO */
|
|
ttyState.c_lflag &= ~ECHO;
|
|
rc = ioctl(fileno(ttyFH), TCSETA, &ttyState);
|
|
if (rc == -1)
|
|
return(-1);
|
|
|
|
printf(text);
|
|
|
|
/* Read the password (quietly) */
|
|
for(p=buffer; !intrupt && (c = getc(ttyFH)) != '\n' && c != EOF; ) {
|
|
if(p < buffer+length)
|
|
*p++ = c;
|
|
}
|
|
*p = '\0';
|
|
|
|
printf("\n");
|
|
|
|
/* Restore the tty state settings */
|
|
rc = ioctl(fileno(ttyFH), TCSETA, &ttyStateSave);
|
|
if (rc == -1)
|
|
return(-1);
|
|
|
|
/* Reset the interrupt handler */
|
|
(void) sigaction( SIGINT, &action, NULL );
|
|
|
|
if(ttyFH != stdin)
|
|
(void) fclose(ttyFH);
|
|
if(intrupt)
|
|
(void) kill(getpid(), SIGINT);
|
|
|
|
return(strlen(buffer));
|
|
}
|
|
|
|
/*
|
|
* Set the TSM Node password
|
|
*
|
|
* We use a callback to process the list, the callback should return:
|
|
*/
|
|
int tsm_setpassword(char *options) {
|
|
uint32 dsmHandle;
|
|
bool_t done = bFalse;
|
|
uint16 pw_trys = 0;
|
|
uint16 len = 0;
|
|
char input[INPUTLEN];
|
|
char pw_cur[DSM_MAX_VERIFIER_LENGTH + 1];
|
|
char pw_new [DSM_MAX_VERIFIER_LENGTH + 1];
|
|
|
|
int rc;
|
|
|
|
while (!done) {
|
|
// Current Password
|
|
rc = ReadPass("Enter your current password: ",input,INPUTLEN);
|
|
len = strlen(input);
|
|
if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) {
|
|
printf("Current password is invalid. Please try again.\n");
|
|
continue;
|
|
} else {
|
|
strcpy(pw_cur,input);
|
|
}
|
|
|
|
// New password
|
|
rc = ReadPass("Enter your new password: ",input,INPUTLEN);
|
|
len = strlen(input);
|
|
if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) {
|
|
printf("New password is invalid. Please try again.\n");
|
|
continue;
|
|
} else {
|
|
strcpy(pw_new,input);
|
|
}
|
|
|
|
// Verify new password
|
|
rc = ReadPass("Enter your new password again: ",input,INPUTLEN);
|
|
len = strlen(input);
|
|
if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) {
|
|
printf("New password is invalid. Please try again.\n");
|
|
continue;
|
|
|
|
} else {
|
|
// Compare new pw copies to make sure no typos from user.
|
|
if ((strcmp(pw_new,input))) {
|
|
pw_trys++;
|
|
|
|
if (pw_trys > 3)
|
|
debugLog(0,__func__,"ERROR: Passwords dont match, tried too many times.",3);
|
|
else
|
|
debugLog(0,__func__,"WARN: Your new passwords do not match, please try again...",0);
|
|
|
|
} else {
|
|
done = bTrue;
|
|
}
|
|
}
|
|
}
|
|
|
|
dsmHandle = tsm_initsess(options,pw_cur);
|
|
if (! dsmHandle) {
|
|
debugLog(0,__func__,"ERROR: Unable to create TSM session with your password.",2);
|
|
}
|
|
|
|
rc = dsmChangePW(dsmHandle,pw_cur,pw_new);
|
|
if (rc)
|
|
debugLog(0,__func__,"ERROR: Password change failed.",2);
|
|
else
|
|
printf("\nYour new password has been accepted and updated.\n");
|
|
|
|
dsmTerminate(dsmHandle);
|
|
|
|
return 1;
|
|
}
|