/* ncpreadprops - print a list of NDS properties of current user Copyright (C) 2001 by Patrick Pollet This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Revision history: 1.00 2001 Nov 02 Patrick Pollet the program is an extension of ncpreadprop to allow: a list of NDS properties a separator between them the first idea was to put in the attribute buffer the list of requested attributes: IT WORKS BUT NDS does not return attributes in the same order example: ./ncpreadprops -o ppollet -A "Postal Address,Full Name,LINUX:uid,Home Directory,CN" -c PC --> Ppollet:0 CN=FCPC2_APPS home\ppollet:1 2 3 4 5 6:Patrick Pollet:9999 1.01 2001 Nov 03 Patrick Pollet we call ReadAttributeValue for every attribute of the list !!! 1.02 2001 Dec 16 Petr Vandrovec const <-> non const pointers cleanup 1.03 2002 June 6 Patrick Pollet emission of separator between multiple values 1.04 2002 Sept 16 Patrick Pollet emission of separator between multiple values when attributes are not read at once */ #include #include #include #include #include #include #include #include #include #include #include #include "getopt.h" #include "private/libintl.h" #define _(X) X static char *progname; static void __attribute__((noreturn)) usage(void) { fprintf(stderr, _("usage: %s [options] \n"), progname); exit(1); } static void help(void) { printf(_("\n" "usage: %s [options] \n"), progname); printf(_("\n" "-h Print this help text\n" "-o object_name Mandatory: Object name \n" "-A attribute_liste Mandatory: One NDS attribute or a comma separated list\n" "-T treename \n" "-c context Default= [root]\n" "-v value Context DCK_FLAGS default=0 \n" "-f character separator between attributes (default= :)\n" "-m character separator between values of multi-valued attributes (default = space) \n" "\n")); exit(1); } static int doPrintOut (NWDSContextHandle ctx, const void * name, const enum SYNTAX synt, char sep ) { /* do not emit CR here */ /* sep is the caracter used to separate multiples values such as postal address or home directory*/ (void) ctx; switch (synt) { case SYN_DIST_NAME: case SYN_CI_STRING: case SYN_CE_STRING: case SYN_PR_STRING: case SYN_NU_STRING: case SYN_TEL_NUMBER: case SYN_CLASS_NAME: printf("%s", (const char*)name); break; case SYN_OCTET_STRING:{ const Octet_String_T* os = (const Octet_String_T*)name; size_t i; printf("%u%c", os->length,sep); for (i = 0; i < os->length; i++) printf("%02X%c", os->data[i],sep); } break; case SYN_COUNTER: case SYN_INTEGER: case SYN_INTERVAL: printf("%u", *((const Integer_T*)name)); break; case SYN_BOOLEAN:{ const Boolean_T* b = (const Boolean_T*)name; printf("%s", (*b==1)?"true":(*b)?"unknown":"false"); } break; case SYN_TIMESTAMP:{ const TimeStamp_T* stamp = (const TimeStamp_T*)name; printf("%u%c%u%c%u",stamp->wholeSeconds,sep, stamp->replicaNum,sep,stamp->eventID); } break; case SYN_NET_ADDRESS:{ const Net_Address_T* na = (const Net_Address_T*)name; size_t z; printf("%u%c%u%c", na->addressType,sep,na->addressLength,sep); for (z = 0; z < na->addressLength; z++) printf("%02X%c", na->address[z],sep); } break; case SYN_OBJECT_ACL:{ const Object_ACL_T* oacl = (const Object_ACL_T*)name; printf("%s%c%s%c%08x", oacl->protectedAttrName,sep,oacl->subjectName,sep,oacl->privileges); } break; case SYN_PATH:{ const Path_T* p = (const Path_T*)name; printf("%u%c%s%c%s", p->nameSpaceType,sep,p->volumeName,sep, p->path); } break; case SYN_TIME:{ printf("%s", ctime((const Time_T*)name)); } break; case SYN_TYPED_NAME:{ const Typed_Name_T* tn = (const Typed_Name_T*)name; printf("%u%c%u%c%s", tn->interval,sep, tn->level,sep, tn->objectName); } break; case SYN_CI_LIST:{ const CI_List_T* cl = (const CI_List_T*)name; for (; cl; cl = cl->next) printf("%s", cl->s); } break; case SYN_OCTET_LIST:{ const Octet_List_T* ol = (const Octet_List_T*)name; for (; ol; ol = ol->next) { size_t i; printf("%u%c", ol->length,sep); for (i = 0; i < ol->length; i++) printf("%02X%c", ol->data[i],sep); } } break; case SYN_BACK_LINK:{ const Back_Link_T* bl = (const Back_Link_T*)name; printf("%08X%c%s", bl->remoteID, sep,bl->objectName); } break; case SYN_FAX_NUMBER:{ const Fax_Number_T* fn = (const Fax_Number_T*)name; printf("%s%c%u", fn->telephoneNumber, sep,fn->parameters.numOfBits); } break; case SYN_EMAIL_ADDRESS:{ const EMail_Address_T* ea = (const EMail_Address_T*)name; printf("%u%c%s", ea->type, sep,ea->address); } break; case SYN_PO_ADDRESS:{ const NWDSChar*const* pa = (const NWDSChar*const*)name; printf("%s%c%s%c%s%c%s%c%s%c%s",pa[0],sep,pa[1],sep,pa[2],sep,pa[3],sep,pa[4],sep,pa[5]); } break; case SYN_HOLD:{ const Hold_T* h = (const Hold_T*)name; printf("%u%c%s", h->amount,sep,h->objectName); } break; default: printf(" *** "); /* don't mess up display */ return 1; } return 0; } static NWCCODE readAttributeValue( NWDSContextHandle ctx, char * objName,char *attrName, char sepvalue) { Buf_T* inbuf=NULL; Buf_T* outbuf=NULL; NWDSCCODE dserr; nuint32 iterHandle; size_t size = DEFAULT_MESSAGE_LEN; iterHandle = NO_MORE_ITERATIONS; /*test at bailout point */ dserr = NWDSAllocBuf(size, &inbuf); if (dserr) { fprintf(stderr, "NWDSAllocBuf() failed with %s\n", strnwerror(dserr)); goto bailout; } dserr = NWDSInitBuf(ctx, DSV_READ, inbuf); if (dserr) { fprintf(stderr, "NWDSInitBuf() failed with %s\n", strnwerror(dserr)); goto bailout; } dserr = NWDSPutAttrName(ctx, inbuf, attrName); if (dserr) { fprintf(stderr, "NWDSPutAttrName(%s) failed with %s\n", attrName, strnwerror(dserr)); goto bailout; } dserr = NWDSAllocBuf(size, &outbuf); if (dserr) { fprintf(stderr, "NWDSAllocBuf() failed with %s\n", strnwerror(dserr)); goto bailout; } do { NWObjectCount attrs; dserr = NWDSRead(ctx, objName, DS_ATTRIBUTE_VALUES, 0, inbuf, &iterHandle, outbuf); if (dserr) { if (dserr == ERR_NO_SUCH_ATTRIBUTE) { /*fprintf(stderr, "NWDSRead() failed with %s\n", strnwerror(dserr));*/ dserr = 0; } else fprintf(stderr, "NWDSRead() failed with %s\n", strnwerror(dserr)); goto bailout; } dserr = NWDSGetAttrCount(ctx, outbuf, &attrs); if (dserr) { fprintf(stderr, "NWDSGetAttrCount() failed with %s\n", strnwerror(dserr)); goto bailout; } /*fprintf(stderr, "%d attributes found\n", attrs);*/ while (attrs--) { NWDSChar attrname[MAX_SCHEMA_NAME_CHARS+1]; enum SYNTAX synt; NWObjectCount vals; dserr = NWDSGetAttrName(ctx, outbuf, attrname, &vals, &synt); if (dserr) { fprintf(stderr, "NWDSGetAttrName() failed with %s\n", strnwerror(dserr)); goto bailout; } /*fprintf(stderr, "%d values found\n", vals);*/ while (vals--) { size_t sz; void* val; dserr = NWDSComputeAttrValSize(ctx, outbuf, synt, &sz); if (dserr) { fprintf(stderr, "NWDSComputeAttrValSize() failed with %s\n", strnwerror(dserr)); goto bailout; } val = malloc(sz); if (!val) { fprintf(stderr, "malloc() failed with %s\n", strnwerror(ENOMEM)); goto bailout; } dserr = NWDSGetAttrVal(ctx,outbuf, synt, val); if (dserr) { free(val); fprintf(stderr, "NWDSGetAttrVal() failed with %s\n", strnwerror(dserr)); goto bailout; } dserr=doPrintOut (ctx,val,synt,sepvalue); free(val); if (dserr) { fprintf(stderr, "doPrintOut failed with %s\n", strnwerror(dserr)); goto bailout; } if ((vals) || (iterHandle != NO_MORE_ITERATIONS)) printf("%c", sepvalue); /* emit separator between values */ } } } while (iterHandle != NO_MORE_ITERATIONS); bailout:; if (iterHandle != NO_MORE_ITERATIONS) { /* let's keep the final dserr as the real one */ NWDSCCODE dserr2 = NWDSCloseIteration(ctx, DSV_READ, iterHandle); if (dserr2) { fprintf(stderr, "NWDSCloseIteration() failed with %s\n", strnwerror(dserr2)); } } if (inbuf) NWDSFreeBuf(inbuf); if (outbuf) NWDSFreeBuf(outbuf); return dserr; } static NWCCODE readAttributesValues( NWDSContextHandle ctx, char * objName,char *attrName, char sepvalue, char sepattr) { /* scan the list of attributes*/ char attrBuf[MAX_DN_CHARS+1]; const char * attrStart; const char * attrEnd; attrStart=attrName; do { if (attrStart) { attrEnd=strchr(attrStart,','); if (attrEnd) { memcpy(attrBuf,attrStart,attrEnd - attrStart); attrBuf[attrEnd-attrStart]=0; attrEnd++; } else strcpy(attrBuf,attrStart); attrStart=attrEnd; } readAttributeValue(ctx, objName,attrBuf, sepvalue); if (attrStart) printf("%c",sepattr); /* emit separator exepct after the last attribute*/ } while (attrStart); printf("\n"); /* change line here */ return 0; } int main(int argc, char *argv[]) { long err; int opt; char * objectName=NULL; char * attributeName=NULL; const char * contextName="[Root]"; char * server=NULL; char sepvalue=' '; /*default separator between multiple values is space */ char sepattr=':'; /* default separator between attributes is :*/ NWDSContextHandle ctx=NULL; NWCONN_HANDLE conn=NULL; NWDSCCODE dserr,dserr2; u_int32_t ctxflag = 0; char treeName [MAX_TREE_NAME_CHARS +1]=""; progname = argv[0]; NWCallsInit(NULL, NULL); #ifndef N_PLAT_MSW4 NWDSInitRequester(); #else setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif while ((opt = getopt(argc, argv, "h?o:A:T:c:S:v:f:m:")) != EOF) { switch (opt) { case 'h': case '?': help(); case 'A': attributeName=optarg; break; case 'T': if (strlen(optarg)