SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddslogserver.c File Reference

Detailed Description

Server program to log data to SDDS files.

This program listens on a specified port and handles multiple client connections to log data into SDDS files. It supports various commands such as adding values, creating channels, making directories, and generating SDDS plots. Key features include:

  • Handling multiple client connections using forked processes.
  • Dynamic creation and management of SDDS channels.
  • Command restrictions through the forbid option.
  • Generating SDDS plots and returning their URLs.

Usage

sddslogserver -port=<portNumber>
[-root=<rootDirectory>]
[-forbid=<command1,command2,...>]
[-sddsplotPath=<path>]

Options

Required Description
-port Port number on which the server listens.
Optional Description
-root Path of the root directory. Defaults to current directory.
-forbid Comma-separated list of commands to forbid.
-sddsplotPath Pathname for SDDS plot output files.

Requirements

  • -port must be a valid positive integer.
  • -root must specify an existing directory.
  • -sddsplotPath requires a valid directory path.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
M. Borland, R. Soliday

Definition in file sddslogserver.c.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/stat.h>
#include <dirent.h>
#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Functions

int dostuff (int)
 
int createChannel (char *spec)
 
int addValue (char *spec)
 
int runSddsplot (char *returnBuffer, char *options)
 
void updateChannelDescription (void)
 
int makeDirectoryList (int64_t *returnNumber, char ***returnBuffer)
 
int getChannelList (int64_t *returnNumber, char ***returnBuffer)
 
void error (const char *msg, char *progName)
 
int writeReply (int sock, const char *message, int code)
 
int writeReplyList (int sock, int64_t nItems, char **messageList)
 
void freeReplyList (int64_t nItems, char **item)
 
int chdirFromRoot (char *path)
 
void shutdownServer (int arg)
 
int main (int argc, char *argv[])
 

Function Documentation

◆ addValue()

int addValue ( char * spec)

Definition at line 533 of file sddslogserver.c.

538{
539 char *ptr;
540 char buffer[BUFLEN];
541 int32_t type;
542 int64_t rows;
543 SDDS_DATASET SDDSin;
544 void *data = NULL;
545
546 if (!(ptr = strchr(spec, ',')))
547 return 1;
548 *ptr++ = 0;
549
550 snprintf(buffer, sizeof(buffer), "%s.sdds", spec);
551 if (!SDDS_InitializeAppendToPage(&SDDSin, buffer, 1, &rows)) {
552 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
553 return 2;
554 }
555 printf("Initialized, %" PRId64 " rows\n", rows);
556 fflush(stdout);
557 if (!SDDS_LengthenTable(&SDDSin, 1)) {
558 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
559 return 3;
560 }
561 printf("Lengthened table\n");
562 fflush(stdout);
563
564 if (SDDS_GetColumnInformation(&SDDSin, "type", &type, SDDS_GET_BY_NAME, spec) != SDDS_LONG) {
565 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
566 SDDS_Terminate(&SDDSin);
567 return 4;
568 }
569 printf("Got type information\n");
570 fflush(stdout);
571
572 if (type != SDDS_STRING)
573 data = SDDS_Malloc(SDDS_type_size[type - 1]);
574 if (SDDS_ScanData(ptr, type, 0, data, 0, 0) == 0) {
575 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
576 SDDS_Terminate(&SDDSin);
577 return 5;
578 }
579 printf("Scanned data\n");
580 fflush(stdout);
581
582 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, "SampleIDNumber", rows, "Time", getTimeInSecs(), NULL)) {
583 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
584 SDDS_Terminate(&SDDSin);
585 return 6;
586 }
587 printf("Set row values\n");
588 fflush(stdout);
589
590 switch (type) {
591 case SDDS_STRING:
592 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, ptr, NULL)) {
593 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
594 return 7;
595 }
596 break;
597 case SDDS_FLOAT:
598 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, *((float *)data), NULL)) {
599 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
600 return 7;
601 }
602 break;
603 case SDDS_DOUBLE:
604 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, *((double *)data), NULL)) {
605 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
606 return 7;
607 }
608 break;
609 case SDDS_SHORT:
610 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, *((short *)data), NULL)) {
611 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
612 return 7;
613 }
614 break;
615 case SDDS_LONG:
616 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, *((int32_t *)data), NULL)) {
617 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
618 return 7;
619 }
620 break;
621 case SDDS_LONG64:
622 if (!SDDS_SetRowValues(&SDDSin, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, rows, spec, *((int64_t *)data), NULL)) {
623 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
624 return 7;
625 }
626 break;
627 default:
628 break;
629 }
630 printf("Set row value\n");
631 fflush(stdout);
632 if (data)
633 free(data);
634
635 if (!SDDS_UpdatePage(&SDDSin, FLUSH_TABLE)) {
636 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
637 return 8;
638 }
639 printf("Updated page\n");
640 fflush(stdout);
641 if (!SDDS_Terminate(&SDDSin)) {
642 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
643 return 9;
644 }
645 printf("Terminated\n");
646 fflush(stdout);
647 return 0;
648}
int32_t SDDS_ScanData(char *string, int32_t type, int32_t field_length, void *data, int64_t index, int32_t is_parameter)
Scans a string and saves the parsed value into a data pointer according to the specified data type.
int32_t SDDS_type_size[SDDS_NUM_TYPES]
Array of sizes for each supported data type.
Definition SDDS_data.c:62
int32_t SDDS_LengthenTable(SDDS_DATASET *SDDS_dataset, int64_t n_additional_rows)
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeAppendToPage(SDDS_DATASET *SDDS_dataset, const char *filename, int64_t updateInterval, int64_t *rowsPresentReturn)
Initializes the SDDS dataset for appending data to the last page of an existing file.
int32_t SDDS_UpdatePage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the current page of the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:705
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
double getTimeInSecs()
Get the current time in seconds since the Epoch with high resolution.

