locking own thread

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#21 Post by wiak »

Let me just explain my dilemma once.
DOWNLOAD LINKS: Absolutely non-official but apparently stable/working, prealpha, downloads intended only for anyone interested in testing (usual disclaimers apply concerning suitability of purpose). Note that though I have removed prealpha in the name this is only provided to allow interested parties to test functionality. It is not to be considered a general release at this stage in any way:
Whilst and if the project remains abandoned, this testing period is over and their is no general release. In that circumstance, I feel duty bound to clean up that thread. I had no intention, personally, of removing any of its technical written content whatsoever - people can read about how gtkwialog would work till the end of time if they wanted to. But... now that murga-forum has taken absolute control of that thread they are leaving the above mentioned prealpha, not for general release, testing binaries available longterm, against my directions in above quoted paragraph from the first post of the thread.

Over time that could be perceived as 'distribution' by murga-forum who cannot fulfill what would be the GPL license requirement resulting from official release, which I have never made. Outside of that defined not for "general release" period, the binaries ought, in my opinion, be removed.

The thread should not have been locked, and Flash's comment is insufficient - my threat regarding intellectual property rights can be safely ignored, however; I was just upset that I was placed in a position where I had no control over my own work, particularly when the abandonment was possibly to be temporary (though the apparently 'sacred' nature of gtkdialog ground may make the continuation of public gtkwialog development culturally difficult).

EDIT: The locking action is, aside from the utterly small scale of this one project, like Microsoft taking control of GitHub; an organisation using power to take control over an author's previous freedom and creation rights on that site/thread. Bad, bad, bad.
Flash wrote:Wiak seemed to imply that other approaches worked better than his and that's why he's abandoning his. I could have simply removed the thread rather than locking it, but failures have value.
Don't be ridiculous. (gtkwialog is the best approach thus far by a mile and it's going to get even better too)


The solution, whatever I chose to later do, is simply to unlock the thread. End of comment.

wiak
Last edited by wiak on Fri 08 Jun 2018, 03:10, edited 1 time in total.

phat7
Posts: 179
Joined: Fri 05 Jun 2015, 08:54

#22 Post by phat7 »

Calm down. As Flash rightly wrote "failures have value". Your work is still valuable for other forum members and may encourage them to pick up where you left. I learned a lot. Unless your pre-alpha binaries are unsafe or malicious they should remain and the thread should be kept under lock.

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#23 Post by wiak »

phat7 wrote:Calm down. As Flash rightly wrote "failures have value". Your work is still valuable for other forum members and may encourage them to pick up where you left. I learned a lot. Unless your pre-alpha binaries are unsafe or malicious they should remain and the thread should be kept under lock.
What cupboard did you crawl out of sigh? :-) Someone else I've never heard of; what a nest of opinionated individuals this is. Mein Godt. EDIT: Oh yes, you asked for some gtkwialog usage help a while back and I helped you out with that...

Like I have already stated above:
Don't be ridiculous. (gtkwialog is the best approach thus far by a mile and it's going to get even better too)
Anyway, 'thanks' for your concern; I am purrfectly calm thanks. In fact I am laughing.

But fact is, my gtkwialog dev project thread should be unlocked for the good of those interested in the project.

wiak

s243a
Posts: 2580
Joined: Tue 02 Sep 2014, 04:48
Contact:

#24 Post by s243a »

wiak wrote:But fact is, my gtkwialog dev project thread should be unlocked for the good of those interested in the project.

wiak
You could document it somewhere, and then once done create a thread referring people to the documentation. Such time spent documenting might give you time to reflect.

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#25 Post by wiak »

s243a wrote:
wiak wrote:But fact is, my gtkwialog dev project thread should be unlocked for the good of those interested in the project.

wiak
You could document it somewhere, and then once done create a thread referring people to the documentation. Such time spent documenting might give you time to reflect.
shouldn't be necessary

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#26 Post by wiak »

From gtkwialog dev thread:
Hello wiak

I haven't used gtkwialog, but i read it adds improvements to gtkdialog

I think the changes can be safely added to gtkdialog. I was thinking of env variables.

For example, a script can be marked as GTKWIALOG by adding
Code:

Code: Select all

#!/bin/sh 
. 
. 
export GTKWIALOG=1
In gtkdialog itself, the code to determine if the new approach is to be used would be as simple as this:

Code:

Code: Select all

#include <stdlib.h> 

if (getenv("GTKWIALOG")) { 
 GTKWIALOG=1; 
} 
This is just an idea i had..
@aaaaa: The following code is from an old (2007) C program of mine (wiak.c) that was published on this forum and elsewhere (at Freshmeat site back then, which is nowadays called Freecode), from which my alias wiak is taken:

Code: Select all

    // if WIAKTMP environment variable is set use its value as the default path 
    // for the storing the wfifo etc., or use the pre-defined default WIAKFIFOPATH.
    // WIAK also has a commandline argument --wiaktmp <arg> for altering this behaviour.
    getenv_ptr = getenv("WIAKTMP");
    if (getenv_ptr)
     ...
In other words, I am aware of the technique.

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

wiak.c for people who love C pointers

#27 Post by wiak »

And since this is a programming thread, so as not to be at all off-topic, here it is (wiak.c) for code reading in full for anyone interested in some C-based IPC techniques - some of which may prove useful in my personal gtkwialog development. Maybe not optimum code selection, but worked well for what it was intended:

For those of us who love C pointers (to pointers to pointers...)

Code: Select all

