~cfuhrman/+junk/netbsd-othersrc-trunk

« back to all changes in this revision

Viewing changes to dist/cdk/demos/syb.c

  • Committer: garbled
  • Date: 2001-01-04 19:59:48 UTC
  • Revision ID: svn-v4:288d5a72-fed7-e111-8680-000c29dcf8fe:trunk:174
Initial import of CDK 4.9.9.  The work to port this was performed by
Charles Hannum, and that is the version being imported:
cdk-4.9.9-20000407-myc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <cdk.h>
 
2
#include <sybfront.h>
 
3
#include <sybdb.h>
 
4
 
 
5
#ifdef HAVE_XCURSES
 
6
char *XCursesProgramName="syb";
 
7
#endif
 
8
 
 
9
#define MAXWIDTH        5000
 
10
#define MAXHISTORY      1000
 
11
 
 
12
/*
 
13
 * This structure is used for keeping command history.
 
14
 */
 
15
struct history_st {
 
16
   int count;
 
17
   int current;
 
18
   char *command[MAXHISTORY];
 
19
};
 
20
 
 
21
/*
 
22
 * Define some global variables.
 
23
 */
 
24
char *GPUsage           = "[-p Command Prompt] [-U User] [-P Password] [-S Server] [-h help]";
 
25
char *GPCurrentDatabase = 0;
 
26
extern char *dberrstr;
 
27
 
 
28
/*
 
29
 * Because the error/message callback do not allow you to pass in
 
30
 * data of your own, we have to make the screen pointer global. :(
 
31
 */
 
32
CDKSCREEN *GPCdkScreen = 0;
 
33
 
 
34
/*
 
35
 * Define function prototypes.
 
36
 */
 
37
DBPROCESS *loginToSybase (CDKSCREEN *screen, char *login, char *password);
 
38
DBPROCESS *sybaseLogin (CDKSCREEN *screen, char *login, char *password, int attempts);
 
39
char *assembleTitle (DBPROCESS *dbProcess);
 
40
char *assembleRow (DBPROCESS *dbProcess);
 
41
char *uc (char *word);
 
42
int getColWidth (DBPROCESS *dbProcess, int col);
 
43
void runIsqlCommand (CDKSCREEN *cdkscreen, CDKSWINDOW *swindow, DBPROCESS *process);
 
44
void useDatabase (CDKSWINDOW *swindow, DBPROCESS *dbProc, char *command);
 
45
void intro (CDKSCREEN *screen);
 
46
void help (CDKENTRY *entry);
 
47
void loadHistory (struct history_st *history);
 
48
void saveHistory (struct history_st *history, int count);
 
49
 
 
50
/*
 
51
 * Define callback prototypes.
 
52
 */
 
53
void viewHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key);
 
54
void swindowHelpCB (EObjectType cdktype, void *object, void *clientData, chtype key);
 
55
void historyUpCB   (EObjectType cdktype, void *object, void *clientData, chtype key);
 
56
void historyDownCB (EObjectType cdktype, void *object, void *clientData, chtype key);
 
57
void listHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key);
 
58
 
 
59
/*
 
60
 * Define Sybase error/message callbacks. This is required by DBLib.
 
61
 */
 
62
int err_handler (DBPROCESS *dbProcess, DBINT mesgNumber, int mesgState,
 
63
                        int severity, char *mesgText);
 
64
int msg_handler (DBPROCESS *dbProcess, DBINT mesgNumber, int mesgState,
 
65
                        int severity, char *mesgText);
 
66
 
 
67
/*
 
68
 * Written by:  Mike Glover
 
69
 * Purpose:
 
70
 *              This creates a very simple interface to Sybase.
 
71
 */
 
72
int main (int argc, char **argv)
 