◆ chdirFromRoot()

int chdirFromRoot ( char * path)

Definition at line 169 of file sddslogserver.c.

169 {
170 char buffer[BUFLEN];
171 snprintf(buffer, sizeof(buffer), "%s/%s", rootDir, (path && *path) ? path : "");
172 fprintf(stderr, "Changing directory to %s\n", buffer);
173 return chdir(buffer);
174}

◆ createChannel()

int createChannel ( char * spec)

Definition at line 473 of file sddslogserver.c.

475{
476 char *chName, *chType, *chUnits, *chDescription;
477 char buffer[BUFLEN];
478 SDDS_DATASET SDDSout;
479 int32_t type;
480
481 chName = spec;
482 if (!(chType = strchr(spec, ',')))
483 return 1;
484 *chType++ = 0;
485 if (!(chUnits = strchr(chType, ',')))
486 return 2;
487 *chUnits++ = 0;
488 if ((type = SDDS_IdentifyType(chType)) == 0)
489 return 2;
490 if (!(chDescription = strchr(chUnits, ',')))
491 return 3;
492 *chDescription++ = 0;
493
494 if (strcmp(chName, "Time") == 0)
495 return 4;
496
497 snprintf(buffer, sizeof(buffer), "%s.sdds", chName);
498 if (fexists(buffer))
499 return 5;
500
501 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, NULL, buffer) ||
502 !SDDS_DefineSimpleColumn(&SDDSout, "SampleIDNumber", NULL, SDDS_LONG64) ||
503 !SDDS_DefineSimpleColumn(&SDDSout, "Time", "s", SDDS_DOUBLE) ||
504 SDDS_DefineColumn(&SDDSout, chName, NULL, chUnits, chDescription, NULL, type, 0) < 0 ||
505 !SDDS_WriteLayout(&SDDSout) ||
506 !SDDS_StartPage(&SDDSout, 1) ||
507 !SDDS_WritePage(&SDDSout) ||
508 !SDDS_Terminate(&SDDSout))
509 return 6;
510
511 snprintf(buffer, sizeof(buffer), "sddsquery %s.sdds -sddsOutput=%s.chd -column", chName, chName);
512 {
513 int sysret = system(buffer);
514 (void)sysret;
515 }
516 snprintf(buffer, sizeof(buffer), "%s.chd", chName);
517 if (!fexists(buffer))
518 return 6;
519
520 updateChannelDescription();
521
522 return 0;
523}
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_IdentifyType(char *typeName)
Identifies the SDDS data type based on its string name.
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27

◆ dostuff()

int dostuff ( int sock)

Definition at line 355 of file sddslogserver.c.