/* **************************************************************************
 Program: wiak (an IPC, non-interactive, shell)  Version: 2.3.0         
 Creation date (YMD): 2007/12/10
 Revision date (YMD): 2008/02/10  
 (C) Copyright 2007 William McEwan (wiakapps A_t wiak D_o_t org)
************************************************************************** */

// wiak
// is free software in the sense that you can redistribute it and/or
// modify it under the terms of the GNU General Public License as 
// published by the Free Software Foundation, either version 3 of the License, 
// or (at your option) any later version. 
// Refer to http://www.fsf.org/ for further license details.

// Revision history:
// 1.0.0  Original released version.
// 1.1.2  Added options --receive and --quit
// 2.0.0  Altered main data structures and added some bash script compatible 
//        System V IPC message queue functionality.
// 2.1.0  Created tiny wiak family (twiak). Changed msgq option to msgqv.
// 2.2.0  Altered --length handling for various --send terminating options.
// 2.3.0  Removed --up logic and simplified channel name scheme etc.
// -------------------------------------------------------------------------

/* Additional Notes:

 WIAK is an extremely lightweight, non-interactive shell optimised for
 InterProcessCommunications. It is written in C, using standard libraries, 
 for portability, high speed and resource usage efficiency. It does not 
 require bash or any other underlying shell.
 Unlike most normal shells, wiak only runs for a fraction of a second. As soon
 as it has performed its assigned task it immediately closes, releasing all
 system resources it was using. It is thus a very efficient mechanism.
 WIAK was originally designed to provide a simpler event-driven mechanism for
 the likes of gtkdialog, but it is not restricted to that purpose at all. 
 Refer to http://wiak.org/ for more details and/or examine the code of the 
 available exemplar "wiakapps" to see how wiak is currently used.
 -----------------------------------------------------------------*/

#include "wiakappswiak.h"

void func_optionslong(int argc, char *argv[], int *ptr_fork_result, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st);

void func_wiak_fifo(int argc, char **argv, int *ptr_fork_result, struct wargv *ptr_wargv_st, int *ptr_server_fifo_fd, int *ptr_server_fifo_fd2, struct mbox_all *ptr_msg_st);

void func_wiak_msgqv(int argc, char **argv, int *ptr_fork_result, struct wargv *ptr_wargv_st, int *ptr_server_fifo_fd,  int *ptr_server_fifo_fd2, struct mbox_all *ptr_msg_st);

void func_up_fork_server(char **argv, int *ptr_fork_result, struct wargv *ptr_wargv_st);

void func_send_fifo(int *ptr_server_fifo_fd2, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st);

void func_receive_fifo(int *ptr_server_fifo_fd, int *ptr_server_fifo_fd2, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st);

void func_send_msgqv(int *ptr_msgid, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st);

void func_receive_msgqv(int *ptr_msgid, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st);


int main(int argc, char **argv)
{
    int fork_result = 0, *ptr_fork_result = &fork_result;
    int server_fifo_fd, *ptr_server_fifo_fd = &server_fifo_fd;
    int server_fifo_fd2, *ptr_server_fifo_fd2 = &server_fifo_fd2;
    struct wargv *ptr_wargv_st = &wargv_st;

    struct mbox_all msg_st = {};
    struct mbox_all *ptr_msg_st = &msg_st;

    // if WIAKTMP environment variable is set use its value as the default path 
    // for the storing the wfifo etc., or use the pre-defined default WIAKFIFOPATH.
    // WIAK also has a commandline argument --wiaktmp <arg> for altering this behaviour.
    getenv_ptr = getenv("WIAKTMP");
    if (getenv_ptr)
        strcpy(wiak_tmp_path, getenv_ptr);
    else
        strcpy(wiak_tmp_path, WIAKFIFOPATH);

    func_optionslong(argc, argv, ptr_fork_result, ptr_wargv_st, ptr_msg_st);


    // make directory for wiak fifo(s)
    mkdir(wiak_tmp_path, FIFOPATHPERMS);

    // Check which IPC mode to use
    if (ptr_wargv_st->wiak_mode[1] != '\0')
    {
        if (strcmp(ptr_wargv_st->wiak_mode, "fifo") == 0)
        {  // named pipes IPC
            func_wiak_fifo(argc, argv, ptr_fork_result, ptr_wargv_st, ptr_server_fifo_fd, ptr_server_fifo_fd2, ptr_msg_st);	
        }
        if (strcmp(ptr_wargv_st->wiak_mode, "msgqv") == 0)
        {  // System V message queues IPC
            func_wiak_msgqv(argc, argv, ptr_fork_result, ptr_wargv_st, ptr_server_fifo_fd, ptr_server_fifo_fd2, ptr_msg_st);	
        }
        if (strcmp(ptr_wargv_st->wiak_mode, "inetsocket") == 0)
        {  // AF_UNIX and AF_INET future plans...
        // func_wiak_inetsocket(argv, ptr_fork_result, ptr_wargv_st, ptr_msg_st);	
        }
        // etc...
    }
    else
    { //default mode case is use fifo (i.e. named pipe)
        func_wiak_fifo(argc, argv, ptr_fork_result, ptr_wargv_st, ptr_server_fifo_fd, ptr_server_fifo_fd2, ptr_msg_st);
    }

    close(server_fifo_fd); // close the fifo for writing but don't remove it.
    exit(fork_result);     // fork_result contains either the process id of any [program_name]
                           // started up by wiak (i.e. if wiak is supplied with a non-optional
                           // cmdline argument wiak attempts to execute the argument name)
                           // or the value 0
} /* end_of_main */