73
{
 
74
   /* Declare variables. */
 
75
   CDKSWINDOW *commandOutput    = 0;
 
76
   CDKENTRY *commandEntry       = 0;
 
77
   DBPROCESS *dbProcess         = 0;
 
78
   WINDOW *cursesWin            = 0;
 
79
   char *dsquery                = 0;
 
80
   char *command                = 0;
 
81
   char *prompt                 = 0;
 
82
   char *upper                  = 0;
 
83
   char *login                  = 0;
 
84
   char *password               = 0;
 
85
   char *server                 = 0;
 
86
   int count                    = 0;
 
87
   int width                    = 0;
 
88
   int ret                      = 0;
 
89
   struct history_st history;
 
90
   char *mesg[5], temp[1000];
 
91
 
 
92
   /* Set up the history. */
 
93
   GPCurrentDatabase    = strdup ("master");
 
94
   history.current      = 0;
 
95
   history.count        = 0;
 
96
 
 
97
   /* Check the command line for options. */
 
98
   while (1)
 
99
   {
 
100
      /* Are there any more command line options to parse. */
 
101
      if ((ret = getopt (argc, argv, "p:U:P:S:h")) == -1)
 
102
      {
 
103
         break;
 
104
      }
 
105
 
 
106
      switch (ret)
 
107
      {
 
108
         case 'p':
 
109
              prompt = copyChar (optarg);
 
110
              break;
 
111
 
 
112
         case 'U':
 
113
              login = copyChar (optarg);
 
114
              break;
 
115
 
 
116
         case 'P':
 
117
              password = copyChar (optarg);
 
118
              break;
 
119
 
 
120
         case 'S':
 
121
              server = copyChar (optarg);
 
122
              break;
 
123
 
 
124
         case 'h':
 
125
              printf ("Usage: %s %s\n", argv[0], GPUsage);
 
126
              exit (0);
 
127
              break;
 
128
      }
 
129
   }
 
130
 
 
131
   /* Set up the command prompt. */
 
132
   if (prompt == 0)
 
133
   {
 
134
      if (server == 0)
 
135
      {
 
136
         if ((dsquery = getenv ("DSQUERY")) != 0)
 
137
         {
 
138
            sprintf (temp, "</B/24>[%s] Command >", dsquery);
 
139
            prompt = copyChar (temp);
 
140
         }
 
141
         else
 
142
         {
 
143
            prompt = copyChar ("</B/24>Command >");
 
144
         }
 
145
      }
 
146
      else
 
147
      {
 
148
         sprintf (temp, "</B/24>[%s] Command >", server);
 
149
         prompt = copyChar (temp);
 
150
      }
 
151
   }
 
152
 
 
153
   /* Set up CDK. */
 
154
   cursesWin = initscr();
 
155
   GPCdkScreen = initCDKScreen (cursesWin);
 
156
 
 
157
   /* Start color. */
 
158
   initCDKColor();
 
159
 
 
160
   /* Initialize DB-Library. */
 
161
   if (dbinit() == FAIL)
 
162
   {
 
163
      mesg[0] = "<C></U>Fatal Error";
 
164
      mesg[1] = "<C>Could not connect to the Sybase database.";
 
165
      popupLabel (GPCdkScreen, mesg, 2);
 
166
      exit (-1);
 
167
   }
 
168
 
 
169
   /* Load the history. */
 
170
   loadHistory (&history);
 
171
 
 
172
   /* Create the scrolling window. */
 
173
   commandOutput = newCDKSwindow (GPCdkScreen, CENTER, TOP, -8, -2,
 
174
                                        "<C></B/5>Command Output Window",
 
175
                                        MAXWIDTH, TRUE, FALSE);
 
176
 
 
177
   /* Create the entry field. */
 
178
   width        = COLS - strlen (prompt) - 1;
 
179
   commandEntry = newCDKEntry (GPCdkScreen, CENTER, BOTTOM,
 
180
                                0, prompt, A_BOLD|COLOR_PAIR(8),
 
181
                                COLOR_PAIR(24)|'_', vMIXED,
 
182
                                width, 1, 512, FALSE, FALSE);
 
183
 
 
184
   /* Create the key bindings. */
 
185
   bindCDKObject (vENTRY, commandEntry, KEY_UP, &historyUpCB, &history);
 
186
   bindCDKObject (vENTRY, commandEntry, KEY_DOWN, &historyDownCB, &history);
 
187
   bindCDKObject (vENTRY, commandEntry, CONTROL('^'), &listHistoryCB, &history);
 
188
   bindCDKObject (vENTRY, commandEntry, TAB, &viewHistoryCB, commandOutput);
 
189
   bindCDKObject (vSWINDOW, commandOutput, '?', swindowHelpCB, commandEntry);
 
190
 
 
191
   /* Draw the screen. */
 
192
   refreshCDKScreen (GPCdkScreen);
 
193
 
 
194
   /* Display the introduction window. */
 
195
   intro (GPCdkScreen);
 
196
 
 
197
   /* Make them login first. */
 
198
   dbProcess = sybaseLogin (GPCdkScreen, login, password, 3);
 
199
   if (dbProcess == 0)
 
200
   {
 
201
      destroyCDKScreen (GPCdkScreen);
 
202
      endCDK ();
 
203
      exit (-1);
 
204
   }
 
205
 
 
206
   /* Do this forever. */
 
207
   for (;;)
 
208
   {
 
209
      /* Get the command. */
 
210
      command = activateCDKEntry (commandEntry, 0);
 
211
 
 
212
      /* Strip off leading and trailing white space. */
 
213
      stripWhiteSpace (vBOTH, command);
 
214
 
 
215
      /* Upper case the command. */
 
216
      upper = uc (command);
 
217
 
 
218
      /* Check the output of the command. */
 
219
      if (strcmp (upper, "QUIT") == 0 ||
 
220
                strcmp (upper, "EXIT") == 0 ||
 
221
                strcmp (upper, "Q") == 0 ||
 
222
                strcmp (upper, "E") == 0 ||
 
223
                commandEntry->exitType == vESCAPE_HIT)
 
224
      {
 
225
         /* Save the history. */
 
226
         saveHistory (&history, 100);
 
227
 
 
228
         /* Exit. */
 
229
         dbclose (dbProcess);
 
230
         dbexit();
 
231
 
 
232
         /* All done. */
 
233
         destroyCDKEntry (commandEntry);
 
234
         destroyCDKSwindow (commandOutput);
 
235
         delwin (cursesWin);
 
236
         freeChar (upper);
 
237
         endCDK();
 
238
         exit (0);
 
239
      }
 
240
      else if (strcmp (command, "login") == 0)
 
241
      {
 
242
         DBPROCESS *newLogin = sybaseLogin (GPCdkScreen, 0, 0, 3);
 
243
         if (newLogin == 0)
 
244
         {
 
245
            addCDKSwindow (commandOutput, "Login Error: Could not switch to new user.", BOTTOM);
 
246
         }
 
247
         else
 
248
         {
 
249
            /* Close the old connection. */
 
250
            dbclose (dbProcess);
 
251
            dbProcess = newLogin;
 
252
 
 
253
            /* Add a message to the scrolling window. */
 
254
            addCDKSwindow (commandOutput,
 
255
                                "Logged into database as new user.",
 
256
                                BOTTOM);
 
257
            count = 0;
 
258
         }
 
259
      }
 
260
      else if (strcmp (command, "logout") == 0)
 
261
      {
 
262
         /* Close the old connection. */
 
263
         dbclose (dbProcess);
 
264
         dbProcess = 0;
 
265
 
 
266
         /* Add a message to the scrolling window. */
 
267
         addCDKSwindow (commandOutput, "Logged out.", BOTTOM);
 
268
         count = 0;
 
269
      }
 
270
      else if (strcmp (command, "clear") == 0)
 
271
      {
 
272
         /* Clear the scrolling window. */
 
273
         cleanCDKSwindow (commandOutput);
 
274
      }
 
275
      else if (strcmp (command, "history") == 0)
 
276
      {
 
277
         listHistoryCB (vENTRY, (void *)commandEntry, (void *)&history, 0);
 
278
      }
 
279
      else if (strcmp (command, "tables") == 0)
 
280
      {
 
281
         /* Check if we are logged in. */
 
282
         if (dbProcess == 0)
 
283
         {
 
284
            addCDKSwindow (commandOutput, "You must login first.", BOTTOM);
 
285
         }
 
286
         else
 
287
         {
 
288
            sprintf (command, "select * from sysobjects where type = 'U'");
 
289
 
 
290
            /* Put the command into the ISQL buffer. */
 
291
            dbcmd (dbProcess, command);
 
292
 
 
293
            /* Put the command into the scrolling window. */
 
294
            sprintf (temp, "</R>%d><!R> %s", count+1, command);
 
295
            addCDKSwindow (commandOutput, temp, BOTTOM);
 
296
 
 
297
            /* Increment the counter. */
 
298
            count++;
 
299
         }
 
300
      }
 
301
      else if (strcmp (command, "help") == 0)
 
302
      {
 
303
         /* Display the help. */
 
304
         help(commandEntry);
 
305
      }
 
306
      else if (command[0] == 'u' && command[1] == 's' &&
 
307
                command[2] == 'e' && command[3] == ' ')
 
308
      {
 
309
         /* They want to use a database. */
 
310
         useDatabase (commandOutput, dbProcess, command);
 
311
         count = 0;
 
312
      }
 
313
      else if (strcmp (command, "go") == 0)
 
314
      {
 
315
         /* Check if we are logged in. */
 
316
         if (dbProcess == 0)
 
317
         {
 
318
            addCDKSwindow (commandOutput, "You must login first.", BOTTOM);
 
319
         }
 
320
         else
 
321
         {
 
322
            /* Put the command into the scrolling window. */
 
323
            sprintf (temp, "</R>%d><!R> %s", count+1, command);
 
324
            addCDKSwindow (commandOutput, temp, BOTTOM);
 
325
            count = 0;
 
326
 
 
327
            /* Run the command. */
 
328
            runIsqlCommand (GPCdkScreen, commandOutput, dbProcess);
 
329
         }
 
330
      }
 
331
      else
 
332
      {
 
333
         /* Check if we are logged in. */
 
334
         if (dbProcess == 0)
 
335
         {
 
336
            addCDKSwindow (commandOutput, "You must login first.", BOTTOM);
 
337
         }
 
338
         else
 
339
         {
 
340
            /* Put the command into the ISQL buffer. */
 
341
            dbcmd (dbProcess, command);
 
342
 
 
343
            /* Put the command into the scrolling window. */
 
344
            sprintf (temp, "</R>%d><!R> %s", count+1, command);
 
345
            addCDKSwindow (commandOutput, temp, BOTTOM);
 
346
 
 
347
            /* Increment the counter. */
 
348
            count++;
 
349
         }
 
350
      }
 
351
 
 
352
      /* Keep the history. */
 
353
      history.command[history.count] = copyChar (command);
 
354
      history.count++;
 
355
      history.current = history.count;
 
356
 
 
357
      /* Clear the entry field. */
 
358
      cleanCDKEntry (commandEntry);
 
359
 
 
360
      /* Free up the memory used by the upper pointer. */
 
361
      freeChar (upper);
 
362
   }
 
363
}
 