355 {
356 int n, code;
357 char buffer[BUFLEN];
358 char *ptr1;
359 short persist = 1;
360 int64_t nItems;
361 char **itemValue;
362
363 while (persist) {
364 memset(buffer, 0, BUFLEN);
365 n = read(sock, buffer, BUFLEN - 1);
366 if (n < 0)
367 error("ERROR reading from socket", "sddslogserver");
368 if (strlen(buffer) == 0)
369 continue;
370 chop_nl(buffer);
371 printf("Here is the message: <%s>\n", buffer);
372
373 if ((ptr1 = strchr(buffer, ':')))
374 *ptr1++ = 0;
375 if ((code = match_string(buffer, command, N_COMMANDS, EXACT_MATCH)) < 0 || forbid[code]) {
376 writeReply(sock, "Forbidden operation.", 0);
377 continue;
378 }
379 switch (code) {
380 case DISCONNECT:
381 printf("Disconnecting\n");
382 fflush(stdout);
383 persist = 0;
384 break;
385 case ADD_VALUE:
386 /* syntax: channel=value */
387 printf("Add value: %s\n", ptr1);
388 if ((code = addValue(ptr1)) == 0)
389 writeReply(sock, "ok", code);
390 else
391 writeReply(sock, "Error: Failed to add value.", code);
392 break;
393 case DELETE_VALUE:
394 /* syntax: channel,sampleID */
395 printf("Delete value: %s\n", ptr1);
396 writeReply(sock, "Error: Can't do that yet.", EXIT_FAILURE);
397 break;
398 case ADD_CHANNEL:
399 /* syntax: channel,type */
400 printf("Add channel: %s\n", ptr1);
401 if ((code = createChannel(ptr1)) == 0)
402 writeReply(sock, "ok", code);
403 else
404 writeReply(sock, "Error: Failed to create channel.", code);
405 break;
406 case MAKE_DIRECTORY:
407 /* syntax: directoryName */
408 printf("Make directory: %s\n", ptr1);
409 if ((code = mkdir(ptr1, 0700))) {
410 writeReply(sock, "Error: Making directory.", code);
411 } else {
412 writeReply(sock, "ok", code);
413 }
414 break;
415 case CHANGE_DIRECTORY:
416 /* syntax: path */
417 if (ptr1 && *ptr1 && strstr(ptr1, "..")) {
418 /* Only absolute paths are allowed */
419 writeReply(sock, "Error: Relative paths not supported.", EXIT_FAILURE);
420 } else {
421 printf("Change directory: %s\n", ptr1 && *ptr1 ? ptr1 : "base");
422 if ((code = chdirFromRoot(ptr1)))
423 writeReply(sock, "Error: CD failed.", code);
424 else
425 writeReply(sock, "CD ok.", code);
426 }
427 break;
428 case GET_TIME_SPAN:
429 /* syntax: channel,startTime,endTime */
430 printf("Get time span: %s\n", ptr1);
431 writeReply(sock, "Error: Can't do that yet.", EXIT_FAILURE);
432 break;
433 case GET_LAST_N:
434 /* syntax: channel,N; if N<=0, return all data */
435 printf("Get last N: %s\n", ptr1);
436 writeReply(sock, "Error: Can't do that yet.", EXIT_FAILURE);
437 break;
438 case SDDSPLOT:
439 /* syntax:<sddsplotCommand> */
440 printf("sddsplot: %s\n", ptr1);
441 code = runSddsplot(buffer, ptr1);
442 writeReply(sock, buffer, code);
443 break;
444 case UPDATE_CHD:
445 updateChannelDescription();
446 writeReply(sock, "ok", EXIT_SUCCESS);
447 break;
448 case LIST_DIRS:
449 if (makeDirectoryList(&nItems, &itemValue))
450 writeReply(sock, "Failed to retrieve directory list.", EXIT_FAILURE);
451 else {
452 writeReplyList(sock, nItems, itemValue);
453 freeReplyList(nItems, itemValue);
454 }
455 break;
456 case LIST_CHANNELS:
457 if (getChannelList(&nItems, &itemValue))
458 writeReply(sock, "Failed to retrieve channel list.", EXIT_FAILURE);
459 else {
460 writeReplyList(sock, nItems, itemValue);
461 freeReplyList(nItems, itemValue);
462 }
463 break;
464 default:
465 printf("Unknown command: %s\n", buffer);
466 writeReply(sock, "Error: Unknown command.", EXIT_FAILURE);
467 break;
468 }
469 }
470 return EXIT_SUCCESS;
471}
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
SddsFile read(input_file)
Mostly backward compatible with the PyLHC sdds module read() function.
Definition sdds.py:1870