void func_optionslong(int argc, char *argv[], int *ptr_fork_result, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st)
{
    char fgets_string[BUF0256_SIZE];
    FILE *fpin;
    int opt;
    struct option long_options[] = {
    {"init", no_argument, NULL, 'i'},          // To tell wiak to create named pipe (i.e. mkfifo)
    {"quit", no_argument, NULL, 'q'},          // To tell wiak to clean up msg box(es) (e.g. rm fifos)
    {"send", required_argument, NULL, 's'},    // arg is the data to send to the message box
    {"receive", required_argument, NULL, 'r'}, // arg is the data to receive from the message box
    {"mode", required_argument, NULL, 'm'},    // Required mode: 
                                               // Currently, fifo (default) or msgqv (Sys V style).
    {"channel", required_argument, NULL, 'c'}, // msg box name, alphanumeric (has a default value).
    {"zid", required_argument, NULL, 'z'},     // msg box name, numeric (has a default value).
                                               // if none of above, will use default fifo name: wfifo
    {"file", required_argument, NULL, 'f'},    // RESERVED (provided as cmdline arg to backend server)
    {"dir", required_argument, NULL, 'd'},     // RESERVED (provided as cmdline arg to backend server)
    {"wiaktmp", required_argument, NULL, 'w'}, // Location of wfifo.
    {"type", required_argument, NULL, 't'},    // type of data to send.
                                               // Default is type CHARSTRDATA as defined in wiakappswiak.h
    {"length", required_argument, NULL, 'l'},  // string length to send; not including terminating \0
    {"perms", required_argument, NULL, 'p'},   // Message box permissions (e.g. for msg queues)
                                               // default is MBOXPERMS as defined in wiakappswiak.h
    {"help", no_argument, NULL, 'h'},
    {"version", no_argument, NULL, 'v'},
    {NULL,0,NULL,0}};

     while((opt = getopt_long(argc, argv, "+iqs:r:m:c:z:f:d:w:t:l:p:hv", long_options, NULL)) != -1) 
     {
        switch(opt) 
        {
          case 'i':
        	ptr_wargv_st->wiak_init = TRUE;
            break;
          case 'q':
        	ptr_wargv_st->wiak_quit = TRUE;
            break;
          case 's':
        	ptr_wargv_st->wiak_send = TRUE;
            strcpy(ptr_msg_st->msgdata.msg_char_str.c_data, optarg);
            break;
          case 'r':
        	strcpy(ptr_wargv_st->wiak_receive, optarg);
            break;
          case 'm':
            strcpy(ptr_wargv_st->wiak_mode, optarg);
            break;
          case 'c':
        	strcpy(ptr_wargv_st->wiak_channel, optarg);
            break;
          case 'z':
        	ptr_wargv_st->wiak_zid = atoi(optarg);
            break;
          case 'f':
        	strcpy(ptr_wargv_st->wiak_file, optarg);
	        break;
          case 'd':
        	strcpy(ptr_wargv_st->wiak_dir, optarg);
	        break;
          case 'w':
        	sprintf(wiak_tmp_path, "%s%s", optarg, "/");
	        break;
          case 't':
        	ptr_wargv_st->wiak_type = atoi(optarg);
            break;
          case 'l':
        	ptr_wargv_st->wiak_length = atoi(optarg);
            break;
          case 'p':
        	ptr_wargv_st->wiak_perms = (int)strtol(optarg, NULL, 8);
            break;
          case 'h':
            printf("Usage: \n\n");
			if ((fpin = fopen("/usr/local/wiakapps/wiak/wiakusage.txt","r")) == NULL)
			{
				printf("Error: Can't find file %s\n", "/usr/local/wiakapps/wiak/wiakusage.txt");
				exit(1);
			}			
			while (fgets(fgets_string, sizeof fgets_string, fpin) != NULL)
	  		{
	  			fprintf(stderr, "%s", fgets_string);
	  		}
            exit(0);
            break;
          case 'v':
            printf("wiak version 2.3.0\n");
            exit(0);
            break;
          case ':':
            printf("option needs a value\n");
            exit(0);
            break;
          case '?':
            printf("unknown option: %c\n", optopt);
            printf("Try `wiak --help' for usage information.\n");
            exit(0);
            break;
        }
    }

    // process wiak_length to determine end chars to --send 
    switch(ptr_wargv_st->wiak_length)
    {
      case 0: // zero extra terminating characters appended
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s", ptr_msg_st->msgdata.msg_char_str.c_data);
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data);
        break;
      case 1: // ends with '\n' but no terminating '\0'; this is like default bash echo I think
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\n');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data);
        break;
      case 2: // ends with '\n' followed by a terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\n', '\0');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data) + 1;
        break;
      case 3: // no '\n' but has terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\0');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data) + 1;
        break;
      case 4: // ends with '\t' but no '\n' or terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\t');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data);
        break;
      case 5: // no '\n', but ends with '\t' followed by a terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\t', '\0');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data) + 1;
        break;
      case 6: // ends with '\t' followed by a '\n' but no terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\t', '\n');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data) + 1;
        break;
      case 7:  // ends with '\t' followed by a '\n' and then a terminating '\0';
        sprintf(ptr_msg_st->msgdata.msg_char_str.c_data, "%s%c%c%c", ptr_msg_st->msgdata.msg_char_str.c_data, '\t', '\n', '\0');
        ptr_wargv_st->wiak_length = strlen(ptr_msg_st->msgdata.msg_char_str.c_data) + 1;
        break;
    }

    if (optind < argc) // only do this if there is a non--option process to also raise
    {
        *ptr_fork_result = fork();  // fork wiak so ready to overlay with new process
                                    // The parent fork_result contains the child process pid
        if (*ptr_fork_result == 0)  // The child process fork_result contains 0
        {                           // in child
                                    // this call wiak's (i.e. wakes) an optional process
                                    // it receives only those args following its name on the cmdline
          (void) execvp(argv[optind], &argv[optind]);
          exit(EXIT_FAILURE);
        }
    }
}