364
 
 
365
/*
 
366
 * This lets a person 'use' a database.
 
367
 */
 
368
void useDatabase (CDKSWINDOW *swindow, DBPROCESS *dbProc, char *command)
 
369
{
 
370
   char *database = 0;
 
371
   char temp[256];
 
372
   char **words;
 
373
   int wordCount, x;
 
374
 
 
375
   /* Split the command line up and get the database name. */
 
376
   words = CDKsplitString (command, ' ');
 
377
   wordCount = CDKcountStrings (words);
 
378
 
 
379
   /* Look for the name. */
 
380
   for (x=1; x < wordCount; x++)
 
381
   {
 
382
      if (strlen (words[x]) != 0)
 
383
      {
 
384
         database = copyChar (words[x]);
 
385
      }
 
386
   }
 
387
   CDKfreeStrings(words);
 
388
 
 
389
   /* Try to actually use the database. */
 
390
   if (dbuse(dbProc, database) == FAIL)
 
391
   {
 
392
      /* We aren't allowed to use that database. */
 
393
      sprintf (temp, "Command: %s", command);
 
394
      addCDKSwindow (swindow, temp, BOTTOM);
 
395
      addCDKSwindow (swindow, "</B/16>Error<!B!16> You are not allowed to use that database.", BOTTOM);
 
396
      return;
 
397
   }
 
398
 
 
399
   /* Set the global database name. */
 
400
   if (database == 0)
 
401
   {
 
402
      /* Put a syntax error in the scrolling window. */
 
403
      sprintf (temp, "Command: %s", command);
 
404
      addCDKSwindow (swindow, temp, BOTTOM);
 
405
      addCDKSwindow (swindow, "</B/16>Error<!B!16> Syntax Error", BOTTOM);
 
406
      return;
 
407
   }
 
408
 
 
409
   /* Clear out the old database name and set the new one. */
 
410
   freeChar (GPCurrentDatabase);
 
411
   GPCurrentDatabase = database;
 
412
 
 
413
   /* Add a message into the scrolling window. */
 
414
   sprintf (temp, "Command: %s", command);
 
415
   addCDKSwindow (swindow, temp, BOTTOM);
 
416
   sprintf (temp, "Default Database set to %s", GPCurrentDatabase);
 
417
   addCDKSwindow (swindow, temp, BOTTOM);
 
418
}
 