◆ error()

void error ( const char * msg,
char * progName )

Definition at line 122 of file sddslogserver.c.

122 {
123 char s[BUFLEN];
124 snprintf(s, sizeof(s), "%s (%s)", msg, progName);
125 perror(s);
126 exit(EXIT_FAILURE);
127}

◆ freeReplyList()

void freeReplyList ( int64_t nItems,
char ** item )

Definition at line 159 of file sddslogserver.c.

159 {
160 int64_t i;
161 if (!item)
162 return;
163 for (i = 0; i < nItems; i++)
164 if (item[i])
165 free(item[i]);
166 free(item);
167}

◆ getChannelList()

int getChannelList ( int64_t * returnNumber,
char *** returnBuffer )

Definition at line 753 of file sddslogserver.c.

753 {
754 SDDS_DATASET SDDSin;
755
756 *returnBuffer = NULL;
757 *returnNumber = 0;
758
759 updateChannelDescription();
760 if (!fexists("allChd.sdds"))
761 return 0;
762 if (!SDDS_InitializeInput(&SDDSin, "allChd.sdds")) {
763 printf("Problem reading allChd.sdds\n");
764 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
765 return 1;
766 }
767 if (SDDS_ReadPage(&SDDSin) < 0)
768 /* Assume file is empty */
769 return 0;
770 if ((*returnNumber = SDDS_RowCount(&SDDSin)) < 0) {
771 printf("Row count: %" PRId64 "\n", *returnNumber);
772 return 2;
773 }
774 if (*returnNumber == 0)
775 return 0;
776 if (!(*returnBuffer = SDDS_GetColumn(&SDDSin, "Name"))) {
777 printf("Problem getting Name\n");
778 return 3;
779 }
780 return 0;
781}
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 212 of file sddslogserver.c.