void func_wiak_fifo(int argc, char **argv, int *ptr_fork_result, struct wargv *ptr_wargv_st, int *ptr_server_fifo_fd,  int *ptr_server_fifo_fd2, struct mbox_all *ptr_msg_st)
{
    // First need to determine the wfifo name before opening it for writing
    // Note that if a backend program was started *ptr_fork_result contains its pid
    if (ptr_wargv_st->wiak_zid == -1234567890) // special case: if --zid value -1234567890
    {
        if (ptr_wargv_st->wiak_channel[0] == '\0')
        {  // use fifo name = backend server process_id
          (void)sprintf(fifo_name, "%s%d", wiak_tmp_path, *ptr_fork_result);
        }
        else
        { // use fifo name = channel value + backend server process_id
          (void)sprintf(fifo_name, "%s%s%d", wiak_tmp_path, ptr_wargv_st->wiak_channel, *ptr_fork_result);
        } 
    }
    else if ((ptr_wargv_st->wiak_channel[0] != '\0') && (ptr_wargv_st->wiak_zid == 0))
           // use fifo name = channel value
           (void)sprintf(fifo_name, "%s%s", wiak_tmp_path, ptr_wargv_st->wiak_channel);
    else if ((ptr_wargv_st->wiak_channel[0] == '\0') && (ptr_wargv_st->wiak_zid == 0))
           // use fifo name = default value = wiakappwiak.h FIFO_DFLT_NAME
           (void)sprintf(fifo_name, "%s%s", wiak_tmp_path, FIFO_DFLT_NAME);
    else if ((ptr_wargv_st->wiak_channel[0] != '\0') && (ptr_wargv_st->wiak_zid != 0))
           // use fifo name = channel value + zid value
           (void)sprintf(fifo_name, "%s%s%d", wiak_tmp_path, ptr_wargv_st->wiak_channel, ptr_wargv_st->wiak_zid);
    else if ((ptr_wargv_st->wiak_channel[0] == '\0') && (ptr_wargv_st->wiak_zid != 0))
    {   // use fifo name = zid value
        (void)sprintf(fifo_name, "%s%d", wiak_tmp_path, ptr_wargv_st->wiak_zid);
    }
    
    if (ptr_wargv_st->wiak_init == TRUE)
    {
        if (access(fifo_name, F_OK) == -1)
        {
            if (mkfifo(fifo_name, ptr_wargv_st->wiak_perms) == -1) // create the fifo named: channelzid
            {
                fprintf(stderr, "Error: failed to create fifo %s\n", fifo_name);
                exit(EXIT_FAILURE);
            }
        }
    }

    if (ptr_wargv_st->wiak_send == TRUE)
        func_send_fifo(ptr_server_fifo_fd2, ptr_wargv_st, ptr_msg_st);
		
    if (ptr_wargv_st->wiak_receive[0] != '\0')
        func_receive_fifo(ptr_server_fifo_fd, ptr_server_fifo_fd2, ptr_wargv_st, ptr_msg_st);	

    if (ptr_wargv_st->wiak_quit == TRUE)
    {
        close(*ptr_server_fifo_fd);
        close(*ptr_server_fifo_fd2);
        unlink(fifo_name);	
    }
} // end func_wiak_fifo


void func_send_fifo(int *ptr_server_fifo_fd2, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st)
{
   	if ((*ptr_server_fifo_fd2 = open(fifo_name, O_WRONLY)) == -1) 
   	{
       	fprintf(stderr, "Error: failed to open zfifo %s for writing\n", fifo_name);
       	exit(EXIT_FAILURE);
   	}
		
    if (ptr_wargv_st->wiak_type < CHARDATA)
    {   // This is the default char_string data case
        write(*ptr_server_fifo_fd2, ptr_msg_st->msgdata.msg_char_str.c_data, (ptr_wargv_st->wiak_length < 0) ? -(ptr_wargv_st->wiak_length) : ptr_wargv_st->wiak_length);
    }
    else // assuming must be STRUCTDATA for the moment
    {
        write(*ptr_server_fifo_fd2, &(ptr_msg_st->msgdata), sizeof(ptr_msg_st->msgdata));
    }
} /* end_of_func_send_fifo */