419
 
 
420
/*
 
421
 * This does the requisite checking for failed login attempts.
 
422
 */
 
423
DBPROCESS *sybaseLogin (CDKSCREEN *screen, char *accountName, char *accountPassword, int attemptCount)
 
424
{
 
425
   DBPROCESS *dbProcess = 0;
 
426
   char *login          = accountName;
 
427
   char *password       = accountPassword;
 
428
   int count            = 0;
 
429
   int lines            = 0;
 
430
   char *mesg[5];
 
431
 
 
432
   /* Give them X attempts, then kick them out. */
 
433
   while (count < attemptCount)
 
434
   {
 
435
      /* Try to login. */
 
436
      dbProcess = loginToSybase (GPCdkScreen, login, password);
 
437
 
 
438
      /*
 
439
       * If the dbprocess is null the account/password
 
440
       * pair does not exist.
 
441
       */
 
442
       if (dbProcess == 0)
 
443
       {
 
444
          /*
 
445
           * If the login and account names were provided,
 
446
           * set them to null and allow the user to enter
 
447
           * the name and password by hand.
 
448
           */
 
449
           login = 0;
 
450
           password = 0;
 
451
 
 
452
          /* Spit out the login error message. */
 
453
          lines = 0;
 
454
          mesg[lines++] = "<C></B/5>Login Error";
 
455
          mesg[lines++] = " ";
 
456
          mesg[lines++] = "<C>The login/password pair does not exist.";
 
457
          mesg[lines++] = " ";
 
458
          mesg[lines++] = "<C>Please try again.";
 
459
 
 
460
          popupLabel (GPCdkScreen, mesg, lines);
 
461
 
 
462
          eraseCDKScreen (GPCdkScreen);
 
463
          refreshCDKScreen (GPCdkScreen);
 
464
          count++;
 
465
       }
 
466
       else
 
467
       {
 
468
          break;
 
469
       }
 
470
   }
 
471
 
 
472
   /* Did we expire the login attempts? */
 
473
   if (count > attemptCount-1)
 
474
   {
 
475
      lines = 0;
 
476
      mesg[lines++] = "<C>Login Error";
 
477
      mesg[lines++] = " ";
 
478
      mesg[lines++] = "<C>Too many attempyts to login.";
 
479
      mesg[lines++] = "<C>Exiting.";
 
480
 
 
481
      popupLabel (GPCdkScreen, mesg, lines);
 
482
 
 
483
      return 0;
 
484
   }
 
485
   return dbProcess;
 
486
}
 
487
 
 
488
/*
 
489
 * Let the user login.
 
490
 */
 
491
DBPROCESS *loginToSybase (CDKSCREEN *screen, char *accountName, char *accountPassword)
 
492
{
 
493
   CDKENTRY *loginEntry         = 0;
 
494
   CDKENTRY *passwordEntry      = 0;
 
495
   LOGINREC *dbLogin            = 0;
 
496
   char *hostAccount            = 0;
 
497
   char *login                  = accountName;
 
498
   char *password               = accountPassword;
 
499
   char *mesg[10], temp[256];
 
500
 
 
501
   /* Draw the screen. */
 
502
   refreshCDKScreen (screen);
 
503
 
 
504
   /* Define the login entry field. */
 
505
   if (login == 0)
 
506
   {
 
507
      loginEntry = newCDKEntry (screen, CENTER, CENTER,
 
508
                                "\n<C></B/5>Sybase Login\n",
 
509
                                "Account Name: ",
 
510
                                A_BOLD|COLOR_PAIR(8),
 
511
                                COLOR_PAIR(24)|'_', vMIXED,
 
512
                                20, 1, 20, TRUE, FALSE);
 
513
 
 
514
      /* Use the current account name as the default answer. */
 
515
      hostAccount = getlogin();
 
516
      setCDKEntryValue (loginEntry, hostAccount);
 
517
 
 
518
      /* Get the login. */
 
519
      while (1)
 
520
      {
 
521
         /* Redraw the screen. */
 
522
         eraseCDKScreen (loginEntry->screen);
 
523
         refreshCDKScreen (loginEntry->screen);
 
524
 
 
525
         /* Get the login to the sybase account. */
 
526
         login = copyChar (activateCDKEntry (loginEntry, 0));
 
527
 
 
528
         /* Check if they hit escape. */
 
529
         if (loginEntry->exitType == vESCAPE_HIT)
 
530
         {
 
531
            mesg[0] = "<C></U>Error";
 
532
            mesg[1] = "A user name must be provided.";
 
533
            popupLabel (screen, mesg, 2);
 
534
         }
 
535
         else
 
536
         {
 
537
            break;
 
538
         }
 
539
      }
 
540
 
 
541
      /* Destroy the widget. */
 
542
      destroyCDKEntry (loginEntry);
 
543
   }
 
544
 
 
545
   /* Get the password if we need too. */
 
546
   if (password == 0)
 
547
   {
 
548
      sprintf (temp, "\n<C></B/5>%s's Password\n", login);
 
549
      passwordEntry = newCDKEntry (screen, CENTER, CENTER,
 
550
                                temp, "Account Password: ",
 
551
                                A_BOLD|COLOR_PAIR(8),
 
552
                                COLOR_PAIR(24)|'_', vHMIXED,
 
553
                                20, 0, 20, TRUE, FALSE);
 
554
      setCDKEntryHiddenChar (passwordEntry, '*');
 
555
 
 
556
      /* Get the password. (the account may not have a password.) */
 
557
      password = copyChar (activateCDKEntry (passwordEntry, 0));
 
558
      if ((passwordEntry->exitType == vESCAPE_HIT) ||
 
559
        ((int)strlen(password) == 0))
 
560
      {
 
561
         password = "";
 
562
      }
 
563
 
 
564
      /* Destroy the widget. */
 
565
      destroyCDKEntry (passwordEntry);
 
566
   }
 
567
 
 
568
   /*
 
569
    * Try to connect to the database and get a LOGINREC structre.
 
570
    */
 
571
   if ((dbLogin = dblogin()) == 0)
 
572
   {
 
573
      mesg[0] = "<C></U>Fatal Error";
 
574
      mesg[1] = "<C>Could not connect to the Sybase database.";
 
575
      popupLabel (screen, mesg, 2);
 
576
      refreshCDKScreen (screen);
 
577
      exit (-1);
 
578
   }
 
579
 
 
580
  /*
 
581
   * Set the login and password and try to login to the database.
 
582
   */
 
583
   DBSETLUSER (dbLogin, login);
 
584
   DBSETLPWD (dbLogin, password);
 
585
   DBSETLAPP (dbLogin, "cdk_syb");
 
586
 
 
587
   /* Create a dbprocess structure to communicate with the database. */
 
588
   return dbopen (dbLogin, 0);
 
589
}
 