212 {
213 int newsockfd, portno, pid;
214 int reuse = 1;
215 socklen_t clilen;
216 struct sockaddr_in serv_addr, cli_addr;
217 int i_arg, j, code;
218 SCANNED_ARG *s_arg;
219
220 /* Allow zombie children to die */
221 signal(SIGCHLD, SIG_IGN);
222 signal(SIGINT, shutdownServer);
223
224 /* Parse arguments */
226 argc = scanargs(&s_arg, argc, argv);
227 if (argc < 2) {
228 fprintf(stderr, "%s", USAGE);
229 exit(EXIT_FAILURE);
230 }
231
232 portno = -1;
233 rootDir = NULL;
234 for (i_arg = 1; i_arg < argc; i_arg++) {
235 if (s_arg[i_arg].arg_type == OPTION) {
236 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
237 case CLI_PORT:
238 if (s_arg[i_arg].n_items != 2 ||
239 sscanf(s_arg[i_arg].list[1], "%d", &portno) != 1 ||
240 portno <= 0) {
241 fprintf(stderr, "Error: Invalid syntax/values for -port argument\n%s", USAGE);
242 exit(EXIT_FAILURE);
243 }
244 break;
245 case CLI_ROOT:
246 if (s_arg[i_arg].n_items != 2 ||
247 strlen(rootDir = s_arg[i_arg].list[1]) == 0) {
248 fprintf(stderr, "Error: Invalid syntax/values for -root argument\n%s", USAGE);
249 exit(EXIT_FAILURE);
250 }
251 break;
252 case CLI_FORBID:
253 if (s_arg[i_arg].n_items < 2) {
254 fprintf(stderr, "Error: Invalid syntax/values for -forbid argument\n%s", USAGE);
255 exit(EXIT_FAILURE);
256 }
257 for (j = 1; j < s_arg[i_arg].n_items; j++) {
258 if ((code = match_string(s_arg[i_arg].list[j], command, N_COMMANDS, 0)) < 0) {
259 fprintf(stderr, "Error: Unknown command for -forbid: %s\n", s_arg[i_arg].list[j]);
260 exit(EXIT_FAILURE);
261 }
262 forbid[code] = 1;
263 }
264 break;
265 case CLI_SDDSPLOT_PATH:
266 if (s_arg[i_arg].n_items != 2) {
267 fprintf(stderr, "Error: Invalid syntax for -sddsplotPath option\n%s", USAGE);
268 exit(EXIT_FAILURE);
269 }
270 sddsplotPath = s_arg[i_arg].list[1];
271 break;
272 default:
273 fprintf(stderr, "Invalid or ambiguous option: %s\n%s", s_arg[i_arg].list[0], USAGE);
274 exit(EXIT_FAILURE);
275 break;
276 }
277 } else {
278 fprintf(stderr, "Invalid or ambiguous option: %s\n%s", s_arg[i_arg].list[0], USAGE);
279 exit(EXIT_FAILURE);
280 }
281 }
282
283 if (!rootDir) {
284 cp_str(&rootDir, ".");
285 }
286 if (!fexists(rootDir))
287 error("Error: Root directory not found", argv[0]);
288 if (chdir(rootDir) != 0)
289 perror("chdir");
290
291 /* Create socket */
292 sockfd = socket(AF_INET, SOCK_STREAM, 0);
293 if (sockfd < 0)
294 error("Error opening socket", argv[0]);
295 printf("sockfd = %d\n", sockfd);
296 memset(&serv_addr, 0, sizeof(serv_addr));
297
298 /* Set the socket to SO_REUSEADDR */
299 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) < 0)
300 perror("setsockopt(SO_REUSEADDR) failed");
301
302#ifdef SO_REUSEPORT
303 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char *)&reuse, sizeof(reuse)) < 0)
304 perror("setsockopt(SO_REUSEPORT) failed");
305#endif
306
307 /* Bind the socket to a port number */
308 serv_addr.sin_family = AF_INET;
309 serv_addr.sin_addr.s_addr = INADDR_ANY;
310 serv_addr.sin_port = htons(portno);
311 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
312 error("Error on port binding. Check port number.", argv[0]);
313
314 listen(sockfd, 5);
315 clilen = sizeof(cli_addr);
316 while (1) {
317 printf("Waiting for new socket connection\n");
318 fflush(stdout);
319 newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
320 printf("Got new socket connection\n");
321 fflush(stdout);
322 if (newsockfd < 0) {
323 if (sockfd >= 0)
324 close(sockfd);
325 error("Error on accept", argv[0]);
326 }
327 pid = fork();
328 if (pid < 0)
329 error("Error on fork", argv[0]);
330 if (pid == 0) {
331 close(sockfd);
332 dostuff(newsockfd);
333 printf("Returned from dostuff\n");
334 fflush(stdout);
335 exit(EXIT_SUCCESS);
336 } else {
337 printf("Forked process\n");
338 fflush(stdout);
339 close(newsockfd);
340 }
341 } /* end of while */
342 printf("Exited while loop\n");
343 fflush(stdout);
344 if (sockfd > 0)
345 close(sockfd);
346 return EXIT_SUCCESS; /* We never get here */
347}
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36

◆ makeDirectoryList()

int makeDirectoryList ( int64_t * returnNumber,
char *** returnBuffer )

Definition at line 716 of file sddslogserver.c.

716 {
717 SDDS_DATASET SDDSin;
718 char command[BUFLEN];
719
720 if (returnNumber)
721 *returnNumber = 0;
722 if (returnBuffer)
723 *returnBuffer = NULL;
724
725 remove("dirList.sdds");
726 snprintf(command, sizeof(command),
727 "find . -type d -maxdepth 1 | tail -n +2 | plaindata2sdds -pipe=in dirList.sdds -input=ascii -column=DirectoryName,string -norow");
728 {
729 int sysret = system(command);
730 (void)sysret;
731 }
732 if (!SDDS_InitializeInput(&SDDSin, "dirList.sdds")) {
733 printf("Problem reading dirList.sdds\n");
734 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
735 return 1;
736 }
737 if (SDDS_ReadPage(&SDDSin) < 0)
738 /* Assume file is empty */
739 return 0;
740 if ((*returnNumber = SDDS_RowCount(&SDDSin)) < 0) {
741 printf("Row count: %" PRId64 "\n", *returnNumber);
742 return 2;
743 }
744 if (*returnNumber == 0)
745 return 0;
746 if (!(*returnBuffer = SDDS_GetColumn(&SDDSin, "DirectoryName"))) {
747 printf("Problem getting DirectoryName\n");
748 return 3;
749 }
750 return 0;
751}