void func_receive_fifo(int *ptr_server_fifo_fd, int *ptr_server_fifo_fd2, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st)
{
    if ((*ptr_server_fifo_fd = open(fifo_name, O_RDONLY)) == -1) 
   	{
       	fprintf(stderr, "Error: failed to open zfifo %s for reading\n", fifo_name);
       	exit(EXIT_FAILURE);
   	}
   	if ((*ptr_server_fifo_fd2 = open(fifo_name, O_WRONLY)) == -1) 
   	{
       	fprintf(stderr, "Error: failed to open zfifo %s for writing\n", fifo_name);
       	exit(EXIT_FAILURE);
   	}
		
    if (ptr_wargv_st->wiak_type < CHARDATA)
    {   // This is the default char_string data case
        read(*ptr_server_fifo_fd, ptr_msg_st->msgdata.msg_char_str.c_data, (ptr_wargv_st->wiak_length < 0) ? -(ptr_wargv_st->wiak_length) : sizeof(ptr_msg_st->msgdata.msg_char_str.c_data));
        write(1, ptr_msg_st->msgdata.msg_char_str.c_data, strlen(ptr_msg_st->msgdata.msg_char_str.c_data));
    }
    else // assuming must be STRUCTDATA for the moment
    {
        read(*ptr_server_fifo_fd, &(ptr_msg_st->msgdata), (ptr_wargv_st->wiak_length == 0) ? sizeof(ptr_msg_st->msgdata) : ptr_wargv_st->wiak_length);

        write(1, ptr_msg_st->msgdata.msg_char_str.c_data, strlen(ptr_msg_st->msgdata.msg_char_str.c_data));
    }
} /* end_of_func_receive_fifo */


void func_wiak_msgqv(int argc, char **argv, int *ptr_fork_result, struct wargv *ptr_wargv_st, int *ptr_server_fifo_fd,  int *ptr_server_fifo_fd2, struct mbox_all *ptr_msg_st)
{
    int msgid, *ptr_msgid = &msgid;

    // First need to determine the msgqv numeric namekey before creating/using it.
    // Since a msgqv namekey is an integer (+ or -), the user is best to initialise
    // it with a unique --zid value or the special --zid value of -1234567890. The
    // latter results in a msgqv namekey being derived from the ptr_fork_result,
    // which can be arranged to be the backend server's process_id since
    // if a backend program was started, *ptr_fork_result contains its pid.

    if (ptr_wargv_st->wiak_zid == -1234567890) // special case: if --zid value -1234567890
                                         // use backend server process_id as msgqv namekey
        msgqv_namekey = *ptr_fork_result;
    else if ((ptr_wargv_st->wiak_channel[0] == '\0') && (ptr_wargv_st->wiak_zid != 0))
        msgqv_namekey = ptr_wargv_st->wiak_zid; // simply use cmdline --zid value
    else if ((ptr_wargv_st->wiak_channel[0] != '\0') && (ptr_wargv_st->wiak_zid != 0))
    {   // special case of dummy channel name and --zid value: combine server pid with zid	
        msgqv_namekey = *ptr_fork_result;
        msgqv_namekey = msgqv_namekey << 10;      // multiply server_pid by 1024
        msgqv_namekey += ptr_wargv_st->wiak_zid; // and add --zid value
    }
    // else use default value MSGQV_DFLT_NAMEKEY from wiakappswiak.h
    
    msgid = msgget((key_t)msgqv_namekey, ptr_wargv_st->wiak_perms | IPC_CREAT); // create the msgqv named: msgqv_namekey
    if (msgid == -1) {
        fprintf(stderr, "Error: failed to create SysV message queue %d\n", msgqv_namekey);
        exit(EXIT_FAILURE);
    }
 
    if (ptr_wargv_st->wiak_send == TRUE)
        func_send_msgqv(ptr_msgid, ptr_wargv_st, ptr_msg_st);
            
    if (ptr_wargv_st->wiak_receive[0] != '\0')
        func_receive_msgqv(ptr_msgid, ptr_wargv_st, ptr_msg_st);

    if (ptr_wargv_st->wiak_quit == TRUE)
    {
        if (msgctl(*ptr_msgid, IPC_RMID, 0) == -1) {
            fprintf(stderr, "Error: func_wiak_msgqv failed to clean up\n");
            exit(EXIT_FAILURE);
        };	
    }
} // end func_wiak_msgqv


void func_send_msgqv(int *ptr_msgid, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st)
{
    if (ptr_wargv_st->wiak_type < CHARDATA)
    {   // This is the default char_string data case
        ptr_msg_st->msgdata.msg_char_str.msgtype = ptr_wargv_st->wiak_type;
        if (msgsnd(*ptr_msgid, (void *) &(ptr_msg_st->msgdata.msg_char_str), (ptr_wargv_st->wiak_length < 0) ? -(ptr_wargv_st->wiak_length) : ptr_wargv_st->wiak_length, 0) == -1) { 
            fprintf(stderr, "Error: func_send_msgqv failed to send data\n");
            exit(EXIT_FAILURE);
        };
    }
    else // assuming must be STRUCTDATA for the moment
    {
        if (msgsnd(*ptr_msgid, (void *)&ptr_msg_st, sizeof(ptr_msg_st->msgdata), 0) == -1) {
            fprintf(stderr, "Error: func_send_msgqv failed to send data\n");
            exit(EXIT_FAILURE);
        };
    }
} /* end_of_func_send_msgqv */


void func_receive_msgqv(int *ptr_msgid, struct wargv *ptr_wargv_st, struct mbox_all *ptr_msg_st)
{
    if (ptr_wargv_st->wiak_type < CHARDATA)
    {   // This is the default char_string data case
        if (msgrcv(*ptr_msgid, (void *)&(ptr_msg_st->msgdata.msg_char_str), sizeof(ptr_msg_st->msgdata.msg_char_str.c_data), ptr_wargv_st->wiak_type, 0) == -1) {
            fprintf(stderr, "Error: func_receive_msgqv failed to recv data\n");
            exit(EXIT_FAILURE);
        };

        write(1, ptr_msg_st->msgdata.msg_char_str.c_data, strlen(ptr_msg_st->msgdata.msg_char_str.c_data));

    }
    else // assuming must be STRUCTDATA for the moment
    {
        if (msgrcv(*ptr_msgid, (void *)&ptr_msg_st, sizeof(ptr_msg_st->msgdata), ptr_wargv_st->wiak_type, 0) == -1) {
            fprintf(stderr, "Error: func_receive_msgqv failed to recv data\n");
            exit(EXIT_FAILURE);
        };

        write(1, ptr_msg_st->msgdata.msg_char_str.c_data, strlen(ptr_msg_st->msgdata.msg_char_str.c_data));
    }
} /* end_of_func_receive_msgqv */

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#28 Post by wiak »