590
 
 
591
/*
 
592
 * This actually runs the command.
 
593
 */
 
594
void runIsqlCommand (CDKSCREEN *screen, CDKSWINDOW *swindow, DBPROCESS *dbProcess)
 
595
{
 
596
   /* Declare local variables. */
 
597
   RETCODE returnCode;
 
598
   int rowCount;
 
599
 
 
600
   /* Add in a output seperation line. */
 
601
   addCDKSwindow (swindow, "<C><#HL(5)> Start of Output <#HL(5)>", BOTTOM);
 
602
 
 
603
   /* Run the command. */
 
604
   dbsqlexec (dbProcess);
 
605
 
 
606
   /* Check the return code of the commands. */
 
607
   while ((returnCode = dbresults (dbProcess)) != NO_MORE_RESULTS)
 
608
   {
 
609
      if (returnCode == FAIL)
 
610
      {
 
611
         /* Oops, the command bombed. */
 
612
         addCDKSwindow (swindow, "</5/16>Command failed.", BOTTOM);
 
613
      }
 
614
      else
 
615
      {
 
616
         if (!(DBCMDROW (dbProcess)))
 
617
         {
 
618
            /* The command could not return any rows. */
 
619
            addCDKSwindow (swindow, "</5/16>Command could not return rows.", BOTTOM);
 
620
         }
 
621
         else
 
622
         {
 
623
            /*
 
624
             * The command returned some rows, print out the title.
 
625
             */
 
626
            char *row = assembleTitle (dbProcess);
 
627
            addCDKSwindow (swindow, row, BOTTOM);
 
628
            freeChar (row);
 
629
 
 
630
            /* For each row returned, assemble the info. */
 
631
            rowCount = 0;
 
632
            while (dbnextrow (dbProcess) != NO_MORE_ROWS)
 
633
            {
 
634
               row = assembleRow (dbProcess);
 
635
               addCDKSwindow (swindow, row, BOTTOM);
 
636
               freeChar (row);
 
637
            }
 
638
         }
 
639
      }
 
640
   }
 
641
 
 
642
   /* Add in a output seperation line. */
 
643
   addCDKSwindow (swindow, "<C><#HL(5)>  End of Output  <#HL(5)>", BOTTOM);
 
644
   addCDKSwindow (swindow, "", BOTTOM);
 
645
 
 
646
   /* Can the query... */
 
647
   dbcanquery (dbProcess);
 
648
}
 
649
 
 
650
/*
 
651
 * This creates a single line from the column widths and values.
 
652
 */
 
653
char *assembleTitle (DBPROCESS *dbProc)
 
654
{
 
655
   char *colName        = 0;
 
656
   int colWidth         = 0;
 
657
   int colNameLen       = 0;
 
658
   int colCount         = dbnumcols (dbProc);
 
659
   int x                = 0;
 
660
   char temp[MAXWIDTH];
 
661
   char row[MAXWIDTH];
 
662
 
 
663
   /* Clean the row out. */
 
664
   memset (row, '\0', MAXWIDTH);
 
665
 
 
666
   /* Start assembling the row. */
 
667
   for (x=1; x <= colCount; x++)
 
668
   {
 
669
      colName           = dbcolname (dbProc, x);
 
670
      colWidth          = getColWidth (dbProc, x);
 
671
      colNameLen        = (int)strlen (colName);
 
672
 
 
673
      /* If we need to pad, then pad. */
 
674
      if (colNameLen < colWidth)
 
675
      {
 
676
         /* Create a string the same length as the col width. */
 
677
         memset (temp, '\0', MAXWIDTH);
 
678
         memset (temp, ' ', (colWidth-colNameLen));
 
679
 
 
680
         /* Copy the name. */
 
681
         sprintf (row, "%s %s%s", row, colName, temp);
 
682
      }
 
683
      else
 
684
      {
 
685
         /* Copy the name. */
 
686
         sprintf (row, "%s %s", row, colName);
 
687
      }
 
688
   }
 
689
   return (char *)strdup (row);
 
690
}
 
691
 
 
692
/*
 
693
 * This assembles a single row.
 
694
 */
 
695
char *assembleRow (DBPROCESS *dbProcess)
 
