dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dtscreen / resource.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: resource.c /main/4 1996/06/19 09:47:56 mustafa $ */
24 /*
25  */
26 /*                                                                      *
27  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
28  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
29  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
30  * (c) Copyright 1993, 1994 Novell, Inc.                                *
31  */
32 /*-
33  * resource.c - resource management for dtscreen, the X Window System lockscreen.
34  *
35  * Copyright (c) 1991 by Patrick J. Naughton.
36  *
37  * See dtscreen.c for copying information.
38  *
39  * Revision History:
40  * 25-Sep-91: added worm mode.
41  * 06-Jun-91: Added flame mode.
42  * 16-May-91: Added random mode and pyro mode.
43  * 26-Mar-91: CheckResources: delay must be >= 0.
44  * 29-Oct-90: Added #include <ctype.h> for missing isupper() on some OS revs.
45  *            moved -mode option, reordered Xrm database evaluation.
46  * 28-Oct-90: Added text strings.
47  * 26-Oct-90: Fix bug in mode specific options.
48  * 31-Jul-90: Fix ':' handling in parsefilepath
49  * 07-Jul-90: Created from resource work in dtscreen.c
50  *
51  */
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include "dtscreen.h"
56 #include <netdb.h>
57 #include <math.h>
58 #include <ctype.h>
59
60 #include <X11/Xresource.h>
61
62 /*              include file for message texts          */
63 #include <limits.h>
64 #include <nl_types.h>
65 #define MF_DTSCREEN "dtscreen.cat"
66
67 #include <locale.h>
68 extern nl_catd  scmc_catd;   /* Cat descriptor for scmc conversion */
69
70 /*
71  * Declare external interface routines for supported screen savers.
72  */
73
74 extern void inithop();
75 extern void drawhop();
76
77 extern void initlife();
78 extern void drawlife();
79
80 extern void initqix();
81 extern void drawqix();
82
83 extern void initimage();
84 extern void drawimage();
85
86 extern void initblank();
87 extern void drawblank();
88
89 extern void initswarm();
90 extern void drawswarm();
91
92 extern void initrotor();
93 extern void drawrotor();
94
95 extern void initpyro();
96 extern void drawpyro();
97
98 extern void initflame();
99 extern void drawflame();
100
101 extern void initworm();
102 extern void drawworm();
103
104 void CheckResources(void);
105
106 typedef struct {
107     char       *cmdline_arg;
108     void        (*lp_init) ();
109     void        (*lp_callback) ();
110     int         def_delay;
111     int         def_batchcount;
112     float       def_saturation;
113     char       *desc;
114 }           LockStruct;
115
116 static char randomstring[] = "random";
117
118 static LockStruct LockProcs[] = {
119     {"hop", inithop, drawhop, 0, 1000, 1.0, "Hopalong iterated fractals"},
120     {"qix", initqix, drawqix, 30000, 64, 1.0, "Spinning lines a la Qix(tm)"},
121     {"image", initimage, drawimage, 2000000, 8, 0.3, "Random bouncing image"},
122     {"life", initlife, drawlife, 1000000, 100, 1.0, "Conway's game of Life"},
123     {"swarm", initswarm, drawswarm, 10000, 100, 1.0, "Swarm of bees"},
124     {"rotor", initrotor, drawrotor, 10000, 4, 0.4, "Rotor"},
125     {"pyro", initpyro, drawpyro, 15000, 40, 1.0, "Fireworks"},
126     {"flame", initflame, drawflame, 10000, 20, 1.0, "Cosmic Flame Fractals"},
127     {"worm", initworm, drawworm, 10000, 20, 1.0, "Wiggly Worms"},
128     {"blank", initblank, drawblank, 5000000, 1, 1.0, "Blank screen"},
129     {randomstring, NULL, NULL, 0, 0, 0.0, "Random mode"},
130 };
131 #define NUMPROCS (sizeof LockProcs / sizeof LockProcs[0])
132
133
134 extern char *getenv();
135
136 #ifndef DEF_FILESEARCHPATH
137 #define DEF_FILESEARCHPATH "/usr/lib/X11/%T/%N%S"
138 #endif
139 #define DEF_DISPLAY     ":0"
140 #define DEF_MODE        "swarm"
141 #define DEF_BG          "White"
142 #define DEF_FG          "Black"
143 #define DEF_BC          "100"   /* vectors (or whatever) per batch */
144 #define DEF_DELAY       "200000"/* microseconds between batches */
145 #define DEF_NICE        "10"    /* dtscreen process nicelevel */
146 #define DEF_SAT         "1.0"   /* color ramp saturation 0->1 */
147 #define DEF_CLASSNAME   "Dtscreen"
148
149 static char *classname;
150 static char modename[1024];
151 static char modeclass[1024];
152
153 static XrmOptionDescRec genTable[] = {
154     {"-mode", ".mode", XrmoptionSepArg, (caddr_t) NULL},
155     {"-mono", ".mono", XrmoptionNoArg, (caddr_t) "on"},
156     {"+mono", ".mono", XrmoptionNoArg, (caddr_t) "off"},
157     {"-nice", ".nice", XrmoptionSepArg, (caddr_t) NULL},
158     {"-create",  ".create", XrmoptionNoArg, (caddr_t) "on"},
159 };
160 #define genEntries (sizeof genTable / sizeof genTable[0])
161
162 /*************************************************************/
163 /** This table was changed for AIX.  In order to read these **/
164 /** command line options properly, the specifier field must **/
165 /** be built on the fly.                                    **/
166 /*************************************************************/
167 static XrmOptionDescRec modeTable[] = {
168     {"-delay",      NULL, XrmoptionSepArg, (caddr_t) NULL},
169     {"-batchcount", NULL, XrmoptionSepArg, (caddr_t) NULL},
170     {"-saturation", NULL, XrmoptionSepArg, (caddr_t) NULL},
171 };
172 #define modeEntries (sizeof modeTable / sizeof modeTable[0])
173
174 static XrmOptionDescRec cmdlineTable[] = {
175     {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
176     {"-xrm",     NULL,       XrmoptionResArg, (caddr_t) NULL},
177 };
178 #define cmdlineEntries (sizeof cmdlineTable / sizeof cmdlineTable[0])
179
180 static XrmOptionDescRec nameTable[] = {
181     {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL},
182 };
183
184
185 typedef struct {
186     char       *opt;
187     char       *desc;
188 }           OptionStruct;
189
190 static OptionStruct opDesc[] = {
191     {"-help", "print out this message"},
192     {"-resources", "print default resource file to standard output"},
193     {"-display displayname", "X server to contact"},
194     {"-/+mono", "turn on/off monochrome override"},
195     {"-delay usecs", "microsecond delay between screen updates"},
196     {"-batchcount num", "number of things per batch"},
197     {"-nice level", "nice level for dtscreen process"},
198     {"-saturation value", "saturation of color ramp"},
199     {"-create", "create a window in which to draw"},
200 };
201 #define opDescEntries (sizeof opDesc / sizeof opDesc[0])
202
203 char       *display;
204 char       *mode;
205 float       saturation;
206 int         nicelevel;
207 int         delay;
208 int         batchcount;
209 Bool        mono;
210 Bool        create;
211
212
213 #define t_String        0
214 #define t_Float         1
215 #define t_Int           2
216 #define t_Bool          3
217
218 typedef struct {
219     caddr_t    *var;
220     char       *name;
221     char       *class;
222     char       *def;
223     int         type;
224 }           argtype;
225
226 static argtype genvars[] = {
227     {(caddr_t *) &nicelevel, "nice", "Nice", DEF_NICE, t_Int},
228     {(caddr_t *) &mono, "mono", "Mono", "off", t_Bool},
229     {(caddr_t *) &create, "create", "Create", "off", t_Bool},
230 };
231 #define NGENARGS (sizeof genvars / sizeof genvars[0])
232
233 static argtype modevars[] = {
234     {(caddr_t *) &delay, "delay", "Delay", DEF_DELAY, t_Int},
235     {(caddr_t *) &batchcount, "batchcount", "BatchCount", DEF_BC, t_Int},
236     {(caddr_t *) &saturation, "saturation", "Saturation", DEF_SAT, t_Float},
237 };
238 #define NMODEARGS (sizeof modevars / sizeof modevars[0])
239
240
241 static void
242 Syntax(char *badOption)
243 {
244     int         col, len, i;
245
246 #ifdef MIT_R5
247     fprintf(stderr, "%s:  bad command line option:  %s.\n\n",
248             ProgramName, badOption);
249 #else
250     fprintf(stderr, catgets(scmc_catd, 2, 1,
251         "%s:  Bad command line option:  %s.\n\n"), 
252         ProgramName, badOption);
253 #endif
254
255     fprintf(stderr, "usage:  %s", ProgramName);
256     col = 8 + strlen(ProgramName);
257     for (i = 0; i < opDescEntries; i++) {
258         len = 3 + strlen(opDesc[i].opt);        /* space [ string ] */
259         if (col + len > 79) {
260             fprintf(stderr, "\n   ");   /* 3 spaces */
261             col = 3;
262         }
263         fprintf(stderr, " [%s]", opDesc[i].opt);
264         col += len;
265     }
266
267     len = 8 + strlen(LockProcs[0].cmdline_arg);
268     if (col + len > 79) {
269         fprintf(stderr, "\n   ");       /* 3 spaces */
270         col = 3;
271     }
272     fprintf(stderr, " [-mode %s", LockProcs[0].cmdline_arg);
273     col += len;
274     for (i = 1; i < NUMPROCS; i++) {
275         len = 3 + strlen(LockProcs[i].cmdline_arg);
276         if (col + len > 79) {
277             fprintf(stderr, "\n   ");   /* 3 spaces */
278             col = 3;
279         }
280         fprintf(stderr, " | %s", LockProcs[i].cmdline_arg);
281         col += len;
282     }
283     fprintf(stderr, "]\n");
284
285 #ifdef MIT_R5
286     fprintf(stderr, "\nType %s -help for a full description.\n\n",
287             ProgramName);
288 #else
289     fprintf(stderr, catgets(scmc_catd, 2, 2,
290         "\nType %s -help for a full description.\n\n"), 
291         ProgramName);
292 #endif
293     exit(1);
294 }
295
296 static void
297 Help(void)
298 {
299     int         i;
300
301 #ifdef MIT_R5
302     fprintf(stderr, "usage:\n        %s [-options ...]\n\n", ProgramName);
303     fprintf(stderr, "where options include:\n");
304
305 #else
306     fprintf(stderr, catgets(scmc_catd, 2, 3,
307         "Usage:\n        %s [-options ...]\n\n\
308         where options include:\n"), ProgramName);
309 #endif
310
311     for (i = 0; i < opDescEntries; i++) {
312         fprintf(stderr, "    %-28s %s\n", opDesc[i].opt, opDesc[i].desc);
313     }
314
315 #ifdef MIT_R5
316     fprintf(stderr, "    %-28s %s\n", "-mode mode", "animation mode");
317     fprintf(stderr, "    where mode is one of:\n");
318 #else
319     fprintf(stderr, catgets(scmc_catd, 2, 5, 
320          "    %-28s %s\n\t where mode is one of:\n"), 
321          "-mode mode", "animation mode");
322 #endif
323     for (i = 0; i < NUMPROCS; i++) {
324         fprintf(stderr, "          %-23s %s\n",
325                 LockProcs[i].cmdline_arg, LockProcs[i].desc);
326     }
327     putc('\n', stderr);
328
329     exit(0);
330 }
331
332 static void
333 DumpResources(void)
334 {
335     int         i;
336
337     printf("%s.mode: %s\n", classname, DEF_MODE);
338
339     for (i = 0; i < NGENARGS; i++)
340         printf("%s.%s: %s\n",
341                classname, genvars[i].name, genvars[i].def);
342
343     for (i = 0; i < NUMPROCS - 1; i++) {
344         printf("%s.%s.%s: %d\n", classname, LockProcs[i].cmdline_arg,
345                "delay", LockProcs[i].def_delay);
346         printf("%s.%s.%s: %d\n", classname, LockProcs[i].cmdline_arg,
347                "batchcount", LockProcs[i].def_batchcount);
348         printf("%s.%s.%s: %g\n", classname, LockProcs[i].cmdline_arg,
349                "saturation", LockProcs[i].def_saturation);
350     }
351     exit(0);
352 }
353
354
355 static void
356 LowerString(char *s)
357 {
358
359     while (*s) {
360         if (isupper(*s))
361             *s += ('a' - 'A');
362         s++;
363     }
364 }
365
366 static void
367 GetResource(XrmDatabase database, char *parentname, char *parentclass,
368             char *name, char *class, int valueType, char *def,
369             caddr_t *valuep /* RETURN */)
370 {
371     char       *type;
372     XrmValue    value;
373     char       *string;
374     char        buffer[1024];
375     char        fullname[1024];
376     char        fullclass[1024];
377     int         len;
378
379     sprintf(fullname, "%s.%s", parentname, name);
380     sprintf(fullclass, "%s.%s", parentclass, class);
381     if (XrmGetResource(database, fullname, fullclass, &type, &value)) {
382         string = value.addr;
383         len = value.size;
384     } else {
385         string = def;
386         len = strlen(string);
387     }
388     (void) strncpy(buffer, string, sizeof(buffer));
389     buffer[sizeof(buffer) - 1] = '\0';
390
391     switch (valueType) {
392     case t_String:
393         {
394             char       *s;
395             s = (char *) malloc(len + 1);
396             if (s == (char *) NULL)
397 #ifdef MIT_R5
398                 error("%s: GetResource - couldn't allocate memory");
399 #else
400             {
401                 fprintf(stderr, catgets(scmc_catd, 2, 18, 
402                      "%s: GetResource - couldn't allocate memory.\n"),ProgramName);
403                 exit(1);
404             }
405 #endif
406             (void) strncpy(s, string, len);
407             s[len] = '\0';
408             *((char **) valuep) = s;
409         }
410         break;
411     case t_Bool:
412         LowerString(buffer);
413         *((int *) valuep) = (!strcmp(buffer, "true") ||
414                              !strcmp(buffer, "on") ||
415                              !strcmp(buffer, "enabled") ||
416                              !strcmp(buffer, "yes")) ? True : False;
417         break;
418     case t_Int:
419         *((int *) valuep) = atoi(buffer);
420         break;
421     case t_Float:
422         *((float *) valuep) = (float) atof(buffer);
423         break;
424     }
425 }
426
427
428 static      XrmDatabase
429 parsefilepath(char *xfilesearchpath, char *TypeName, char *ClassName)
430 {
431     XrmDatabase database = NULL;
432     char        appdefaults[1024];
433     char       *src;
434     char       *dst;
435
436     src = xfilesearchpath;
437     appdefaults[0] = '\0';
438     dst = appdefaults;
439     while (1) {
440         if (*src == '%') {
441             src++;
442             switch (*src) {
443             case '%':
444             case ':':
445                 *dst++ = *src++;
446                 *dst = '\0';
447                 break;
448             case 'T':
449                 (void) strcat(dst, TypeName);
450                 src++;
451                 dst += strlen(TypeName);
452                 break;
453             case 'N':
454                 (void) strcat(dst, ClassName);
455                 src++;
456                 dst += strlen(ClassName);
457                 break;
458             case 'S':
459                 src++;
460                 break;
461             default:
462                 src++;
463                 break;
464             }
465         } else if (*src == ':') {
466             database = XrmGetFileDatabase(appdefaults);
467             if (database == NULL) {
468                 dst = appdefaults;
469                 src++;
470             } else
471                 break;
472         } else if (*src == '\0') {
473             database = XrmGetFileDatabase(appdefaults);
474             break;
475         } else {
476             *dst++ = *src++;
477             *dst = '\0';
478         }
479     }
480     return database;
481 }
482
483 /*******************************************************************/
484 /** screenIOErrorHandler                                          **/
485 /**                                                               **/
486 /** this function will exit cleanly when the connection is broken **/
487 /*******************************************************************/
488 static int screenIOErrorHandler(Display *dpy)
489 {
490         exit(1);
491         return 1;
492 }
493
494 static void
495 open_display(void)
496 {
497     if (display != NULL) {
498         char       *colon = strchr(display, ':');
499
500         if (colon == NULL)
501 #ifdef MIT_R5
502             error("%s: Malformed -display argument, \"%s\"\n", display);
503 #else
504         {
505             fprintf(stderr, catgets(scmc_catd, 2, 19,
506                 "%s: Malformed -display argument:  %s.\n"), ProgramName,display);
507             exit(1);
508         }
509 #endif
510
511     } else
512         display = ":0.0";
513     if (!(dsp = XOpenDisplay(display)))
514 #ifdef MIT_R5
515         error("%s: unable to open display %s.\n", display);
516 #else
517     {
518         fprintf(stderr, catgets(scmc_catd, 2, 17,
519                 "%s: Unable to open display %s.\n"),ProgramName, display);
520         exit(1);
521     }
522 #endif
523
524     XSetIOErrorHandler(screenIOErrorHandler);
525 }
526
527 void
528 printvar(char *class, argtype var)
529 {
530     switch (var.type) {
531     case t_String:
532         fprintf(stderr, "%s.%s: %s\n",
533                 class, var.name, *((char **) var.var));
534         break;
535     case t_Bool:
536         fprintf(stderr, "%s.%s: %s\n",
537                 class, var.name, *((int *) var.var)
538                 ? "True" : "False");
539         break;
540     case t_Int:
541         fprintf(stderr, "%s.%s: %d\n",
542                 class, var.name, *((int *) var.var));
543         break;
544     case t_Float:
545         fprintf(stderr, "%s.%s: %g\n",
546                 class, var.name, *((float *) var.var));
547         break;
548     }
549 }
550
551
552 void
553 GetResources(int argc, char *argv[])
554 {
555     XrmDatabase RDB = NULL;
556     XrmDatabase modeDB = NULL;
557     XrmDatabase nameDB = NULL;
558     XrmDatabase cmdlineDB = NULL;
559     XrmDatabase generalDB = NULL;
560     XrmDatabase homeDB = NULL;
561     XrmDatabase applicationDB = NULL;
562     XrmDatabase serverDB = NULL;
563     XrmDatabase userDB = NULL;
564     char        userfile[1024];
565     char       *homeenv;
566     char       *userpath;
567     char       *env;
568     char       *serverString;
569     int         i;
570     /***************************/
571     /** new variables for AIX **/
572     /***************************/
573     char        delaySpecifier[64];
574     char        batchcountSpecifier[64];
575     char        saturationSpecifier[64];
576
577     XrmInitialize();
578
579     for (i = 0; i < argc; i++) {
580         if (!strncmp(argv[i], "-help", strlen(argv[i])))
581             Help();
582         /* NOTREACHED */
583     }
584
585     /*
586      * get -name arg from command line so you can have different resource
587      * files for different configurations/machines etc...
588      */
589     XrmParseCommand(&nameDB, nameTable, 1, ProgramName,
590                     &argc, argv);
591     GetResource(nameDB, ProgramName, "*", "name", "Name", t_String,
592                 DEF_CLASSNAME, &classname);
593
594     homeenv = getenv("HOME");
595     if (!homeenv)
596         homeenv = "";
597
598     env = getenv("XFILESEARCHPATH");
599     applicationDB = parsefilepath(env ? env : DEF_FILESEARCHPATH,
600                                   "app-defaults", classname);
601
602     XrmParseCommand(&cmdlineDB, cmdlineTable, cmdlineEntries, ProgramName,
603                     &argc, argv);
604
605     userpath = getenv("XUSERFILESEARCHPATH");
606     if (!userpath) {
607         env = getenv("XAPPLRESDIR");
608         if (env)
609           snprintf(userfile, 1024 - 1, "%s/%%N:%s/%%N", env, homeenv);
610         else
611           snprintf(userfile, 1024 - 1, "%s/%%N", homeenv);
612         userpath = userfile;
613     }
614     userDB = parsefilepath(userpath, "app-defaults", classname);
615
616     (void) XrmMergeDatabases(applicationDB, &RDB);
617     (void) XrmMergeDatabases(userDB, &RDB);
618     (void) XrmMergeDatabases(cmdlineDB, &RDB);
619
620     env = getenv("DISPLAY");
621     GetResource(RDB, ProgramName, classname, "display", "Display", t_String,
622                 env ? env : DEF_DISPLAY, &display);
623     open_display();
624     serverString = XResourceManagerString(dsp);
625     if (serverString) {
626         serverDB = XrmGetStringDatabase(serverString);
627         (void) XrmMergeDatabases(serverDB, &RDB);
628     } else {
629         char        buf[1024];
630         sprintf(buf, "%s/.Xdefaults", homeenv);
631         homeDB = XrmGetFileDatabase(buf);
632         (void) XrmMergeDatabases(homeDB, &RDB);
633     }
634
635     XrmParseCommand(&generalDB, genTable, genEntries, ProgramName, &argc, argv);
636     (void) XrmMergeDatabases(generalDB, &RDB);
637
638     GetResource(RDB, ProgramName, classname, "mode", "Mode", t_String,
639                 DEF_MODE, (caddr_t *) &mode);
640
641     /*
642      * if random< mode, then just grab a random entry from the table
643      */
644     if (!strcmp(mode, randomstring))
645         mode = LockProcs[random() % (NUMPROCS - 2)].cmdline_arg;
646
647     sprintf(modename, "%s.%s", ProgramName, mode);
648     sprintf(modeclass, "%s.%s", classname, mode);
649
650
651     /*********************************************************************/
652     /** New code for AIX                                                **/
653     /** We must build the specifier fields of the modeTable on the fly. **/
654     /*********************************************************************/
655     sprintf(delaySpecifier,      ".%s.delay",      mode);
656     sprintf(batchcountSpecifier, ".%s.batchcount", mode);
657     sprintf(saturationSpecifier, ".%s.saturation", mode);
658     modeTable[0].specifier = delaySpecifier;
659     modeTable[1].specifier = batchcountSpecifier;
660     modeTable[2].specifier = saturationSpecifier;
661
662
663     XrmParseCommand(&modeDB, modeTable, modeEntries, ProgramName, &argc, argv);
664     (void) XrmMergeDatabases(modeDB, &RDB);
665
666     /* Parse the rest of the command line */
667     for (argc--, argv++; argc > 0; argc--, argv++) {
668         if (**argv != '-')
669             Syntax(*argv);
670         switch (argv[0][1]) {
671         case 'r':
672             DumpResources();
673             /* NOTREACHED */
674         default:
675             Syntax(*argv);
676             /* NOTREACHED */
677         }
678     }
679
680     /* the RDB is set, now query load the variables from the database */
681
682     for (i = 0; i < NGENARGS; i++)
683         GetResource(RDB, ProgramName, classname,
684                     genvars[i].name, genvars[i].class,
685                     genvars[i].type, genvars[i].def, genvars[i].var);
686
687     for (i = 0; i < NMODEARGS; i++)
688         GetResource(RDB, modename, modeclass,
689                     modevars[i].name, modevars[i].class,
690                     modevars[i].type, modevars[i].def, modevars[i].var);
691
692     (void) XrmDestroyDatabase(RDB);
693
694 }
695
696
697 void CheckResources(void)
698 {
699     int         i;
700
701     if (batchcount < 1)
702         Syntax("-batchcount argument must be positive.");
703     if (saturation < 0.0 || saturation > 1.0)
704         Syntax("-saturation argument must be between 0.0 and 1.0.");
705     if (delay < 0)
706         Syntax("-delay argument must be positive.");
707
708     for (i = 0; i < NUMPROCS; i++) {
709         if (!strncmp(LockProcs[i].cmdline_arg, mode, strlen(mode))) {
710             init = LockProcs[i].lp_init;
711             callback = LockProcs[i].lp_callback;
712             break;
713         }
714     }
715     if (i == NUMPROCS) {
716 #ifdef MIT_R5
717         fprintf(stderr, "Unknown mode: ");
718 #else
719         fprintf(stderr, "%s", catgets(scmc_catd, 2, 7, 
720              "Unknown mode: "));
721 #endif
722         Syntax(mode);
723     }
724 }