@Flash:

Why are you not unlocking the gtkwialog dev thread when requested?!

Do you have something personal against the Puppy Linux version of gtkdialog being forked for possible use on the Dogs or is there some other actually logical good reason? You haven't given a logically justifiable reason thus far, aside from a demonstration of power.

Otherwise, what is your problem with unlocking the thread exactly? Certainly I can continue discussions here or on another thread, but you would have to be some motive, surely, for forcing that fragmented situation when you can simply unlock?

wiak

Sailor Enceladus
Posts: 1543
Joined: Mon 22 Feb 2016, 19:43

#29 Post by Sailor Enceladus »

This thread should have been sent by PM (Inbox) to a moderator, and as a nice request, not a public outcry. That seems pretty obvious to me, not sure why wiak couldn't have possibly realized this... wiak has just exposed that he/she is a emotional unstable and fickle loose cannon to everyone. Entertaining? A bit. But more uncomfortable and awkward I think. Is jamesbond the only fatdog developer who isn't completely self-absorbed and hasn't completely lost their marbles? Where is that Semme image? Save the drama for your Momma!

Image

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#30 Post by wiak »

Sailor Enceladus wrote:This thread should have been sent by PM (Inbox) to a moderator, and as a nice request, not a public outcry. That seems pretty obvious to me, not sure why wiak couldn't have possibly realized this... wiak has just exposed that he/she is a emotional unstable and fickle loose cannon to everyone. Entertaining? A bit. But more uncomfortable and awkward I think. Is jamesbond the only fatdog developer who isn't completely self-absorbed and hasn't completely lost their marbles? Where is that Semme image? Save the drama for your Momma!
Well, thankyou for that Sailor Enceladus... puppy enthusiast and faithful one. What you fail to recognise is that Flash did not have the courtesy to PM me before locking that development thread. Instead it was a public snub so public it is.
Sailor Enceladus wrote:We could just delete every thread in Puppy Projects that does not fit with the idea mavrothal proposed. Better luck next time guys, should have posted your fork in Puppy Derivatives :twisted: :D
Actually, from your trolling flame comments it is clearly you who is the emotionally insecure and "fickle loose cannon" who needs his mama :-)

But, were this not such a biased forum I expect it is you who would be banned for such non-technical attacks on a person like that.

Your issues are too sensitive to discuss further:
wikipedia wrote:[Enceladus] shoot[s] geyser-like jets of water vapor, molecular hydrogen, other volatiles, and solid material, including sodium chloride crystals and ice particles, into space, totaling about 200 kg (440 lb) per second.[14][17][19] Over 100 geysers have been identified.
:-)

wiak

User avatar
fredx181
Posts: 4448
Joined: Wed 11 Dec 2013, 12:37
Location: holland

#31 Post by fredx181 »

Sailor Enceladus wrote:We could just delete every thread in Puppy Projects that does not fit with the idea mavrothal proposed. Better luck next time guys, should have posted your fork in Puppy Derivatives Twisted Evil Very Happy
Indeed that was an awkward thing to say, probably you may think of it as "Just a joke", well... not funny at all.

Fred

Sailor Enceladus
Posts: 1543
Joined: Mon 22 Feb 2016, 19:43

#32 Post by Sailor Enceladus »

fredx181 wrote:Indeed that was an awkward thing to say, probably you may think of it as "Just a joke", well... not funny at all.
I guess we'll never know what mavrothal thinks about it, he seems to be more interested in global warming now :P

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

Re: wiak.c for people who love C pointers

#33 Post by technosaurus »

wiak wrote:

Code: Select all

/* **************************************************************************
 Program: wiak (an IPC, non-interactive, shell)  Version: 2.3.0         
//...
/* end_of_func_receive_msgqv */
I am assuming you wanted feedback on the code.
I don't know what is in your header file, but its not portable C. write() is in <unistd.h>
You use sprintf instead of snprintf on a fixed size buffer.
When you do a switch-case, it helps readability if you do it in ASCII order and it can help the compiler optimize.
There are several places where you check the same conditional multiple times - those could be factored out. for example:

Code: Select all

else if ((ptr_wargv_st->wiak_channel[0] != '\0') &&  ...
There are places where you are copying strings (unnecessarily?) instead of just using the pointers, though I didn't fully explore its usage.
One of the switch statements has a lot of repetitive code that could be refactored using fallthroughs (and probably replacing the sprintf with string functions)
Using the *printf functions adds quite a bit of bloat, it looks like a few extra functions could save you several Kb in static builds (not a big concern though)
For readability, try to wrap to 78 characters if possible.
It may still be difficult to read because some functions exceed a page. Consider using inline functions or possibly "hugging your if-elses" so that its possible to read a whole function at a time.

Code: Select all

if (cond){ //comment for cond
  foo();
  return 0;
}else{ //comment for !cond
  bar();
  return 1;
}
vs

Code: Select all

if (cond) //comment for cond
{
  foo();
  return 0;
}
else //comment for !cond
{
  bar();
  return 1;
}
Geany's (and other IDE's) code folding makes the former more condensed yet readable
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