696
{
 
697
   char *dataValue      = 0;
 
698
   int colCount         = dbnumcols (dbProcess);
 
699
   int columnType       = 0;
 
700
   int colWidth         = 0;
 
701
   int valueLen         = 0;
 
702
   char value[MAXWIDTH];
 
703
   char temp[MAXWIDTH];
 
704
   char row[MAXWIDTH];
 
705
   char format[20];
 
706
   int x;
 
707
 
 
708
   /* Clean out the row. */
 
709
   memset (row, '\0', MAXWIDTH);
 
710
 
 
711
   /* Start assembling the row. */
 
712
   for (x=1; x <= colCount; x++)
 
713
   {
 
714
      columnType        = (int)dbcoltype (dbProcess, x);
 
715
      colWidth          = (int)getColWidth (dbProcess, x);
 
716
      valueLen          = (int)dbdatlen (dbProcess, x);
 
717
 
 
718
      /* Check the column type. */
 
719
      if (columnType == SYBINT1)
 
720
      {
 
721
         DBINT object_id = *((DBINT *)dbdata(dbProcess, x));
 
722
         sprintf (format, "%%-%dd", colWidth);
 
723
         sprintf (value, format, (int)object_id);
 
724
      }
 
725
      else if (columnType == SYBINT2)
 
726
      {
 
727
         DBINT object_id = *((DBINT *)dbdata(dbProcess, x));
 
728
         sprintf (format, "%%-%dd", colWidth);
 
729
         sprintf (value, format, (int)object_id);
 
730
      }
 
731
      else if (columnType == SYBINT4)
 
732
      {
 
733
         DBINT object_id = *((DBINT *)dbdata(dbProcess, x));
 
734
         sprintf (format, "%%-%dd", colWidth);
 
735
         sprintf (value, format, (int)object_id);
 
736
      }
 
737
      else if (columnType == SYBREAL)
 
738
      {
 
739
         DBREAL object_id = *((DBREAL *)dbdata(dbProcess, x));
 
740
         sprintf (format, "%%-%d.2f", colWidth);
 
741
         sprintf (value, format, object_id);
 
742
      }
 
743
      else if (columnType == SYBFLT8)
 
744
      {
 
745
         DBFLT8 object_id = *((DBFLT8 *)dbdata(dbProcess, x));
 
746
         sprintf (format, "%%-%d.2f", colWidth);
 
747
         sprintf (value, format, object_id);
 
748
      }
 
749
      else
 
750
      {
 
751
         if (valueLen <= 0)
 
752
         {
 
753
            strcpy (value, " ");
 
754
         }
 
755
         else
 
756
         {
 
757
            memset (value, '\0', MAXWIDTH);
 
758
            dataValue = (DBCHAR *)dbdata (dbProcess, x);
 
759
            strncpy (value, dataValue, valueLen);
 
760
         }
 
761
      }
 
762
 
 
763
      /* If we need to pad, then pad. */
 
764
      if (valueLen < colWidth)
 
765
      {
 
766
         /* Copy the value into the string. */
 
767
         memset (temp, '\0', MAXWIDTH);
 
768
         memset (temp, ' ', (colWidth-valueLen));
 
769
         sprintf  (row, "%s %s%s", row, value, temp);
 
770
      }
 
771
      else
 
772
      {
 
773
         sprintf  (row, "%s %s", row, value);
 
774
      }
 
775
   }
 
776
   return copyChar (row);
 
777
}
 
778
 
 
779
/*
 
780
 * This function returns the correct width of a column, taking
 
781
 * into account the width of the title, the width of the data
 
782
 * element.
 
783
 */
 
784
int getColWidth (DBPROCESS *dbProcess, int col)
 
785
{
 
786
   char *colName        = dbcolname (dbProcess, col);
 
787
   int colNameLen       = (int)strlen(colName);
 
788
   int colWidth         = dbcollen (dbProcess, col);
 
789
   int columnType       = (int)dbcoltype (dbProcess, col);
 
790
 
 
791
   /* If the colType is int/real/float adjust accordingly. */
 
792
   if (columnType == SYBINT1 || columnType == SYBINT2 ||
 
793
        columnType == SYBINT4)
 
794
   {
 
795
      colWidth = 5;
 
796
   }
 
797
   else if (columnType == SYBREAL || columnType == SYBFLT8)
 
798
   {
 
799
      colWidth = 8;
 
800
   }
 
801
 
 
802
   /* Is the name of the column wider than the col width? */
 
803
   if (colNameLen >= colWidth)
 
804
   {
 
805
      return (colNameLen+1);
 
806
   }
 
807
   return colWidth;
 
808
}
 
809
 
 
810
/*
 
811
 * This callback allows the user to play with the scrolling window.
 
812
 */
 
813
void viewHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key)
 
814
{
 
815
   CDKSWINDOW *swindow  = (CDKSWINDOW *)clientData;
 
816
   CDKENTRY *entry      = (CDKENTRY *)object;
 
817
 
 
818
   /* Let them play... */
 
819
   activateCDKSwindow (swindow, 0);
 
820
 
 
821
   /* Redraw the entry field. */
 
822
   drawCDKEntry (entry, ObjOf(entry)->box);
 
823
}
 
824
 
 
825
/*
 
826
 * This displays a little introduction screen.
 
827
 */
 
828
void intro (CDKSCREEN *screen)
 
829
{
 
830
   int lines    = 0;
 
831
   char *mesg[10];
 
832
 
 
833
   /* Create the message. */
 
834
   mesg[lines++] = "";
 
835
   mesg[lines++] = "<C></B/16>Sybase Command Interface";
 
836
   mesg[lines++] = "<C>Written by Mike Glover";
 
837
   mesg[lines++] = "";
 
838
   mesg[lines++] = "<C>Type </B>help<!B> to get help.";
 
839
 
 
840
   /* Display the message. */
 
841
   popupLabel (screen, mesg, lines);
 
842
}
 
843
 
 
844
/*
 
845
 * This function displays help.
 
846
 */
 
847
void help (CDKENTRY *entry)
 
