|
|
1.1 ! root 1: /* imagesbr.c - image subroutines */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/others/image/RCS/imagesbr.c,v 7.4 90/04/18 08:50:12 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/others/image/RCS/imagesbr.c,v 7.4 90/04/18 08:50:12 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: imagesbr.c,v $ ! 12: * Revision 7.4 90/04/18 08:50:12 mrose ! 13: * typo ! 14: * ! 15: * Revision 7.3 90/03/29 20:39:18 mrose ! 16: * update ! 17: * ! 18: * Revision 7.2 90/03/15 11:18:10 mrose ! 19: * quipu-sync ! 20: * ! 21: * Revision 7.1 90/03/08 08:04:12 mrose ! 22: * touch-up ! 23: * ! 24: * Revision 7.0 89/11/23 21:59:58 mrose ! 25: * Release 6.0 ! 26: * ! 27: */ ! 28: ! 29: /* ! 30: * NOTICE ! 31: * ! 32: * Acquisition, use, and distribution of this module and related ! 33: * materials are subject to the restrictions of a license agreement. ! 34: * Consult the Preface in the User's Manual for the full terms of ! 35: * this agreement. ! 36: * ! 37: */ ! 38: ! 39: ! 40: #include <ctype.h> ! 41: #include <stdio.h> ! 42: #include <varargs.h> ! 43: #include "imagesbr.h" ! 44: #include "quipu/bind.h" ! 45: #include "quipu/ds_search.h" ! 46: #include "quipu/entry.h" ! 47: ! 48: /* GENERAL */ ! 49: ! 50: static char *myname = "image"; ! 51: ! 52: int recording = 0; ! 53: ! 54: static LLog _pgm_log = { ! 55: "./image.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, ! 56: LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK ! 57: }; ! 58: LLog *pgm_log = &_pgm_log; ! 59: ! 60: ! 61: /* AKA */ ! 62: ! 63: struct aka { ! 64: struct aka *ak_forw; ! 65: struct aka *ak_back; ! 66: ! 67: char *ak_domain; ! 68: char *ak_local; ! 69: ! 70: struct dn_seq *ak_bases; ! 71: struct type_IMAGE_Image *ak_image; ! 72: }; ! 73: static struct aka akas; ! 74: static struct aka *AHead = &akas; ! 75: ! 76: ! 77: static int stay_bound = 0; ! 78: ! 79: DN local_dn; ! 80: ! 81: ! 82: struct dn_seq *dm2dn_seq (); ! 83: ! 84: ! 85: extern char *local_dit; ! 86: struct dn_seq *dn_seq_push (); ! 87: int dn_seq_print (); ! 88: ! 89: /* */ ! 90: ! 91: void init_aka (pgm, stayopen, dit) ! 92: char *pgm, ! 93: *dit; ! 94: int stayopen; ! 95: { ! 96: char *cp; ! 97: register struct aka *ak; ! 98: static int once_only = 0; ! 99: ! 100: if (once_only == 0) { ! 101: int argp; ! 102: char *arg[2], ! 103: **argptr; ! 104: ! 105: quipu_syntaxes (); ! 106: ! 107: argp = 0; ! 108: arg[argp++] = myname; ! 109: arg[argp] = NULLCP; ! 110: ! 111: dsap_init (&argp, (argptr = arg, &argptr)); ! 112: ! 113: once_only = 1; ! 114: } ! 115: stay_bound = stayopen; ! 116: myname = pgm; ! 117: ! 118: AHead -> ak_forw = AHead -> ak_back = AHead; ! 119: if ((ak = (struct aka *) calloc (1, sizeof *ak)) == NULL) ! 120: adios (NULLCP, "out of memory"); ! 121: ! 122: ak -> ak_domain = ak -> ak_local = ""; ! 123: ! 124: insque (ak, AHead -> ak_back); ! 125: ! 126: if ((local_dn = str2dn (cp = dit ? dit ! 127: : *local_dit != '@' ? local_dit ! 128: : local_dit + 1)) ! 129: == NULLDN) ! 130: adios (NULLCP, "local_dit invalid: \"%s\"", cp); ! 131: } ! 132: ! 133: /* */ ! 134: ! 135: static struct aka *mbox2ak (local, domain) ! 136: char *local, ! 137: *domain; ! 138: { ! 139: register struct aka *ak, ! 140: *am; ! 141: ! 142: if (domain == NULL) ! 143: domain = ""; ! 144: if (local == NULL) ! 145: local = ""; ! 146: ! 147: for (ak = AHead -> ak_forw; ak != AHead; ak = ak -> ak_forw) ! 148: if (!lexequ (domain, ak -> ak_domain) ! 149: && !lexequ (local, ak -> ak_local)) { ! 150: if (recording) ! 151: LLOG (pgm_log, LLOG_NOTICE, ! 152: ("hit \"%s\" \"%s\"", domain, local)); ! 153: ! 154: return ak; ! 155: } ! 156: ! 157: if ((am = (struct aka *) calloc (1, sizeof *am)) == NULL ! 158: || (am -> ak_domain = strdup (domain)) == NULL ! 159: || (am -> ak_local = strdup (local)) == NULL) ! 160: adios (NULLCP, "out of memory"); ! 161: ! 162: if (recording) ! 163: LLOG (pgm_log, LLOG_NOTICE, ("miss \"%s\" \"%s\"", domain, local)); ! 164: ! 165: if (index (domain, '.')) ! 166: am -> ak_bases = dm2dn_seq (domain); ! 167: else ! 168: am -> ak_bases = dn_seq_push (local_dn, NULLDNSEQ); ! 169: ! 170: insque (ak = am, AHead); ! 171: ! 172: return ak; ! 173: } ! 174: ! 175: /* DIRECTORY */ ! 176: ! 177: #define ADOMAIN "associatedDomain" ! 178: #define PHOTO "photo" ! 179: #define USERID "userid" ! 180: ! 181: static int bound = 0; ! 182: static int dlevel = 0; ! 183: ! 184: struct dn_seq *dm2dn_seq_aux (); ! 185: ! 186: ! 187: static struct dn_seq *dm2dn_seq (dm) ! 188: char *dm; ! 189: { ! 190: register char *dp; ! 191: ! 192: for (dp = dm; *dp; dp++) ! 193: if (isupper (*dp)) ! 194: *dp = tolower (*dp); ! 195: ! 196: dlevel = 0; ! 197: ! 198: if (!bound && do_bind () == NOTOK) ! 199: return NULLDNSEQ; ! 200: ! 201: return dm2dn_seq_aux (dm, NULLDN, NULLDNSEQ); ! 202: } ! 203: ! 204: /* */ ! 205: ! 206: static struct dn_seq *dm2dn_seq_aux (dm, dn, dlist) ! 207: char *dm; ! 208: DN dn; ! 209: struct dn_seq *dlist; ! 210: { ! 211: register char *dp; ! 212: char buffer[BUFSIZ]; ! 213: struct ds_search_arg search_arg; ! 214: register struct ds_search_arg *sa = &search_arg; ! 215: struct ds_search_result search_result; ! 216: register CommonArgs *ca; ! 217: register struct ds_search_result *sr = &search_result; ! 218: struct DSError error; ! 219: register struct DSError *se = &error; ! 220: PS ps; ! 221: ! 222: if ((ps = ps_alloc (str_open)) ! 223: && str_setup (ps, buffer, sizeof buffer, 1) != NOTOK) { ! 224: dn_print (ps, dn, EDBOUT); ! 225: *ps -> ps_ptr = NULL; ! 226: } ! 227: else ! 228: buffer[0] = NULL; ! 229: if (ps) ! 230: (void) ps_free (ps); ! 231: ! 232: if (debug) ! 233: fprintf (stderr, "dlevel=%d dm=%s dn=%s\n", dlevel, dm, buffer); ! 234: ! 235: bzero ((char *) sa, sizeof *sa); ! 236: ! 237: ca = &sa -> sra_common; ! 238: ca -> ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; ! 239: ca -> ca_servicecontrol.svc_prio = SVC_PRIO_LOW; ! 240: ca -> ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT; ! 241: ca -> ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT; ! 242: ca -> ca_servicecontrol.svc_scopeofreferral = SVC_REFSCOPE_NONE; ! 243: ! 244: sa -> sra_baseobject = dn; ! 245: sa -> sra_subset = SRA_ONELEVEL; ! 246: sa -> sra_searchaliases = FALSE; ! 247: ! 248: dp = dm; ! 249: for (;;) { ! 250: int i; ! 251: EntryInfo *ptr; ! 252: register filter *fi; ! 253: register AttributeType at; ! 254: ! 255: if (debug) ! 256: fprintf (stderr, "-- dlevel=%d dp=%s(%d) dn=%s\n", ! 257: dlevel, dp, strlen (dp), buffer); ! 258: ! 259: if ((i = strlen (dp)) < dlevel) ! 260: break; ! 261: ! 262: sa -> sra_filter = fi = filter_alloc (); ! 263: ! 264: bzero ((char *) fi, sizeof *fi); ! 265: fi -> flt_type = FILTER_ITEM; ! 266: fi -> FUITEM.fi_type = FILTERITEM_EQUALITY; ! 267: if ((fi -> FUITEM.UNAVA.ava_type = at = AttrT_new (ADOMAIN)) == NULL) ! 268: adios ("invalid attribute type \"%s\"", ADOMAIN); ! 269: fi -> FUITEM.UNAVA.ava_value = ! 270: str2AttrV (dp, at -> at_table -> oa_syntax); ! 271: ! 272: if (ds_search (sa, se, sr) != DS_OK) { ! 273: if (recording) ! 274: LLOG (pgm_log, LLOG_EXCEPTIONS, ! 275: ("search operation failed")); ! 276: ! 277: (void) ds_unbind (); ! 278: ! 279: bound = 0; ! 280: ! 281: goto free_filter; ! 282: } ! 283: ! 284: if (sr -> srr_correlated != TRUE) ! 285: correlate_search_results (sr); ! 286: ! 287: if (sr -> CSR_entries == NULLENTRYINFO) { ! 288: if (recording) ! 289: LLOG (pgm_log, LLOG_NOTICE, ! 290: ("search for %s \"%s\" at baseobject \"%s\" failed", ! 291: ADOMAIN, dp, buffer)); ! 292: ! 293: filter_free (sa -> sra_filter); ! 294: if (dp = index (dp, '.')) ! 295: dp++; ! 296: if (dp == NULL) ! 297: break; ! 298: continue; ! 299: } ! 300: ! 301: if (recording) ! 302: LLOG (pgm_log, LLOG_NOTICE, ! 303: ("search for %s \"%s\" at baseobject \"%s\" succeeded", ! 304: ADOMAIN, dp, buffer)); ! 305: ! 306: if (i > dlevel) { ! 307: dlevel = i; ! 308: if (dlist) ! 309: dn_seq_free (dlist), dlist = NULLDNSEQ; ! 310: } ! 311: ! 312: if (i == dlevel) ! 313: for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) { ! 314: struct dn_seq *dprev = dlist; ! 315: (void) dn_decode (ptr -> ent_dn); ! 316: ! 317: dlist = dm2dn_seq_aux (dm, ptr -> ent_dn, dlist); ! 318: ! 319: if (dprev == dlist) ! 320: dlist = dn_seq_push (ptr -> ent_dn, dlist); ! 321: else ! 322: if (i < dlevel) ! 323: break; ! 324: } ! 325: ! 326: entryinfo_free (sr -> CSR_entries, 0); ! 327: free_filter: ; ! 328: filter_free (sa -> sra_filter); ! 329: break; ! 330: } ! 331: ! 332: return dlist; ! 333: } ! 334: ! 335: /* */ ! 336: ! 337: static PE image_search (ak) ! 338: register struct aka *ak; ! 339: { ! 340: register struct dn_seq *dlist; ! 341: struct ds_search_arg search_arg; ! 342: register struct ds_search_arg *sa = &search_arg; ! 343: struct ds_search_result search_result; ! 344: register CommonArgs *ca; ! 345: register struct ds_search_result *sr = &search_result; ! 346: struct DSError error; ! 347: register struct DSError *se = &error; ! 348: PE pe = NULLPE; ! 349: ! 350: bzero ((char *) sa, sizeof *sa); ! 351: ! 352: ca = &sa -> sra_common; ! 353: ca -> ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; ! 354: ca -> ca_servicecontrol.svc_prio = SVC_PRIO_LOW; ! 355: ca -> ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT; ! 356: ca -> ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT; ! 357: ca -> ca_servicecontrol.svc_scopeofreferral = SVC_REFSCOPE_NONE; ! 358: ! 359: sa -> sra_subset = SRA_WHOLESUBTREE; ! 360: sa -> sra_searchaliases = TRUE; ! 361: ! 362: if (recording) { ! 363: LLOG (pgm_log, LLOG_NOTICE, ("searching for %s %s", ! 364: ak -> ak_domain, ak -> ak_local)); ! 365: pslog (pgm_log, LLOG_NOTICE, " using baseobjects ", ! 366: dn_seq_print, (caddr_t) ak -> ak_bases); ! 367: } ! 368: ! 369: for (dlist = ak -> ak_bases; dlist; dlist = dlist -> dns_next) { ! 370: register filter *fi; ! 371: register AttributeType at; ! 372: ! 373: if ((sa -> sra_baseobject = dlist -> dns_dn) == NULL) ! 374: continue; ! 375: ! 376: sa -> sra_filter = fi = filter_alloc (); ! 377: ! 378: bzero ((char *) fi, sizeof *fi); ! 379: fi -> flt_type = FILTER_ITEM; ! 380: fi -> FUITEM.fi_type = FILTERITEM_EQUALITY; ! 381: if ((fi -> FUITEM.UNAVA.ava_type = at = AttrT_new (USERID)) == NULL) ! 382: adios ("invalid attribute type \"%s\"", USERID); ! 383: fi -> FUITEM.UNAVA.ava_value = ! 384: str2AttrV (ak -> ak_local, at -> at_table -> oa_syntax); ! 385: ! 386: sa -> sra_eis.eis_allattributes = FALSE; ! 387: sa -> sra_eis.eis_select = as_comp_new (str2AttrT (PHOTO), NULLAV, ! 388: NULLACL_INFO); ! 389: sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; ! 390: ! 391: if (ds_search (sa, se, sr) != DS_OK) { ! 392: if (recording) ! 393: LLOG (pgm_log, LLOG_EXCEPTIONS, ("search operation failed")); ! 394: ! 395: (void) ds_unbind (); ! 396: ! 397: bound = 0; ! 398: ! 399: goto free_filter; ! 400: } ! 401: ! 402: if (sr -> srr_correlated != TRUE) ! 403: correlate_search_results (sr); ! 404: ! 405: if (sr -> CSR_entries == NULLENTRYINFO) { ! 406: if (recording) ! 407: pslog (pgm_log, LLOG_NOTICE, ! 408: "search failed at baseobject ", dn_print, ! 409: (caddr_t) dlist -> dns_dn); ! 410: filter_free (sa -> sra_filter); ! 411: continue; ! 412: } ! 413: ! 414: if (sr -> CSR_entries -> ent_attr == NULLATTR) { ! 415: if (recording) ! 416: pslog (pgm_log, LLOG_NOTICE, ! 417: "search succeeded (but no attribute) at baseobject ", ! 418: dn_print, (caddr_t) dlist -> dns_dn); ! 419: } ! 420: else { ! 421: AttributeValue av = &sr -> CSR_entries -> ent_attr -> attr_value ! 422: -> avseq_av; ! 423: ! 424: pe = (PE) av -> av_struct; ! 425: av -> av_struct = NULL; ! 426: ! 427: if (recording) ! 428: pslog (pgm_log, LLOG_NOTICE, "search succeeded at baseobject ", ! 429: dn_print, (caddr_t) dlist -> dns_dn); ! 430: } ! 431: ! 432: entryinfo_free (sr -> CSR_entries, 0); ! 433: free_filter: ; ! 434: filter_free (sa -> sra_filter); ! 435: break; ! 436: } ! 437: ! 438: return pe; ! 439: } ! 440: ! 441: /* */ ! 442: ! 443: static do_bind () ! 444: { ! 445: struct ds_bind_arg bind_arg, ! 446: bind_result; ! 447: register struct ds_bind_arg *ba = &bind_arg, ! 448: *br = &bind_result; ! 449: struct ds_bind_error bind_error; ! 450: register struct ds_bind_error *be = &bind_error; ! 451: ! 452: bzero ((char *) ba, sizeof *ba); ! 453: ba -> dba_version = DBA_VERSION_V1988; ! 454: ! 455: if (ds_bind (ba, be, br) != DS_OK) { ! 456: if (recording) ! 457: LLOG (pgm_log, LLOG_EXCEPTIONS, ! 458: ("directory bind failed: %s", ! 459: be -> dbe_type == DBE_TYPE_SECURITY ? "security error" ! 460: : "DSA unavailable")); ! 461: ! 462: return NOTOK; ! 463: } ! 464: ! 465: bound = 1; ! 466: ! 467: return OK; ! 468: } ! 469: ! 470: /* IMAGE */ ! 471: ! 472: static int passno; ! 473: static int x, y, maxx; ! 474: ! 475: static struct type_IMAGE_Image *im = NULL; ! 476: ! 477: /* */ ! 478: ! 479: struct type_IMAGE_Image *fetch_image (local, domain) ! 480: char *local, ! 481: *domain; ! 482: { ! 483: PE pe; ! 484: PS ps; ! 485: register struct aka *ak; ! 486: ! 487: if ((ak = mbox2ak (local, domain)) == NULL) ! 488: return NULL; ! 489: if (ak -> ak_image) ! 490: return ak -> ak_image; ! 491: ! 492: if (!bound && do_bind () == NOTOK) ! 493: return NULL; ! 494: ! 495: if ((pe = image_search (ak)) == NULLPE) ! 496: return NULL; ! 497: ! 498: if (!stay_bound) { ! 499: (void) ds_unbind (); ! 500: bound = 0; ! 501: } ! 502: ! 503: im = NULL; ! 504: ! 505: if ((ps = ps_alloc (str_open)) == NULLPS) { ! 506: if (debug) ! 507: fprintf (stderr, "ps_alloc: failed\n"); ! 508: ! 509: goto out; ! 510: } ! 511: if (str_setup (ps, NULLCP, 0, 0) == NOTOK) { ! 512: if (debug) ! 513: fprintf (stderr, "ps_alloc: %s\n", ps_error (ps -> ps_errno)); ! 514: ! 515: goto out; ! 516: } ! 517: ! 518: if (pe2ps (ps, pe) == NOTOK) { ! 519: if (debug) ! 520: fprintf (stderr, "pe2ps: %s\n", pe_error (pe -> pe_errno)); ! 521: ! 522: goto out; ! 523: } ! 524: ! 525: for (passno = 1; passno < 3; passno++) ! 526: if (decode_t4 (ps -> ps_base, PHOTO, 0) == NOTOK) { ! 527: fprintf (stderr, "\n"); ! 528: if (im) { ! 529: qb_free (im -> data); ! 530: free ((char *) im); ! 531: im = NULL; ! 532: } ! 533: break; ! 534: } ! 535: ! 536: out: ; ! 537: if (ps) ! 538: ps_free (ps); ! 539: pe_free (pe); ! 540: ! 541: return (ak -> ak_image = im); ! 542: } ! 543: ! 544: /* */ ! 545: ! 546: /* ARGSUSED */ ! 547: ! 548: photo_start (name) ! 549: char *name; ! 550: { ! 551: if (passno == 1) ! 552: maxx = 0; ! 553: x = y = 0; ! 554: ! 555: return OK; ! 556: } ! 557: ! 558: ! 559: /* ARGSUSED */ ! 560: ! 561: photo_end (name) ! 562: char *name; ! 563: { ! 564: int len; ! 565: register struct qbuf *qb, ! 566: *pb; ! 567: ! 568: if (passno == 1) { ! 569: x = maxx, y--; ! 570: ! 571: if (debug) ! 572: fprintf (stderr, "ending pass one for \"%s\", %dx%d\n", ! 573: name, x, y); ! 574: ! 575: if ((im = (struct type_IMAGE_Image *) calloc (1, sizeof *im)) ! 576: == NULL) { ! 577: if (debug) ! 578: fprintf (stderr, "calloc fails"); ! 579: return NOTOK; ! 580: } ! 581: im -> width = x, im -> height = y; ! 582: ! 583: len = ((im -> width + 7) / 8) * im -> height; ! 584: if ((im -> data = qb = (struct qbuf *) malloc (sizeof *qb)) == NULL) { ! 585: if (debug) ! 586: fprintf (stderr, "unable to allocate qbuf"); ! 587: return NOTOK; ! 588: } ! 589: qb -> qb_forw = qb -> qb_back = qb; ! 590: qb -> qb_data = NULL, qb -> qb_len = len; ! 591: ! 592: if ((pb = (struct qbuf *) calloc ((unsigned) (sizeof *pb + len), 1)) ! 593: == NULL) { ! 594: if (debug) ! 595: fprintf (stderr, "unable to allocate qbuf (%d+%d)", ! 596: sizeof *qb, len); ! 597: return NOTOK; ! 598: } ! 599: pb -> qb_data = pb -> qb_base, pb -> qb_len = len; ! 600: insque (pb, qb); ! 601: } ! 602: ! 603: return OK; ! 604: } ! 605: ! 606: ! 607: photo_black (length) ! 608: int length; ! 609: { ! 610: if (passno == 2) { ! 611: register int i, ! 612: j; ! 613: register unsigned char *cp; ! 614: ! 615: cp = (unsigned char *) im -> data -> qb_forw -> qb_data ! 616: + ((im -> width + 7) / 8) * y + x / 8; ! 617: i = x % 8; ! 618: for (j = length; j > 0; j--) { ! 619: *cp |= 1 << i; ! 620: if (++i == 8) ! 621: cp++, i = 0; ! 622: } ! 623: ! 624: } ! 625: ! 626: x += length; ! 627: ! 628: return OK; ! 629: } ! 630: ! 631: ! 632: photo_white (length) ! 633: int length; ! 634: { ! 635: x += length; ! 636: ! 637: return OK; ! 638: } ! 639: ! 640: ! 641: /* ARGSUSED */ ! 642: ! 643: photo_line_end (line) ! 644: caddr_t line; ! 645: { ! 646: if (passno == 1 && x > maxx) ! 647: maxx = x; ! 648: x = 0, y++; ! 649: ! 650: return OK; ! 651: } ! 652: ! 653: /* ERRORS */ ! 654: ! 655: #ifndef lint ! 656: void _advise (); ! 657: ! 658: ! 659: void adios (va_alist) ! 660: va_dcl ! 661: { ! 662: va_list ap; ! 663: ! 664: va_start (ap); ! 665: ! 666: _advise (ap); ! 667: ! 668: va_end (ap); ! 669: ! 670: _exit (1); ! 671: } ! 672: #else ! 673: /* VARARGS */ ! 674: ! 675: void adios (what, fmt) ! 676: char *what, ! 677: *fmt; ! 678: { ! 679: adios (what, fmt); ! 680: } ! 681: #endif ! 682: ! 683: ! 684: #ifndef lint ! 685: void advise (va_alist) ! 686: va_dcl ! 687: { ! 688: va_list ap; ! 689: ! 690: va_start (ap); ! 691: ! 692: _advise (ap); ! 693: ! 694: va_end (ap); ! 695: } ! 696: ! 697: ! 698: static void _advise (ap) ! 699: va_list ap; ! 700: { ! 701: char buffer[BUFSIZ]; ! 702: ! 703: asprintf (buffer, ap); ! 704: ! 705: (void) fflush (stdout); ! 706: ! 707: if (errsw != NOTOK) { ! 708: fprintf (stderr, "%s: ", myname); ! 709: (void) fputs (buffer, stderr); ! 710: (void) fputc ('\n', stderr); ! 711: ! 712: (void) fflush (stderr); ! 713: } ! 714: } ! 715: #else ! 716: /* VARARGS */ ! 717: ! 718: void advise (what, fmt) ! 719: char *what, ! 720: *fmt; ! 721: { ! 722: advise (what, fmt); ! 723: } ! 724: #endif ! 725: ! 726: /* MISC */ ! 727: ! 728: #ifndef lint ! 729: char *strdup (s) ! 730: char *s; ! 731: { ! 732: char *p; ! 733: ! 734: if (p = malloc ((unsigned) (strlen (s) + 1))) ! 735: (void) strcpy (p, s); ! 736: ! 737: return p; ! 738: } ! 739: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.