◆ runSddsplot()

int runSddsplot ( char * returnBuffer,
char * options )

Definition at line 650 of file sddslogserver.c.

650 {
651 char command[BUFLEN];
652 char template[BUFLEN];
653 int fd;
654
655 // Ensure sddsplotPath is set
656 if (!sddsplotPath) {
657 fprintf(stderr, "Error: sddsplotPath is not set.\n");
658 return 1;
659 }
660
661 // Create the template with sddsplotPath and "png-XXXXXX.png"
662 // mkstemps requires the template to end with "XXXXXX" followed by the suffix
663 snprintf(template, sizeof(template), "%s/png-XXXXXX.png", sddsplotPath);
664
665 // Create a mutable copy of the template for mkstemps
666 char *tempTemplate = strdup(template);
667 if (!tempTemplate) {
668 perror("strdup");
669 return 1;
670 }
671
672 // mkstemps replaces "XXXXXX" with a unique suffix and keeps the ".png" extension
673 fd = mkstemps(tempTemplate, 4); // 4 is the length of ".png"
674 if (fd == -1) {
675 perror("mkstemps");
676 free(tempTemplate);
677 return 1;
678 }
679
680 // Close the file descriptor as we don't need it
681 close(fd);
682
683 // tempTemplate now contains the unique filename with ".png"
684 snprintf(command, sizeof(command), "sddsplot -device=png -output=%s %s", tempTemplate, options);
685 printf("Executing: %s\n", command);
686 fflush(stdout);
687
688 // Copy the filename to returnBuffer
689 strncpy(returnBuffer, tempTemplate, BUFLEN - 1);
690 returnBuffer[BUFLEN - 1] = '\0';
691
692 // Free the duplicated template
693 free(tempTemplate);
694
695 // Execute the command
696 return system(command);
697}

◆ shutdownServer()

void shutdownServer ( int arg)

Definition at line 204 of file sddslogserver.c.

204 {
205 printf("Closing sockfd=%d\n", sockfd);
206 fflush(stdout);
207 if (sockfd >= 0)
208 close(sockfd);
209 exit(EXIT_SUCCESS);
210}

◆ updateChannelDescription()

void updateChannelDescription ( void )

Definition at line 525 of file sddslogserver.c.

525 {
526 char *command = "sddscombine *.chd -merge -pipe=out | sddsprocess -pipe=in -match=col,Name=SampleIDNumber,! -match=col,Name=Time,! allChd.sdds";
527 {
528 int sysret = system(command);
529 (void)sysret;
530 }
531}

◆ writeReply()

int writeReply ( int sock,
const char * message,
int code )

Definition at line 129 of file sddslogserver.c.

129 {
130 char buffer[BUFLEN + 20];
131 if (code) {
132 snprintf(buffer, sizeof(buffer), "error:%s (code %d)\n", message, code);
133 return write(sock, buffer, strlen(buffer));
134 } else {
135 // snprintf(buffer, sizeof(buffer), "ok:%s\n", message);
136 return write(sock, message, strlen(message));
137 }
138}
write(SddsFile sdds_file, output_file)
Mostly backward compatible with the PyLHC sdds module write() function.
Definition sdds.py:1967

◆ writeReplyList()

int writeReplyList ( int sock,
int64_t nItems,
char ** messageList )

Definition at line 140 of file sddslogserver.c.

140 {
141 int64_t i;
142 char message[BUFLEN];
143 strncpy(message, "ok:", sizeof(message) - 1);
144 message[sizeof(message) - 1] = 0;
145
146 /* Need to check for buffer overflow */
147 printf("%" PRId64 " reply items\n", nItems);
148 for (i = 0; i < nItems; i++) {
149 printf("Item %" PRId64 ": %s\n", i, messageList[i]);
150 strncat(message, messageList[i], sizeof(message) - strlen(message) - 1);
151 if (i != (nItems - 1))
152 strncat(message, ",", sizeof(message) - strlen(message) - 1);
153 }
154 strncat(message, "\n", sizeof(message) - strlen(message) - 1);
155 printf("message: %s", message);
156 return write(sock, message, strlen(message));
157}