848
{
 
849
   int lines    = 0;
 
850
   char *mesg[25];
 
851
 
 
852
   /* Create the help message. */
 
853
   mesg[lines++] = "<C></B/29>Help";
 
854
   mesg[lines++] = "";
 
855
   mesg[lines++] = "</B/24>When in the command line.";
 
856
   mesg[lines++] = "<B=Up Arrow  > Scrolls back one command.";
 
857
   mesg[lines++] = "<B=Down Arrow> Scrolls forward one command.";
 
858
   mesg[lines++] = "<B=Tab       > Activates the scrolling window.";
 
859
   mesg[lines++] = "<B=help      > Displays this help window.";
 
860
   mesg[lines++] = "";
 
861
   mesg[lines++] = "</B/24>When in the scrolling window.";
 
862
   mesg[lines++] = "<B=l or L    > Loads a file into the window.";
 
863
   mesg[lines++] = "<B=s or S    > Saves the contents of the window to a file.";
 
864
   mesg[lines++] = "<B=Up Arrow  > Scrolls up one line.";
 
865
   mesg[lines++] = "<B=Down Arrow> Scrolls down one line.";
 
866
   mesg[lines++] = "<B=Page Up   > Scrolls back one page.";
 
867
   mesg[lines++] = "<B=Page Down > Scrolls forward one page.";
 
868
   mesg[lines++] = "<B=Tab or Esc> Returns to the command line.";
 
869
   mesg[lines++] = "<B=?         > Displays this help window.";
 
870
   mesg[lines++] = "";
 
871
   mesg[lines++] = "<C> (</B/24>Refer to the scrolling window online manual for more help<!B!24>.)";
 
872
 
 
873
   /* Pop up the help message. */
 
874
   popupLabel (entry->screen, mesg, lines);
 
875
}
 
876
 
 
877
/*
 
878
 * This converts a word to upper case.
 
879
 */
 
880
char *uc (char *word)
 
881
{
 
882
   int length   = strlen (word);
 
883
   char *upper  = (char *)malloc (sizeof (char *) * (length+2));
 
884
   int x;
 
885
 
 
886
   /* Start converting the case. */
 
887
   for (x=0; x < length; x++)
 
888
   {
 
889
      if (isalpha ((int)word[x]))
 
890
      {
 
891
         upper[x] = toupper(word[x]);
 
892
      }
 
893
      else
 
894
      {
 
895
         upper[x] = word[x];
 
896
      }
 
897
   }
 
898
   upper[length] = '\0';
 
899
   return upper;
 
900
}
 
901
 
 
902
/*
 
903
 * The following two functions are the error and message handler callbacks.
 
904
 * which will be called by Sybase when and error occurs.
 
905
 */
 
906
int err_handler (DBPROCESS *dbProcess, DBINT mesgNumber, int mesgState, int severity, char *mesgText)
 
907
{
 
908
   /* Declare local variables. */
 
909
   char *mesg[10], temp[256];
 
910
   int errorCount = 0;
 
911
 
 
912
   /* Check if the process is dead. */
 
913
   if ((dbProcess == 0) || (DBDEAD(dbProcess)))
 
914
   {
 
915
      mesg[0] = "</B/32>Database Process Error";
 
916
      mesg[1] = "<C>The database process seems to have died.";
 
917
      mesg[2] = "<C>Try logging in again with the </R>login<!R> command";
 
918
      popupLabel (GPCdkScreen, mesg, 3);
 
919
      return INT_EXIT;
 
920
   }
 
921
   else
 
922
   {
 
923
      mesg[0] = "</B/32>DB-Library Error";
 
924
      sprintf (temp, "<C>%s", dberrstr);
 
925
      mesg[1] = copyChar (temp);
 
926
      errorCount = 2;
 
927
   }
 
928
 
 
929
   /* Display the message if we have an error. */
 
930
   if (errorCount > 0)
 
931
   {
 
932
      popupLabel (GPCdkScreen, mesg, --errorCount);
 
933
   }
 
934
 
 
935
   /* Clean up. */
 
936
   if (errorCount == 2)
 
937
   {
 
938
      freeChar (mesg[1]);
 
939
   }
 
940
   return (1);
 
941
}
 
942
int mesg_handler (DBPROCESS *dbProcess, DBINT mesgNumber, int mesgState, int severity, char *mesgText)
 
943
{
 
944
   /* Declare local variables. */
 
945
   char *mesg[10], temp[256];
 
946
 
 
947
   /* Create the message. */
 
948
   mesg[0] = "<C></B/16>SQL Server Message";
 
949
   sprintf (temp, "</R>Message Number<!R> %ld", mesgNumber);
 
950
   mesg[1] = copyChar (temp);
 
951
   sprintf (temp, "</R>State         <!R> %d", mesgState);
 
952
   mesg[2] = copyChar (temp);
 
953
   sprintf (temp, "</R>Severity      <!R> %d", severity);
 
954
   mesg[3] = copyChar (temp);
 
955
   sprintf (temp, "</R>Message       <!R> %s", mesgText);
 
956
   mesg[4] = copyChar (temp);
 
957
   popupLabel (GPCdkScreen, mesg, 5);
 
958
 
 
959
   /* Clean up. */
 
960
   freeChar (mesg[1]); freeChar (mesg[2]);
 
961
   freeChar (mesg[3]); freeChar (mesg[4]);
 
962
   return (1);
 
963
}
 
964
 
 
965
/*
 
966
 * This is for the scrolling window help callback.
 
967
 */
 
968
void swindowHelpCB (EObjectType cdktype, void *object, void *clientData, chtype key)
 
969
{
 
970
   CDKENTRY *entry      = (CDKENTRY *)clientData;
 
971
   help(entry);
 
972
}
 
973
 
 
974
/*
 
975
 * This is the callback for the down arrow.
 
976
 */
 
977
void historyUpCB (EObjectType cdktype, void *object, void *clientData, chtype key)
 