Re: wiak.c for people who love C pointers

#34 Post by wiak »

technosaurus wrote:
wiak wrote:

Code: Select all

/* **************************************************************************
 Program: wiak (an IPC, non-interactive, shell)  Version: 2.3.0         
//...
/* end_of_func_receive_msgqv */
I am assuming you wanted feedback on the code.
Yes, thanks technosaurus, the codes over 10 years old and was written just off the cuff in a hurry at the time and I did know it was badly needing refactored. Actually that much I remember - I just basically verbatim copied some of the code lines repetively knowing I should factor them later as major simplifications, but never bothered. Also, yeah I wasn't being careful to avoid sprintf's and so on. But yeah, I'll take a quick look at some of your suggestions - I actually can't remember much of what the code does exactly, but that partly why I dug it out because I wanted to remind myself of the IPC details. I would have to look more carefully at it myself to see the string copies I was making directly other than via pointers - that surprises me, i would usually use pointers for that certainly, but you'd have to indeed also look at the header file, because its impossible to tell if some of these variables are pointers or not, but you may well be correct.

Of course, I expected the code to get put over the coals in terms of style and various inefficiencies - back then I was used to writing quick and dirty code without much thought as to how perfect or otherwise it was - main thing was writing quick TCP/IP test scripts (on other scripts in the Uni research group I worked) where code error trapping was irrelevant and time was short so as long as it generated the appropriate protocol data that was good enough. I wasn't a big system programmer where critical details matter - C was just a quick hack tool amongst many others in that early Internet protocol design research group I was in (but that was around 1990 and wiak was first C I had written for almost 20 years is my only excuse), and for me, still is.

You may be doing more regular bigger system C programming than I ever did, and never now will. but at least I know a little, which has been useful to me.

Thanks for your analysis.

wiak

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

#35 Post by wiak »

This was the header, by the way - I haven't looked at it, and maybe won't either...!

Code: Select all

#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define WIAKFIFOPATH "/tmp/wiak/"
#define FIFOPATHPERMS 0666
#define MBOXPERMS 0666
#define FIFO_DFLT_NAME "wfifo" // default fifo name
#define MSGQV_DFLT_NAMEKEY 45678
#define WAITFIFO 5

#define BUF65536_SIZE 65536
#define BUF32768_SIZE 32768
#define BUF16384_SIZE 16384
#define BUF8192_SIZE 8192
#define BUF4096_SIZE 4096
#define BUF0256_SIZE 256
#define BUF0128_SIZE 128
#define BUF0064_SIZE 64
#define BUF0032_SIZE 32
#define BUF0016_SIZE 16
#define BUF0008_SIZE 8
#define BUF0004_SIZE 4

#define MAX_FIFOMSG BUF65536_SIZE 
#define TRUE 0
#define FALSE 1

// The following #defines are RESERVED and subject to change:
#define CHARSTRDATA 1     // Range 1 to 2047.
#define CHARDATA 2048     // planned Range 2048 to 4095 RESERVED
#define LONGINTDATA 4096  // planned Range 4096 to 6143 RESERVED
#define DOUBLEDATA 6144   // planned Range 6144 to 8191 RESERVED
#define STRUCTDATA 8192   // Experimental, uses 8192 and up RESERVED

static key_t msgqv_namekey = MSGQV_DFLT_NAMEKEY; // key (like a numeric name) to use for the msgqv
static char fifo_name[PATH_MAX] = {'\0'}; // complete fifo name
static char wiak_tmp_path[PATH_MAX] = {WIAKFIFOPATH}; // default fifo path
char *getenv_ptr;

// currently only using CHARSTRDATA
// Any code for STRUCTDATA messages is purely experimental
// Currently can --send messages of max sizes =
// 65536 bytes for fifo IPC and 8192 for SysV message queue IPC
// The above values are system/platform dependent. Results are from
// a Linux system with kernel version 2.6.21.5

struct mbox_char { // RESERVED and subject to change
    long int msgtype; // msg queue C-char type.
                      // Initialise to CHARDATA
    char c_data;
};

struct mbox_long { // RESERVED and subject to change
    long int msgtype; // msg queue C-char type.
                      // Initialise to LONGINTDATA
    long int c_data;
};

struct mbox_char_str {
    long int msgtype; // msg queue C-char_stringdata type.
                      // Initialise to CHARSTRDATA
    char c_data[MAX_FIFOMSG]; // to/from mbox channel to/from wargv_st->wiak_send buffer
};

struct mbox_double { // RESERVED and subject to change
    long int msgtype; // msg queue C-char type.
                      // Initialise to DOUBLEDATA
    double c_data;
};

struct msgdata_struct { // used in fifo and SysV msgqueue mode
    struct mbox_char msg_char; // RESERVED and subject to change
    struct mbox_long msg_long; // RESERVED and subject to change
    struct mbox_char_str msg_char_str; // used in fifo and SysV msgqueue mode
    struct mbox_double msg_double; // RESERVED and subject to change
        
    pid_t pid_t_array[BUF0004_SIZE]; // RESERVED and subject to change
};

struct mbox_all {
    long int msgtype; // msg queue C_struct data type.
                      // Initialise to STRUCTDATA
    struct msgdata_struct msgdata;
};