978
{
 
979
   CDKENTRY *entry = (CDKENTRY *)object;
 
980
   struct history_st *history = (struct history_st *) clientData;
 
981
 
 
982
   /* Make sure we don't go out of bounds. */
 
983
   if (history->current == 0)
 
984
   {
 
985
      Beep();
 
986
      return;
 
987
   }
 
988
 
 
989
   /* Decrement the counter. */
 
990
   history->current--;
 
991
 
 
992
   /* Display the command. */
 
993
   setCDKEntryValue (entry, history->command[history->current]);
 
994
   drawCDKEntry (entry, ObjOf(entry)->box);
 
995
}
 
996
 
 
997
/*
 
998
 * This is the callback for the down arrow.
 
999
 */
 
1000
void historyDownCB (EObjectType cdktype, void *object, void *clientData, chtype key)
 
1001
{
 
1002
   CDKENTRY *entry = (CDKENTRY *)object;
 
1003
   struct history_st *history = (struct history_st *) clientData;
 
1004
 
 
1005
   /* Make sure we don't go out of bounds. */
 
1006
   if (history->current == history->count)
 
1007
   {
 
1008
      Beep();
 
1009
      return;
 
1010
   }
 
1011
 
 
1012
   /* Increment the counter... */
 
1013
   history->current++;
 
1014
 
 
1015
   /* If we are at the end, clear the entry field. */
 
1016
   if (history->current == history->count)
 
1017
   {
 
1018
      cleanCDKEntry (entry);
 
1019
      drawCDKEntry (entry, ObjOf(entry)->box);
 
1020
      return;
 
1021
   }
 
1022
 
 
1023
   /* Display the command. */
 
1024
   setCDKEntryValue (entry, history->command[history->current]);
 
1025
   drawCDKEntry (entry, ObjOf(entry)->box);
 
1026
}
 
1027
 
 
1028
/*
 
1029
 * This callback allows the user to pick from the history list from a
 
1030
 * scrolling list.
 
1031
 */
 
1032
void listHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key)
 
1033
{
 
1034
   CDKSCROLL *scrollList        = 0;
 
1035
   CDKENTRY *entry              = (CDKENTRY *)object;
 
1036
   struct history_st *history   = (struct history_st *) clientData;
 
1037
   int height                   = (history->count < 10 ? history->count+3 : 13);
 
1038
   int selection;
 
1039
 
 
1040
   /* No history, no list. */
 
1041
   if (history->count == 0)
 
1042
   {
 
1043
      /* Popup a little window telling the user there are no commands. */
 
1044
      char *mesg[] = {"<C></B/16>No Commands Entered", "<C>No History"};
 
1045
      popupLabel (entry->screen, mesg, 2);
 
1046
 
 
1047
      /* Redraw the screen. */
 
1048
      eraseCDKEntry (ObjOf(entry));
 
1049
      drawCDKScreen (entry->screen);
 
1050
 
 
1051
      /* And leave... */
 
1052
      return;
 
1053
   }
 
1054
 
 
1055
   /* Create the scrolling list of previous commands. */
 
1056
   scrollList = newCDKScroll (entry->screen, CENTER, CENTER, RIGHT,
 
1057
                                height, -10, "<C></B/29>Command History",
 
1058
                                history->command, history->count,
 
1059
                                NUMBERS, A_REVERSE, TRUE, FALSE);
 
1060
 
 
1061
   /* Get the command to execute. */
 
1062
   selection = activateCDKScroll (scrollList, 0);
 
1063
   destroyCDKScroll (scrollList);
 
1064
 
 
1065
   /* Check the results of the selection. */
 
1066
   if (selection >= 0)
 
1067
   {
 
1068
      /* Get the command and stick it back in the entry field. */
 
1069
      setCDKEntryValue (entry, history->command[selection]);
 
1070
   }
 
1071
 
 
1072
   /* Redraw the screen. */
 
1073
   eraseCDKEntry (ObjOf(entry));
 
1074
   drawCDKScreen (ScreenOf(entry));
 
1075
}
 
1076
 
 
1077
/*
 
1078
 * This loads the history into the editor from the RC file.
 
1079
 */
 
1080
void loadHistory (struct history_st *history)
 
1081
{
 
1082
   char *home   = 0;
 
1083
   char filename[1000];
 
1084
 
 
1085
   /* Create the RC filename. */
 
1086
   if ((home = getenv ("HOME")) == 0)
 
1087
   {
 
1088
      home = ".";
 
1089
   }
 
1090
   sprintf (filename, "%s/.sybrc", home);
 
1091
 
 
1092
   /* Set some variables. */
 
1093
   history->current     = 0;
 
1094
   history->count       = 0;
 
1095
 
 
1096
   /* Read the file. */
 
1097
   if ((history->count = readFile (filename, history->command, MAXHISTORY)) != -1)
 
1098
   {
 
1099
      history->current = history->count;
 
1100
   }
 
1101
   return;
 
1102
}
 
1103
 
 
1104
/*
 
1105
 * This saves the history into RC file.
 
1106
 */
 
1107
void saveHistory (struct history_st *history, int count)
 
1108
{
 
1109
   FILE *fd     = 0;
 
1110
   char *home   = 0;
 
1111
   char filename[1000];
 
1112
   int x;
 
1113
 
 
1114
   /* Create the RC filename. */
 
1115
   if ((home = getenv ("HOME")) == 0)
 
1116
   {
 
1117
      home = ".";
 
1118
   }
 
1119
   sprintf (filename, "%s/.sybrc", home);
 
1120
 
 
1121
   /* Open the file for writing. */
 
1122
   if ((fd = fopen (filename, "w")) == 0)
 
1123
   {
 
1124
      return;
 
1125
   }
 
1126
 
 
1127
   /* Start saving the history. */
 
1128
   for (x=0; x < history->count; x++)
 
1129
   {
 
1130
      fprintf (fd, "%s\n", history->command[x]);
 
1131
   }
 
1132
   fclose (fd);
 
1133
   return;
 
1134
}