struct wargv {
	char wiak_up[BUF0256_SIZE];   // program <path>/name of wiakapp backend server to raise
	char wiak_mode[BUF0016_SIZE]; // default is fifo (alternatives: msgqv, ... others coming)
	char wiak_send;	    // set to FALSE (=1) for no --send option selected (i.e. nothing to send)
                        // and TRUE (=0) for --send option selected (i.e. something to send)
	char wiak_receive[BUF0256_SIZE];  // device on which wiak should receive mbox message
	                                  // currently, user should specify stdout
	char wiak_channel[BUF0256_SIZE];  // alphanumeric name for the mbox channel (optional)
                                      // else fifo uses default ch name [+ any zid value]
	pid_t wiak_zid;  // numeric id for identifying the mbox channel (optional)
	char wiak_file[BUF0256_SIZE]; 	// RESERVED and subject to change
	char wiak_dir[BUF0256_SIZE];    // RESERVED and subject to change
	long int wiak_type; // type/priority of messages to send (used in mess queue mode)
                        // default is CHARSTRDATA = char_string_c_data.
                        // Can use for prioritising SysV message queue data.
                        // struct_c_data messages (STRUCTDATA) are currently experimental
                        // and subject to changes in format
	long int wiak_length; // negative values directly indicate string length to --send
                          // positive values indicate terminating chars to --send
                          // 0 = don't append anything; 1 = '\n' only; 2 = '\n' then a '\0'; 
                          // 3 = '\0' only (i.e. a simple C char string);
                          // 4 = '\t' only; 5 = '\t' then a '\0'; 
                          //  6 = '\t', then a '\n'; 7 = '\t', then a '\n' and then a '\0'; 
                          // default is 1, which results in the same behaviour as the default  
                          // (no options used) bash echo command
	int wiak_perms;       // message box (octal rwx) permissions (used in mess queue mode)
	char wiak_init;	      // set to FALSE (=1) for don't make new channel (e.g. fifo)
                          // and TRUE (=0) for make new channel (e.g. create new fifo)
	char wiak_quit;	    // set to FALSE (=1) for don't clean up
                        // and TRUE (=0) for clean up e.g. remove fifo(s) or SysV message queue(s)
}wargv_st =
{ //defaults
    "",
    "",
    FALSE,
    "",
    "",
    0,
    "wiakrecord.conf",
    "/usr/local/wiakapps/morfi/",
    CHARSTRDATA,
    1,
    MBOXPERMS,
    FALSE,
    FALSE
};
Yes, all a bit quick and nasty generally. Worked very reliably though (was very efficient in practical use) - that's one thing... :-)

I remember very well the struggle I had writing it - long hours of reminding myself of enough C to cope. After such a long time I was really very rusty. I'm far worse now unfortunately... But I'm retired and an old man now really as far as coding goes so it doesn't matter any more (and even when I wrote wiak.c I was far past middle-aged so not at my sharpest probably). Time you young guys did all the coding!

wiak
Posts: 2040
Joined: Tue 11 Dec 2007, 05:12
Location: not Bulgaria

reconsidering my old wiak.c code

#36 Post by wiak »

@technosaurus:

I've now had time to have a quick look at my old program code wiak.c and check it against your criticism.

I don't follow what you mean when you say that it is not 'portable C'. From my later posted wiakapps.h header file you should see that I use unistd.h for POSIX API and write() system call does indeed require that.

Yes, I have used sprintf (carefully) when I could have possibly more safely used snprintf to reduce the chance of buffer overloads.

Now that I've looked I can't say I see what you mean that I copied some strings ("unnecessarily?") when I could just have used pointers. The target and destination arguments required by strcpy() are of type pointer. Certainly, I could have written my own very simple strcpy() function but I am not inclined to do that preferring the often more sophisticated library provided well tested versions. I'm not trying to make tiny C code library substitutes in that sense, which I personally wouldn't trust, no matter how good the coder thinks he or she is. Depends on how critical the code is however in terms of end user purpose.

As I said, in practice, the program 'wiak' did everything asked of it and with no exhibited bugs during my testing; I couldn't ask more than that.

As for readability, I personally hate 'hugged' if..else type formatting and I'm not at all keen on in-line functions either. Regarding the length of my functions, they are not in any way too long for my own ability to comprehend them, which is all I strive for. Readability is IMO largely a matter of taste and more important is sticking to a consistent format.

Regarding the switch case statement - yes, I didn't bother rearranging it in alphabetical order - I don't agree that any compiler optimisation would be anything but negligible if I did. I could have allowed some of the logic to 'fallthrough' as you suggest, but I am very aware that there are dangers involved in allowing fallthroughs to occur - an error in that flowthrough logic can cause a major bug in the resultant code, so generally I much prefer to maintain tight control over each case via specific break statements on each satisfied case condition.

Useful to hear another's perspective though, so thanks again.

wiak

Note: My own self-criticism would actually be about the header file itself, which is a complete mess (I don't know what I was thinking about when I created it). No way should I have been defining static elements in there (when in practice I was using them as globals anyway). Nor should I really have been defining (rather than just declaring anything in there). I only 'got away with it' because there was only one .c source file it was being used in. And as for putting the function declarations in wiak.c rather than inside the header?!!! Of course if I had stared modularising things a bit, I would have had to organise the header (sensibly/correctly) accordingly - but I was too busy testing the IPC operations rather than worrying about (highly) potential linking issues, that didn't arise in this case of single .c source.

Post Reply